diff --git a/.doc/contributing-guide/2021.contributing-stickers-side-by-side.png b/.doc/contributing-guide/2021.contributing-stickers-side-by-side.png new file mode 100644 index 000000000..d63f1f72a Binary files /dev/null and b/.doc/contributing-guide/2021.contributing-stickers-side-by-side.png differ diff --git a/.doc/contributing-guide/contributing-stickers-side-by-side.png b/.doc/contributing-guide/2022.contributing-stickers-side-by-side.png similarity index 100% rename from .doc/contributing-guide/contributing-stickers-side-by-side.png rename to .doc/contributing-guide/2022.contributing-stickers-side-by-side.png diff --git a/.doc/itop-version-history.md b/.doc/itop-version-history.md index 6ee4f10e6..32ee32dbf 100644 --- a/.doc/itop-version-history.md +++ b/.doc/itop-version-history.md @@ -53,5 +53,9 @@ gitGraph commit id: "2022-01-04" tag: "3.0.0" branch support/3.0 order: 850 commit id: "2022-04-08" tag: "3.0.1" + checkout support/2.7 + commit id: "2022-07-11" tag: "2.7.7" + checkout support/3.0 + commit id: "2022-09-12" tag: "3.0.2-1" checkout develop -``` \ No newline at end of file +``` diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..690f3fdbc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,48 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.bash text eol=lf +*.bat text eol=lf +*.cmd text eol=lf +*.css text eol=lf +*.scss text eol=lf +*.dist text eol=lf +.editorconfig text eol=lf +.env* text eol=lf +.gitignore text eol=lf +.htaccess text eol=lf +*.htm text eol=lf +*.html text eol=lf +*.ini text eol=lf +*.js text eol=lf +*.json text eol=lf +*.lock text eol=lf +*.md text eol=lf +*.php text eol=lf +*.php_cs text eol=lf +*.php8 text eol=lf +*.plex text eol=lf +*.sh text eol=lf +*.svg text eol=lf +*.ts text eol=lf +*.twig text eol=lf +*.txt text eol=lf +*.xml text eol=lf +*.xsd text eol=lf +*.yaml text eol=lf +*.yml text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpeg binary +*.jpg binary +*.gif binary +*.ico binary +*.pdf binary +*.swf binary +*.zip binary +*.ttf binary +*.woff binary +*.woff2 binary diff --git a/.gitignore b/.gitignore index e0f65ee58..077e29e35 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ test/vendor/* # Jetbrains /.idea/** +!/.idea/IntelliLang.xml # doc. generation /.doc/vendor diff --git a/.idea/IntelliLang.xml b/.idea/IntelliLang.xml new file mode 100644 index 000000000..2703c6f18 --- /dev/null +++ b/.idea/IntelliLang.xml @@ -0,0 +1,15 @@ + + + + + iTop - Class method code + + name(..) = 'method' and count(/itop_design) = 1 + + + iTop - Snippet code + + name(..) = 'snippets' and count(/itop_design) = 1 + + + \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 10c079c99..32c75ebcc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -114,9 +114,9 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file * Use the present tense ("Add feature" not "Added feature") * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") * Limit the first line to 72 characters or less -* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)). - Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now... - Emoji examples : +* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.dev/)). + Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now... + Emoji examples : * 🌐 `:globe_with_meridians:` for translations * 🎹 `:art:` when improving the format/structure of the code * âšĄïž `:zap:` when improving performance @@ -160,4 +160,4 @@ We have one sticker per contribution type. You might get multiple stickers with Here is the design of each stickers for year 2022: -![iTop stickers 2022](.doc/contributing-guide/contributing-stickers-side-by-side.png) +![iTop stickers 2022](.doc/contributing-guide/2022.contributing-stickers-side-by-side.png) diff --git a/README.md b/README.md index d387112d8..637259ecc 100644 --- a/README.md +++ b/README.md @@ -100,8 +100,11 @@ We would like to give a special thank you đŸ€— to the people from the community - Lucas, Jonathan - Malik, Remie - MindĂȘllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam)) +- Mozart de Oliveira, Eduardo (a.k.a [@eduardomozart](https://github.com/eduardomozart)) - Raenker, Martin +- Roháč, Richard (a.k.a [@RohacRichard](https://github.com/RohacRichard)) - Rosenke, Stephan +- Rudner, Björn (a.k.a [@rudnerbjoern](https://github.com/rudnerbjoern)) - Seki, Shoji - Shilov, Vladimir - Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov) @@ -115,6 +118,7 @@ We would like to give a special thank you đŸ€— to the people from the community - DudekArtur - Karkoff1212 - Laura +- nv35 - Purple Grape - Schlobinux - theBigOne diff --git a/addons/userrights/userrightsprofile.class.inc.php b/addons/userrights/userrightsprofile.class.inc.php index c6b1ca722..9d1c771be 100644 --- a/addons/userrights/userrightsprofile.class.inc.php +++ b/addons/userrights/userrightsprofile.class.inc.php @@ -124,7 +124,7 @@ class URP_Profiles extends UserRightsBaseClassGUI $bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); if ($bGrant === true) { - $aStimuli[] = ''.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').''; + $aStimuli[] = ''.utils::EscapeHtml($oStimulus->GetLabel()).''; } } $sStimuli = implode(', ', $aStimuli); diff --git a/addons/userrights/userrightsprofile.db.class.inc.php b/addons/userrights/userrightsprofile.db.class.inc.php index 44b40ab30..10fc826d9 100644 --- a/addons/userrights/userrightsprofile.db.class.inc.php +++ b/addons/userrights/userrightsprofile.db.class.inc.php @@ -278,8 +278,8 @@ class URP_Profiles extends UserRightsBaseClassGUI { $oGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); if (is_object($oGrant) && ($oGrant->Get('permission') == 'yes')) - { - $aStimuli[] = ''.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').''; + { + $aStimuli[] = ''.utils::EscapeHtml($oStimulus->GetLabel()).''; } } $sStimuli = implode(', ', $aStimuli); diff --git a/addons/userrights/userrightsprojection.class.inc.php b/addons/userrights/userrightsprojection.class.inc.php index 6aa5eefc0..84f239c52 100644 --- a/addons/userrights/userrightsprojection.class.inc.php +++ b/addons/userrights/userrightsprojection.class.inc.php @@ -110,8 +110,8 @@ class URP_Profiles extends UserRightsBaseClass { $oGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); if (is_object($oGrant) && ($oGrant->Get('permission') == 'yes')) - { - $aStimuli[] = ''.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').''; + { + $aStimuli[] = ''.utils::EscapeHtml($oStimulus->GetLabel()).''; } } $sStimuli = implode(', ', $aStimuli); diff --git a/application/applicationcontext.class.inc.php b/application/applicationcontext.class.inc.php index 1361f92d3..903fa2cee 100644 --- a/application/applicationcontext.class.inc.php +++ b/application/applicationcontext.class.inc.php @@ -224,7 +224,7 @@ class ApplicationContext { $sContext = ""; foreach ($this->aValues as $sName => $sValue) { - $sContext .= "\n"; + $sContext .= "\n"; } return $sContext; } @@ -238,7 +238,7 @@ class ApplicationContext { $aContextInputBlocks = []; foreach ($this->aValues as $sName => $sValue) { - $aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", htmlentities($sValue, ENT_QUOTES, 'UTF-8')); + $aContextInputBlocks[] = InputUIBlockFactory::MakeForHidden("c[$sName]", utils::EscapeHtml($sValue)); } return $aContextInputBlocks; } diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 8feea05fe..2a2f9495b 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -342,7 +342,7 @@ JS } /** - * @param \WebPage $oPage warning, since 3.0.0 this parameter was kept for compatibility reason. You shouldn't write directly on the page ! + * @param \WebPage $oPage Warning, since 3.0.0 this parameter was kept for compatibility reason. You shouldn't write directly on the page! * When writing to the page, markup will be put above the real header of the panel. * To insert something IN the panel, we now need to add UIBlocks in either the "subtitle" or "toolbar" sections of the array that will be returned. * @param bool $bEditMode Deprecated parameter in iTop 3.0.0, use {@see GetDisplayMode()} and ENUM_DISPLAY_MODE_* constants instead @@ -362,7 +362,7 @@ JS * @throws \OQLException * * @since 3.0.0 $bEditMode is deprecated, see param documentation above - * @since 3.0.0 changed signature : method must return header content in an array (no more writing directly to the $oPage) + * @since 3.0.0 Changed signature: Method must return header content in an array (no more writing directly to the $oPage) * * @noinspection PhpUnusedParameterInspection */ @@ -988,10 +988,8 @@ HTML $this->GetSynchroReplicaFlags($sAttCode, $aReasons); $sTip = ''; foreach ($aReasons as $aRow) { - $sDescription = htmlentities($aRow['description'], ENT_QUOTES, - 'UTF-8'); - $sDescription = str_replace(array("\r\n", "\n"), "
", - $sDescription); + $sDescription = utils::EscapeHtml($aRow['description']); + $sDescription = str_replace(array("\r\n", "\n"), "
", $sDescription); $sTip .= "
"; $sTip .= "
Synchronized with {$aRow['name']}
"; $sTip .= "
$sDescription
"; @@ -1404,7 +1402,7 @@ HTML } else { if ($oAttDef instanceof AttributeCaseLog) { $rawValue = $oObj->Get($sAttCodeEx); - $outputValue = str_replace("\n", "
", htmlentities($rawValue->__toString(), ENT_QUOTES, 'UTF-8')); + $outputValue = str_replace("\n", "
", utils::EscapeHtml($rawValue->__toString())); // Trick for Excel: treat the content as text even if it begins with an equal sign $aRow[$oAttDef->GetCode()] = $outputValue; } else { @@ -1418,9 +1416,9 @@ HTML } } if ($bLocalize) { - $outputValue = htmlentities($oFinalAttDef->GetEditValue($rawValue), ENT_QUOTES, 'UTF-8'); + $outputValue = utils::EscapeHtml($oFinalAttDef->GetEditValue($rawValue)); } else { - $outputValue = htmlentities($rawValue, ENT_QUOTES, 'UTF-8'); + $outputValue = utils::EscapeHtml($rawValue); } $aRow[$oAttDef->GetCode()] = $outputValue; } @@ -1896,7 +1894,7 @@ HTML { $rawValue = $oObj->Get($sAttCodeEx); $outputValue = str_replace("\n", "
", - htmlentities($rawValue->__toString(), ENT_QUOTES, 'UTF-8')); + utils::EscapeHtml($rawValue->__toString())); // Trick for Excel: treat the content as text even if it begins with an equal sign $aRow[] = ''.$outputValue.''; } @@ -1913,14 +1911,11 @@ HTML $rawValue = ''; } } - if ($bLocalize) - { - $outputValue = htmlentities($oFinalAttDef->GetEditValue($rawValue), ENT_QUOTES, - 'UTF-8'); + if ($bLocalize) { + $outputValue = utils::EscapeHtml($oFinalAttDef->GetEditValue($rawValue)); } - else - { - $outputValue = htmlentities($rawValue, ENT_QUOTES, 'UTF-8'); + else { + $outputValue = utils::EscapeHtml($rawValue); } $aRow[] = ''.$outputValue.''; } @@ -2157,7 +2152,7 @@ HTML; $sHours = ""; $sMinutes = ""; $sSeconds = ""; - $sHidden = ""; + $sHidden = ""; $sHTMLValue = Dict::Format('UI:DurationForm_Days_Hours_Minutes_Seconds', $sDays, $sHours, $sMinutes, $sSeconds).$sHidden." ".$sValidationSpan.$sReloadSpan; $oPage->add_ready_script("$('#{$iId}').on('update', function(evt, sFormId) { return ToggleDurationField('$iId'); });"); break; @@ -2167,8 +2162,7 @@ HTML; $aEventsList[] = 'validate'; $aEventsList[] = 'keyup'; $aEventsList[] = 'change'; - $sHTMLValue = "
{$sValidationSpan}{$sReloadSpan}"; + $sHTMLValue = "
{$sValidationSpan}{$sReloadSpan}"; break; case 'OQLExpression': @@ -2320,13 +2314,13 @@ EOF $sHeader = '
'; // will be hidden in CSS (via :empty) if it remains empty $sEditValue = is_object($value) ? $value->GetModifiedEntry('html') : ''; - $sPreviousLog = is_object($value) ? $value->GetAsHTML($oPage, true /* bEditMode */, array('AttributeText', 'RenderWikiHtml')) : ''; + $sPreviousLog = is_object($value) ? $value->GetAsHTML($oPage, true /* bEditMode */, array('AttributeText', 'RenderWikiHtml')) : ''; $iEntriesCount = is_object($value) ? count($value->GetIndex()) : 0; $sHidden = ""; // To know how many entries the case log already contains $sHTMLValue = "$sHeader
"; - $sHTMLValue .= ""; - $sHTMLValue .= "$sPreviousLog
{$sValidationSpan}{$sReloadSpan}$sHidden"; + $sHTMLValue .= ""; + $sHTMLValue .= "$sPreviousLog
{$sValidationSpan}{$sReloadSpan}$sHidden"; // Note: This should be refactored for all types of attribute (see at the end of this function) but as we are doing this for a maintenance release, we are scheduling it for the next main release in to order to avoid regressions as much as possible. $sNullValue = $oAttDef->GetNullValue(); @@ -2571,16 +2565,16 @@ JS case 'Set': case 'TagSet': - $sInputType = self::ENUM_INPUT_TYPE_TAGSET; - $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js'); - $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css'); - $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.itop-set-widget.js'); + $sInputType = self::ENUM_INPUT_TYPE_TAGSET; + $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js'); + $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css'); + $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.itop-set-widget.js'); - $oPage->add_dict_entry('Core:AttributeSet:placeholder'); + $oPage->add_dict_entry('Core:AttributeSet:placeholder'); - /** @var \ormSet $value */ + /** @var \ormSet $value */ $sJson = $oAttDef->GetJsonForWidget($value, $aArgs); - $sEscapedJson = htmlentities($sJson, ENT_QUOTES, 'UTF-8'); + $sEscapedJson = utils::EscapeHtml($sJson); $sSetInputName = "attr_{$sFormPrefix}{$sAttCode}"; // handle form validation @@ -3693,8 +3687,7 @@ HTML; break; default: - $oPage->add("
".htmlentities(MyHelpers::beautifulstr($data, 1000, true), ENT_QUOTES,
-								'UTF-8')."
\n"); + $oPage->add("
".utils::EscapeHtml(MyHelpers::beautifulstr($data, 1000, true))."
\n"); } break; @@ -4743,9 +4736,8 @@ HTML; { $aReasons = array(); $sTip = ''; - foreach($aReasons as $aRow) - { - $sDescription = htmlentities($aRow['description'], ENT_QUOTES, 'UTF-8'); + foreach($aReasons as $aRow) { + $sDescription = utils::EscapeHtml($aRow['description']); $sDescription = str_replace(array("\r\n", "\n"), "
", $sDescription); $sTip .= "
"; $sTip .= "
Synchronized with {$aRow['name']}
"; @@ -4757,8 +4749,7 @@ HTML; // Attribute is read-only $sHTMLValue = $this->GetAsHTML($sAttCode); - $sHTMLValue .= ''; + $sHTMLValue .= ''; $aFieldsMap[$sAttCode] = $sInputId; } else @@ -5094,7 +5085,7 @@ HTML if ($sAttCode != MetaModel::GetStateAttributeCode($sClass) || !MetaModel::HasLifecycle($sClass)) { $sValueCheckbox = ''; } - $aComments[$sAttCode] .= '
'.$iCount.$sValueCheckbox.'
'; + $aComments[$sAttCode] .= '
'.$iCount.$sValueCheckbox.'
'; } $sReadyScript .= 'ToggleField('.(($iCount == 1) ? 'true' : 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n"; } @@ -5213,10 +5204,13 @@ EOF $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped'); } + $aErrorsToDisplay = array_map(function($sError) { + return utils::HtmlEntities($sError); + }, $aErrors); $aRows[] = array( 'object' => $oObj->GetHyperlink(), 'status' => $sStatus, - 'errors' => '

'.($bResult ? '' : implode('

', $aErrors)).'

', + 'errors' => '

'.($bResult ? '' : implode('

', $aErrorsToDisplay)).'

', ); if ($bResult && (!$bPreview)) { $oObj->DBUpdate(); diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 9dfe47e7e..534d3031a 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -1207,6 +1207,7 @@ JS $sTitle = Dict::Format($sFormat, $iTotalCount); $oBlock = PanelUIBlockFactory::MakeForClass($aExtraParams["panel_class"], $aExtraParams["panel_title"]); $oBlock->AddSubTitleBlock(new Html($sTitle)); + $oBlock->AddCSSClass('ibo-datatable-panel'); if(isset($aExtraParams["panel_icon"]) && strlen($aExtraParams["panel_icon"]) > 0){ $oBlock->SetIcon($aExtraParams["panel_icon"]); } diff --git a/application/exceptions/CoreCannotSaveObjectException.php b/application/exceptions/CoreCannotSaveObjectException.php index d7e4235d9..dcbe20ff5 100644 --- a/application/exceptions/CoreCannotSaveObjectException.php +++ b/application/exceptions/CoreCannotSaveObjectException.php @@ -44,15 +44,15 @@ class CoreCannotSaveObjectException extends CoreException public function getHtmlMessage() { $sTitle = Dict::S('UI:Error:SaveFailed'); - $sContent = "{$sTitle}"; + $sContent = "".utils::HtmlEntities($sTitle).""; if (count($this->aIssues) == 1) { $sIssue = reset($this->aIssues); - $sContent .= " {$sIssue}"; + $sContent .= " ".utils::HtmlEntities($sIssue).""; } else { $sContent .= ''; } diff --git a/application/forms.class.inc.php b/application/forms.class.inc.php index bec82cab4..3a720c39b 100644 --- a/application/forms.class.inc.php +++ b/application/forms.class.inc.php @@ -838,7 +838,8 @@ class DesignerFormField { $sId = $this->oForm->GetFieldId($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode); - return array('label' => $this->sLabel, 'value' => "defaultValue, ENT_QUOTES, 'UTF-8')."\">"); + + return array('label' => $this->sLabel, 'value' => "defaultValue)."\">"); } /** @@ -1012,9 +1013,8 @@ class DesignerTextField extends DesignerFormField $sId = $this->oForm->GetFieldId($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode); - if ($this->IsReadOnly()) - { - $sHtmlValue = "".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."defaultValue, ENT_QUOTES, 'UTF-8')."\"/>"; + if ($this->IsReadOnly()) { + $sHtmlValue = "".utils::EscapeHtml($this->defaultValue)."defaultValue)."\"/>"; } else { @@ -1038,11 +1038,10 @@ $('#$sId').on('change keyup validate', function() { ValidateWithPattern('$sId', EOF ); $sCSSClasses = ''; - if (count($this->aCSSClasses) > 0) - { + if (count($this->aCSSClasses) > 0) { $sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"'; } - $sHtmlValue = "defaultValue, ENT_QUOTES, 'UTF-8')."\">"; + $sHtmlValue = "defaultValue)."\">"; } return array('label' => $this->sLabel, 'value' => $sHtmlValue); } @@ -1101,10 +1100,9 @@ class DesignerLongTextField extends DesignerTextField { $sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"'; } - if (!$this->IsReadOnly()) - { + if (!$this->IsReadOnly()) { $oP->add_ready_script( -<<".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8').""; + $sValue = ""; } - else - { - $sValue = "
".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."
"; + else { + $sValue = "
".utils::EscapeHtml($this->defaultValue)."
"; } return array('label' => $this->sLabel, 'value' => $sValue); } @@ -1145,9 +1142,8 @@ class DesignerIntegerField extends DesignerFormField $sId = $this->oForm->GetFieldId($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode); - if ($this->IsReadOnly()) - { - $sHtmlValue = "".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."defaultValue, ENT_QUOTES, 'UTF-8')."\"/>"; + if ($this->IsReadOnly()) { + $sHtmlValue = "".utils::EscapeHtml($this->defaultValue)."defaultValue)."\"/>"; } else { @@ -1164,11 +1160,10 @@ $('#$sId').on('change keyup validate', function() { ValidateInteger('$sId', $sMa EOF ); $sCSSClasses = ''; - if (count($this->aCSSClasses) > 0) - { + if (count($this->aCSSClasses) > 0) { $sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"'; } - $sHtmlValue = "defaultValue, ENT_QUOTES, 'UTF-8')."\">"; + $sHtmlValue = "defaultValue)."\">"; } return array('label' => $this->sLabel, 'value' => $sHtmlValue); } @@ -1289,22 +1284,18 @@ class DesignerComboField extends DesignerFormField { if ($this->bMultipleSelection) { - if(in_array($sKey, $this->defaultValue)) - { + if(in_array($sKey, $this->defaultValue)) { $aSelected[] = $sDisplayValue; - $aHiddenValues[] = ""; + $aHiddenValues[] = ""; } - } - else - { - if ($sKey == $this->defaultValue) - { + } else { + if ($sKey == $this->defaultValue) { $aSelected[] = $sDisplayValue; - $aHiddenValues[] = ""; + $aHiddenValues[] = ""; } } } - $sHtml = "".htmlentities(implode(', ', $aSelected), ENT_QUOTES, 'UTF-8').implode($aHiddenValues).""; + $sHtml = "".utils::EscapeHtml(implode(', ', $aSelected)).implode($aHiddenValues).""; } else { @@ -1328,7 +1319,7 @@ class DesignerComboField extends DesignerFormField } // Quick and dirty: display the menu parents as a tree $sHtmlValue = str_replace(' ', ' ', $sDisplayValue); - $sHtml .= ""; + $sHtml .= ""; } $sHtml .= ""; if ($this->bOtherChoices) @@ -1379,10 +1370,9 @@ class DesignerBooleanField extends DesignerFormField $sId = $this->oForm->GetFieldId($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode); $sChecked = $this->defaultValue ? 'checked' : ''; - if ($this->IsReadOnly()) - { + if ($this->IsReadOnly()) { $sLabel = $this->defaultValue ? Dict::S('UI:UserManagement:ActionAllowed:Yes') : Dict::S('UI:UserManagement:ActionAllowed:No'); //TODO use our own yes/no translations - $sHtmlValue = "".htmlentities($sLabel)."defaultValue, ENT_QUOTES, 'UTF-8')."\"/>"; + $sHtmlValue = "".utils::EscapeHtml($sLabel)."defaultValue)."\"/>"; } else { @@ -1450,8 +1440,8 @@ class DesignerHiddenField extends DesignerFormField { $sId = $this->oForm->GetFieldId($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode); - $sChecked = $this->defaultValue ? 'checked' : ''; - return array('label' =>'', 'value' => "defaultValue, ENT_QUOTES, 'UTF-8')."\">"); + + return array('label' => '', 'value' => "defaultValue)."\">"); } } @@ -1518,7 +1508,7 @@ class DesignerIconSelectionField extends DesignerFormField EOF ); } else { - $sValue = ' '.htmlentities($this->aAllowedValues[$idx]['label'], ENT_QUOTES, 'UTF-8').''; + $sValue = ' '.utils::EscapeHtml($this->aAllowedValues[$idx]['label']).''; } $sReadOnly = $this->IsReadOnly() ? 'disabled' : ''; return array('label' => $this->sLabel, 'value' => $sValue); @@ -1665,14 +1655,14 @@ class DesignerSortableField extends DesignerFormField $sId = $this->oForm->GetFieldId($this->sCode); $sName = $this->oForm->GetFieldName($this->sCode); $sReadOnly = $this->IsReadOnly() ? 'readonly="readonly"' : ''; - $aResult = array('label' => $this->sLabel, 'value' => "defaultValue, ENT_QUOTES, 'UTF-8')."\">"); - + $aResult = array('label' => $this->sLabel, 'value' => "defaultValue)."\">"); + $sJSFields = json_encode(array_keys($this->aAllowedValues)); $oP->add_ready_script( "$('#$sId').sortable_field({aAvailableFields: $sJSFields});" ); - + return $aResult; } } @@ -1761,8 +1751,8 @@ class DesignerFormSelectorField extends DesignerFormField foreach ($this->aSubForms as $iKey => $aFormData) { if ($iKey == $this->defaultValue) // Default value is actually the index { - $sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8'); - $sHiddenValue = ""; + $sDisplayValue = utils::EscapeHtml($aFormData['label']); + $sHiddenValue = ""; break; } } @@ -1770,8 +1760,8 @@ class DesignerFormSelectorField extends DesignerFormField } else { $sHtml = "'; + $sHTMLValue .= ''; $aFieldsMap[$sAttCode] = $iInputId; $aParams['this->comments('.$sAttCode.')'] = $sSynchroIcon; } diff --git a/application/ui.extkeywidget.class.inc.php b/application/ui.extkeywidget.class.inc.php index 4162ebcfe..162198c31 100644 --- a/application/ui.extkeywidget.class.inc.php +++ b/application/ui.extkeywidget.class.inc.php @@ -211,14 +211,23 @@ class UIExtKeyWidget $sClassAllowed = $oAllowedValues->GetClass(); $bAddingValue = false; + // N°4792 - load only the required fields + $aFieldsToLoad = []; + $aComplementAttributeSpec = MetaModel::GetNameSpec($oAllowedValues->GetClass(), FriendlyNameType::COMPLEMENTARY); $sFormatAdditionalField = $aComplementAttributeSpec[0]; $aAdditionalField = $aComplementAttributeSpec[1]; if (count($aAdditionalField) > 0) { $bAddingValue = true; + $aFieldsToLoad[$sClassAllowed] = $aAdditionalField; } $sObjectImageAttCode = MetaModel::GetImageAttributeCode($sClassAllowed); + if (!empty($sObjectImageAttCode)) { + $aFieldsToLoad[$sClassAllowed][] = $sObjectImageAttCode; + } + $aFieldsToLoad[$sClassAllowed][] = 'friendlyname'; + $oAllowedValues->OptimizeColumnLoad($aFieldsToLoad); $bInitValue = false; while ($oObj = $oAllowedValues->Fetch()) { $aOption = []; @@ -298,7 +307,7 @@ EOF $sHTMLValue .= "iId\" value=\"$sDisplayValue\" placeholder='...'/>"; // another hidden input to store & pass the object's Id - $sHTMLValue .= "iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n"; + $sHTMLValue .= "iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".utils::HtmlEntities($value)."\" />\n"; $JSSearchMode = $this->bSearchMode ? 'true' : 'false'; // Scripts to start the autocomplete and bind some events to it @@ -610,7 +619,7 @@ EOF $sHTMLValue .= "
iId}\" onClick=\"oACWidget_{$this->iId}.Search();\">
"; // another hidden input to store & pass the object's Id - $sHTMLValue .= "iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n"; + $sHTMLValue .= "iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".utils::EscapeHtml($value)."\" />\n"; $JSSearchMode = $this->bSearchMode ? 'true' : 'false'; // Scripts to start the autocomplete and bind some events to it @@ -769,16 +778,14 @@ JS * @param DBObject $oObj The current object for the OQL context * @param string $sContains The text of the autocomplete to filter the results * @param string $sOutputFormat - * @param null $sOperation for the values @see ValueSetObjects->LoadValues() + * @param null $sOperation for the values @see ValueSetObjects->LoadValues() not used since 3.0.0 * * @throws CoreException * @throws OQLException * * @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $oObj for PHP 8.0 compatibility */ - public function AutoComplete( - WebPage $oP, $sFilter, $oObj, $sContains, $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null - ) + public function AutoComplete(WebPage $oP, $sFilter, $oObj, $sContains, $sOutputFormat = self::ENUM_OUTPUT_FORMAT_CSV, $sOperation = null ) { if (is_null($sFilter)) { throw new Exception('Implementation: null value for allowed values definition'); @@ -792,13 +799,13 @@ JS $oValuesSet->SetSort(false); $oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode); $oValuesSet->SetLimit($iMax); - $aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with'); - asort($aValuesContains); - $aValues = $aValuesContains; + $aValuesStartWith = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with'); + asort($aValuesStartWith); + $aValues = $aValuesStartWith; if (sizeof($aValues) < $iMax) { $aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains'); asort($aValuesContains); - $iSize = sizeof($aValuesContains); + $iSize = sizeof($aValues); foreach ($aValuesContains as $sKey => $sFriendlyName) { if (!isset($aValues[$sKey])) @@ -814,7 +821,9 @@ JS elseif (!in_array($sContains, $aValues)) { $aValuesEquals = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'equals'); - $aValues = array_merge($aValuesEquals, $aValues); + // Note: Here we cannot use array_merge as it would reindex the numeric keys starting from 0 when keys are actually the objects ID. + // As a workaround we use array_replace as it does preserve numeric keys. It's ok if some values from $aValuesEquals are replaced with values from $aValues as they contain the same data. + $aValues = array_replace($aValuesEquals, $aValues); } switch($sOutputFormat) @@ -962,7 +971,7 @@ HTML foreach (MetaModel::ListAttributeDefs($this->sTargetClass) as $sAttCode => $oAttDef) { if (($oAttDef instanceof AttributeBlob) || (false)) { $aFieldsFlags[$sAttCode] = OPT_ATT_READONLY; - $aFieldsComments[$sAttCode] = ' '; + $aFieldsComments[$sAttCode] = ' '; } } cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), array('formPrefix' => $this->iId, 'noRelations' => true, 'fieldsFlags' => $aFieldsFlags, 'fieldsComments' => $aFieldsComments)); @@ -973,7 +982,7 @@ HTML ); $oPage->add_ready_script(<<iId}').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true}); +$('#ac_create_{$this->iId}').dialog({ width: $(window).width() * 0.6, height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true}); $('#dcr_{$this->iId} form').removeAttr('onsubmit'); $('#dcr_{$this->iId} form').find('button[type="submit"]').on('click', oACWidget_{$this->iId}.DoCreateObject); JS diff --git a/application/ui.linksdirectwidget.class.inc.php b/application/ui.linksdirectwidget.class.inc.php index 1a750e327..2bd2d1646 100644 --- a/application/ui.linksdirectwidget.class.inc.php +++ b/application/ui.linksdirectwidget.class.inc.php @@ -255,7 +255,7 @@ class UILinksWidgetDirect $oDiv = UIContentBlockUIBlockFactory::MakeStandard($this->sInputid, ['listContainer']); $oPage->AddSubBlock($oDiv); $oDatatable = DataTableUIBlockFactory::MakeForForm($this->sInputid, $aAttribs, $aData); - $oDatatable->SetOptions(['select_mode' => 'custom']); + $oDatatable->SetOptions(['select_mode' => 'custom', 'disable_hyperlinks' => true]); $oDiv->AddSubBlock($oDatatable); $sInputName = $sFormPrefix.'attr_'.$this->sAttCode; $aLabels = array( diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index 1f4e63da5..c8b599068 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -377,33 +377,34 @@ JS $aForm = array(); $iMaxAddedId = 0; $iAddedId = -1; // Unique id for new links - while ($oCurrentLink = $oValue->Fetch()) - { + $oBlock->aRemoved = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$this->m_sAttCode}_tbd", '[]', 'raw_data')); + while ($oCurrentLink = $oValue->Fetch()) { // We try to retrieve the remote object as usual - $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), - false /* Must not be found */); - // If successful, it means that we can edit its link - if ($oLinkedObj !== null) { - $bReadOnly = false; - } // Else we retrieve it without restrictions (silos) and will display its link as readonly - else { - $bReadOnly = true; - $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */, true); - } + if (!in_array($oCurrentLink->GetKey(), $oBlock->aRemoved)) { + $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */); + // If successful, it means that we can edit its link + if ($oLinkedObj !== null) { + $bReadOnly = false; + } // Else we retrieve it without restrictions (silos) and will display its link as readonly + else { + $bReadOnly = true; + $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */, true); + } - if ($oCurrentLink->IsNew()) { - $key = $iAddedId--; - } else { - $key = $oCurrentLink->GetKey(); - } + if ($oCurrentLink->IsNew()) { + $key = $iAddedId--; + } else { + $key = $oCurrentLink->GetKey(); + } - $iMaxAddedId = max($iMaxAddedId, $key); - $aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly); + $iMaxAddedId = max($iMaxAddedId, $key); + $aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly); + } } - $oBlock->iMaxAddedId = (int) $iMaxAddedId; + $oBlock->iMaxAddedId = (int)$iMaxAddedId; $oDataTable = DataTableUIBlockFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aForm); - $oDataTable->SetOptions(['select_mode' => 'custom']); + $oDataTable->SetOptions(['select_mode' => 'custom', 'disable_hyperlinks' => true]); $oBlock->AddSubBlock($oDataTable); $oBlock->AddControls(); diff --git a/application/ui.passwordwidget.class.inc.php b/application/ui.passwordwidget.class.inc.php index 16e333ab3..58aca4fa3 100644 --- a/application/ui.passwordwidget.class.inc.php +++ b/application/ui.passwordwidget.class.inc.php @@ -60,8 +60,8 @@ class UIPasswordWidget $sChangedValue = (($sPasswordValue != '*****') || ($sConfirmPasswordValue != '*****')) ? 1 : 0; $sHtmlValue = ''; $sHtmlValue .= '
'; - $sHtmlValue .= ''; - $sHtmlValue .= '
'; + $sHtmlValue .= ''; + $sHtmlValue .= '
'; $sHtmlValue .= '
'; $sHtmlValue .= ''; diff --git a/application/utils.inc.php b/application/utils.inc.php index 09f60bb13..eb451d9af 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -813,21 +813,20 @@ class utils */ public static function StringToTime($sDate, $sFormat) { - // Source: http://php.net/manual/fr/function.strftime.php + // Source: http://php.net/manual/fr/function.strftime.php // (alternative: http://www.php.net/manual/fr/datetime.formats.date.php) static $aDateTokens = null; static $aDateRegexps = null; - if (is_null($aDateTokens)) - { - $aSpec = array( - '%d' =>'(?[0-9]{2})', + if (is_null($aDateTokens)) { + $aSpec = array( + '%d' => '(?[0-9]{2})', '%m' => '(?[0-9]{2})', '%y' => '(?[0-9]{2})', '%Y' => '(?[0-9]{4})', '%H' => '(?[0-2][0-9])', '%i' => '(?[0-5][0-9])', '%s' => '(?[0-5][0-9])', - ); + ); $aDateTokens = array_keys($aSpec); $aDateRegexps = array_values($aSpec); } @@ -1827,7 +1826,7 @@ class utils */ public static function HtmlEntities($sValue) { - return htmlentities($sValue, ENT_QUOTES, 'UTF-8'); + return htmlentities($sValue ?? '', ENT_QUOTES, 'UTF-8'); } /** @@ -1843,7 +1842,7 @@ class utils public static function EscapeHtml($sValue) { return htmlspecialchars( - $sValue, + $sValue ?? '', ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, WebPage::PAGES_CHARSET, false @@ -1892,7 +1891,8 @@ class utils { $sText = str_replace("\r\n", "\n", $sText); $sText = str_replace("\r", "\n", $sText); - return str_replace("\n", '
', htmlentities($sText, ENT_QUOTES, 'UTF-8')); + + return str_replace("\n", '
', utils::EscapeHtml($sText)); } /** @@ -1942,25 +1942,24 @@ class utils */ public static function CompileCSSFromSASS($sSassContent, $aImportPaths = array(), $aVariables = array()) { - $oSass = new Compiler();//['checkImportResolutions'=>true]); + $oSass = new Compiler(); $oSass->setOutputStyle(OutputStyle::COMPRESSED); // Setting our variables - $aCssVariable = []; - foreach ($aVariables as $entry=>$value) { - $aCssVariable[$entry] = ValueConverter::parseValue($value); + $aScssVariables = []; + foreach ($aVariables as $entry => $value) { + $aScssVariables[$entry] = ValueConverter::parseValue($value); } - $oSass->addVariables($aCssVariable); + $oSass->addVariables($aScssVariables); // Setting our imports paths $oSass->setImportPaths($aImportPaths); // Temporary disabling max exec time while compiling $iCurrentMaxExecTime = (int) ini_get('max_execution_time'); set_time_limit(0); // Compiling SASS - //checkImportResolutions - $sCss = $oSass->compileString($sSassContent); + $oCompilationRes = $oSass->compileString($sSassContent); set_time_limit(intval($iCurrentMaxExecTime)); - return $sCss->getCss(); + return $oCompilationRes->getCss(); } /** @@ -2719,10 +2718,24 @@ HTML; $aAutoloadClassMaps = array_merge($aAutoloadClassMaps, glob(APPROOT.'env-'.utils::GetCurrentEnvironment().'/*/vendor/composer/autoload_classmap.php')); $aClassMap = []; + $aAutoloaderErrors = []; foreach ($aAutoloadClassMaps as $sAutoloadFile) { + if (false === static::RealPath($sAutoloadFile, APPROOT)) { + // can happen when we still have the autoloader symlink in env-*, but it points to a file that no longer exists + $aAutoloaderErrors[] = $sAutoloadFile; + continue; + } $aTmpClassMap = include $sAutoloadFile; + /** @noinspection SlowArrayOperationsInLoopInspection we are getting an associative array so the documented workarounds cannot be used */ $aClassMap = array_merge($aClassMap, $aTmpClassMap); } + if (count($aAutoloaderErrors) > 0) { + IssueLog::Debug( + "\utils::GetClassesForInterface cannot load some of the autoloader files", + LogChannels::CORE, + ['autoloader_errors' => $aAutoloaderErrors] + ); + } // Add already loaded classes $aCurrentClasses = array_fill_keys(get_declared_classes(), ''); @@ -2730,7 +2743,7 @@ HTML; foreach ($aClassMap as $sPHPClass => $sPHPFile) { $bSkipped = false; - + // Check if our class matches name filter, or is in an excluded path if ($sClassNameFilter !== '' && strpos($sPHPClass, $sClassNameFilter) === false) { $bSkipped = true; @@ -2845,6 +2858,36 @@ HTML; return strlen($sString ?? ''); } + /** + * Helper around the native strlen() PHP method to test a string for null or empty value + * + * @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated" + * + * @param string|null $sString + * + * @return bool if string null or empty + * @since 3.0.2 N°5302 + */ + public static function IsNullOrEmptyString(?string $sString): bool + { + return $sString === null || strlen($sString) === 0; + } + + /** + * Helper around the native strlen() PHP method to test a string not null or empty value + * + * @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated" + * + * @param string|null $sString + * + * @return bool if string is not null and not empty + * @since 3.0.2 N°5302 + */ + public static function IsNotNullOrEmptyString(?string $sString): bool + { + return !static::IsNullOrEmptyString($sString); + } + //---------------------------------------------- // Environment helpers //---------------------------------------------- diff --git a/composer.json b/composer.json index 5b668d290..52d6fe3ee 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,10 @@ { + "name": "combodo/itop", + "description": "IT Operations Portal", "type": "project", - "license": "AGPLv3", + "license": "AGPL-3.0-only", "require": { - "php": ">=7.2.5 <8.0.0", + "php": ">=7.4.0 <8.2.0", "ext-ctype": "*", "ext-dom": "*", "ext-gd": "*", @@ -10,14 +12,15 @@ "ext-json": "*", "ext-mysqli": "*", "ext-soap": "*", + "apereo/phpcas" : "~1.3", "combodo/tcpdf": "~6.4.4", - "guzzlehttp/guzzle": "^6.5.8", + "guzzlehttp/guzzle": "^7.4.5", "laminas/laminas-mail": "^2.11", "laminas/laminas-servicemanager": "^3.5", "league/oauth2-google": "^3.0", "nikic/php-parser": "~4.14.0", "pear/archive_tar": "~1.4.14", - "pelago/emogrifier": "~3.1.0", + "pelago/emogrifier": "^6.0.0", "scssphp/scssphp": "^1.10.3", "symfony/console": "5.4.*", "symfony/dotenv": "5.4.*", @@ -40,7 +43,7 @@ }, "config": { "platform": { - "php": "7.2.5" + "php": "7.4.0" }, "vendor-dir": "lib", "preferred-install": { @@ -57,12 +60,6 @@ "sources" ], "exclude-from-classmap": [ - "core/dbobjectsearch.class.php", - "core/legacy/dbobjectsearchlegacy.class.php", - "core/querybuildercontext.class.inc.php", - "core/legacy/querybuildercontextlegacy.class.inc.php", - "core/querybuilderexpressions.class.inc.php", - "core/legacy/querybuilderexpressionslegacy.class.inc.php", "application/twigextension.class.inc.php", "core/oql/build/PHP/", "core/apc-emulation.php", diff --git a/composer.lock b/composer.lock index dbf7f11d6..a9a26c686 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,76 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0f484bd03531fb617bd76b2e55b12ba2", + "content-hash": "276d2024de344c0d4105b15850560696", "packages": [ + { + "name": "apereo/phpcas", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/apereo/phpCAS.git", + "reference": "d6f5797fb568726f34c8e48741776d81e4a2646b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/apereo/phpCAS/zipball/d6f5797fb568726f34c8e48741776d81e4a2646b", + "reference": "d6f5797fb568726f34c8e48741776d81e4a2646b", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-dom": "*", + "php": ">=7.1.0", + "psr/log": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "monolog/monolog": "^1.0.0 || ^2.0.0", + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": ">=7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "source/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Joachim Fritschi", + "email": "jfritschi@freenet.de", + "homepage": "https://github.com/jfritschi" + }, + { + "name": "Adam Franco", + "homepage": "https://github.com/adamfranco" + }, + { + "name": "Henry Pan", + "homepage": "https://github.com/phy25" + } + ], + "description": "Provides a simple API for authenticating users against a CAS server", + "homepage": "https://wiki.jasig.org/display/CASC/phpCAS", + "keywords": [ + "apereo", + "cas", + "jasig" + ], + "support": { + "issues": "https://github.com/apereo/phpCAS/issues", + "source": "https://github.com/apereo/phpCAS/tree/1.5.0" + }, + "time": "2022-05-03T21:12:54+00:00" + }, { "name": "combodo/tcpdf", "version": "6.4.4", @@ -84,61 +152,30 @@ ], "time": "2022-03-10T14:36:39+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": "firebase/php-jwt", - "version": "v5.5.1", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "83b609028194aa042ea33b5af2d41a7427de80e6" + "reference": "018dfc4e1da92ad8a1b90adc4893f476a3b41cb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6", - "reference": "83b609028194aa042ea33b5af2d41a7427de80e6", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/018dfc4e1da92ad8a1b90adc4893f476a3b41cb8", + "reference": "018dfc4e1da92ad8a1b90adc4893f476a3b41cb8", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.1||^8.0" }, "require-dev": { - "phpunit/phpunit": ">=4.8 <=9" + "guzzlehttp/guzzle": "^6.5||^7.4", + "phpspec/prophecy-phpunit": "^1.1", + "phpunit/phpunit": "^7.5||^9.5", + "psr/cache": "^1.0||^2.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" }, "suggest": { "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" @@ -173,43 +210,51 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v5.5.1" + "source": "https://github.com/firebase/php-jwt/tree/v6.3.0" }, - "time": "2021-11-08T20:18:51+00:00" + "time": "2022-07-15T16:48:45+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.5.8", + "version": "7.4.5", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981" + "reference": "1dd98b0564cb3f6bd16ce683cb755f94c10fbd82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1dd98b0564cb3f6bd16ce683cb755f94c10fbd82", + "reference": "1dd98b0564cb3f6bd16ce683cb755f94c10fbd82", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.9", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.17" + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.9 || ^2.4", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.1" + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.5-dev" + "dev-master": "7.4-dev" } }, "autoload": { @@ -262,19 +307,20 @@ } ], "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", "keywords": [ "client", "curl", "framework", "http", "http client", + "psr-18", + "psr-7", "rest", "web service" ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/6.5.8" + "source": "https://github.com/guzzle/guzzle/tree/7.4.5" }, "funding": [ { @@ -290,7 +336,7 @@ "type": "tidelift" } ], - "time": "2022-06-20T22:16:07+00:00" + "time": "2022-06-20T22:16:13+00:00" }, { "name": "guzzlehttp/promises", @@ -378,29 +424,32 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.9.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318" + "reference": "13388f00956b1503577598873fffb5ae994b5737" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", - "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/13388f00956b1503577598873fffb5ae994b5737", + "reference": "13388f00956b1503577598873fffb5ae994b5737", "shasum": "" }, "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { - "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + "bamarni/composer-bin-plugin": "^1.4.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.8 || ^9.3.10" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -408,13 +457,10 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "2.4-dev" } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } @@ -453,6 +499,11 @@ "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" + }, + { + "name": "Mårk Sågi-Kazår", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", @@ -468,7 +519,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.9.0" + "source": "https://github.com/guzzle/psr7/tree/2.4.0" }, "funding": [ { @@ -484,40 +535,33 @@ "type": "tidelift" } ], - "time": "2022-06-20T21:43:03+00:00" + "time": "2022-06-20T21:43:11+00:00" }, { "name": "laminas/laminas-loader", - "version": "2.6.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-loader.git", - "reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc" + "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/5d01c2c237ae9e68bec262f339947e2ea18979bc", - "reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc", + "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/d0589ec9dd48365fd95ad10d1c906efd7711c16b", + "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b", "shasum": "" }, "require": { - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^5.6 || ^7.0" + "php": "^7.3 || ~8.0.0 || ~8.1.0" }, - "replace": { - "zendframework/zend-loader": "self.version" + "conflict": { + "zendframework/zend-loader": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4" + "laminas/laminas-coding-standard": "~2.2.1", + "phpunit/phpunit": "^9.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6.x-dev", - "dev-develop": "2.7.x-dev" - } - }, "autoload": { "psr-4": { "Laminas\\Loader\\": "src/" @@ -541,41 +585,51 @@ "rss": "https://github.com/laminas/laminas-loader/releases.atom", "source": "https://github.com/laminas/laminas-loader" }, - "time": "2019-12-31T17:18:27+00:00" + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2021-09-02T18:30:53+00:00" }, { "name": "laminas/laminas-mail", - "version": "2.12.5", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-mail.git", - "reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856" + "reference": "1ee1a384b96c8af29ecad9b3a7adc27a150ebc49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mail/zipball/ed5b36a0deef4ffafe6138c2ae9cafcffafab856", - "reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856", + "url": "https://api.github.com/repos/laminas/laminas-mail/zipball/1ee1a384b96c8af29ecad9b3a7adc27a150ebc49", + "reference": "1ee1a384b96c8af29ecad9b3a7adc27a150ebc49", "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" + "laminas/laminas-loader": "^2.8", + "laminas/laminas-mime": "^2.9.1", + "laminas/laminas-stdlib": "^3.6", + "laminas/laminas-validator": "^2.15", + "php": "^7.3 || ~8.0.0 || ~8.1.0", + "symfony/polyfill-intl-idn": "^1.24.0", + "symfony/polyfill-mbstring": "^1.12.0", + "webmozart/assert": "^1.10" }, - "replace": { - "zendframework/zend-mail": "^2.10.0" + "conflict": { + "zendframework/zend-mail": "*" }, "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" + "laminas/laminas-crypt": "^2.6 || ^3.4", + "laminas/laminas-db": "^2.13.3", + "laminas/laminas-servicemanager": "^3.7", + "phpunit/phpunit": "^9.5.5", + "psalm/plugin-phpunit": "^0.15.1", + "symfony/process": "^5.3.7", + "vimeo/psalm": "^4.7" }, "suggest": { "laminas/laminas-crypt": "Crammd5 support in SMTP Auth", @@ -617,45 +671,38 @@ "type": "community_bridge" } ], - "time": "2020-12-31T11:41:57+00:00" + "time": "2022-02-23T21:08:17+00:00" }, { "name": "laminas/laminas-mime", - "version": "2.7.4", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-mime.git", - "reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add" + "reference": "72d21a1b4bb7086d4a4d7058c0abca180b209184" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mime/zipball/e45a7d856bf7b4a7b5bd00d6371f9961dc233add", - "reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add", + "url": "https://api.github.com/repos/laminas/laminas-mime/zipball/72d21a1b4bb7086d4a4d7058c0abca180b209184", + "reference": "72d21a1b4bb7086d4a4d7058c0abca180b209184", "shasum": "" }, "require": { "laminas/laminas-stdlib": "^2.7 || ^3.0", - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^5.6 || ^7.0" + "php": "^7.3 || ~8.0.0 || ~8.1.0" }, - "replace": { - "zendframework/zend-mime": "^2.7.2" + "conflict": { + "zendframework/zend-mime": "*" }, "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" + "laminas/laminas-coding-standard": "~2.2.1", + "laminas/laminas-mail": "^2.12", + "phpunit/phpunit": "^9.3" }, "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/" @@ -679,59 +726,70 @@ "rss": "https://github.com/laminas/laminas-mime/releases.atom", "source": "https://github.com/laminas/laminas-mime" }, - "time": "2020-03-29T13:12:07+00:00" + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2021-09-20T21:19:24+00:00" }, { "name": "laminas/laminas-servicemanager", - "version": "3.5.2", + "version": "3.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-servicemanager.git", - "reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259" + "reference": "863c66733740cd36ebf5e700f4258ef2c68a2a24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/0669e1eec8d9f61e35a5bc5012796d49f418b259", - "reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259", + "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/863c66733740cd36ebf5e700f4258ef2c68a2a24", + "reference": "863c66733740cd36ebf5e700f4258ef2c68a2a24", "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", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0", "psr/container": "^1.0" }, + "conflict": { + "ext-psr": "*", + "laminas/laminas-code": "<3.3.1", + "zendframework/zend-code": "<3.3.1", + "zendframework/zend-servicemanager": "*" + }, "provide": { - "container-interop/container-interop-implementation": "^1.2", "psr/container-implementation": "^1.0" }, "replace": { - "zendframework/zend-servicemanager": "^3.4.0" + "container-interop/container-interop": "^1.2.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" + "composer/package-versions-deprecated": "^1.0", + "laminas/laminas-coding-standard": "~2.3.0", + "laminas/laminas-container-config-test": "^0.7", + "laminas/laminas-dependency-plugin": "^2.1.2", + "mikey179/vfsstream": "^1.6.10@alpha", + "ocramius/proxy-manager": "^2.11", + "phpbench/phpbench": "^1.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5.5", + "psalm/plugin-phpunit": "^0.17.0", + "vimeo/psalm": "^4.8" }, "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" + "ocramius/proxy-manager": "ProxyManager ^2.1.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": { + "files": [ + "src/autoload.php" + ], "psr-4": { "Laminas\\ServiceManager\\": "src/" } @@ -765,41 +823,37 @@ "type": "community_bridge" } ], - "time": "2021-01-17T16:54:43+00:00" + "time": "2022-07-27T14:58:17+00:00" }, { "name": "laminas/laminas-stdlib", - "version": "3.2.1", + "version": "3.12.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6" + "reference": "c5aed3c798018e31fbb7b1e421b8d96bf2cda453" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6", - "reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6", + "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/c5aed3c798018e31fbb7b1e421b8d96bf2cda453", + "reference": "c5aed3c798018e31fbb7b1e421b8d96bf2cda453", "shasum": "" }, "require": { - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^5.6 || ^7.0" + "php": "^7.4 || ~8.0.0 || ~8.1.0" }, - "replace": { - "zendframework/zend-stdlib": "self.version" + "conflict": { + "zendframework/zend-stdlib": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "phpbench/phpbench": "^0.13", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2" + "laminas/laminas-coding-standard": "~2.3.0", + "phpbench/phpbench": "^1.2.6", + "phpstan/phpdoc-parser": "^0.5.4", + "phpunit/phpunit": "^9.5.23", + "psalm/plugin-phpunit": "^0.17.0", + "vimeo/psalm": "^4.26" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev", - "dev-develop": "3.3.x-dev" - } - }, "autoload": { "psr-4": { "Laminas\\Stdlib\\": "src/" @@ -823,54 +877,57 @@ "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", "source": "https://github.com/laminas/laminas-stdlib" }, - "time": "2019-12-31T17:51:15+00:00" + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2022-08-22T22:55:58+00:00" }, { "name": "laminas/laminas-validator", - "version": "2.13.5", + "version": "2.23.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-validator.git", - "reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7" + "reference": "6d61b6cc3b222f13807a18d9247cdfb084958b03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/d334dddda43af263d6a7e5024fd2b013cb6981f7", - "reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7", + "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/6d61b6cc3b222f13807a18d9247cdfb084958b03", + "reference": "6d61b6cc3b222f13807a18d9247cdfb084958b03", "shasum": "" }, "require": { - "container-interop/container-interop": "^1.1", - "laminas/laminas-stdlib": "^3.2.1", - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^7.1" + "laminas/laminas-servicemanager": "^3.12.0", + "laminas/laminas-stdlib": "^3.10", + "php": "^7.4 || ~8.0.0 || ~8.1.0" }, - "replace": { - "zendframework/zend-validator": "^2.13.0" + "conflict": { + "zendframework/zend-validator": "*" }, "require-dev": { - "laminas/laminas-cache": "^2.6.1", - "laminas/laminas-coding-standard": "~1.0.0", - "laminas/laminas-config": "^2.6", + "laminas/laminas-coding-standard": "~2.3.0", "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", + "laminas/laminas-filter": "^2.14.0", + "laminas/laminas-http": "^2.14.2", + "laminas/laminas-i18n": "^2.15.0", + "laminas/laminas-session": "^2.12.1", + "laminas/laminas-uri": "^2.9.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5.21", + "psalm/plugin-phpunit": "^0.17.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0", + "vimeo/psalm": "^4.24.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", @@ -912,67 +969,7 @@ "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" + "time": "2022-07-27T19:17:59+00:00" }, { "name": "league/oauth2-client", @@ -1445,39 +1442,39 @@ }, { "name": "pelago/emogrifier", - "version": "v3.1.0", + "version": "v6.0.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/emogrifier.git", - "reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8" + "reference": "aa72d5407efac118f3896bcb995a2cba793df0ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/f6a5c7d44612d86c3901c93f1592f5440e6b2cd8", - "reference": "f6a5c7d44612d86c3901c93f1592f5440e6b2cd8", + "url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/aa72d5407efac118f3896bcb995a2cba793df0ae", + "reference": "aa72d5407efac118f3896bcb995a2cba793df0ae", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", - "php": "^5.6 || ~7.0 || ~7.1 || ~7.2 || ~7.3 || ~7.4", - "symfony/css-selector": "^2.8 || ^3.0 || ^4.0 || ^5.0" + "php": "~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0", + "sabberworm/php-css-parser": "^8.3.1", + "symfony/css-selector": "^3.4.32 || ^4.4 || ^5.3 || ^6.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.15.3", - "phpmd/phpmd": "^2.7.0", - "phpunit/phpunit": "^5.7.27", - "squizlabs/php_codesniffer": "^3.5.0" + "php-parallel-lint/php-parallel-lint": "^1.3.0", + "phpunit/phpunit": "^8.5.16", + "rawr/cross-data-providers": "^2.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-main": "7.0.x-dev" } }, "autoload": { "psr-4": { - "Pelago\\": "src/" + "Pelago\\Emogrifier\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1519,7 +1516,7 @@ "issues": "https://github.com/MyIntervals/emogrifier/issues", "source": "https://github.com/MyIntervals/emogrifier" }, - "time": "2019-12-26T19:37:31+00:00" + "time": "2021-09-16T16:22:04+00:00" }, { "name": "psr/cache", @@ -1572,20 +1569,20 @@ }, { "name": "psr/container", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", "autoload": { @@ -1614,9 +1611,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "source": "https://github.com/php-fig/container/tree/1.1.2" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/event-dispatcher", @@ -1668,6 +1665,113 @@ }, "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -1816,17 +1920,70 @@ "time": "2019-03-08T08:55:37+00:00" }, { - "name": "scssphp/scssphp", - "version": "v1.10.3", + "name": "sabberworm/php-css-parser", + "version": "8.4.0", "source": { "type": "git", - "url": "https://github.com/scssphp/scssphp.git", - "reference": "0f1e1516ed2412ad43e42a6a319e77624ba1f713" + "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", + "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/scssphp/scssphp/zipball/0f1e1516ed2412ad43e42a6a319e77624ba1f713", - "reference": "0f1e1516ed2412ad43e42a6a319e77624ba1f713", + "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", + "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=5.6.20" + }, + "require-dev": { + "codacy/coverage": "^1.4", + "phpunit/phpunit": "^4.8.36" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", + "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" + }, + "time": "2021-12-11T13:40:54+00:00" + }, + { + "name": "scssphp/scssphp", + "version": "v1.10.5", + "source": { + "type": "git", + "url": "https://github.com/scssphp/scssphp.git", + "reference": "6d44282ccf283e133ab70b6282f8e068ff2f9bf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scssphp/scssphp/zipball/6d44282ccf283e133ab70b6282f8e068ff2f9bf9", + "reference": "6d44282ccf283e133ab70b6282f8e068ff2f9bf9", "shasum": "" }, "require": { @@ -1853,6 +2010,12 @@ "bin/pscss" ], "type": "library", + "extra": { + "bamarni-bin": { + "forward-command": false, + "bin-links": false + } + }, "autoload": { "psr-4": { "ScssPhp\\ScssPhp\\": "src/" @@ -1885,22 +2048,22 @@ ], "support": { "issues": "https://github.com/scssphp/scssphp/issues", - "source": "https://github.com/scssphp/scssphp/tree/v1.10.3" + "source": "https://github.com/scssphp/scssphp/tree/v1.10.5" }, - "time": "2022-05-16T07:22:18+00:00" + "time": "2022-07-27T15:52:39+00:00" }, { "name": "symfony/cache", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a50b7249bea81ddd6d3b799ce40c5521c2f72f0b" + "reference": "5a0fff46df349f0db3fe242263451fddf5277362" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a50b7249bea81ddd6d3b799ce40c5521c2f72f0b", - "reference": "a50b7249bea81ddd6d3b799ce40c5521c2f72f0b", + "url": "https://api.github.com/repos/symfony/cache/zipball/5a0fff46df349f0db3fe242263451fddf5277362", + "reference": "5a0fff46df349f0db3fe242263451fddf5277362", "shasum": "" }, "require": { @@ -1968,7 +2131,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v5.4.9" + "source": "https://github.com/symfony/cache/tree/v5.4.11" }, "funding": [ { @@ -1984,11 +2147,11 @@ "type": "tidelift" } ], - "time": "2022-05-21T10:24:18+00:00" + "time": "2022-07-28T15:25:17+00:00" }, { "name": "symfony/cache-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", @@ -2047,7 +2210,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/cache-contracts/tree/v2.5.2" }, "funding": [ { @@ -2067,16 +2230,16 @@ }, { "name": "symfony/config", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "8f551fe22672ac7ab2c95fe46d899f960ed4d979" + "reference": "ec79e03125c1d2477e43dde8528535d90cc78379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/8f551fe22672ac7ab2c95fe46d899f960ed4d979", - "reference": "8f551fe22672ac7ab2c95fe46d899f960ed4d979", + "url": "https://api.github.com/repos/symfony/config/zipball/ec79e03125c1d2477e43dde8528535d90cc78379", + "reference": "ec79e03125c1d2477e43dde8528535d90cc78379", "shasum": "" }, "require": { @@ -2126,7 +2289,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.9" + "source": "https://github.com/symfony/config/tree/v5.4.11" }, "funding": [ { @@ -2142,20 +2305,20 @@ "type": "tidelift" } ], - "time": "2022-05-17T10:39:36+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/console", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb" + "reference": "535846c7ee6bc4dd027ca0d93220601456734b10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb", + "url": "https://api.github.com/repos/symfony/console/zipball/535846c7ee6bc4dd027ca0d93220601456734b10", + "reference": "535846c7ee6bc4dd027ca0d93220601456734b10", "shasum": "" }, "require": { @@ -2225,7 +2388,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.9" + "source": "https://github.com/symfony/console/tree/v5.4.11" }, "funding": [ { @@ -2241,20 +2404,20 @@ "type": "tidelift" } ], - "time": "2022-05-18T06:17:34+00:00" + "time": "2022-07-22T10:42:43+00:00" }, { "name": "symfony/css-selector", - "version": "v5.4.3", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "b0a190285cd95cb019237851205b8140ef6e368e" + "reference": "c1681789f059ab756001052164726ae88512ae3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/b0a190285cd95cb019237851205b8140ef6e368e", - "reference": "b0a190285cd95cb019237851205b8140ef6e368e", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/c1681789f059ab756001052164726ae88512ae3d", + "reference": "c1681789f059ab756001052164726ae88512ae3d", "shasum": "" }, "require": { @@ -2291,7 +2454,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.3" + "source": "https://github.com/symfony/css-selector/tree/v5.4.11" }, "funding": [ { @@ -2307,20 +2470,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "symfony/dependency-injection", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "beecae161577305926ec078c4ed973f2b98880b3" + "reference": "a8b9251016e9476db73e25fa836904bc0bf74c62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/beecae161577305926ec078c4ed973f2b98880b3", - "reference": "beecae161577305926ec078c4ed973f2b98880b3", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a8b9251016e9476db73e25fa836904bc0bf74c62", + "reference": "a8b9251016e9476db73e25fa836904bc0bf74c62", "shasum": "" }, "require": { @@ -2380,7 +2543,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.9" + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.11" }, "funding": [ { @@ -2396,11 +2559,11 @@ "type": "tidelift" } ], - "time": "2022-05-27T06:40:03+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -2447,7 +2610,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" }, "funding": [ { @@ -2538,16 +2701,16 @@ }, { "name": "symfony/error-handler", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "c116cda1f51c678782768dce89a45f13c949455d" + "reference": "f75d17cb4769eb38cd5fccbda95cd80a054d35c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/c116cda1f51c678782768dce89a45f13c949455d", - "reference": "c116cda1f51c678782768dce89a45f13c949455d", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/f75d17cb4769eb38cd5fccbda95cd80a054d35c8", + "reference": "f75d17cb4769eb38cd5fccbda95cd80a054d35c8", "shasum": "" }, "require": { @@ -2589,7 +2752,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.4.9" + "source": "https://github.com/symfony/error-handler/tree/v5.4.11" }, "funding": [ { @@ -2605,7 +2768,7 @@ "type": "tidelift" } ], - "time": "2022-05-21T13:57:48+00:00" + "time": "2022-07-29T07:37:50+00:00" }, { "name": "symfony/event-dispatcher", @@ -2694,7 +2857,7 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -2753,7 +2916,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" }, "funding": [ { @@ -2773,16 +2936,16 @@ }, { "name": "symfony/filesystem", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba" + "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/36a017fa4cce1eff1b8e8129ff53513abcef05ba", - "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/6699fb0228d1bc35b12aed6dd5e7455457609ddd", + "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd", "shasum": "" }, "require": { @@ -2817,7 +2980,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.9" + "source": "https://github.com/symfony/filesystem/tree/v5.4.11" }, "funding": [ { @@ -2833,20 +2996,20 @@ "type": "tidelift" } ], - "time": "2022-05-20T13:55:35+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/finder", - "version": "v5.4.8", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9b630f3427f3ebe7cd346c277a1408b00249dad9" + "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9b630f3427f3ebe7cd346c277a1408b00249dad9", - "reference": "9b630f3427f3ebe7cd346c277a1408b00249dad9", + "url": "https://api.github.com/repos/symfony/finder/zipball/7872a66f57caffa2916a584db1aa7f12adc76f8c", + "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c", "shasum": "" }, "require": { @@ -2880,7 +3043,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.8" + "source": "https://github.com/symfony/finder/tree/v5.4.11" }, "funding": [ { @@ -2896,20 +3059,20 @@ "type": "tidelift" } ], - "time": "2022-04-15T08:07:45+00:00" + "time": "2022-07-29T07:37:50+00:00" }, { "name": "symfony/framework-bundle", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "1cb89cd3e36d5060545d0f223f00a774fa6430ef" + "reference": "a0660b602357d5c2ceaac1c9f80c5820bbff803d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/1cb89cd3e36d5060545d0f223f00a774fa6430ef", - "reference": "1cb89cd3e36d5060545d0f223f00a774fa6430ef", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/a0660b602357d5c2ceaac1c9f80c5820bbff803d", + "reference": "a0660b602357d5c2ceaac1c9f80c5820bbff803d", "shasum": "" }, "require": { @@ -3031,7 +3194,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v5.4.9" + "source": "https://github.com/symfony/framework-bundle/tree/v5.4.11" }, "funding": [ { @@ -3047,20 +3210,20 @@ "type": "tidelift" } ], - "time": "2022-05-27T06:29:07+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "6b0d0e4aca38d57605dcd11e2416994b38774522" + "reference": "0a5868e0999e9d47859ba3d918548ff6943e6389" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b0d0e4aca38d57605dcd11e2416994b38774522", - "reference": "6b0d0e4aca38d57605dcd11e2416994b38774522", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0a5868e0999e9d47859ba3d918548ff6943e6389", + "reference": "0a5868e0999e9d47859ba3d918548ff6943e6389", "shasum": "" }, "require": { @@ -3104,7 +3267,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.9" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.11" }, "funding": [ { @@ -3120,20 +3283,20 @@ "type": "tidelift" } ], - "time": "2022-05-17T15:07:29+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "34b121ad3dc761f35fe1346d2f15618f8cbf77f8" + "reference": "4fd590a2ef3f62560dbbf6cea511995dd77321ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/34b121ad3dc761f35fe1346d2f15618f8cbf77f8", - "reference": "34b121ad3dc761f35fe1346d2f15618f8cbf77f8", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4fd590a2ef3f62560dbbf6cea511995dd77321ee", + "reference": "4fd590a2ef3f62560dbbf6cea511995dd77321ee", "shasum": "" }, "require": { @@ -3216,7 +3379,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.4.9" + "source": "https://github.com/symfony/http-kernel/tree/v5.4.11" }, "funding": [ { @@ -3232,7 +3395,7 @@ "type": "tidelift" } ], - "time": "2022-05-27T07:09:08+00:00" + "time": "2022-07-29T12:30:22+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3970,16 +4133,16 @@ }, { "name": "symfony/routing", - "version": "v5.4.8", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e07817bb6244ea33ef5ad31abc4a9288bef3f2f7" + "reference": "3e01ccd9b2a3a4167ba2b3c53612762300300226" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e07817bb6244ea33ef5ad31abc4a9288bef3f2f7", - "reference": "e07817bb6244ea33ef5ad31abc4a9288bef3f2f7", + "url": "https://api.github.com/repos/symfony/routing/zipball/3e01ccd9b2a3a4167ba2b3c53612762300300226", + "reference": "3e01ccd9b2a3a4167ba2b3c53612762300300226", "shasum": "" }, "require": { @@ -4040,7 +4203,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.4.8" + "source": "https://github.com/symfony/routing/tree/v5.4.11" }, "funding": [ { @@ -4056,20 +4219,20 @@ "type": "tidelift" } ], - "time": "2022-04-18T21:45:37+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { @@ -4123,7 +4286,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -4139,20 +4302,20 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:07:29+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99" + "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", + "url": "https://api.github.com/repos/symfony/string/zipball/5eb661e49ad389e4ae2b6e4df8d783a8a6548322", + "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322", "shasum": "" }, "require": { @@ -4209,7 +4372,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.9" + "source": "https://github.com/symfony/string/tree/v5.4.11" }, "funding": [ { @@ -4225,20 +4388,20 @@ "type": "tidelift" } ], - "time": "2022-04-19T10:40:37+00:00" + "time": "2022-07-24T16:15:25+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07" + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1211df0afa701e45a04253110e959d4af4ef0f07", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", "shasum": "" }, "require": { @@ -4287,7 +4450,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" }, "funding": [ { @@ -4303,20 +4466,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "symfony/twig-bridge", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "fd13c89a1abdbaa7ee2e655d9a11405adcb7a6cf" + "reference": "63b8a50d48c9fe3d04e77307d4f1771dd848baa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/fd13c89a1abdbaa7ee2e655d9a11405adcb7a6cf", - "reference": "fd13c89a1abdbaa7ee2e655d9a11405adcb7a6cf", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/63b8a50d48c9fe3d04e77307d4f1771dd848baa8", + "reference": "63b8a50d48c9fe3d04e77307d4f1771dd848baa8", "shasum": "" }, "require": { @@ -4408,7 +4571,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v5.4.9" + "source": "https://github.com/symfony/twig-bridge/tree/v5.4.11" }, "funding": [ { @@ -4424,7 +4587,7 @@ "type": "tidelift" } ], - "time": "2022-05-21T10:24:18+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/twig-bundle", @@ -4517,16 +4680,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.4.9", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "af52239a330fafd192c773795520dc2dd62b5657" + "reference": "b8f306d7b8ef34fb3db3305be97ba8e088fb4861" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/af52239a330fafd192c773795520dc2dd62b5657", - "reference": "af52239a330fafd192c773795520dc2dd62b5657", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b8f306d7b8ef34fb3db3305be97ba8e088fb4861", + "reference": "b8f306d7b8ef34fb3db3305be97ba8e088fb4861", "shasum": "" }, "require": { @@ -4586,7 +4749,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.9" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.11" }, "funding": [ { @@ -4602,20 +4765,20 @@ "type": "tidelift" } ], - "time": "2022-05-21T10:24:18+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "63249ebfca4e75a357679fa7ba2089cfb898aa67" + "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/63249ebfca4e75a357679fa7ba2089cfb898aa67", - "reference": "63249ebfca4e75a357679fa7ba2089cfb898aa67", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/8fc03ee75eeece3d9be1ef47d26d79bea1afb340", + "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340", "shasum": "" }, "require": { @@ -4659,7 +4822,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.9" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.10" }, "funding": [ { @@ -4675,20 +4838,20 @@ "type": "tidelift" } ], - "time": "2022-05-21T10:24:18+00:00" + "time": "2022-05-27T12:56:18+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.3", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e80f87d2c9495966768310fc531b487ce64237a2" + "reference": "05d4ea560f3402c6c116afd99fdc66e60eda227e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", - "reference": "e80f87d2c9495966768310fc531b487ce64237a2", + "url": "https://api.github.com/repos/symfony/yaml/zipball/05d4ea560f3402c6c116afd99fdc66e60eda227e", + "reference": "05d4ea560f3402c6c116afd99fdc66e60eda227e", "shasum": "" }, "require": { @@ -4734,7 +4897,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.3" + "source": "https://github.com/symfony/yaml/tree/v5.4.11" }, "funding": [ { @@ -4750,26 +4913,28 @@ "type": "tidelift" } ], - "time": "2022-01-26T16:32:32+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "thenetworg/oauth2-azure", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/TheNetworg/oauth2-azure.git", - "reference": "2649422a0dc74af32d21d9d738d37abcd5b03998" + "reference": "06fb2d620fb6e6c934f632c7ec7c5ea2e978a844" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/2649422a0dc74af32d21d9d738d37abcd5b03998", - "reference": "2649422a0dc74af32d21d9d738d37abcd5b03998", + "url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/06fb2d620fb6e6c934f632c7ec7c5ea2e978a844", + "reference": "06fb2d620fb6e6c934f632c7ec7c5ea2e978a844", "shasum": "" }, "require": { - "firebase/php-jwt": "~3.0||~4.0||~5.0", + "ext-json": "*", + "ext-openssl": "*", + "firebase/php-jwt": "~3.0||~4.0||~5.0||~6.0", "league/oauth2-client": "~2.0", - "php": "^5.6|^7.0|^8.0" + "php": "^7.1|^8.0" }, "type": "library", "autoload": { @@ -4803,72 +4968,22 @@ ], "support": { "issues": "https://github.com/TheNetworg/oauth2-azure/issues", - "source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.0.1" + "source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.1.1" }, - "time": "2021-01-11T12:20:12+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" + "time": "2022-06-23T10:35:36+00:00" }, { "name": "twig/twig", - "version": "v3.4.1", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342" + "reference": "e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/e939eae92386b69b49cfa4599dd9bead6bf4a342", - "reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077", + "reference": "e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077", "shasum": "" }, "require": { @@ -4919,7 +5034,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.4.1" + "source": "https://github.com/twigphp/Twig/tree/v3.4.2" }, "funding": [ { @@ -4931,7 +5046,65 @@ "type": "tidelift" } ], - "time": "2022-05-17T05:48:52+00:00" + "time": "2022-08-12T06:47:24+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "packages-dev": [ @@ -4999,16 +5172,16 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v5.4.8", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "909c6eea7815066a80d0a362ed41abd7924e376a" + "reference": "f61c99d8dbd864b11935851b598f784bcff36fc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/909c6eea7815066a80d0a362ed41abd7924e376a", - "reference": "909c6eea7815066a80d0a362ed41abd7924e376a", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/f61c99d8dbd864b11935851b598f784bcff36fc7", + "reference": "f61c99d8dbd864b11935851b598f784bcff36fc7", "shasum": "" }, "require": { @@ -5059,7 +5232,7 @@ "description": "Provides a development tool that gives detailed information about the execution of any request", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v5.4.8" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v5.4.10" }, "funding": [ { @@ -5075,7 +5248,7 @@ "type": "tidelift" } ], - "time": "2022-04-22T08:14:12+00:00" + "time": "2022-06-06T19:10:58+00:00" } ], "aliases": [], @@ -5084,7 +5257,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.2.5 <8.0.0", + "php": ">=7.4.0 <8.2.0", "ext-ctype": "*", "ext-dom": "*", "ext-gd": "*", @@ -5095,7 +5268,7 @@ }, "platform-dev": [], "platform-overrides": { - "php": "7.2.5" + "php": "7.4.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.1.0" } diff --git a/core/MyHelpers.class.inc.php b/core/MyHelpers.class.inc.php index f5260d987..d3f47be31 100644 --- a/core/MyHelpers.class.inc.php +++ b/core/MyHelpers.class.inc.php @@ -470,9 +470,9 @@ class Str public static function pure2html($pure, $maxLength = false) { // Check for HTML entities, but be careful the DB is in UTF-8 - return $maxLength - ? htmlentities(substr($pure, 0, $maxLength), ENT_QUOTES, 'UTF-8') - : htmlentities($pure, ENT_QUOTES, 'UTF-8'); + return $maxLength + ? utils::EscapeHtml(substr($pure, 0, $maxLength)) + : utils::EscapeHtml($pure); } public static function pure2sql($pure, $maxLength = false) { diff --git a/core/action.class.inc.php b/core/action.class.inc.php index 2ff7ee69c..b2d070bb5 100644 --- a/core/action.class.inc.php +++ b/core/action.class.inc.php @@ -566,7 +566,7 @@ class ActionEmail extends ActionNotification // Prefix $sPrefix = sprintf('%s_%s_%d', $sAppName, $sObjClass, $sObjId); if ($sHeaderName === static::ENUM_HEADER_NAME_MESSAGE_ID) { - $sPrefix .= sprintf('_%f', microtime(true /* get as float*/)); + $sPrefix .= sprintf('_%F', microtime(true /* get as float*/)); } // Suffix $sSuffix = sprintf('@%s.openitop.org', MetaModel::GetEnvironmentId()); diff --git a/core/asynctask.class.inc.php b/core/asynctask.class.inc.php index 69eb4e1a4..05bc5bd74 100644 --- a/core/asynctask.class.inc.php +++ b/core/asynctask.class.inc.php @@ -293,7 +293,7 @@ abstract class AsyncTask extends DBObject $this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode)); } - $this->Set('last_error', $sErrorMessage); + $this->SetTrim('last_error', $sErrorMessage); $this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!! $this->Set('last_attempt', time()); diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 7b0c34c57..95553ff6f 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -1690,7 +1690,7 @@ class AttributeLinkedSet extends AttributeDefinition { if ($sObjClass == $this->GetLinkedClass()) { - // Simplify the output if the exact class could be determined implicitely + // Simplify the output if the exact class could be determined implicitely continue; } } @@ -2012,7 +2012,7 @@ class AttributeLinkedSet extends AttributeDefinition { if ($sObjClass == $this->GetLinkedClass()) { - // Simplify the output if the exact class could be determined implicitely + // Simplify the output if the exact class could be determined implicitely continue; } } @@ -2417,7 +2417,7 @@ class AttributeDBFieldVoid extends AttributeDefinition return false; } - // + // protected function ScalarToSQL($value) { return $value; @@ -4179,20 +4179,21 @@ class AttributeText extends AttributeString public function GetEditValue($sValue, $oHostObj = null) { - if ($this->GetFormat() == 'text') - { - if (preg_match_all(WIKI_OBJECT_REGEXP, $sValue, $aAllMatches, PREG_SET_ORDER)) - { - foreach($aAllMatches as $iPos => $aMatches) - { + // N°4517 - PHP 8.1 compatibility: str_replace call with null cause deprecated message + if ($sValue == null) { + return ''; + } + + if ($this->GetFormat() == 'text') { + if (preg_match_all(WIKI_OBJECT_REGEXP, $sValue, $aAllMatches, PREG_SET_ORDER)) { + foreach ($aAllMatches as $iPos => $aMatches) { $sClass = trim($aMatches[1]); $sName = trim($aMatches[2]); $sLabel = (!empty($aMatches[4])) ? trim($aMatches[4]) : null; - if (MetaModel::IsValidClass($sClass)) - { + if (MetaModel::IsValidClass($sClass)) { $sClassLabel = MetaModel::GetName($sClass); - $sReplacement = "[[$sClassLabel:$sName" . (!empty($sLabel) ? " | $sLabel" : "") . "]]"; + $sReplacement = "[[$sClassLabel:$sName".(!empty($sLabel) ? " | $sLabel" : "")."]]"; $sValue = str_replace($aMatches[0], $sReplacement, $sValue); } } @@ -4229,31 +4230,31 @@ class AttributeText extends AttributeString public function MakeRealValue($proposedValue, $oHostObj) { $sValue = $proposedValue; - switch ($this->GetFormat()) - { + + // N°4517 - PHP 8.1 compatibility: str_replace call with null cause deprecated message + if ($sValue == null) { + return ''; + } + + switch ($this->GetFormat()) { case 'html': - if (($sValue !== null) && ($sValue !== '')) - { + if (($sValue !== null) && ($sValue !== '')) { $sValue = HTMLSanitizer::Sanitize($sValue); } break; case 'text': default: - if (preg_match_all(WIKI_OBJECT_REGEXP, $sValue, $aAllMatches, PREG_SET_ORDER)) - { - foreach($aAllMatches as $iPos => $aMatches) - { + if (preg_match_all(WIKI_OBJECT_REGEXP, $sValue, $aAllMatches, PREG_SET_ORDER)) { + foreach ($aAllMatches as $iPos => $aMatches) { $sClassLabel = trim($aMatches[1]); $sName = trim($aMatches[2]); - $sLabel = (!empty($aMatches[4])) ? trim($aMatches[4]) : null; + $sLabel = (!empty($aMatches[4])) ? trim($aMatches[4]) : null; - if (!MetaModel::IsValidClass($sClassLabel)) - { + if (!MetaModel::IsValidClass($sClassLabel)) { $sClass = MetaModel::GetClassFromLabel($sClassLabel); - if ($sClass) - { - $sReplacement = "[[$sClassLabel:$sName" . (!empty($sLabel) ? " | $sLabel" : "") . "]]"; + if ($sClass) { + $sReplacement = "[[$sClassLabel:$sName".(!empty($sLabel) ? " | $sLabel" : "")."]]"; $sValue = str_replace($aMatches[0], $sReplacement, $sValue); } } @@ -4592,7 +4593,13 @@ class AttributeCaseLog extends AttributeLongText { if (strlen($proposedValue) > 0) { - $oCaseLog->AddLogEntry($proposedValue); + //N°5135 - add impersonation information in caselog + if (UserRights::IsImpersonated()){ + $sOnBehalfOf = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUserFriendlyName(), UserRights::GetUserFriendlyName()); + $oCaseLog->AddLogEntry($proposedValue, $sOnBehalfOf, UserRights::GetConnectedUserId()); + } else { + $oCaseLog->AddLogEntry($proposedValue); + } } } $ret = $oCaseLog; @@ -5399,7 +5406,7 @@ class AttributeEnum extends AttributeString { if (is_null($sValue)) { - // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label + // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label $sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, Dict::S('Enum:Undefined')); } @@ -5421,7 +5428,7 @@ class AttributeEnum extends AttributeString { if (is_null($sValue)) { - // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label + // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', Dict::S('Enum:Undefined')); } @@ -7220,7 +7227,7 @@ class AttributeExternalField extends AttributeDefinition protected function GetSQLCol($bFullSpec = false) { - // throw new CoreException("external attribute: does it make any sense to request its type ?"); + // throw new CoreException("external attribute: does it make any sense to request its type ?"); $oExtAttDef = $this->GetExtAttDef(); return $oExtAttDef->GetSQLCol($bFullSpec); @@ -9273,7 +9280,7 @@ class AttributeSubItem extends AttributeDefinition return $res; } - // + // // protected function ScalarToSQL($value) {return $value;} // format value as a valuable SQL literal (quoted outside) public function FromSQLToValue($aCols, $sPrefix = '') @@ -12790,7 +12797,7 @@ class AttributeCustomFields extends AttributeDefinition $sRet = $value->GetAsHTML($bLocalize); } catch (Exception $e) { - $sRet = 'Custom field error: '.htmlentities($e->getMessage(), ENT_QUOTES, 'UTF-8'); + $sRet = 'Custom field error: '.utils::EscapeHtml($e->getMessage()); } return $sRet; diff --git a/core/cmdbchangeop.class.inc.php b/core/cmdbchangeop.class.inc.php index d4d90e308..3c5e814aa 100644 --- a/core/cmdbchangeop.class.inc.php +++ b/core/cmdbchangeop.class.inc.php @@ -78,7 +78,7 @@ class CMDBChangeOp extends DBObject implements iCMDBChangeOp } /** - * Describe (as a text string) the modifications corresponding to this change + * @inheritDoc */ public function GetDescription() { @@ -350,20 +350,30 @@ class CMDBChangeOpSetAttributeURL extends CMDBChangeOpSetAttribute { $aParams = array ( - "category" => "core/cmdb", - "key_type" => "", - "name_attcode" => "change", - "state_attcode" => "", - "reconc_keys" => array(), - "db_table" => "priv_changeop_setatt_url", - "db_key_field" => "id", + "category" => "core/cmdb", + "key_type" => "", + "name_attcode" => "change", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_changeop_setatt_url", + "db_key_field" => "id", "db_finalclass_field" => "", ); MetaModel::Init_Params($aParams); MetaModel::Init_InheritAttributes(); - MetaModel::Init_AddAttribute(new AttributeURL("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "target" => '_blank', "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeURL("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "target" => '_blank', "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); - + + // N°4910 (oldvalue), N°5423 (newvalue) + // We cannot have validation here, as AttributeUrl validation is field dependant. + // The validation will be done when editing the iTop object, it isn't the history API responsibility + // + // Pattern is retrieved using this order : + // 1. try to get the pattern from the field definition (datamodel) + // 2. from the iTop config + // 3. config parameter default value + // see \AttributeURL::GetValidationPattern + MetaModel::Init_AddAttribute(new AttributeURL("oldvalue", array("allowed_values" => null, "sql" => "oldvalue", "target" => '_blank', "default_value" => null, "is_null_allowed" => true, "depends_on" => array(), "validation_pattern" => '.*'))); + MetaModel::Init_AddAttribute(new AttributeURL("newvalue", array("allowed_values" => null, "sql" => "newvalue", "target" => '_blank', "default_value" => null, "is_null_allowed" => true, "depends_on" => array(), "validation_pattern" => '.*'))); + // Display lists MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list @@ -875,7 +885,7 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute */ protected function ToHtml($sRawText) { - return str_replace(array("\r\n", "\n", "\r"), "
", htmlentities($sRawText, ENT_QUOTES, 'UTF-8')); + return str_replace(array("\r\n", "\n", "\r"), "
", utils::EscapeHtml($sRawText)); } } @@ -1167,9 +1177,8 @@ class CMDBChangeOpSetAttributeCustomFields extends CMDBChangeOpSetAttribute $oHandler = $oAttDef->GetHandler($aValues); $sValueDesc = $oHandler->GetAsHTML($aValues); } - catch (Exception $e) - { - $sValueDesc = 'Custom field error: '.htmlentities($e->getMessage(), ENT_QUOTES, 'UTF-8'); + catch (Exception $e) { + $sValueDesc = 'Custom field error: '.utils::EscapeHtml($e->getMessage()); } $sTextView = '
'.$sValueDesc.'
'; diff --git a/core/cmdbobject.class.inc.php b/core/cmdbobject.class.inc.php index e2c9032e3..751bfd675 100644 --- a/core/cmdbobject.class.inc.php +++ b/core/cmdbobject.class.inc.php @@ -3,7 +3,7 @@ // // This file is part of iTop. // -// iTop is free software; you can redistribute it and/or modify +// iTop is free software; you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. @@ -214,7 +214,12 @@ abstract class CMDBObject extends DBObject if (is_null(self::$m_sInfo)) { return CMDBChange::GetCurrentUserName(); } else { - return self::$m_sInfo; + //N°5135 - add impersonation information in activity log/current cmdb change + if (UserRights::IsImpersonated()){ + return sprintf("%s (%s)", CMDBChange::GetCurrentUserName(), self::$m_sInfo); + } else { + return self::$m_sInfo; + } } } @@ -227,7 +232,10 @@ abstract class CMDBObject extends DBObject */ protected static function GetTrackUserId() { - if (is_null(self::$m_sUserId)) + if (is_null(self::$m_sUserId) + //N°5135 - indicate impersonation inside changelogs + && (false === UserRights::IsImpersonated()) + ) { return CMDBChange::GetCurrentUserId(); } @@ -236,10 +244,10 @@ abstract class CMDBObject extends DBObject return self::$m_sUserId; } } - + /** * Get the 'origin' information (defaulting to 'interactive') - */ + */ protected static function GetTrackOrigin() { if (is_null(self::$m_sOrigin)) @@ -268,7 +276,7 @@ abstract class CMDBObject extends DBObject * @since 2.7.7 3.0.2 3.1.0 N°3717 {@see CMDBChange} **will be persisted later** in {@see \CMDBChangeOp::OnInsert} (was done previously directly here) * This will avoid creating in DB CMDBChange lines without any corresponding CMDBChangeOp */ - protected static function CreateChange() + public static function CreateChange() { self::$m_oCurrChange = MetaModel::NewObject("CMDBChange"); self::$m_oCurrChange->Set("date", time()); @@ -711,11 +719,11 @@ abstract class CMDBObject extends DBObject class CMDBObjectSet extends DBObjectSet { // this is the public interface (?) - + // I have to define those constructors here... :-( // just to get the right object class in return. // I have to think again to those things: maybe it will work fine if a have a constructor define here (?) - + static public function FromScratch($sClass) { $oFilter = new DBObjectSearch($sClass); @@ -724,7 +732,7 @@ class CMDBObjectSet extends DBObjectSet // NOTE: THIS DOES NOT WORK IF m_bLoaded is private in the base class (and you will not get any error message) $oRetSet->m_bLoaded = true; // no DB load return $oRetSet; - } + } // create an object set ex nihilo // input = array of objects @@ -733,7 +741,7 @@ class CMDBObjectSet extends DBObjectSet $oRetSet = self::FromScratch($sClass); $oRetSet->AddObjectArray($aObjects, $sClass); return $oRetSet; - } + } static public function FromArrayAssoc($aClasses, $aObjects) { diff --git a/core/cmdbsource.class.inc.php b/core/cmdbsource.class.inc.php index aae7e65fd..c725d0cec 100644 --- a/core/cmdbsource.class.inc.php +++ b/core/cmdbsource.class.inc.php @@ -157,7 +157,7 @@ class CMDBSource $iPort = null; self::InitServerAndPort($sDbHost, $sServer, $iPort); - $iFlags = null; + $iFlags = 0; // *some* errors (like connection errors) will throw mysqli_sql_exception instead of generating warnings printed to the output // but some other errors will still cause the query() method to return false !!! @@ -166,7 +166,6 @@ class CMDBSource try { $oMysqli = new mysqli(); - $oMysqli->init(); if ($bTlsEnabled) { diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 405997818..eeef51320 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -546,7 +546,7 @@ class Config ], 'email_transport' => [ 'type' => 'string', - 'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)', + 'description' => 'Mean to send emails: PHPMail (uses the function mail()), SMTP (implements the client protocol) or SMTP_OAuth (connect to the server using OAuth 2.0)', 'default' => "PHPMail", 'value' => "PHPMail", 'source_of_value' => '', @@ -1472,14 +1472,6 @@ class Config 'source_of_value' => '', 'show_in_conf_sample' => false, ], - 'use_legacy_dbsearch' => [ - 'type' => 'bool', - 'description' => 'Deprecated since 3.1.0, there is now only one dbsearch method.', - 'default' => false, - 'value' => false, - 'source_of_value' => '', - 'show_in_conf_sample' => false, - ], 'query_cache_enabled' => [ 'type' => 'bool', 'description' => 'If set, DBSearch will use cache for query generation', @@ -1895,7 +1887,7 @@ class Config { // Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack) throw new ConfigException('Syntax error in configuration file', - array('file' => $sConfigFile, 'error' => ''.htmlentities($sNoise, ENT_QUOTES, 'UTF-8').'')); + array('file' => $sConfigFile, 'error' => ''.utils::EscapeHtml($sNoise, ENT_QUOTES).'')); } if (!isset($MySettings) || !is_array($MySettings)) diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index 50a92f8f0..dd445217e 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -125,8 +125,8 @@ class CSVBulkExport extends TabularBulkExport $sRawSeparator = utils::ReadParam('separator', ',', true, 'raw_data'); $sCustomDateTimeFormat = utils::ReadParam('', ',', true, 'raw_data'); $aSep = array( - ';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'), - ',' => Dict::S('UI:CSVImport:SeparatorComma+'), + ';' => Dict::S('UI:CSVImport:SeparatorSemicolon+'), + ',' => Dict::S('UI:CSVImport:SeparatorComma+'), 'tab' => Dict::S('UI:CSVImport:SeparatorTab+'), ); $sOtherSeparator = ''; @@ -134,10 +134,10 @@ class CSVBulkExport extends TabularBulkExport $sOtherSeparator = $sRawSeparator; $sRawSeparator = 'other'; } - $aSep['other'] = Dict::S('UI:CSVImport:SeparatorOther').' '; + $aSep['other'] = Dict::S('UI:CSVImport:SeparatorOther').' '; foreach ($aSep as $sVal => $sLabel) { - $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "separator", htmlentities($sVal, ENT_QUOTES, 'UTF-8'), $sLabel, "radio"); + $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "separator", utils::EscapeHtml($sVal), $sLabel, "radio"); $oRadio->GetInput()->SetIsChecked(($sVal == $sRawSeparator)); $oRadio->SetBeforeInput(false); $oRadio->GetInput()->AddCSSClass('ibo-input--label-right'); @@ -152,7 +152,7 @@ class CSVBulkExport extends TabularBulkExport $sRawQualifier = utils::ReadParam('text-qualifier', '"', true, 'raw_data'); $aQualifiers = array( - '"' => Dict::S('UI:CSVImport:QualifierDoubleQuote+'), + '"' => Dict::S('UI:CSVImport:QualifierDoubleQuote+'), '\'' => Dict::S('UI:CSVImport:QualifierSimpleQuote+'), ); $sOtherQualifier = ''; @@ -160,10 +160,10 @@ class CSVBulkExport extends TabularBulkExport $sOtherQualifier = $sRawQualifier; $sRawQualifier = 'other'; } - $aQualifiers['other'] = Dict::S('UI:CSVImport:QualifierOther').' '; + $aQualifiers['other'] = Dict::S('UI:CSVImport:QualifierOther').' '; foreach ($aQualifiers as $sVal => $sLabel) { - $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "text-qualifier", htmlentities($sVal, ENT_QUOTES, 'UTF-8'), $sLabel, "radio"); + $oRadio = InputUIBlockFactory::MakeForInputWithLabel($sLabel, "text-qualifier", utils::EscapeHtml($sVal), $sLabel, "radio"); $oRadio->GetInput()->SetIsChecked(($sVal == $sRawSeparator)); $oRadio->SetBeforeInput(false); $oRadio->GetInput()->AddCSSClass('ibo-input--label-right'); @@ -209,8 +209,8 @@ class CSVBulkExport extends TabularBulkExport $sDateTimeFormat = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data'); - $sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8'); - $sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8'); + $sDefaultFormat = utils::EscapeHtml((string)AttributeDateTime::GetFormat()); + $sExample = utils::EscapeHtml(date((string)AttributeDateTime::GetFormat())); $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "csv_date_format_radio", "default", "csv_date_time_format_default", "radio"); $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); $oRadioDefault->SetBeforeInput(false); @@ -218,7 +218,7 @@ class CSVBulkExport extends TabularBulkExport $oFieldSetDate->AddSubBlock($oRadioDefault); $oFieldSetDate->AddSubBlock(new Html('
')); - $sFormatInput = ''; + $sFormatInput = ''; $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "csv_date_format_radio", "custom", "csv_date_time_format_custom", "radio"); $oRadioCustom->SetDescription(Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip')); $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); @@ -246,17 +246,18 @@ EOF } protected function GetSampleData($oObj, $sAttCode) - { - if ($sAttCode != 'id') - { + { + if ($sAttCode != 'id') { $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime { $sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date'; - return '
'.htmlentities($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj), ENT_QUOTES, 'UTF-8').'
'; + + return '
'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'
'; } } - return '
'.htmlentities($this->GetValue($oObj, $sAttCode), ENT_QUOTES, 'UTF-8').'
'; + + return '
'.utils::EscapeHtml($this->GetValue($oObj, $sAttCode)).'
'; } protected function GetValue($oObj, $sAttCode) diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 6b07c17d1..ea19b5464 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -1120,9 +1120,10 @@ abstract class DBObject implements iDisplay } else { - $sHtmlLabel = htmlentities($this->Get($sAttCode.'_friendlyname'), ENT_QUOTES, 'UTF-8'); + $sHtmlLabel = utils::EscapeHtml($this->Get($sAttCode.'_friendlyname')); $bArchived = $this->IsArchived($sAttCode); $bObsolete = $this->IsObsolete($sAttCode); + return $this->MakeHyperLink($sTargetClass, $iTargetKey, $sHtmlLabel, null, true, $bArchived, $bObsolete); } } @@ -1620,7 +1621,7 @@ abstract class DBObject implements iDisplay */ public function GetName($sType = FriendlyNameType::SHORT) { - return htmlentities($this->GetRawName($sType), ENT_QUOTES, 'UTF-8'); + return utils::EscapeHtml($this->GetRawName($sType)); } /** @@ -1961,7 +1962,7 @@ abstract class DBObject implements iDisplay /** @var \AttributeExternalKey $oAtt */ $sTargetClass = $oAtt->GetTargetClass(); if (false === MetaModel::IsObjectInDB($sTargetClass, $toCheck)) { - return "Target object not found (".utils::HtmlEntities($sTargetClass).".::".utils::HtmlEntities($toCheck).")"; + return "Target object not found (".$sTargetClass.".::".$toCheck.")"; } } if ($oAtt->IsHierarchicalKey()) @@ -1970,7 +1971,7 @@ abstract class DBObject implements iDisplay $aValues = $oAtt->GetAllowedValues(array('this' => $this)); if (!array_key_exists($toCheck, $aValues)) { - return "Value not allowed [". utils::HtmlEntities($toCheck)."]"; + return "Value not allowed [$toCheck]"; } } } @@ -1984,7 +1985,7 @@ abstract class DBObject implements iDisplay $oTag->SetValues(explode(' ', $toCheck)); } catch (Exception $e) { - return "Tag value [". utils::HtmlEntities($toCheck)."] is not a valid tag list"; + return "Tag value '$toCheck' is not a valid tag list"; } return true; @@ -2012,7 +2013,7 @@ abstract class DBObject implements iDisplay $oTag->SetValues($aValues); } catch (Exception $e) { - return "Set value[". utils::HtmlEntities($toCheck)."] is not a valid set"; + return "Set value '$toCheck' is not a valid set"; } return true; @@ -2032,7 +2033,7 @@ abstract class DBObject implements iDisplay { if (!array_key_exists($toCheck, $aValues)) { - return "Value not allowed [". utils::HtmlEntities($toCheck)."]"; + return "Value not allowed [$toCheck]"; } } if (!is_null($iMaxSize = $oAtt->GetMaxSize())) @@ -2045,7 +2046,7 @@ abstract class DBObject implements iDisplay } if (!$oAtt->CheckFormat($toCheck)) { - return "Wrong format [". utils::HtmlEntities($toCheck)."]"; + return "Wrong format [$toCheck]"; } } else @@ -3195,11 +3196,21 @@ abstract class DBObject implements iDisplay // Save the original values (will be reset to the new values when the object get written to the DB) $aOriginalValues = $this->m_aOrigValues; - $aHierarchicalKeys = []; - $aDBChanges = []; + // Activate any existing trigger + $sClass = get_class($this); + // - TriggerOnObjectMention + $this->ActivateOnMentionTriggers(false); + + $bNeedReload = false; + $aHierarchicalKeys = array(); + $aDBChanges = array(); foreach ($aChanges as $sAttCode => $valuecurr) { - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode); + if ($oAttDef->IsExternalKey() || $oAttDef->IsLinkSet()) + { + $bNeedReload = true; + } if ($oAttDef->IsBasedOnDBColumns()) { $aDBChanges[$sAttCode] = $aChanges[$sAttCode]; @@ -3352,22 +3363,27 @@ abstract class DBObject implements iDisplay $this->m_aModifiedAtt = array(); try { - // Reset original values although the object has not been reloaded - foreach ($this->m_aLoadedAtt as $sAttCode => $bLoaded) - { - if ($bLoaded) - { - $value = $this->m_aCurrValues[$sAttCode]; - $this->m_aOrigValues[$sAttCode] = is_object($value) ? clone $value : $value; - } - } - $this->EventUpdateAfter(['changes' => $aChanges]); $this->AfterUpdate(); + // Reload to get the external attributes + if ($bNeedReload) { + $this->Reload(true /* AllowAllData */); + } else { + // Reset original values although the object has not been reloaded + foreach ($this->m_aLoadedAtt as $sAttCode => $bLoaded) + { + if ($bLoaded) + { + $value = $this->m_aCurrValues[$sAttCode]; + $this->m_aOrigValues[$sAttCode] = is_object($value) ? clone $value : $value; + } + } + } + // - TriggerOnObjectUpdate $aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)); - $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)"), + $oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)'), array(), $aParams); while ($oTrigger = $oSet->Fetch()) { /** @var \TriggerOnObjectUpdate $oTrigger */ @@ -3810,7 +3826,7 @@ abstract class DBObject implements iDisplay } /** - * @internal + * @overwritable-hook You can extend this method in order to provide your own logic. * * @return array * @@ -5878,7 +5894,7 @@ abstract class DBObject implements iDisplay protected function EventArchive() { - + } protected function EventUnarchive() diff --git a/core/dbobjectiterator.php b/core/dbobjectiterator.php index 85e1e5208..8f9311266 100644 --- a/core/dbobjectiterator.php +++ b/core/dbobjectiterator.php @@ -38,7 +38,7 @@ interface iDBObjectSetIterator extends Countable * * @return int */ - public function Count(); + public function Count(): int; /** * Reset the cursor to the first item in the collection. Equivalent to Seek(0) @@ -52,7 +52,7 @@ interface iDBObjectSetIterator extends Countable * * @param int $iRow */ - public function Seek($iPosition); + public function Seek($iPosition): void; /** * Fetch the object at the current position in the collection and move the cursor to the next position. diff --git a/core/dbobjectset.class.php b/core/dbobjectset.class.php index 57c2da786..fb8ebb43b 100644 --- a/core/dbobjectset.class.php +++ b/core/dbobjectset.class.php @@ -842,7 +842,7 @@ class DBObjectSet implements iDBObjectSetIterator * @throws \MySQLException * @throws \MySQLHasGoneAwayException */ - public function Count() + public function Count(): int { if (is_null($this->m_iNumTotalDBRows)) { @@ -1077,14 +1077,13 @@ class DBObjectSet implements iDBObjectSetIterator * * @param int $iRow * - * @return int|mixed - * * @throws \CoreException * @throws \MissingQueryArgument * @throws \MySQLException * @throws \MySQLHasGoneAwayException + * @since 3.1.0 N°4517 Now returns void for return type to match parent class and be compatible with PHP 8.1 */ - public function Seek($iRow) + public function Seek($iRow): void { if (!$this->m_bLoaded) $this->Load(); @@ -1093,7 +1092,6 @@ class DBObjectSet implements iDBObjectSetIterator { $this->m_oSQLResult->data_seek($this->m_iCurrRow); } - return $this->m_iCurrRow; } /** diff --git a/core/dbsearch.class.php b/core/dbsearch.class.php index 849f2a56f..e0eb85cbe 100644 --- a/core/dbsearch.class.php +++ b/core/dbsearch.class.php @@ -18,23 +18,6 @@ */ -$bUseLegacyDBSearch = utils::GetConfig()->Get('use_legacy_dbsearch'); - -if ($bUseLegacyDBSearch) -{ - // excluded from autoload - require_once (APPROOT.'core/legacy/querybuilderexpressionslegacy.class.inc.php'); - require_once (APPROOT.'core/legacy/querybuildercontextlegacy.class.inc.php'); - require_once(APPROOT.'core/legacy/dbobjectsearchlegacy.class.php'); -} -else -{ - // excluded from autoload - require_once (APPROOT.'core/querybuilderexpressions.class.inc.php'); - require_once (APPROOT.'core/querybuildercontext.class.inc.php'); - require_once(APPROOT.'core/dbobjectsearch.class.php'); -} - /** * An object search * @@ -1659,7 +1642,7 @@ abstract class DBSearch $oSet = new DBObjectSet($this); if (MetaModel::IsStandaloneClass($sClass)) { - $oSet->OptimizeColumnLoad(array($this->GetClassAlias() => array(''))); + $oSet->OptimizeColumnLoad(array($this->GetClassAlias() => array())); $aIds = array($sClass => $oSet->GetColumnAsArray('id')); } else @@ -1724,4 +1707,16 @@ abstract class DBSearch { $this->SetShowObsoleteData(utils::ShowObsoleteData()); } + + /** + * To ease the debug of filters + * @internal + * + * @return string + * + */ + public function __toString() + { + return $this->ToOQL(); + } } diff --git a/core/designdocument.class.inc.php b/core/designdocument.class.inc.php index 4384c2a7d..e7ece78b0 100644 --- a/core/designdocument.class.inc.php +++ b/core/designdocument.class.inc.php @@ -28,6 +28,8 @@ namespace Combodo\iTop; use DOMDocument; use DOMFormatException; +use IssueLog; +use LogAPI; /** * Class \Combodo\iTop\DesignDocument @@ -64,9 +66,13 @@ class DesignDocument extends DOMDocument * @param $filename * @param int $options */ - public function load($filename, $options = 0) + public function load($filename, $options = null) { - parent::load($filename, LIBXML_NOBLANKS); + libxml_clear_errors(); + if (parent::load($filename, LIBXML_NOBLANKS) === false) { + $aErrors = libxml_get_errors(); + IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors); + } } /** @@ -77,10 +83,12 @@ class DesignDocument extends DOMDocument * * @return int */ - public function save($filename, $options = 0) + // Return type union is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+ + #[\ReturnTypeWillChange] + public function save($filename, $options = null) { $this->documentElement->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance"); - return parent::save($filename, LIBXML_NOBLANKS); + return parent::save($filename); } /** @@ -91,13 +99,12 @@ class DesignDocument extends DOMDocument public function Dump($bReturnRes = false) { $sXml = $this->saveXML(); - if ($bReturnRes) - { + if ($bReturnRes) { return $sXml; } echo "
\n";
-		echo htmlentities($sXml);
+		echo utils::EscapeHtml($sXml);
 		echo "
\n"; return ''; @@ -210,13 +217,13 @@ class DesignElement extends \DOMElement $oDoc->appendChild($oClone); $sXml = $oDoc->saveXML($oClone); - if ($bReturnRes) - { + if ($bReturnRes) { return $sXml; } echo "
\n";
-		echo htmlentities($sXml);
+		echo utils::EscapeHtml($sXml);
 		echo "
\n"; + return ''; } /** diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php index 330e585e8..0602e4e8d 100644 --- a/core/displayablegraph.class.inc.php +++ b/core/displayablegraph.class.inc.php @@ -459,11 +459,10 @@ class DisplayableNode extends GraphNode { $aContext = $aContextDefs[$key]; $aRootCauses = array(); - foreach($aObjects as $oRootCause) - { + foreach ($aObjects as $oRootCause) { $aRootCauses[] = $oRootCause->GetHyperlink(); } - $sHtml .= '

 '.implode(', ', $aRootCauses).'

'; + $sHtml .= '

 '.implode(', ', $aRootCauses).'

'; } $sHtml .= '
'; } @@ -1335,18 +1334,17 @@ class DisplayableGraph extends SimpleGraph } $oPdf->Rect($xMin, $yMin, $fMaxWidth + $fIconSize + 3*$fPadding, $yMax - $yMin, 'D'); - if ($sComments != '') - { + if ($sComments != '') { // Draw the comment text (surrounded by a rectangle) - $xPos = $xMin + $fMaxWidth + $fIconSize + 4*$fPadding; - $w = $xMax - $xPos - 2*$fPadding; + $xPos = $xMin + $fMaxWidth + $fIconSize + 4 * $fPadding; + $w = $xMax - $xPos - 2 * $fPadding; $iNbLines = 1; - $sText = '

'.str_replace("\n", '
', htmlentities($sComments, ENT_QUOTES, 'UTF-8'), $iNbLines).'

'; + $sText = '

'.str_replace("\n", '
', utils::EscapeHtml($sComments), $iNbLines).'

'; $fLineHeight = $oPdf->getStringHeight($w, $sText); - $h = (1+$iNbLines) * $fLineHeight; - $yPos = $yMax - 2*$fPadding - $h; + $h = (1 + $iNbLines) * $fLineHeight; + $yPos = $yMax - 2 * $fPadding - $h; $oPdf->writeHTMLCell($w, $h, $xPos + $fPadding, $yPos + $fPadding, $sText, 0 /* border */, 1 /* ln */); - $oPdf->Rect($xPos, $yPos, $w + 2*$fPadding, $h + 2*$fPadding, 'D'); + $oPdf->Rect($xPos, $yPos, $w + 2 * $fPadding, $h + 2 * $fPadding, 'D'); $yMax = $yPos - $fPadding; } diff --git a/core/email.class.inc.php b/core/email.class.inc.php index 54e372b4d..722359291 100644 --- a/core/email.class.inc.php +++ b/core/email.class.inc.php @@ -33,6 +33,13 @@ define ('EMAIL_SEND_ERROR', 2); class EMail implements iEMail { + /** + * @see self::LoadConfig() + * @var Config + * @since 2.7.7 3.0.2 3.1.0 N°3169 N°5102 Move attribute to children classes + * @since 2.7.8 3.0.3 3.1.0 N°4947 pull up the attribute back to the Email class as config init is done here + */ + protected static $m_oConfig = null; protected $oMailer; // Serialization formats @@ -45,6 +52,42 @@ class EMail implements iEMail $this->oMailer = EmailFactory::GetMailer(); } + /** + * Sets {@see m_oConfig} if current attribute is null + * + * @returns \Config the current {@see m_oConfig} value + * @throws \ConfigException + * @throws \CoreException + * + * @uses utils::GetConfig() + * + * @since 2.7.7 3.0.2 3.1.0 N°3169 N°5102 Move method to children classes + * @since 2.7.8 3.0.3 3.1.0 N°4947 Pull up to the parent class, and remove `$sConfigFile` param + */ + public function LoadConfig() + { + if (is_null(static::$m_oConfig)) { + static::$m_oConfig = utils::GetConfig(); + } + + return static::$m_oConfig; + } + + /** + * @return void + * @throws \ConfigException + * @throws \CoreException + * @since 2.7.>8 3.0.3 3.1.0 N°4947 Method creation, to factorize same code in children classes + */ + protected function InitRecipientFrom() + { + $oConfig = $this->LoadConfig(); + $this->SetRecipientFrom( + $oConfig->Get('email_default_sender_address'), + $oConfig->Get('email_default_sender_label') + ); + } + /** * Custom serialization method * No longer use the brute force "serialize" method since @@ -159,5 +202,4 @@ class EMail implements iEMail { $this->oMailer->SetRecipientReplyTo($sAddress); } - } \ No newline at end of file diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php index caecf7111..78c81ed5d 100644 --- a/core/excelbulkexport.class.inc.php +++ b/core/excelbulkexport.class.inc.php @@ -100,8 +100,8 @@ class ExcelBulkExport extends TabularBulkExport $sDateTimeFormat = utils::ReadParam('date_format', (string)AttributeDateTime::GetFormat(), true, 'raw_data'); - $sDefaultFormat = htmlentities((string)AttributeDateTime::GetFormat(), ENT_QUOTES, 'UTF-8'); - $sExample = htmlentities(date((string)AttributeDateTime::GetFormat()), ENT_QUOTES, 'UTF-8'); + $sDefaultFormat = utils::EscapeHtml((string)AttributeDateTime::GetFormat()); + $sExample = utils::EscapeHtml(date((string)AttributeDateTime::GetFormat())); $oRadioDefault = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatDefault_Example', $sDefaultFormat, $sExample), "excel_date_format_radio", "default", "excel_date_time_format_default", "radio"); $oRadioDefault->GetInput()->SetIsChecked(($sDateTimeFormat == (string)AttributeDateTime::GetFormat())); $oRadioDefault->SetBeforeInput(false); @@ -109,7 +109,7 @@ class ExcelBulkExport extends TabularBulkExport $oFieldSetDate->AddSubBlock($oRadioDefault); $oFieldSetDate->AddSubBlock(new Html('
')); - $sFormatInput = ''; + $sFormatInput = ''; $oRadioCustom = InputUIBlockFactory::MakeForInputWithLabel(Dict::Format('Core:BulkExport:DateTimeFormatCustom_Format', $sFormatInput), "excel_date_format_radio", "custom", "excel_date_time_format_custom", "radio"); $oRadioCustom->SetDescription(Dict::S('UI:CSVImport:CustomDateTimeFormatTooltip')); $oRadioCustom->GetInput()->SetIsChecked($sDateTimeFormat !== (string)AttributeDateTime::GetFormat()); @@ -156,16 +156,17 @@ EOF protected function GetSampleData($oObj, $sAttCode) { - if ($sAttCode != 'id') - { + if ($sAttCode != 'id') { $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode); if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime { $sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date'; - return '
'.htmlentities($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj), ENT_QUOTES, 'UTF-8').'
'; + + return '
'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'
'; } } - return '
'.htmlentities($this->GetValue($oObj, $sAttCode), ENT_QUOTES, 'UTF-8').'
'; + + return '
'.utils::EscapeHtml($this->GetValue($oObj, $sAttCode)).'
'; } protected function GetValue($oObj, $sAttCode) diff --git a/core/htmlbulkexport.class.inc.php b/core/htmlbulkexport.class.inc.php index 0b5a62bf2..685734e86 100644 --- a/core/htmlbulkexport.class.inc.php +++ b/core/htmlbulkexport.class.inc.php @@ -62,7 +62,8 @@ class HTMLBulkExport extends TabularBulkExport if ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime { $sClass = (get_class($oAttDef) == 'AttributeDateTime') ? 'user-formatted-date-time' : 'user-formatted-date'; - return '
'.htmlentities($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj), ENT_QUOTES, 'UTF-8').'
'; + + return '
'.utils::EscapeHtml($oAttDef->GetEditValue($oObj->Get($sAttCode), $oObj)).'
'; } } return $this->GetValue($oObj, $sAttCode); diff --git a/core/inlineimage.class.inc.php b/core/inlineimage.class.inc.php index ec71d82a0..66aa6d70d 100644 --- a/core/inlineimage.class.inc.php +++ b/core/inlineimage.class.inc.php @@ -295,13 +295,12 @@ class InlineImage extends DBObject { $sImgTag = $aImgInfo[0][0]; $sSecret = ''; - if (preg_match('/data-img-secret="([0-9a-f]+)"/', $sImgTag, $aSecretMatches)) - { + if (preg_match('/data-img-secret="([0-9a-f]+)"/', $sImgTag, $aSecretMatches)) { $sSecret = '&s='.$aSecretMatches[1]; } $sAttId = $aImgInfo[2][0]; - - $sNewImgTag = preg_replace('/src="[^"]+"/', 'src="'.htmlentities($sUrl.$sAttId.$sSecret, ENT_QUOTES, 'UTF-8').'"', $sImgTag); // preserve other attributes, must convert & to & to be idempotent with CKEditor + + $sNewImgTag = preg_replace('/src="[^"]+"/', 'src="'.utils::EscapeHtml($sUrl.$sAttId.$sSecret).'"', $sImgTag); // preserve other attributes, must convert & to & to be idempotent with CKEditor $aNeedles[] = $sImgTag; $aReplacements[] = $sNewImgTag; } @@ -536,8 +535,8 @@ JS $iObjKey = $oObject->GetKey(); $sAbsoluteUrlAppRoot = utils::GetAbsoluteUrlAppRoot(); - $sToggleFullScreen = htmlentities(Dict::S('UI:ToggleFullScreen'), ENT_QUOTES, 'UTF-8'); - + $sToggleFullScreen = utils::EscapeHtml(Dict::S('UI:ToggleFullScreen')); + return << -// - -/* -* @deprecated 3.0.0 N°3141 - Deprecate legacy SQL build -*/ -DeprecatedCallsLog::NotifyDeprecatedFile("dbobjectsearchlegacy.class.php is deprecated. Please use dbobjectsearch.class.php instead"); -/** @internal Dev hack for disabling some query build optimizations (Folding/Merging) */ -define('ENABLE_OPT', true); - -/** - * A search over a DBObject - * - * This is the most common search cases, the other class representing a search is DBUnionSearch. - * For clarity purpose, since only the constructor vary between DBObjectSearch and DBUnionSearch, all the API is documented on the common - * ancestor: DBSearch Please refer to DBSearch's documentation - * - * @api - * @see DBSearch - * @see DBUnionSearch - * @package iTopORM - * @phpdoc-tuning-exclude-inherited this tag prevent PHPdoc from displaying inherited methods. This is done in order to force the API doc. - * location into DBSearch only. - */ -class DBObjectSearch extends DBSearch -{ - private $m_aClasses; // queried classes (alias => class name), the first item is the class corresponding to this filter (the rest is coming from subfilters) - private $m_aSelectedClasses; // selected for the output (alias => class name) - private $m_oSearchCondition; - private $m_aParams; - private $m_aPointingTo; - private $m_aReferencedBy; - - /** - * @var bool whether or not some information should be hidden to the current user. Default to false == hide information. - * @see AllowAllData() - */ - protected $m_bAllowAllData = false; - protected $m_bDataFiltered = false; - - public function ToJSON() - { - return '{}'; - } - - /** - * DBObjectSearch constructor. - * - * @api - * - * @param string $sClass - * @param string|null $sClassAlias - * - * @throws Exception - */ - public function __construct($sClass, $sClassAlias = null) - { - parent::__construct(); - - if (is_null($sClassAlias)) $sClassAlias = $sClass; - if(!is_string($sClass)) throw new Exception('DBObjectSearch::__construct called with a non-string parameter: $sClass = '.print_r($sClass, true)); - if(!MetaModel::IsValidClass($sClass)) throw new Exception('DBObjectSearch::__construct called for an invalid class: "'.$sClass.'"'); - - $this->m_aSelectedClasses = array($sClassAlias => $sClass); - $this->m_aClasses = array($sClassAlias => $sClass); - $this->m_oSearchCondition = new TrueExpression; - $this->m_aParams = array(); - $this->m_aPointingTo = array(); - $this->m_aReferencedBy = array(); - } - - public function AllowAllData($bAllowAllData = true) {$this->m_bAllowAllData = $bAllowAllData;} - public function IsAllDataAllowed() {return $this->m_bAllowAllData;} - protected function IsDataFiltered() {return $this->m_bDataFiltered; } - protected function SetDataFiltered() {$this->m_bDataFiltered = true;} - - // Create a search definition that leads to 0 result, still a valid search object - static public function FromEmptySet($sClass) - { - $oResultFilter = new DBObjectSearch($sClass); - $oResultFilter->m_oSearchCondition = new FalseExpression; - return $oResultFilter; - } - - - public function GetJoinedClasses() {return $this->m_aClasses;} - - public function GetClassName($sAlias) - { - if (array_key_exists($sAlias, $this->m_aSelectedClasses)) - { - return $this->m_aSelectedClasses[$sAlias]; - } - else - { - throw new CoreException("Invalid class alias '$sAlias'"); - } - } - - public function GetClass() - { - return reset($this->m_aSelectedClasses); - } - public function GetClassAlias() - { - reset($this->m_aSelectedClasses); - return key($this->m_aSelectedClasses); - } - - public function GetFirstJoinedClass() - { - return reset($this->m_aClasses); - } - public function GetFirstJoinedClassAlias() - { - reset($this->m_aClasses); - return key($this->m_aClasses); - } - - /** - * Change the class (only subclasses are supported as of now, because the conditions must fit the new class) - * Defaults to the first selected class (most of the time it is also the first joined class - * - * @param $sNewClass - * @param null $sAlias - * - * @throws \CoreException - */ - public function ChangeClass($sNewClass, $sAlias = null) - { - if (is_null($sAlias)) - { - $sAlias = $this->GetClassAlias(); - } - else - { - if (!array_key_exists($sAlias, $this->m_aSelectedClasses)) - { - // discard silently - necessary when recursing on the related nodes (see code below) - return; - } - } - $sCurrClass = $this->GetClassName($sAlias); - if ($sNewClass == $sCurrClass) - { - // Skip silently - return; - } - if (!MetaModel::IsParentClass($sCurrClass, $sNewClass)) - { - throw new Exception("Could not change the search class from '$sCurrClass' to '$sNewClass'. Only child classes are permitted."); - } - - // Change for this node - // - $this->m_aSelectedClasses[$sAlias] = $sNewClass; - $this->m_aClasses[$sAlias] = $sNewClass; - - // Change for all the related node (yes, this was necessary with some queries - strange effects otherwise) - // - foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oExtFilter) - { - $oExtFilter->ChangeClass($sNewClass, $sAlias); - } - } - } - foreach($this->m_aReferencedBy as $sForeignClass => $aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $oForeignFilter->ChangeClass($sNewClass, $sAlias); - } - } - } - } - } - - public function GetSelectedClasses() - { - return $this->m_aSelectedClasses; - } - - /** - * @param array $aSelectedClasses array of aliases - * @throws CoreException - */ - public function SetSelectedClasses($aSelectedClasses) - { - $this->m_aSelectedClasses = array(); - foreach ($aSelectedClasses as $sAlias) - { - if (!array_key_exists($sAlias, $this->m_aClasses)) - { - throw new CoreException("SetSelectedClasses: Invalid class alias $sAlias"); - } - $this->m_aSelectedClasses[$sAlias] = $this->m_aClasses[$sAlias]; - } - } - - /** - * Change any alias of the query tree - * - * @param $sOldName - * @param $sNewName - * - * @return bool True if the alias has been found and changed - * @throws \Exception - */ - public function RenameAlias($sOldName, $sNewName) - { - $bFound = false; - if (array_key_exists($sOldName, $this->m_aClasses)) - { - $bFound = true; - } - if (array_key_exists($sNewName, $this->m_aClasses)) - { - throw new Exception("RenameAlias: alias '$sNewName' already used"); - } - - $aClasses = array(); - foreach ($this->m_aClasses as $sAlias => $sClass) - { - if ($sAlias === $sOldName) - { - $aClasses[$sNewName] = $sClass; - } - else - { - $aClasses[$sAlias] = $sClass; - } - } - $this->m_aClasses = $aClasses; - - $aSelectedClasses = array(); - foreach ($this->m_aSelectedClasses as $sAlias => $sClass) - { - if ($sAlias === $sOldName) - { - $aSelectedClasses[$sNewName] = $sClass; - } - else - { - $aSelectedClasses[$sAlias] = $sClass; - } - } - $this->m_aSelectedClasses = $aSelectedClasses; - - $this->m_oSearchCondition->RenameAlias($sOldName, $sNewName); - - foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oExtFilter) - { - $bFound = $oExtFilter->RenameAlias($sOldName, $sNewName) || $bFound; - } - } - } - foreach($this->m_aReferencedBy as $sForeignClass => $aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $bFound = $oForeignFilter->RenameAlias($sOldName, $sNewName) || $bFound; - } - } - } - } - return $bFound; - } - - - public function RenameAliasesInNameSpace($aClassAliases, $aAliasTranslation = array()) - { - } - - public function TranslateConditions($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true) - { - } - - - public function SetModifierProperty($sPluginClass, $sProperty, $value) - { - $this->m_aModifierProperties[$sPluginClass][$sProperty] = $value; - } - - public function GetModifierProperties($sPluginClass) - { - if (array_key_exists($sPluginClass, $this->m_aModifierProperties)) - { - return $this->m_aModifierProperties[$sPluginClass]; - } - else - { - return array(); - } - } - - public function IsAny() - { - if (!$this->m_oSearchCondition->IsTrue()) return false; - if (count($this->m_aPointingTo) > 0) return false; - if (count($this->m_aReferencedBy) > 0) return false; - return true; - } - - protected function TransferConditionExpression($oFilter, $aTranslation) - { - // Prevent collisions in the parameter names by renaming them if needed - foreach($this->m_aParams as $sParam => $value) - { - if (array_key_exists($sParam, $oFilter->m_aParams) && ($value != $oFilter->m_aParams[$sParam])) - { - // Generate a new and unique name for the collinding parameter - $index = 1; - while(array_key_exists($sParam.$index, $oFilter->m_aParams)) - { - $index++; - } - $secondValue = $oFilter->m_aParams[$sParam]; - $oFilter->RenameParam($sParam, $sParam.$index); - unset($oFilter->m_aParams[$sParam]); - $oFilter->m_aParams[$sParam.$index] = $secondValue; - } - } - $oTranslated = $oFilter->GetCriteria()->Translate($aTranslation, false, false /* leave unresolved fields */); - $this->AddConditionExpression($oTranslated); - $this->m_aParams = array_merge($this->m_aParams, $oFilter->m_aParams); - } - - protected function RenameParam($sOldName, $sNewName) - { - $this->m_oSearchCondition->RenameParam($sOldName, $sNewName); - foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oExtFilter) - { - $oExtFilter->RenameParam($sOldName, $sNewName); - } - } - } - foreach($this->m_aReferencedBy as $sForeignClass => $aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $oForeignFilter->RenameParam($sOldName, $sNewName); - } - } - } - } - } - - public function ResetCondition() - { - $this->m_oSearchCondition = new TrueExpression(); - // ? is that usefull/enough, do I need to rebuild the list after the subqueries ? - } - - public function MergeConditionExpression($oExpression) - { - $this->m_oSearchCondition = $this->m_oSearchCondition->LogOr($oExpression); - } - - public function AddConditionExpression($oExpression) - { - $this->m_oSearchCondition = $this->m_oSearchCondition->LogAnd($oExpression); - } - - public function AddNameCondition($sName) - { - $oValueExpr = new ScalarExpression($sName); - $oNameExpr = new FieldExpression('friendlyname', $this->GetClassAlias()); - $oNewCondition = new BinaryExpression($oNameExpr, '=', $oValueExpr); - $this->AddConditionExpression($oNewCondition); - } - - /** - * @param string $sFilterCode - * @param mixed $value - * @param string $sOpCode operator to use : 'IN', 'NOT IN', 'Contains',' Begins with', 'Finishes with', ... - * @param bool $bParseSearchString - * - * @throws \CoreException - * - * @see AddConditionForInOperatorUsingParam for IN/NOT IN queries with lots of params - */ - public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSearchString = false) - { - MyHelpers::CheckKeyInArray('filter code in class: '.$this->GetClass(), $sFilterCode, MetaModel::GetClassFilterDefs($this->GetClass())); - - $oField = new FieldExpression($sFilterCode, $this->GetClassAlias()); - if (empty($sOpCode)) - { - if ($sFilterCode == 'id') - { - $sOpCode = '='; - } - else - { - $oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode); - $oNewCondition = $oAttDef->GetSmartConditionExpression($value, $oField, $this->m_aParams); - $this->AddConditionExpression($oNewCondition); - return; - } - } - // Parse search strings if needed and if the filter code corresponds to a valid attcode - if($bParseSearchString && MetaModel::IsValidAttCode($this->GetClass(), $sFilterCode)) - { - $oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode); - $value = $oAttDef->ParseSearchString($value); - } - - // Preserve backward compatibility - quick n'dirty way to change that API semantic - // - switch($sOpCode) - { - case 'SameDay': - case 'SameMonth': - case 'SameYear': - case 'Today': - case '>|': - case '<|': - case '=|': - throw new CoreException('Deprecated operator, please consider using OQL (SQL) expressions like "(TO_DAYS(NOW()) - TO_DAYS(x)) AS AgeDays"', array('operator' => $sOpCode)); - break; - - case 'IN': - if (!is_array($value)) $value = array($value); - if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.'); - $sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')'; - $sOQLCondition = $oField->Render()." IN $sListExpr"; - break; - - case 'NOTIN': - if (!is_array($value)) $value = array($value); - if (count($value) === 0) throw new Exception('AddCondition '.$sOpCode.': Value cannot be an empty array.'); - $sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')'; - $sOQLCondition = $oField->Render()." NOT IN $sListExpr"; - break; - - case 'Contains': - $this->m_aParams[$sFilterCode] = "%$value%"; - $sOperator = 'LIKE'; - break; - - case 'Begins with': - $this->m_aParams[$sFilterCode] = "$value%"; - $sOperator = 'LIKE'; - break; - - case 'Finishes with': - $this->m_aParams[$sFilterCode] = "%$value"; - $sOperator = 'LIKE'; - break; - - default: - if ($value === null) - { - switch ($sOpCode) - { - case '=': - $sOpCode = '*Expression*'; - $oExpression = new FunctionExpression('ISNULL', array($oField)); - break; - case '!=': - $sOpCode = '*Expression*'; - $oExpression = new FunctionExpression('ISNULL', array($oField)); - $oExpression = new BinaryExpression($oExpression, '=', new ScalarExpression(0)); - break; - default: - throw new Exception("AddCondition on null value: unsupported operator '$sOpCode''"); - } - } - else - { - $this->m_aParams[$sFilterCode] = $value; - $sOperator = $sOpCode; - } - } - - switch($sOpCode) - { - case '*Expression*': - $oNewCondition = $oExpression; - break; - case "IN": - case "NOTIN": - // this will parse all of the values... Can take forever if there are lots of them ! - // In this case using a parameter is far better : WHERE ... IN (:my_param) - $oNewCondition = Expression::FromOQL($sOQLCondition); - break; - - case 'MATCHES': - $oRightExpr = new ScalarExpression($value); - $oNewCondition = new MatchExpression($oField, $oRightExpr); - break; - - case 'Contains': - case 'Begins with': - case 'Finishes with': - default: - $oRightExpr = new VariableExpression($sFilterCode); - $oNewCondition = new BinaryExpression($oField, $sOperator, $oRightExpr); - } - - $this->AddConditionExpression($oNewCondition); - } - - /** - * @param string $sFilterCode attribute code to use - * @param array $aValues - * @param bool $bPositiveMatch if true will add a IN filter, else a NOT IN - * - * @throws \CoreException - * - * @since 2.5.0 N°1418 - */ - public function AddConditionForInOperatorUsingParam($sFilterCode, $aValues, $bPositiveMatch = true) - { - $oFieldExpression = new FieldExpression($sFilterCode, $this->GetClassAlias()); - - $sOperator = $bPositiveMatch ? 'IN' : 'NOT IN'; - - $sInParamName = $this->GenerateUniqueParamName(); - $oParamExpression = new VariableExpression($sInParamName); - $this->GetInternalParamsByRef()[$sInParamName] = $aValues; - - $oListExpression = new ListExpression(array($oParamExpression)); - - $oInCondition = new BinaryExpression($oFieldExpression, $sOperator, $oListExpression); - $this->AddConditionExpression($oInCondition); - } - - /** - * Specify a condition on external keys or link sets - * @param string $sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively - * Example: infra_list->ci_id->location_id->country - * @param $value - * @return void - * @throws \CoreException - * @throws \CoreWarning - */ - public function AddConditionAdvanced($sAttSpec, $value) - { - $sClass = $this->GetClass(); - - $iPos = strpos($sAttSpec, '->'); - if ($iPos !== false) - { - $sAttCode = substr($sAttSpec, 0, $iPos); - $sSubSpec = substr($sAttSpec, $iPos + 2); - - if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) - { - throw new Exception("Invalid attribute code '$sClass/$sAttCode' in condition specification '$sAttSpec'"); - } - - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - if ($oAttDef->IsLinkSet()) - { - $sTargetClass = $oAttDef->GetLinkedClass(); - $sExtKeyToMe = $oAttDef->GetExtKeyToMe(); - - $oNewFilter = new DBObjectSearch($sTargetClass); - $oNewFilter->AddConditionAdvanced($sSubSpec, $value); - - $this->AddCondition_ReferencedBy($oNewFilter, $sExtKeyToMe); - } - elseif ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) - { - $sTargetClass = $oAttDef->GetTargetClass(EXTKEY_ABSOLUTE); - - $oNewFilter = new DBObjectSearch($sTargetClass); - $oNewFilter->AddConditionAdvanced($sSubSpec, $value); - - $this->AddCondition_PointingTo($oNewFilter, $sAttCode); - } - else - { - throw new Exception("Attribute specification '$sAttSpec', '$sAttCode' should be either a link set or an external key"); - } - } - else - { - // $sAttSpec is an attribute code - // - if (is_array($value)) - { - $oField = new FieldExpression($sAttSpec, $this->GetClass()); - $oListExpr = ListExpression::FromScalars($value); - $oInValues = new BinaryExpression($oField, 'IN', $oListExpr); - - $this->AddConditionExpression($oInValues); - } - else - { - $this->AddCondition($sAttSpec, $value); - } - } - } - - public function AddCondition_FullText($sNeedle) - { - // Transform the full text condition into additional condition expression - $aFullTextFields = array(); - foreach (MetaModel::ListAttributeDefs($this->GetClass()) as $sAttCode => $oAttDef) - { - if (!$oAttDef->IsScalar()) continue; - if ($oAttDef->IsExternalKey()) continue; - $aFullTextFields[] = new FieldExpression($sAttCode, $this->GetClassAlias()); - } - $oTextFields = new CharConcatWSExpression(' ', $aFullTextFields); - - $sQueryParam = 'needle'; - $oFlexNeedle = new CharConcatExpression(array(new ScalarExpression('%'), new VariableExpression($sQueryParam), new ScalarExpression('%'))); - - $oNewCond = new BinaryExpression($oTextFields, 'LIKE', $oFlexNeedle); - $this->AddConditionExpression($oNewCond); - $this->m_aParams[$sQueryParam] = $sNeedle; - } - - protected function AddToNameSpace(&$aClassAliases, &$aAliasTranslation, $bTranslateMainAlias = true) - { - if ($bTranslateMainAlias) - { - $sOrigAlias = $this->GetFirstJoinedClassAlias(); - if (array_key_exists($sOrigAlias, $aClassAliases)) - { - $sNewAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $this->GetFirstJoinedClass()); - if (isset($this->m_aSelectedClasses[$sOrigAlias])) - { - $this->m_aSelectedClasses[$sNewAlias] = $this->GetFirstJoinedClass(); - unset($this->m_aSelectedClasses[$sOrigAlias]); - } - - // TEMPORARY ALGORITHM (m_aClasses is not correctly updated, it is not possible to add a subtree onto a subnode) - // Replace the element at the same position (unset + set is not enough because the hash array is ordered) - $aPrevList = $this->m_aClasses; - $this->m_aClasses = array(); - foreach ($aPrevList as $sSomeAlias => $sSomeClass) - { - if ($sSomeAlias == $sOrigAlias) - { - $this->m_aClasses[$sNewAlias] = $sSomeClass; // note: GetFirstJoinedClass now returns '' !!! - } - else - { - $this->m_aClasses[$sSomeAlias] = $sSomeClass; - } - } - - // Translate the condition expression with the new alias - $aAliasTranslation[$sOrigAlias]['*'] = $sNewAlias; - } - - // add the alias into the filter aliases list - $aClassAliases[$this->GetFirstJoinedClassAlias()] = $this->GetFirstJoinedClass(); - } - - foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oFilter) - { - $oFilter->AddToNameSpace($aClassAliases, $aAliasTranslation); - } - } - } - - foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $oForeignFilter->AddToNameSpace($aClassAliases, $aAliasTranslation); - } - } - } - } - } - - - // Browse the tree nodes recursively - // - protected function GetNode($sAlias) - { - if ($this->GetFirstJoinedClassAlias() == $sAlias) - { - return $this; - } - else - { - foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oFilter) - { - $ret = $oFilter->GetNode($sAlias); - if (is_object($ret)) - { - return $ret; - } - } - } - } - foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $ret = $oForeignFilter->GetNode($sAlias); - if (is_object($ret)) - { - return $ret; - } - } - } - } - } - } - // Not found - return null; - } - - /** - * Helper to - * - convert a translation table (format optimized for the translation in an expression tree) into simple hash - * - compile over an eventually existing map - * - * @param array $aRealiasingMap Map to update - * @param array $aAliasTranslation Translation table resulting from calls to MergeWith_InNamespace - * @return void of => - */ - protected function UpdateRealiasingMap(&$aRealiasingMap, $aAliasTranslation) - { - if ($aRealiasingMap !== null) - { - foreach ($aAliasTranslation as $sPrevAlias => $aRules) - { - if (isset($aRules['*'])) - { - $sNewAlias = $aRules['*']; - $sOriginalAlias = array_search($sPrevAlias, $aRealiasingMap); - if ($sOriginalAlias !== false) - { - $aRealiasingMap[$sOriginalAlias] = $sNewAlias; - } - else - { - $aRealiasingMap[$sPrevAlias] = $sNewAlias; - } - } - } - } - } - - /** - * Completes the list of alias=>class by browsing the whole structure recursively - * This a workaround to handle some cases in which the list of classes is not correctly updated. - * This code should disappear as soon as DBObjectSearch get split between a container search class and a Node class - * - * @param array $aClasses List to be completed - */ - protected function RecomputeClassList(&$aClasses) - { - $aClasses[$this->GetFirstJoinedClassAlias()] = $this->GetFirstJoinedClass(); - - // Recurse in the query tree - foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oFilter) - { - $oFilter->RecomputeClassList($aClasses); - } - } - } - - foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $oForeignFilter->RecomputeClassList($aClasses); - } - } - } - } - } - - /** - * @param DBObjectSearch $oFilter - * @param $sExtKeyAttCode - * @param int $iOperatorCode - * @param null $aRealiasingMap array of => , for each alias that has changed - * @throws CoreException - * @throws CoreWarning - */ - public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null) - { - if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode)) - { - throw new CoreWarning("The attribute code '$sExtKeyAttCode' is not an external key of the class '{$this->GetClass()}'"); - } - $oAttExtKey = MetaModel::GetAttributeDef($this->GetClass(), $sExtKeyAttCode); - if(!MetaModel::IsSameFamilyBranch($oFilter->GetClass(), $oAttExtKey->GetTargetClass())) - { - throw new CoreException("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}"); - } - if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !($oAttExtKey instanceof AttributeHierarchicalKey)) - { - throw new CoreException("The specified tree operator $iOperatorCode is not applicable to the key '{$this->GetClass()}::$sExtKeyAttCode', which is not a HierarchicalKey"); - } - // Note: though it seems to be a good practice to clone the given source filter - // (as it was done and fixed an issue in Intersect()) - // this was not implemented here because it was causing a regression (login as admin, select an org, click on any badge) - // root cause: FromOQL relies on the fact that the passed filter can be modified later - // NO: $oFilter = $oFilter->DeepClone(); - // See also: Trac #639, and self::AddCondition_ReferencedBy() - $aAliasTranslation = array(); - $res = $this->AddCondition_PointingTo_InNameSpace($oFilter, $sExtKeyAttCode, $this->m_aClasses, $aAliasTranslation, $iOperatorCode); - $this->TransferConditionExpression($oFilter, $aAliasTranslation); - $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); - - if (ENABLE_OPT && ($oFilter->GetClass() == $oFilter->GetFirstJoinedClass())) - { - if (isset($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode])) - { - foreach ($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode] as $oRemoteFilter) - { - if ($this->GetClass() == $oRemoteFilter->GetClass()) - { - // Optimization - fold sibling query - $aAliasTranslation = array(); - $this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation); - unset($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode]); - $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false); - $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); - break; - } - } - } - } - $this->RecomputeClassList($this->m_aClasses); - return $res; - } - - protected function AddCondition_PointingTo_InNameSpace(DBObjectSearch $oFilter, $sExtKeyAttCode, &$aClassAliases, &$aAliasTranslation, $iOperatorCode) - { - // Find the node on which the new tree must be attached (most of the time it is "this") - $oReceivingFilter = $this->GetNode($this->GetClassAlias()); - - $bMerged = false; - if (ENABLE_OPT && isset($oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode])) - { - foreach ($oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode] as $oExisting) - { - if ($oExisting->GetClass() == $oFilter->GetClass()) - { - $oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation); - $bMerged = true; - break; - } - } - } - if (!$bMerged) - { - $oFilter->AddToNamespace($aClassAliases, $aAliasTranslation); - $oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][] = $oFilter; - } - } - - /** - * @param DBObjectSearch $oFilter - * @param $sForeignExtKeyAttCode - * @param int $iOperatorCode - * @param null $aRealiasingMap array of => , for each alias that has changed - * @return void - * @throws \CoreException - */ - public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null) - { - $sForeignClass = $oFilter->GetClass(); - if (!MetaModel::IsValidKeyAttCode($sForeignClass, $sForeignExtKeyAttCode)) - { - throw new CoreException("The attribute code '$sForeignExtKeyAttCode' is not an external key of the class '{$sForeignClass}'"); - } - $oAttExtKey = MetaModel::GetAttributeDef($sForeignClass, $sForeignExtKeyAttCode); - if(!MetaModel::IsSameFamilyBranch($this->GetClass(), $oAttExtKey->GetTargetClass())) - { - // à refaire en spécifique dans FromOQL - throw new CoreException("The specified filter (objects referencing an object of class {$this->GetClass()}) is not compatible with the key '{$sForeignClass}::$sForeignExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}"); - } - - // Note: though it seems to be a good practice to clone the given source filter - // (as it was done and fixed an issue in Intersect()) - // this was not implemented here because it was causing a regression (login as admin, select an org, click on any badge) - // root cause: FromOQL relies on the fact that the passed filter can be modified later - // NO: $oFilter = $oFilter->DeepClone(); - // See also: Trac #639, and self::AddCondition_PointingTo() - $aAliasTranslation = array(); - $this->AddCondition_ReferencedBy_InNameSpace($oFilter, $sForeignExtKeyAttCode, $this->m_aClasses, $aAliasTranslation, $iOperatorCode); - $this->TransferConditionExpression($oFilter, $aAliasTranslation); - $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); - - if (ENABLE_OPT && ($oFilter->GetClass() == $oFilter->GetFirstJoinedClass())) - { - if (isset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode])) - { - foreach ($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode] as $oRemoteFilter) - { - if ($this->GetClass() == $oRemoteFilter->GetClass()) - { - // Optimization - fold sibling query - $aAliasTranslation = array(); - $this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation); - unset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode]); - $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false); - $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); - break; - } - } - } - } - $this->RecomputeClassList($this->m_aClasses); - } - - protected function AddCondition_ReferencedBy_InNameSpace(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, &$aClassAliases, &$aAliasTranslation, $iOperatorCode) - { - $sForeignClass = $oFilter->GetClass(); - - // Find the node on which the new tree must be attached (most of the time it is "this") - $oReceivingFilter = $this->GetNode($this->GetClassAlias()); - - $bMerged = false; - if (ENABLE_OPT && isset($oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode])) - { - foreach ($oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode] as $oExisting) - { - if ($oExisting->GetClass() == $oFilter->GetClass()) - { - $oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation); - $bMerged = true; - break; - } - } - } - if (!$bMerged) - { - $oFilter->AddToNamespace($aClassAliases, $aAliasTranslation); - $oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][] = $oFilter; - } - } - - /** - * Filter this search with another search. - * Initial search is unmodified. - * The difference with Intersect, is that an alias can be provided, - * the filtered class does not need to be the first joined class. - * - * @param string $sClassAlias class being filtered - * @param DBSearch $oFilter Filter to apply - * - * @return DBSearch The filtered search - * @throws \CoreException - */ - public function Filter($sClassAlias, DBSearch $oFilter) - { - // If the conditions are the correct ones for Intersect - if (($this->GetFirstJoinedClassAlias() == $sClassAlias)) - { - return $this->Intersect($oFilter); - } - - /** @var \DBObjectSearch $oFilteredSearch */ - $oFilteredSearch = $this->DeepClone(); - $oFilterExpression = self::FilterSubClass($oFilteredSearch, $sClassAlias, $oFilter, $this->m_aClasses); - if ($oFilterExpression === false) - { - throw new CoreException("Limitation: cannot filter search"); - } - - $oFilteredSearch->AddConditionExpression($oFilterExpression); - - return $oFilteredSearch; - } - - /** - * Filter "in place" the search (filtered part is replaced in the initial search) - * - * @param DBObjectSearch $oSearch Search to filter, modified with the given filter - * @param string $sClassAlias class to filter - * @param \DBSearch $oFilter Filter to apply - * - * @return \Expression|false - * @throws \CoreException - */ - private static function FilterSubClass(DBObjectSearch &$oSearch, $sClassAlias, DBSearch $oFilter, $aRootClasses) - { - if (($oSearch->GetFirstJoinedClassAlias() == $sClassAlias)) - { - $oSearch->ResetCondition(); - $oSearch = $oSearch->IntersectSubClass($oFilter, $aRootClasses); - return $oSearch->GetCriteria(); - } - - /** @var Expression $oFilterExpression */ - // Search in the filter tree where is the correct DBSearch - foreach ($oSearch->m_aPointingTo as $sExtKey => $aPointingTo) - { - foreach ($aPointingTo as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $index => $oExtFilter) - { - $oFilterExpression = self::FilterSubClass($oExtFilter, $sClassAlias, $oFilter, $aRootClasses); - if ($oFilterExpression !== false) - { - $oSearch->m_aPointingTo[$sExtKey][$iOperatorCode][$index] = $oExtFilter; - return $oFilterExpression; - } - } - } - } - - foreach($oSearch->m_aReferencedBy as $sForeignClass => $aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $index => $oForeignFilter) - { - $oFilterExpression = self::FilterSubClass($oForeignFilter, $sClassAlias, $oFilter, $aRootClasses); - if ($oFilterExpression !== false) - { - $oSearch->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][$index] = $oForeignFilter; - return $oFilterExpression; - } - } - } - } - } - - return false; - } - - /** - * @inheritDoc - * @throws \CoreException - */ - public function Intersect(DBSearch $oFilter) - { - return $this->IntersectSubClass($oFilter, $this->m_aClasses); - } - - /** - * @param \DBSearch $oFilter - * @param array $aRootClasses classes of the root search (for aliases) - * - * @return \DBUnionSearch|mixed - * @throws \CoreException - */ - protected function IntersectSubClass(DBSearch $oFilter, $aRootClasses) - { - if ($oFilter instanceof DBUnionSearch) - { - // Develop! - $aFilters = $oFilter->GetSearches(); - } - else - { - $aFilters = array($oFilter); - } - - $aSearches = array(); - foreach ($aFilters as $oRightFilter) - { - // Limitation: the queried class must be the first declared class - if ($oRightFilter->GetFirstJoinedClassAlias() != $oRightFilter->GetClassAlias()) - { - throw new CoreException("Limitation: cannot merge two queries if the queried class ({$oRightFilter->GetClass()} AS {$oRightFilter->GetClassAlias()}) is not the first joined class ({$oRightFilter->GetFirstJoinedClass()} AS {$oRightFilter->GetFirstJoinedClassAlias()})"); - } - - /** @var \DBObjectSearch $oLeftFilter */ - $oLeftFilter = $this->DeepClone(); - $oRightFilter = $oRightFilter->DeepClone(); - - $bAllowAllData = ($oLeftFilter->IsAllDataAllowed() && $oRightFilter->IsAllDataAllowed()); - if ($bAllowAllData) - { - $oLeftFilter->AllowAllData(); - } - - if ($oLeftFilter->GetFirstJoinedClass() != $oRightFilter->GetClass()) - { - if (MetaModel::IsParentClass($oLeftFilter->GetFirstJoinedClass(), $oRightFilter->GetClass())) - { - // Specialize $oLeftFilter - $oLeftFilter->ChangeClass($oRightFilter->GetClass(), $oLeftFilter->GetFirstJoinedClassAlias()); - } - elseif (MetaModel::IsParentClass($oRightFilter->GetFirstJoinedClass(), $oLeftFilter->GetClass())) - { - // Specialize $oRightFilter - $oRightFilter->ChangeClass($oLeftFilter->GetClass()); - } - else - { - throw new CoreException("Attempting to merge a filter of class '{$oLeftFilter->GetClass()}' with a filter of class '{$oRightFilter->GetClass()}'"); - } - } - - $aAliasTranslation = array(); - $oLeftFilter->MergeWith_InNamespace($oRightFilter, $aRootClasses, $aAliasTranslation); - $oLeftFilter->TransferConditionExpression($oRightFilter, $aAliasTranslation); - $aSearches[] = $oLeftFilter; - } - if (count($aSearches) == 1) - { - // return a DBObjectSearch - return $aSearches[0]; - } - else - { - return new DBUnionSearch($aSearches); - } - } - - protected function MergeWith_InNamespace($oFilter, &$aClassAliases, &$aAliasTranslation) - { - if ($this->GetClass() != $oFilter->GetClass()) - { - throw new CoreException("Attempting to merge a filter of class '{$this->GetClass()}' with a filter of class '{$oFilter->GetClass()}'"); - } - - // Translate search condition into our aliasing scheme - $aAliasTranslation[$oFilter->GetClassAlias()]['*'] = $this->GetClassAlias(); - - foreach($oFilter->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oExtFilter) - { - $this->AddCondition_PointingTo_InNamespace($oExtFilter, $sExtKeyAttCode, $aClassAliases, $aAliasTranslation, $iOperatorCode); - } - } - } - foreach($oFilter->m_aReferencedBy as $sForeignClass => $aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $this->AddCondition_ReferencedBy_InNamespace($oForeignFilter, $sForeignExtKeyAttCode, $aClassAliases, $aAliasTranslation, $iOperatorCode); - } - } - } - } - } - - public function GetCriteria() {return $this->m_oSearchCondition;} - public function GetCriteria_FullText() {throw new Exception("Removed GetCriteria_FullText");} - public function GetCriteria_PointingTo($sKeyAttCode = "") - { - if (empty($sKeyAttCode)) - { - return $this->m_aPointingTo; - } - if (!array_key_exists($sKeyAttCode, $this->m_aPointingTo)) return array(); - return $this->m_aPointingTo[$sKeyAttCode]; - } - protected function GetCriteria_ReferencedBy() - { - return $this->m_aReferencedBy; - } - - public function SetInternalParams($aParams) - { - return $this->m_aParams = $aParams; - } - - /** - * @return array warning : array returned by value - * @see self::GetInternalParamsByRef to get the attribute by reference - */ - public function GetInternalParams() - { - return $this->m_aParams; - } - - /** - * @return array - * @see http://php.net/manual/en/language.references.return.php - * @since 2.5.1 N°1582 - */ - public function &GetInternalParamsByRef() - { - return $this->m_aParams; - } - - /** - * @param string $sKey - * @param mixed $value - * @param bool $bDoNotOverride - * - * @throws \CoreUnexpectedValue if $bDoNotOverride and $sKey already exists - */ - public function AddInternalParam($sKey, $value, $bDoNotOverride = false) - { - if ($bDoNotOverride) - { - if (array_key_exists($sKey, $this->m_aParams)) - { - throw new CoreUnexpectedValue("The key $sKey already exists with value : ".$this->m_aParams[$sKey]); - } - } - - $this->m_aParams[$sKey] = $value; - } - - public function GetQueryParams($bExcludeMagicParams = true) - { - $aParams = array(); - $this->m_oSearchCondition->Render($aParams, true); - - if ($bExcludeMagicParams) - { - $aRet = array(); - - // Make the list of acceptable arguments... could be factorized with run_query, into oSearch->GetQueryParams($bExclude magic params) - $aNakedMagicArguments = array(); - foreach (MetaModel::PrepareQueryArguments(array()) as $sArgName => $value) - { - $iPos = strpos($sArgName, '->object()'); - if ($iPos === false) - { - $aNakedMagicArguments[$sArgName] = $value; - } - else - { - $aNakedMagicArguments[substr($sArgName, 0, $iPos)] = true; - } - } - foreach ($aParams as $sParam => $foo) - { - $iPos = strpos($sParam, '->'); - if ($iPos === false) - { - $sRefName = $sParam; - } - else - { - $sRefName = substr($sParam, 0, $iPos); - } - if (!array_key_exists($sRefName, $aNakedMagicArguments)) - { - $aRet[$sParam] = $foo; - } - } - } - - return $aRet; - } - - public function ListConstantFields() - { - return $this->m_oSearchCondition->ListConstantFields(); - } - - /** - * Turn the parameters (:xxx) into scalar values in order to easily - * serialize a search - * @param $aArgs -*/ - public function ApplyParameters($aArgs) - { - $this->m_oSearchCondition->ApplyParameters(array_merge($this->m_aParams, $aArgs)); - } - - public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false) - { - // Currently unused, but could be useful later - $bRetrofitParams = false; - - if ($bDevelopParams) - { - if (is_null($aContextParams)) - { - $aParams = array_merge($this->m_aParams); - } - else - { - $aParams = array_merge($aContextParams, $this->m_aParams); - } - $aParams = MetaModel::PrepareQueryArguments($aParams); - } - else - { - // Leave it as is, the rendering will be made with parameters in clear - $aParams = null; - } - - $aSelectedAliases = array(); - foreach ($this->m_aSelectedClasses as $sAlias => $sClass) - { - $aSelectedAliases[] = '`' . $sAlias . '`'; - } - $sSelectedClasses = implode(', ', $aSelectedAliases); - $sRes = 'SELECT '.$sSelectedClasses.' FROM'; - - $sRes .= ' ' . $this->GetFirstJoinedClass() . ' AS `' . $this->GetFirstJoinedClassAlias() . '`'; - $sRes .= $this->ToOQL_Joins(); - $sRes .= " WHERE ".$this->m_oSearchCondition->Render($aParams, $bRetrofitParams); - - if ($bWithAllowAllFlag && $this->m_bAllowAllData) - { - $sRes .= " ALLOW ALL DATA"; - } - return $sRes; - } - - protected function OperatorCodeToOQL($iOperatorCode) - { - switch($iOperatorCode) - { - case TREE_OPERATOR_EQUALS: - $sOperator = ' = '; - break; - - case TREE_OPERATOR_BELOW: - $sOperator = ' BELOW '; - break; - - case TREE_OPERATOR_BELOW_STRICT: - $sOperator = ' BELOW STRICT '; - break; - - case TREE_OPERATOR_NOT_BELOW: - $sOperator = ' NOT BELOW '; - break; - - case TREE_OPERATOR_NOT_BELOW_STRICT: - $sOperator = ' NOT BELOW STRICT '; - break; - - case TREE_OPERATOR_ABOVE: - $sOperator = ' ABOVE '; - break; - - case TREE_OPERATOR_ABOVE_STRICT: - $sOperator = ' ABOVE STRICT '; - break; - - case TREE_OPERATOR_NOT_ABOVE: - $sOperator = ' NOT ABOVE '; - break; - - case TREE_OPERATOR_NOT_ABOVE_STRICT: - $sOperator = ' NOT ABOVE STRICT '; - break; - - } - return $sOperator; - } - - protected function ToOQL_Joins() - { - $sRes = ''; - foreach($this->m_aPointingTo as $sExtKey => $aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - $sOperator = $this->OperatorCodeToOQL($iOperatorCode); - foreach($aFilter as $oFilter) - { - $sRes .= ' JOIN ' . $oFilter->GetFirstJoinedClass() . ' AS `' . $oFilter->GetFirstJoinedClassAlias() . '` ON `' . $this->GetFirstJoinedClassAlias() . '`.' . $sExtKey . $sOperator . '`' . $oFilter->GetFirstJoinedClassAlias() . '`.id'; - $sRes .= $oFilter->ToOQL_Joins(); - } - } - } - foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - $sOperator = $this->OperatorCodeToOQL($iOperatorCode); - foreach ($aFilters as $oForeignFilter) - { - $sRes .= ' JOIN ' . $oForeignFilter->GetFirstJoinedClass() . ' AS `' . $oForeignFilter->GetFirstJoinedClassAlias() . '` ON `' . $oForeignFilter->GetFirstJoinedClassAlias() . '`.' . $sForeignExtKeyAttCode . $sOperator . '`' . $this->GetFirstJoinedClassAlias() . '`.id'; - $sRes .= $oForeignFilter->ToOQL_Joins(); - } - } - } - } - return $sRes; - } - - protected function OQLExpressionToCondition($sQuery, $oExpression, $aClassAliases) - { - if ($oExpression instanceof BinaryOqlExpression) - { - $sOperator = $oExpression->GetOperator(); - $oLeft = $this->OQLExpressionToCondition($sQuery, $oExpression->GetLeftExpr(), $aClassAliases); - $oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases); - return new BinaryExpression($oLeft, $sOperator, $oRight); - } - elseif ($oExpression instanceof MatchOqlExpression) - { - $oLeft = $this->OQLExpressionToCondition($sQuery, $oExpression->GetLeftExpr(), $aClassAliases); - $oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases); - - return new MatchExpression($oLeft, $oRight); - } - elseif ($oExpression instanceof FieldOqlExpression) - { - $sClassAlias = $oExpression->GetParent(); - $sFltCode = $oExpression->GetName(); - if (empty($sClassAlias)) - { - // Need to find the right alias - // Build an array of field => array of aliases - $aFieldClasses = array(); - foreach($aClassAliases as $sAlias => $sReal) - { - foreach(MetaModel::GetFiltersList($sReal) as $sAnFltCode) - { - $aFieldClasses[$sAnFltCode][] = $sAlias; - } - } - $sClassAlias = $aFieldClasses[$sFltCode][0]; - } - return new FieldExpression($sFltCode, $sClassAlias); - } - elseif ($oExpression instanceof VariableOqlExpression) - { - return new VariableExpression($oExpression->GetName()); - } - elseif ($oExpression instanceof TrueOqlExpression) - { - return new TrueExpression; - } - elseif ($oExpression instanceof ScalarOqlExpression) - { - return new ScalarExpression($oExpression->GetValue()); - } - elseif ($oExpression instanceof ListOqlExpression) - { - $aItems = array(); - foreach ($oExpression->GetItems() as $oItemExpression) - { - $aItems[] = $this->OQLExpressionToCondition($sQuery, $oItemExpression, $aClassAliases); - } - return new ListExpression($aItems); - } - elseif ($oExpression instanceof FunctionOqlExpression) - { - $aArgs = array(); - foreach ($oExpression->GetArgs() as $oArgExpression) - { - $aArgs[] = $this->OQLExpressionToCondition($sQuery, $oArgExpression, $aClassAliases); - } - return new FunctionExpression($oExpression->GetVerb(), $aArgs); - } - elseif ($oExpression instanceof IntervalOqlExpression) - { - return new IntervalExpression($oExpression->GetValue(), $oExpression->GetUnit()); - } - else - { - throw new CoreException('Unknown expression type', array('class'=>get_class($oExpression), 'query'=>$sQuery)); - } - } - - public function InitFromOqlQuery(OqlQuery $oOqlQuery, $sQuery) - { - $oModelReflection = new ModelReflectionRuntime(); - $sClass = $oOqlQuery->GetClass($oModelReflection); - $sClassAlias = $oOqlQuery->GetClassAlias(); - - $aAliases = array($sClassAlias => $sClass); - - // Note: the condition must be built here, it may be altered later on when optimizing some joins - $oConditionTree = $oOqlQuery->GetCondition(); - if ($oConditionTree instanceof Expression) - { - $aRawAliases = array($sClassAlias => $sClass); - $aJoinSpecs = $oOqlQuery->GetJoins(); - if (is_array($aJoinSpecs)) - { - foreach ($aJoinSpecs as $oJoinSpec) - { - $aRawAliases[$oJoinSpec->GetClassAlias()] = $oJoinSpec->GetClass(); - } - } - $this->m_oSearchCondition = $this->OQLExpressionToCondition($sQuery, $oConditionTree, $aRawAliases); - } - - // Maintain an array of filters, because the flat list is in fact referring to a tree - // And this will be an easy way to dispatch the conditions - // $this will be referenced by the other filters, or the other way around... - $aJoinItems = array($sClassAlias => $this); - - $aJoinSpecs = $oOqlQuery->GetJoins(); - if (is_array($aJoinSpecs)) - { - $aAliasTranslation = array(); - foreach ($aJoinSpecs as $oJoinSpec) - { - $sJoinClass = $oJoinSpec->GetClass(); - $sJoinClassAlias = $oJoinSpec->GetClassAlias(); - if (isset($aAliasTranslation[$sJoinClassAlias]['*'])) - { - $sJoinClassAlias = $aAliasTranslation[$sJoinClassAlias]['*']; - } - - // Assumption: ext key on the left only !!! - // normalization should take care of this - $oLeftField = $oJoinSpec->GetLeftField(); - $sFromClass = $oLeftField->GetParent(); - if (isset($aAliasTranslation[$sFromClass]['*'])) - { - $sFromClass = $aAliasTranslation[$sFromClass]['*']; - } - $sExtKeyAttCode = $oLeftField->GetName(); - - $oRightField = $oJoinSpec->GetRightField(); - $sToClass = $oRightField->GetParent(); - if (isset($aAliasTranslation[$sToClass]['*'])) - { - $sToClass = $aAliasTranslation[$sToClass]['*']; - } - - $aAliases[$sJoinClassAlias] = $sJoinClass; - $aJoinItems[$sJoinClassAlias] = new DBObjectSearch($sJoinClass, $sJoinClassAlias); - - $sOperator = $oJoinSpec->GetOperator(); - switch($sOperator) - { - case '=': - default: - $iOperatorCode = TREE_OPERATOR_EQUALS; - break; - case 'BELOW': - $iOperatorCode = TREE_OPERATOR_BELOW; - break; - case 'BELOW_STRICT': - $iOperatorCode = TREE_OPERATOR_BELOW_STRICT; - break; - case 'NOT_BELOW': - $iOperatorCode = TREE_OPERATOR_NOT_BELOW; - break; - case 'NOT_BELOW_STRICT': - $iOperatorCode = TREE_OPERATOR_NOT_BELOW_STRICT; - break; - case 'ABOVE': - $iOperatorCode = TREE_OPERATOR_ABOVE; - break; - case 'ABOVE_STRICT': - $iOperatorCode = TREE_OPERATOR_ABOVE_STRICT; - break; - case 'NOT_ABOVE': - $iOperatorCode = TREE_OPERATOR_NOT_ABOVE; - break; - case 'NOT_ABOVE_STRICT': - $iOperatorCode = TREE_OPERATOR_NOT_ABOVE_STRICT; - break; - } - - if ($sFromClass == $sJoinClassAlias) - { - $oReceiver = $aJoinItems[$sToClass]; - $oNewComer = $aJoinItems[$sFromClass]; - $oReceiver->AddCondition_ReferencedBy_InNameSpace($oNewComer, $sExtKeyAttCode, $oReceiver->m_aClasses, $aAliasTranslation, $iOperatorCode); - } - else - { - $oReceiver = $aJoinItems[$sFromClass]; - $oNewComer = $aJoinItems[$sToClass]; - $oReceiver->AddCondition_PointingTo_InNameSpace($oNewComer, $sExtKeyAttCode, $oReceiver->m_aClasses, $aAliasTranslation, $iOperatorCode); - } - } - $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false /* leave unresolved fields */); - } - - // Check and prepare the select information - $this->m_aSelectedClasses = array(); - foreach ($oOqlQuery->GetSelectedClasses() as $oClassDetails) - { - $sClassToSelect = $oClassDetails->GetValue(); - $this->m_aSelectedClasses[$sClassToSelect] = $aAliases[$sClassToSelect]; - } - $this->m_aClasses = $aAliases; - } - - //////////////////////////////////////////////////////////////////////////// - // - // Construction of the SQL queries - // - //////////////////////////////////////////////////////////////////////////// - - public function MakeDeleteQuery($aArgs = array()) - { - $aModifierProperties = MetaModel::MakeModifierProperties($this); - $oBuild = new QueryBuilderContext($this, $aModifierProperties); - $oSQLQuery = $this->MakeSQLObjectQuery($oBuild, array($this->GetClassAlias() => array()), array()); - $oSQLQuery->SetCondition($oBuild->m_oQBExpressions->GetCondition()); - $oSQLQuery->SetSelect($oBuild->m_oQBExpressions->GetSelect()); - $oSQLQuery->OptimizeJoins(array()); - $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams()); - $sRet = $oSQLQuery->RenderDelete($aScalarArgs); - return $sRet; - } - - public function MakeUpdateQuery($aValues, $aArgs = array()) - { - // $aValues is an array of $sAttCode => $value - $aModifierProperties = MetaModel::MakeModifierProperties($this); - $oBuild = new QueryBuilderContext($this, $aModifierProperties); - $aRequested = array(); // Requested attributes are the updated attributes - foreach ($aValues as $sAttCode => $value) - { - $aRequested[$sAttCode] = MetaModel::GetAttributeDef($this->GetClass(), $sAttCode); - } - $oSQLQuery = $this->MakeSQLObjectQuery($oBuild, array($this->GetClassAlias() => $aRequested), $aValues); - $oSQLQuery->SetCondition($oBuild->m_oQBExpressions->GetCondition()); - $oSQLQuery->SetSelect($oBuild->m_oQBExpressions->GetSelect()); - $oSQLQuery->OptimizeJoins(array()); - $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams()); - $sRet = $oSQLQuery->RenderUpdate($aScalarArgs); - return $sRet; - } - - /** - * Generate an INSERT statement. - * Note : unlike `RenderUpdate` and `RenderSelect`, it is limited to one and only one table. - * - * @param array $aValues is an array of $sAttCode => $value - * @param array $aArgs - * - * @return string - * @throws \CoreException - */ - public function MakeInsertQuery($aValues, $aArgs = array()) - { - $oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this); - $oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues); - $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams()); - $sRet = $oSQLQuery->RenderInsert($aScalarArgs); - return $sRet; - } - - public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null) - { - // Hide objects that are not visible to the current user - // - $oSearch = $this; - if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered()) - { - $oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter')); - if ($oVisibleObjects === false) - { - // Make sure this is a valid search object, saying NO for all - $oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass()); - } - if (is_object($oVisibleObjects)) - { - $oVisibleObjects->AllowAllData(); - $oSearch = $this->Intersect($oVisibleObjects); - $oSearch->SetDataFiltered(); - } - } - - // Compute query modifiers properties (can be set in the search itself, by the context, etc.) - // - $aModifierProperties = MetaModel::MakeModifierProperties($oSearch); - - // Create a unique cache id - // - $aContextData = array(); - $bCanCache = true; - if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries) - { - if (isset($_SERVER['REQUEST_URI'])) - { - $aContextData['sRequestUri'] = $_SERVER['REQUEST_URI']; - } - else if (isset($_SERVER['SCRIPT_NAME'])) - { - $aContextData['sRequestUri'] = $_SERVER['SCRIPT_NAME']; - } - else - { - $aContextData['sRequestUri'] = ''; - } - - // Need to identify the query - $sOqlQuery = $oSearch->ToOql(false, null, true); - if ((strpos($sOqlQuery, '`id` IN (') !== false) || (strpos($sOqlQuery, '`id` NOT IN (') !== false)) - { - // Requests containing "id IN" are not worth caching - $bCanCache = false; - } - - $aContextData['sOqlQuery'] = $sOqlQuery; - - if (count($aModifierProperties)) - { - array_multisort($aModifierProperties); - $sModifierProperties = json_encode($aModifierProperties); - } - else - { - $sModifierProperties = ''; - } - $aContextData['sModifierProperties'] = $sModifierProperties; - - $sRawId = Dict::GetUserLanguage().'-'.$sOqlQuery.$sModifierProperties; - if (!is_null($aAttToLoad)) - { - $sRawId .= json_encode($aAttToLoad); - } - $aContextData['aAttToLoad'] = $aAttToLoad; - if (!is_null($aGroupByExpr)) - { - foreach($aGroupByExpr as $sAlias => $oExpr) - { - $sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render(); - } - } - if (!is_null($aSelectExpr)) - { - foreach($aSelectExpr as $sAlias => $oExpr) - { - $sRawId .= 'se:'.$sAlias.'!'.$oExpr->Render(); - } - } - $aContextData['aGroupByExpr'] = $aGroupByExpr; - $aContextData['aSelectExpr'] = $aSelectExpr; - $sRawId .= $bGetCount; - $aContextData['bGetCount'] = $bGetCount; - if (is_array($aSelectedClasses)) - { - $sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns - } - $aContextData['aSelectedClasses'] = $aSelectedClasses; - $bIsArchiveMode = $oSearch->GetArchiveMode(); - $sRawId .= $bIsArchiveMode ? '--arch' : ''; - $bShowObsoleteData = $oSearch->GetShowObsoleteData(); - $sRawId .= $bShowObsoleteData ? '--obso' : ''; - $aContextData['bIsArchiveMode'] = $bIsArchiveMode; - $aContextData['bShowObsoleteData'] = $bShowObsoleteData; - $sOqlId = md5($sRawId); - } - else - { - $sOqlQuery = "SELECTING... ".$oSearch->GetClass(); - $sOqlId = "query id ? n/a"; - } - - - // Query caching - // - $sOqlAPCCacheId = null; - if (self::$m_bQueryCacheEnabled && $bCanCache) - { - // Warning: using directly the query string as the key to the hash array can FAIL if the string - // is long and the differences are only near the end... so it's safer (but not bullet proof?) - // to use a hash (like md5) of the string as the key ! - // - // Example of two queries that were found as similar by the hash array: - // SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTO' AND CustomerContract.customer_id = 2 - // and - // SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTR' AND CustomerContract.customer_id = 2 - // the only difference is R instead or O at position 285 (TTR instead of TTO)... - // - if (array_key_exists($sOqlId, self::$m_aQueryStructCache)) - { - // hit! - - $oSQLQuery = unserialize(serialize(self::$m_aQueryStructCache[$sOqlId])); - // Note: cloning is not enough because the subtree is made of objects - } - elseif (self::$m_bUseAPCCache) - { - // Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter - // - $sOqlAPCCacheId = 'itop-'.MetaModel::GetEnvironmentId().'-query-cache-'.$sOqlId; - $oKPI = new ExecutionKPI(); - $result = apc_fetch($sOqlAPCCacheId); - $oKPI->ComputeStats('Query APC (fetch)', $sOqlQuery); - - if (is_object($result)) - { - $oSQLQuery = $result; - self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery; - } - } - } - - if (!isset($oSQLQuery)) - { - $oKPI = new ExecutionKPI(); - $oSQLQuery = $oSearch->BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr, $aSelectedClasses, $aSelectExpr); - $oKPI->ComputeStats('BuildSQLQueryStruct', $sOqlQuery); - - if (self::$m_bQueryCacheEnabled) - { - if ($bCanCache && self::$m_bUseAPCCache) - { - $oSQLQuery->m_aContextData = $aContextData; - $oKPI = new ExecutionKPI(); - apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL); - $oKPI->ComputeStats('Query APC (store)', $sOqlQuery); - } - - self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery->DeepClone(); - } - } - return $oSQLQuery; - } - - /** - * @param array $aAttToLoad - * @param bool $bGetCount - * @param array $aModifierProperties - * @param array $aGroupByExpr - * @param array $aSelectedClasses - * @param array $aSelectExpr - * - * @return null|SQLObjectQuery - * @throws \CoreException - */ - protected function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null) - { - $oBuild = new QueryBuilderContext($this, $aModifierProperties, $aGroupByExpr, $aSelectedClasses, $aSelectExpr); - - $oSQLQuery = $this->MakeSQLObjectQuery($oBuild, $aAttToLoad, array()); - $oSQLQuery->SetCondition($oBuild->m_oQBExpressions->GetCondition()); - if (is_array($aGroupByExpr)) - { - $aCols = $oBuild->m_oQBExpressions->GetGroupBy(); - $oSQLQuery->SetGroupBy($aCols); - $oSQLQuery->SetSelect($aCols); - } - else - { - $oSQLQuery->SetSelect($oBuild->m_oQBExpressions->GetSelect()); - } - if ($aSelectExpr) - { - // Get the fields corresponding to the select expressions - foreach($oBuild->m_oQBExpressions->GetSelect() as $sAlias => $oExpr) - { - if (key_exists($sAlias, $aSelectExpr)) - { - $oSQLQuery->AddSelect($sAlias, $oExpr); - } - } - } - - $aMandatoryTables = null; - if (self::$m_bOptimizeQueries) - { - if ($bGetCount) - { - // Simplify the query if just getting the count - $oSQLQuery->SetSelect(array()); - } - $oBuild->m_oQBExpressions->GetMandatoryTables($aMandatoryTables); - $oSQLQuery->OptimizeJoins($aMandatoryTables); - } - // Filter tables as late as possible: do not interfere with the optimization process - foreach ($oBuild->GetFilteredTables() as $sTableAlias => $aConditions) - { - if ($aMandatoryTables && array_key_exists($sTableAlias, $aMandatoryTables)) - { - foreach ($aConditions as $oCondition) - { - $oSQLQuery->AddCondition($oCondition); - } - } - } - - return $oSQLQuery; - } - - - /** - * @param $oBuild - * @param null $aAttToLoad - * @param array $aValues - * @return null|SQLObjectQuery - * @throws \CoreException - */ - protected function MakeSQLObjectQuery(&$oBuild, $aAttToLoad = null, $aValues = array()) - { - // Note: query class might be different than the class of the filter - // -> this occurs when we are linking our class to an external class (referenced by, or pointing to) - $sClass = $this->GetFirstJoinedClass(); - $sClassAlias = $this->GetFirstJoinedClassAlias(); - - $bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses()); - - //self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY")); - - //$sRootClass = MetaModel::GetRootClass($sClass); - $sKeyField = MetaModel::DBGetKey($sClass); - - if ($bIsOnQueriedClass) - { - // default to the whole list of attributes + the very std id/finalclass - $oBuild->m_oQBExpressions->AddSelect($sClassAlias.'id', new FieldExpression('id', $sClassAlias)); - if (is_null($aAttToLoad) || !array_key_exists($sClassAlias, $aAttToLoad)) - { - $sSelectedClass = $oBuild->GetSelectedClass($sClassAlias); - $aAttList = MetaModel::ListAttributeDefs($sSelectedClass); - } - else - { - $aAttList = $aAttToLoad[$sClassAlias]; - } - foreach ($aAttList as $sAttCode => $oAttDef) - { - if (!$oAttDef->IsScalar()) continue; - // keep because it can be used for sorting - if (!$oAttDef->LoadInObject()) continue; - - if ($oAttDef->IsBasedOnOQLExpression()) - { - $oBuild->m_oQBExpressions->AddSelect($sClassAlias.$sAttCode, new FieldExpression($sAttCode, $sClassAlias)); - } - else - { - foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr) - { - $oBuild->m_oQBExpressions->AddSelect($sClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias)); - } - } - } - } - //echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; - $aExpectedAtts = array(); // array of (attcode => fieldexpression) - //echo "

".__LINE__.": GetUnresolvedFields($sClassAlias, ...)

\n"; - $oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts); - - // Compute a clear view of required joins (from the current class) - // Build the list of external keys: - // -> ext keys required by an explicit join - // -> ext keys mentionned in a 'pointing to' condition - // -> ext keys required for an external field - // -> ext keys required for a friendly name - // - $aExtKeys = array(); // array of sTableClass => array of (sAttCode (keys) => array of (sAttCode (fields)=> oAttDef)) - // - // Optimization: could be partially computed once for all (cached) ? - // - - if ($bIsOnQueriedClass) - { - // Get all Ext keys for the queried class (??) - foreach(MetaModel::GetKeysList($sClass) as $sKeyAttCode) - { - $sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode); - $aExtKeys[$sKeyTableClass][$sKeyAttCode] = array(); - } - } - // Get all Ext keys used by the filter - foreach ($this->GetCriteria_PointingTo() as $sKeyAttCode => $aPointingTo) - { - if (array_key_exists(TREE_OPERATOR_EQUALS, $aPointingTo)) - { - $sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode); - $aExtKeys[$sKeyTableClass][$sKeyAttCode] = array(); - } - } - - $aFNJoinAlias = array(); // array of (subclass => alias) - foreach ($aExpectedAtts as $sExpectedAttCode => $oExpression) - { - if (!MetaModel::IsValidAttCode($sClass, $sExpectedAttCode)) continue; - $oAttDef = MetaModel::GetAttributeDef($sClass, $sExpectedAttCode); - if ($oAttDef->IsBasedOnOQLExpression()) - { - // To optimize: detect a restriction on child classes in the condition expression - // e.g. SELECT FunctionalCI WHERE finalclass IN ('Server', 'VirtualMachine') - $oExpression = static::GetPolymorphicExpression($sClass, $sExpectedAttCode); - - $aRequiredFields = array(); - $oExpression->GetUnresolvedFields('', $aRequiredFields); - $aTranslateFields = array(); - foreach($aRequiredFields as $sSubClass => $aFields) - { - foreach($aFields as $sAttCode => $oField) - { - $oAttDef = MetaModel::GetAttributeDef($sSubClass, $sAttCode); - if ($oAttDef->IsExternalKey()) - { - $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode); - $aExtKeys[$sClassOfAttribute][$sAttCode] = array(); - } - elseif ($oAttDef->IsExternalField()) - { - $sKeyAttCode = $oAttDef->GetKeyAttCode(); - $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sKeyAttCode); - $aExtKeys[$sClassOfAttribute][$sKeyAttCode][$sAttCode] = $oAttDef; - } - else - { - $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode); - } - - if (MetaModel::IsParentClass($sClassOfAttribute, $sClass)) - { - // The attribute is part of the standard query - // - $sAliasForAttribute = $sClassAlias; - } - else - { - // The attribute will be available from an additional outer join - // For each subclass (table) one single join is enough - // - if (!array_key_exists($sClassOfAttribute, $aFNJoinAlias)) - { - $sAliasForAttribute = $oBuild->GenerateClassAlias($sClassAlias.'_fn_'.$sClassOfAttribute, $sClassOfAttribute); - $aFNJoinAlias[$sClassOfAttribute] = $sAliasForAttribute; - } - else - { - $sAliasForAttribute = $aFNJoinAlias[$sClassOfAttribute]; - } - } - - $aTranslateFields[$sSubClass][$sAttCode] = new FieldExpression($sAttCode, $sAliasForAttribute); - } - } - $oExpression = $oExpression->Translate($aTranslateFields, false); - - $aTranslateNow = array(); - $aTranslateNow[$sClassAlias][$sExpectedAttCode] = $oExpression; - $oBuild->m_oQBExpressions->Translate($aTranslateNow, false); - } - } - - // Add the ext fields used in the select (eventually adds an external key) - foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef) - { - if ($oAttDef->IsExternalField()) - { - if (array_key_exists($sAttCode, $aExpectedAtts)) - { - // Add the external attribute - $sKeyAttCode = $oAttDef->GetKeyAttCode(); - $sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode); - $aExtKeys[$sKeyTableClass][$sKeyAttCode][$sAttCode] = $oAttDef; - } - } - } - - $bRootFirst = MetaModel::GetConfig()->Get('optimize_requests_for_join_count'); - if ($bRootFirst) - { - // First query built from the root, adding all tables including the leaf - // Before N.1065 we were joining from the leaf first, but this wasn't a good choice : - // most of the time (obsolescence, friendlyname, ...) we want to get a root attribute ! - // - $oSelectBase = null; - $aClassHierarchy = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, true); - $bIsClassStandaloneClass = (count($aClassHierarchy) == 1); - foreach($aClassHierarchy as $sSomeClass) - { - if (!MetaModel::HasTable($sSomeClass)) - { - continue; - } - - self::DbgTrace("Adding join from root to leaf: $sSomeClass... let's call MakeSQLObjectQuerySingleTable()"); - $oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSomeClass, $aExtKeys, $aValues); - if (is_null($oSelectBase)) - { - $oSelectBase = $oSelectParentTable; - if (!$bIsClassStandaloneClass && (MetaModel::IsRootClass($sSomeClass))) - { - // As we're linking to root class first, we're adding a where clause on the finalClass attribute : - // COALESCE($sRootClassFinalClass IN ('$sExpectedClasses'), 1) - // If we don't, the child classes can be removed in the query optimisation phase, including the leaf that was queried - // So we still need to filter records to only those corresponding to the child classes ! - // The coalesce is mandatory if we have a polymorphic query (left join) - $oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL)); - $sFinalClassSqlColumnName = MetaModel::DBGetClassField($sSomeClass); - $oClassExpr = new FieldExpression($sFinalClassSqlColumnName, $oSelectBase->GetTableAlias()); - $oInExpression = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr); - $oTrueExpression = new TrueExpression(); - $aCoalesceAttr = array($oInExpression, $oTrueExpression); - $oFinalClassRestriction = new FunctionExpression("COALESCE", $aCoalesceAttr); - - $oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction); - } - } - else - { - $oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sSomeClass)); - } - } - } - else - { - // First query built upon on the leaf (ie current) class - // - self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()"); - if (MetaModel::HasTable($sClass)) - { - $oSelectBase = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues); - } - else - { - $oSelectBase = null; - - // As the join will not filter on the expected classes, we have to specify it explicitely - $sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL)); - $oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')"); - $oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction); - } - - // Then we join the queries of the eventual parent classes (compound model) - foreach(MetaModel::EnumParentClasses($sClass) as $sParentClass) - { - if (!MetaModel::HasTable($sParentClass)) continue; - - self::DbgTrace("Parent class: $sParentClass... let's call MakeSQLObjectQuerySingleTable()"); - $oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sParentClass, $aExtKeys, $aValues); - if (is_null($oSelectBase)) - { - $oSelectBase = $oSelectParentTable; - } - else - { - $oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sParentClass)); - } - } - } - - // Filter on objects referencing me - // - foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences) - { - foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator) - { - foreach ($aFiltersByOperator as $iOperatorCode => $aFilters) - { - foreach ($aFilters as $oForeignFilter) - { - $oForeignKeyAttDef = MetaModel::GetAttributeDef($sForeignClass, $sForeignExtKeyAttCode); - - self::DbgTrace("Referenced by foreign key: $sForeignExtKeyAttCode... let's call MakeSQLObjectQuery()"); - //self::DbgTrace($oForeignFilter); - //self::DbgTrace($oForeignFilter->ToOQL()); - //self::DbgTrace($oSelectForeign); - //self::DbgTrace($oSelectForeign->RenderSelect(array())); - - $sForeignClassAlias = $oForeignFilter->GetFirstJoinedClassAlias(); - $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression($sForeignExtKeyAttCode, $sForeignClassAlias)); - - if ($oForeignKeyAttDef instanceof AttributeObjectKey) - { - $sClassAttCode = $oForeignKeyAttDef->Get('class_attcode'); - - // Add the condition: `$sForeignClassAlias`.$sClassAttCode IN (subclasses of $sClass') - $oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL)); - $oClassExpr = new FieldExpression($sClassAttCode, $sForeignClassAlias); - $oClassRestriction = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr); - $oBuild->m_oQBExpressions->AddCondition($oClassRestriction); - } - - $oSelectForeign = $oForeignFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad); - - $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField(); - $sForeignKeyTable = $oJoinExpr->GetParent(); - $sForeignKeyColumn = $oJoinExpr->GetName(); - - if ($iOperatorCode == TREE_OPERATOR_EQUALS) - { - $oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyColumn, $sForeignKeyTable); - } - else - { - // Hierarchical key - $KeyLeft = $oForeignKeyAttDef->GetSQLLeft(); - $KeyRight = $oForeignKeyAttDef->GetSQLRight(); - - $oSelectBase->AddInnerJoinTree($oSelectForeign, $KeyLeft, $KeyRight, $KeyLeft, $KeyRight, $sForeignKeyTable, $iOperatorCode, true); - } - } - } - } - } - - // Additional JOINS for Friendly names - // - foreach ($aFNJoinAlias as $sSubClass => $sSubClassAlias) - { - $oSubClassFilter = new DBObjectSearch($sSubClass, $sSubClassAlias); - $oSelectFN = $oSubClassFilter->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSubClass, $aExtKeys, array()); - $oSelectBase->AddLeftJoin($oSelectFN, $sKeyField, MetaModel::DBGetKey($sSubClass)); - } - - // That's all... cross fingers and we'll get some working query - - //MyHelpers::var_dump_html($oSelectBase, true); - //MyHelpers::var_dump_html($oSelectBase->RenderSelect(), true); - if (self::$m_bDebugQuery) $oSelectBase->DisplayHtml(); - return $oSelectBase; - } - - protected function MakeSQLObjectQuerySingleTable(&$oBuild, $aAttToLoad, $sTableClass, $aExtKeys, $aValues) - { - // $aExtKeys is an array of sTableClass => array of (sAttCode (keys) => array of sAttCode (fields)) - - // Prepare the query for a single table (compound objects) - // Ignores the items (attributes/filters) that are not on the target table - // Perform an (inner or left) join for every external key (and specify the expected fields) - // - // Returns an SQLQuery - // - $sTargetClass = $this->GetFirstJoinedClass(); - $sTargetAlias = $this->GetFirstJoinedClassAlias(); - $sTable = MetaModel::DBGetTable($sTableClass); - $sTableAlias = $oBuild->GenerateTableAlias($sTargetAlias.'_'.$sTable, $sTable); - - $aTranslation = array(); - $aExpectedAtts = array(); - $oBuild->m_oQBExpressions->GetUnresolvedFields($sTargetAlias, $aExpectedAtts); - - $bIsOnQueriedClass = array_key_exists($sTargetAlias, $oBuild->GetRootFilter()->GetSelectedClasses()); - - self::DbgTrace("Entering: tableclass=$sTableClass, filter=".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY")); - - // 1 - SELECT and UPDATE - // - // Note: no need for any values nor fields for foreign Classes (ie not the queried Class) - // - $aUpdateValues = array(); - - - // 1/a - Get the key and friendly name - // - // We need one pkey to be the key, let's take the first one available - $oSelectedIdField = null; - $oIdField = new FieldExpressionResolved(MetaModel::DBGetKey($sTableClass), $sTableAlias); - $aTranslation[$sTargetAlias]['id'] = $oIdField; - - if ($bIsOnQueriedClass) - { - // Add this field to the list of queried fields (required for the COUNT to work fine) - $oSelectedIdField = $oIdField; - } - - // 1/b - Get the other attributes - // - foreach(MetaModel::ListAttributeDefs($sTableClass) as $sAttCode=>$oAttDef) - { - // Skip this attribute if not defined in this table - if (MetaModel::GetAttributeOrigin($sTargetClass, $sAttCode) != $sTableClass) continue; - - // Skip this attribute if not made of SQL columns - if (count($oAttDef->GetSQLExpressions()) == 0) continue; - - // Update... - // - if ($bIsOnQueriedClass && array_key_exists($sAttCode, $aValues)) - { - assert ($oAttDef->IsBasedOnDBColumns()); - foreach ($oAttDef->GetSQLValues($aValues[$sAttCode]) as $sColumn => $sValue) - { - $aUpdateValues[$sColumn] = $sValue; - } - } - } - - // 2 - The SQL query, for this table only - // - $oSelectBase = new SQLObjectQuery($sTable, $sTableAlias, array(), $bIsOnQueriedClass, $aUpdateValues, $oSelectedIdField); - - // 3 - Resolve expected expressions (translation table: alias.attcode => table.column) - // - foreach(MetaModel::ListAttributeDefs($sTableClass) as $sAttCode=>$oAttDef) - { - // Skip this attribute if not defined in this table - if (MetaModel::GetAttributeOrigin($sTargetClass, $sAttCode) != $sTableClass) continue; - - // Select... - // - if ($oAttDef->IsExternalField()) - { - // skip, this will be handled in the joined tables (done hereabove) - } - else - { - // standard field, or external key - // add it to the output - foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr) - { - if (array_key_exists($sAttCode.$sColId, $aExpectedAtts)) - { - $oFieldSQLExp = new FieldExpressionResolved($sSQLExpr, $sTableAlias); - /** - * @var string $sPluginClass - * @var iQueryModifier $oQueryModifier - */ - foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier) - { - $oFieldSQLExp = $oQueryModifier->GetFieldExpression($oBuild, $sTargetClass, $sAttCode, $sColId, $oFieldSQLExp, $oSelectBase); - } - $aTranslation[$sTargetAlias][$sAttCode.$sColId] = $oFieldSQLExp; - } - } - } - } - - // 4 - The external keys -> joins... - // - $aAllPointingTo = $this->GetCriteria_PointingTo(); - - if (array_key_exists($sTableClass, $aExtKeys)) - { - foreach ($aExtKeys[$sTableClass] as $sKeyAttCode => $aExtFields) - { - $oKeyAttDef = MetaModel::GetAttributeDef($sTableClass, $sKeyAttCode); - - $aPointingTo = $this->GetCriteria_PointingTo($sKeyAttCode); - if (!array_key_exists(TREE_OPERATOR_EQUALS, $aPointingTo)) - { - // The join was not explicitely defined in the filter, - // we need to do it now - $sKeyClass = $oKeyAttDef->GetTargetClass(); - $sKeyClassAlias = $oBuild->GenerateClassAlias($sKeyClass.'_'.$sKeyAttCode, $sKeyClass); - $oExtFilter = new DBObjectSearch($sKeyClass, $sKeyClassAlias); - - $aAllPointingTo[$sKeyAttCode][TREE_OPERATOR_EQUALS][$sKeyClassAlias] = $oExtFilter; - } - } - } - - foreach ($aAllPointingTo as $sKeyAttCode => $aPointingTo) - { - foreach($aPointingTo as $iOperatorCode => $aFilter) - { - foreach($aFilter as $oExtFilter) - { - if (!MetaModel::IsValidAttCode($sTableClass, $sKeyAttCode)) continue; // Not defined in the class, skip it - // The aliases should not conflict because normalization occured while building the filter - $oKeyAttDef = MetaModel::GetAttributeDef($sTableClass, $sKeyAttCode); - $sKeyClass = $oExtFilter->GetFirstJoinedClass(); - $sKeyClassAlias = $oExtFilter->GetFirstJoinedClassAlias(); - - // Note: there is no search condition in $oExtFilter, because normalization did merge the condition onto the top of the filter tree - - if ($iOperatorCode == TREE_OPERATOR_EQUALS) - { - if (array_key_exists($sTableClass, $aExtKeys) && array_key_exists($sKeyAttCode, $aExtKeys[$sTableClass])) - { - // Specify expected attributes for the target class query - // ... and use the current alias ! - $aTranslateNow = array(); // Translation for external fields - must be performed before the join is done (recursion...) - foreach($aExtKeys[$sTableClass][$sKeyAttCode] as $sAttCode => $oAtt) - { - $oExtAttDef = $oAtt->GetExtAttDef(); - if ($oExtAttDef->IsBasedOnOQLExpression()) - { - $aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression($oExtAttDef->GetCode(), $sKeyClassAlias); - } - else - { - $sExtAttCode = $oAtt->GetExtAttCode(); - // Translate mainclass.extfield => remoteclassalias.remotefieldcode - $oRemoteAttDef = MetaModel::GetAttributeDef($sKeyClass, $sExtAttCode); - foreach ($oRemoteAttDef->GetSQLExpressions() as $sColId => $sRemoteAttExpr) - { - $aTranslateNow[$sTargetAlias][$sAttCode.$sColId] = new FieldExpression($sExtAttCode, $sKeyClassAlias); - } - } - } - - if ($oKeyAttDef instanceof AttributeObjectKey) - { - // Add the condition: `$sTargetAlias`.$sClassAttCode IN (subclasses of $sKeyClass') - $sClassAttCode = $oKeyAttDef->Get('class_attcode'); - $oClassAttDef = MetaModel::GetAttributeDef($sTargetClass, $sClassAttCode); - foreach ($oClassAttDef->GetSQLExpressions() as $sColId => $sSQLExpr) - { - $aTranslateNow[$sTargetAlias][$sClassAttCode.$sColId] = new FieldExpressionResolved($sSQLExpr, $sTableAlias); - } - - $oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sKeyClass, ENUM_CHILD_CLASSES_ALL)); - $oClassExpr = new FieldExpression($sClassAttCode, $sTargetAlias); - $oClassRestriction = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr); - $oBuild->m_oQBExpressions->AddCondition($oClassRestriction); - } - - // Translate prior to recursing - // - $oBuild->m_oQBExpressions->Translate($aTranslateNow, false); - - self::DbgTrace("External key $sKeyAttCode (class: $sKeyClass), call MakeSQLObjectQuery()"); - $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression('id', $sKeyClassAlias)); - - $oSelectExtKey = $oExtFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad); - - $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField(); - $sExternalKeyTable = $oJoinExpr->GetParent(); - $sExternalKeyField = $oJoinExpr->GetName(); - - $aCols = $oKeyAttDef->GetSQLExpressions(); // Workaround a PHP bug: sometimes issuing a Notice if invoking current(somefunc()) - $sLocalKeyField = current($aCols); // get the first column for an external key - - self::DbgTrace("External key $sKeyAttCode, Join on $sLocalKeyField = $sExternalKeyField"); - if ($oKeyAttDef->IsNullAllowed()) - { - $oSelectBase->AddLeftJoin($oSelectExtKey, $sLocalKeyField, $sExternalKeyField); - } - else - { - $oSelectBase->AddInnerJoin($oSelectExtKey, $sLocalKeyField, $sExternalKeyField, $sExternalKeyTable); - } - } - } - elseif(MetaModel::GetAttributeOrigin($sKeyClass, $sKeyAttCode) == $sTableClass) - { - $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression($sKeyAttCode, $sKeyClassAlias)); - $oSelectExtKey = $oExtFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad); - $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField(); - $sExternalKeyTable = $oJoinExpr->GetParent(); - $sExternalKeyField = $oJoinExpr->GetName(); - $sLeftIndex = $sExternalKeyField.'_left'; // TODO use GetSQLLeft() - $sRightIndex = $sExternalKeyField.'_right'; // TODO use GetSQLRight() - - $LocalKeyLeft = $oKeyAttDef->GetSQLLeft(); - $LocalKeyRight = $oKeyAttDef->GetSQLRight(); - - $oSelectBase->AddInnerJoinTree($oSelectExtKey, $LocalKeyLeft, $LocalKeyRight, $sLeftIndex, $sRightIndex, $sExternalKeyTable, $iOperatorCode); - } - } - } - } - - // Translate the selected columns - // - $oBuild->m_oQBExpressions->Translate($aTranslation, false); - - // Filter out archived records - // - if (MetaModel::IsArchivable($sTableClass)) - { - if (!$oBuild->GetRootFilter()->GetArchiveMode()) - { - $bIsOnJoinedClass = array_key_exists($sTargetAlias, $oBuild->GetRootFilter()->GetJoinedClasses()); - if ($bIsOnJoinedClass) - { - if (MetaModel::IsParentClass($sTableClass, $sTargetClass)) - { - $oNotArchived = new BinaryExpression(new FieldExpressionResolved('archive_flag', $sTableAlias), '=', new ScalarExpression(0)); - $oBuild->AddFilteredTable($sTableAlias, $oNotArchived); - } - } - } - } - return $oSelectBase; - } - - /** - * Get the expression for the class and its subclasses (if finalclass = 'subclass' ...) - * Simplifies the final expression by grouping classes having the same expression - * @param $sClass - * @param $sAttCode - * @return \FunctionExpression|mixed|null - * @throws \CoreException -*/ - static public function GetPolymorphicExpression($sClass, $sAttCode) - { - $oExpression = ExpressionCache::GetCachedExpression($sClass, $sAttCode); - if (!empty($oExpression)) - { - return $oExpression; - } - - // 1st step - get all of the required expressions (instantiable classes) - // and group them using their OQL representation - // - $aExpressions = array(); // signature => array('expression' => oExp, 'classes' => array of classes) - foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass) - { - if (($sSubClass != $sClass) && MetaModel::IsAbstract($sSubClass)) continue; - - $oAttDef = MetaModel::GetAttributeDef($sSubClass, $sAttCode); - $oSubClassExp = $oAttDef->GetOQLExpression($sSubClass); - - // 3rd step - position the attributes in the hierarchy of classes - // - $oSubClassExp->Browse(function($oNode) use ($sSubClass) { - if ($oNode instanceof FieldExpression) - { - $sAttCode = $oNode->GetName(); - $oAttDef = MetaModel::GetAttributeDef($sSubClass, $sAttCode); - if ($oAttDef->IsExternalField()) - { - $sKeyAttCode = $oAttDef->GetKeyAttCode(); - $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sKeyAttCode); - } - else - { - $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode); - } - $sParent = MetaModel::GetAttributeOrigin($sClassOfAttribute, $oNode->GetName()); - $oNode->SetParent($sParent); - } - }); - - $sSignature = $oSubClassExp->Render(); - if (!array_key_exists($sSignature, $aExpressions)) - { - $aExpressions[$sSignature] = array( - 'expression' => $oSubClassExp, - 'classes' => array(), - ); - } - $aExpressions[$sSignature]['classes'][] = $sSubClass; - } - - // 2nd step - build the final name expression depending on the finalclass - // - if (count($aExpressions) == 1) - { - $aExpData = reset($aExpressions); - $oExpression = $aExpData['expression']; - } - else - { - $oExpression = null; - foreach ($aExpressions as $sSignature => $aExpData) - { - $oClassListExpr = ListExpression::FromScalars($aExpData['classes']); - $oClassExpr = new FieldExpression('finalclass', $sClass); - $oClassInList = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr); - - if (is_null($oExpression)) - { - $oExpression = $aExpData['expression']; - } - else - { - $oExpression = new FunctionExpression('IF', array($oClassInList, $aExpData['expression'], $oExpression)); - } - } - } - return $oExpression; - } - - /** - * @param array $aAttCodes array of attCodes to search into - * @param string $sNeedle one word to be searched - * - * @throws \CoreException - */ - public function AddCondition_FullTextOnAttributes(array $aAttCodes, $sNeedle) - { - } - - public function ListParameters() - { - return $this->GetCriteria()->ListParameters(); - } -} diff --git a/core/legacy/querybuildercontextlegacy.class.inc.php b/core/legacy/querybuildercontextlegacy.class.inc.php deleted file mode 100644 index c17a0da04..000000000 --- a/core/legacy/querybuildercontextlegacy.class.inc.php +++ /dev/null @@ -1,109 +0,0 @@ - - -/** - * @deprecated 3.1.0 N°3141 - Deprecate legacy SQL build - * Associated with the metamodel -> MakeQuery/MakeQuerySingleTable - * - * @copyright Copyright (C) 2010-2021 Combodo SARL - * @license http://opensource.org/licenses/AGPL-3.0 - */ -DeprecatedCallsLog::NotifyDeprecatedFile("querybuildercontextlegacy.class.inc.php is deprecated. Please use querybuildercontext.class.inc.php instead"); - -class QueryBuilderContext -{ - protected $m_oRootFilter; - protected $m_aClassAliases; - protected $m_aTableAliases; - protected $m_aModifierProperties; - protected $m_aSelectedClasses; - protected $m_aFilteredTables; - - public $m_oQBExpressions; - - public function __construct($oFilter, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null) - { - $this->m_oRootFilter = $oFilter; - $this->m_oQBExpressions = new QueryBuilderExpressions($oFilter, $aGroupByExpr, $aSelectExpr); - - $this->m_aClassAliases = $oFilter->GetJoinedClasses(); - $this->m_aTableAliases = array(); - $this->m_aFilteredTables = array(); - - $this->m_aModifierProperties = $aModifierProperties; - if (is_null($aSelectedClasses)) - { - $this->m_aSelectedClasses = $oFilter->GetSelectedClasses(); - } - else - { - // For the unions, the selected classes can be upper in the hierarchy (lowest common ancestor) - $this->m_aSelectedClasses = $aSelectedClasses; - } - } - - public function GetRootFilter() - { - return $this->m_oRootFilter; - } - - public function GenerateTableAlias($sNewName, $sRealName) - { - return MetaModel::GenerateUniqueAlias($this->m_aTableAliases, $sNewName, $sRealName); - } - - public function GenerateClassAlias($sNewName, $sRealName) - { - return MetaModel::GenerateUniqueAlias($this->m_aClassAliases, $sNewName, $sRealName); - } - - public function GetModifierProperties($sPluginClass) - { - if (array_key_exists($sPluginClass, $this->m_aModifierProperties)) - { - return $this->m_aModifierProperties[$sPluginClass]; - } - else - { - return array(); - } - } - - public function GetSelectedClass($sAlias) - { - return $this->m_aSelectedClasses[$sAlias]; - } - - public function AddFilteredTable($sTableAlias, $oCondition) - { - if (array_key_exists($sTableAlias, $this->m_aFilteredTables)) - { - $this->m_aFilteredTables[$sTableAlias][] = $oCondition; - } - else - { - $this->m_aFilteredTables[$sTableAlias] = array($oCondition); - } - } - - public function GetFilteredTables() - { - return $this->m_aFilteredTables; - } -} - diff --git a/core/legacy/querybuilderexpressionslegacy.class.inc.php b/core/legacy/querybuilderexpressionslegacy.class.inc.php deleted file mode 100644 index cd1157376..000000000 --- a/core/legacy/querybuilderexpressionslegacy.class.inc.php +++ /dev/null @@ -1,190 +0,0 @@ -m_oConditionExpr = $oSearch->GetCriteria(); - if (!$oSearch->GetShowObsoleteData()) - { - foreach ($oSearch->GetSelectedClasses() as $sAlias => $sClass) - { - if (MetaModel::IsObsoletable($sClass)) - { - $oNotObsolete = new BinaryExpression(new FieldExpression('obsolescence_flag', $sAlias), '=', new ScalarExpression(0)); - $this->m_oConditionExpr = $this->m_oConditionExpr->LogAnd($oNotObsolete); - } - } - } - $this->m_aSelectExpr = is_null($aSelectExpr) ? array() : $aSelectExpr; - $this->m_aGroupByExpr = $aGroupByExpr; - $this->m_aJoinFields = array(); - - $this->m_aClassIds = array(); - foreach ($oSearch->GetJoinedClasses() as $sClassAlias => $sClass) - { - $this->m_aClassIds[$sClassAlias] = new FieldExpression('id', $sClassAlias); - } - } - - public function GetSelect() - { - return $this->m_aSelectExpr; - } - - public function GetGroupBy() - { - return $this->m_aGroupByExpr; - } - - public function GetCondition() - { - return $this->m_oConditionExpr; - } - - /** - * @return Expression|mixed - */ - public function PopJoinField() - { - return array_pop($this->m_aJoinFields); - } - - /** - * @param string $sAttAlias - * @param Expression $oExpression - */ - public function AddSelect($sAttAlias, Expression $oExpression) - { - $this->m_aSelectExpr[$sAttAlias] = $oExpression; - } - - /** - * @param Expression $oExpression - */ - public function AddCondition(Expression $oExpression) - { - $this->m_oConditionExpr = $this->m_oConditionExpr->LogAnd($oExpression); - } - - /** - * @param Expression $oExpression - */ - public function PushJoinField(Expression $oExpression) - { - array_push($this->m_aJoinFields, $oExpression); - } - - /** - * Get tables representing the queried objects - * Could be further optimized: when the first join is an outer join, then the rest can be omitted - * - * @param array $aTables - * - * @return array - */ - public function GetMandatoryTables(&$aTables = null) - { - if (is_null($aTables)) - { - $aTables = array(); - } - - foreach ($this->m_aClassIds as $sClass => $oExpression) - { - $oExpression->CollectUsedParents($aTables); - } - - return $aTables; - } - - public function GetUnresolvedFields($sAlias, &$aUnresolved) - { - $this->m_oConditionExpr->GetUnresolvedFields($sAlias, $aUnresolved); - foreach ($this->m_aSelectExpr as $sColAlias => $oExpr) - { - $oExpr->GetUnresolvedFields($sAlias, $aUnresolved); - } - if ($this->m_aGroupByExpr) - { - foreach ($this->m_aGroupByExpr as $sColAlias => $oExpr) - { - $oExpr->GetUnresolvedFields($sAlias, $aUnresolved); - } - } - foreach ($this->m_aJoinFields as $oExpression) - { - $oExpression->GetUnresolvedFields($sAlias, $aUnresolved); - } - } - - public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true) - { - $this->m_oConditionExpr = $this->m_oConditionExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved); - foreach ($this->m_aSelectExpr as $sColAlias => $oExpr) - { - $this->m_aSelectExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved); - } - if ($this->m_aGroupByExpr) - { - foreach ($this->m_aGroupByExpr as $sColAlias => $oExpr) - { - $this->m_aGroupByExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved); - } - } - foreach ($this->m_aJoinFields as $index => $oExpression) - { - $this->m_aJoinFields[$index] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved); - } - - foreach ($this->m_aClassIds as $sClass => $oExpression) - { - $this->m_aClassIds[$sClass] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved); - } - } - - public function RenameParam($sOldName, $sNewName) - { - $this->m_oConditionExpr->RenameParam($sOldName, $sNewName); - foreach ($this->m_aSelectExpr as $sColAlias => $oExpr) - { - $this->m_aSelectExpr[$sColAlias] = $oExpr->RenameParam($sOldName, $sNewName); - } - if ($this->m_aGroupByExpr) - { - foreach ($this->m_aGroupByExpr as $sColAlias => $oExpr) - { - $this->m_aGroupByExpr[$sColAlias] = $oExpr->RenameParam($sOldName, $sNewName); - } - } - foreach ($this->m_aJoinFields as $index => $oExpression) - { - $this->m_aJoinFields[$index] = $oExpression->RenameParam($sOldName, $sNewName); - } - } -} \ No newline at end of file diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 85fc04798..9c7c91235 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -465,13 +465,13 @@ abstract class MetaModel $oStyle = self::$m_aClassParams[$sClass]['style']; $sIcon = $oStyle->GetIconAsAbsUrl(); } - if (utils::StrLen($sIcon) == 0) { + if (utils::IsNullOrEmptyString($sIcon)) { $sParentClass = self::GetParentPersistentClass($sClass); if (strlen($sParentClass) > 0) { return self::GetClassIcon($sParentClass, $bImgTag, $sMoreStyles); } } - $sIcon = str_replace('/modules/', '/env-'.self::$m_sEnvironment.'/', $sIcon); // Support of pre-2.0 modules + $sIcon = str_replace('/modules/', '/env-'.self::$m_sEnvironment.'/', $sIcon ?? ''); // Support of pre-2.0 modules if ($bImgTag && ($sIcon != '')) { $sIcon = ""; } @@ -498,7 +498,7 @@ abstract class MetaModel $oStyle = new ormStyle("ibo-class-style--$sClass", "ibo-class-style-alt--$sClass"); } - if ((utils::StrLen($oStyle->GetMainColor()) > 0) && (utils::StrLen($oStyle->GetComplementaryColor()) > 0) && (utils::StrLen($oStyle->GetIconAsRelPath()) > 0)) { + if (utils::IsNotNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNotNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNotNullOrEmptyString($oStyle->GetIconAsRelPath())) { // all the parameters are set, no need to search in the parent classes return $oStyle; } @@ -508,18 +508,18 @@ abstract class MetaModel while (strlen($sParentClass) > 0) { $oParentStyle = self::GetClassStyle($sParentClass); if (!is_null($oParentStyle)) { - if (utils::StrLen($oStyle->GetMainColor()) == 0) { + if (utils::IsNullOrEmptyString($oStyle->GetMainColor())) { $oStyle->SetMainColor($oParentStyle->GetMainColor()); $oStyle->SetStyleClass($oParentStyle->GetStyleClass()); } - if (utils::StrLen($oStyle->GetComplementaryColor()) == 0) { + if (utils::IsNullOrEmptyString($oStyle->GetComplementaryColor())) { $oStyle->SetComplementaryColor($oParentStyle->GetComplementaryColor()); $oStyle->SetAltStyleClass($oParentStyle->GetAltStyleClass()); } - if (utils::StrLen($oStyle->GetIconAsRelPath()) == 0) { + if (utils::IsNullOrEmptyString($oStyle->GetIconAsRelPath())) { $oStyle->SetIcon($oParentStyle->GetIconAsRelPath()); } - if ((utils::StrLen($oStyle->GetMainColor()) > 0) && (utils::StrLen($oStyle->GetComplementaryColor()) > 0) && (utils::StrLen($oStyle->GetIconAsRelPath()) > 0)) { + if (utils::IsNotNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNotNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNotNullOrEmptyString($oStyle->GetIconAsRelPath())) { // all the parameters are set, no need to search in the parent classes return $oStyle; } @@ -527,7 +527,7 @@ abstract class MetaModel $sParentClass = self::GetParentPersistentClass($sParentClass); } - if ((utils::StrLen($oStyle->GetMainColor()) == 0) && (utils::StrLen($oStyle->GetComplementaryColor()) == 0) && (utils::StrLen($oStyle->GetIconAsRelPath()) == 0)) { + if (utils::IsNullOrEmptyString($oStyle->GetMainColor()) && utils::IsNullOrEmptyString($oStyle->GetComplementaryColor()) && utils::IsNullOrEmptyString($oStyle->GetIconAsRelPath())) { return null; } @@ -2250,17 +2250,14 @@ abstract class MetaModel $aNeighbourData['sFromClass'] = $aNeighbourData['sDefinedInClass']; try { - if (strlen($aNeighbourData['sQueryDown']) == 0) - { + if (Utils::StrLen($aNeighbourData['sQueryDown']) == 0) { $oAttDef = self::GetAttributeDef($sClass, $aNeighbourData['sAttribute']); - if ($oAttDef instanceof AttributeExternalKey) - { + if ($oAttDef instanceof AttributeExternalKey) { $sTargetClass = $oAttDef->GetTargetClass(); $aNeighbourData['sToClass'] = $sTargetClass; $aNeighbourData['sQueryDown'] = 'SELECT '.$sTargetClass.' AS o WHERE o.id = :this->'.$aNeighbourData['sAttribute']; $aNeighbourData['sQueryUp'] = 'SELECT '.$aNeighbourData['sFromClass'].' AS o WHERE o.'.$aNeighbourData['sAttribute'].' = :this->id'; - } - elseif ($oAttDef instanceof AttributeLinkedSet) + } elseif ($oAttDef instanceof AttributeLinkedSet) { $sLinkedClass = $oAttDef->GetLinkedClass(); $sExtKeyToMe = $oAttDef->GetExtKeyToMe(); @@ -5004,27 +5001,23 @@ abstract class MetaModel */ public static function DBShowApplyForm($sRepairUrl, $sSQLStatementArgName, $aSQLFixes) { - if (empty($sRepairUrl)) - { + if (empty($sRepairUrl)) { return; } // By design, some queries might be blank, we have to ignore them $aCleanFixes = array(); - foreach($aSQLFixes as $sSQLFix) - { - if (!empty($sSQLFix)) - { + foreach ($aSQLFixes as $sSQLFix) { + if (!empty($sSQLFix)) { $aCleanFixes[] = $sSQLFix; } } - if (count($aCleanFixes) == 0) - { + if (count($aCleanFixes) == 0) { return; } echo "
\n"; - echo " \n"; + echo " \n"; echo " \n"; echo "
\n"; } @@ -5270,24 +5263,21 @@ abstract class MetaModel $sRes = ''; $sRes .= "// Dictionnay conventions\n"; - $sRes .= htmlentities("// Class:\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:+\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:/Attribute:\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:/Attribute:+\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:/Attribute:/Value:\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:/Attribute:/Value:+\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:/Stimulus:\n", ENT_QUOTES, 'UTF-8'); - $sRes .= htmlentities("// Class:/Stimulus:+\n", ENT_QUOTES, 'UTF-8'); + $sRes .= utils::EscapeHtml("// Class:\n"); + $sRes .= utils::EscapeHtml("// Class:+\n"); + $sRes .= utils::EscapeHtml("// Class:/Attribute:\n"); + $sRes .= utils::EscapeHtml("// Class:/Attribute:+\n"); + $sRes .= utils::EscapeHtml("// Class:/Attribute:/Value:\n"); + $sRes .= utils::EscapeHtml("// Class:/Attribute:/Value:+\n"); + $sRes .= utils::EscapeHtml("// Class:/Stimulus:\n"); + $sRes .= utils::EscapeHtml("// Class:/Stimulus:+\n"); $sRes .= "\n"; // Note: I did not use EnumCategories(), because a given class maybe found in several categories // Need to invent the "module", to characterize the origins of a class - if (strlen($sModules) == 0) - { + if (strlen($sModules) == 0) { $aModules = array('bizmodel', 'core/cmdb', 'gui', 'application', 'addon/userrights'); - } - else - { + } else { $aModules = explode(', ', $sModules); } @@ -5295,17 +5285,14 @@ abstract class MetaModel $sRes .= "// Note: The classes have been grouped by categories: ".implode(', ', $aModules)."\n"; $sRes .= "//////////////////////////////////////////////////////////////////////\n"; - foreach($aModules as $sCategory) - { + foreach ($aModules as $sCategory) { $sRes .= "//////////////////////////////////////////////////////////////////////\n"; $sRes .= "// Classes in '$sCategory'\n"; $sRes .= "//////////////////////////////////////////////////////////////////////\n"; $sRes .= "//\n"; $sRes .= "\n"; - foreach(self::GetClasses($sCategory) as $sClass) - { - if (!self::HasTable($sClass)) - { + foreach (self::GetClasses($sCategory) as $sClass) { + if (!self::HasTable($sClass)) { continue; } @@ -7042,30 +7029,26 @@ abstract class MetaModel */ public static function GetHyperLink($sTargetClass, $iKey) { - if ($iKey < 0) - { + if ($iKey < 0) { return "$sTargetClass: $iKey (invalid value)"; } $oObj = self::GetObject($sTargetClass, $iKey, false); - if (is_null($oObj)) - { + if (is_null($oObj)) { // Whatever we are looking for, the root class is the key to search for $sRootClass = self::GetRootClass($sTargetClass); $oSearch = DBObjectSearch::FromOQL('SELECT CMDBChangeOpDelete WHERE objclass = :objclass AND objkey = :objkey', array('objclass' => $sRootClass, 'objkey' => $iKey)); $oSet = new DBObjectSet($oSearch); $oRecord = $oSet->Fetch(); // An empty fname is obtained with iTop < 2.0 - if (is_null($oRecord) || (strlen(trim($oRecord->Get('fname'))) == 0)) - { + if (is_null($oRecord) || (strlen(trim($oRecord->Get('fname'))) == 0)) { $sName = Dict::Format('Core:UnknownObjectLabel', $sTargetClass, $iKey); $sTitle = Dict::S('Core:UnknownObjectTip'); - } - else - { + } else { $sName = $oRecord->Get('fname'); $sTitle = Dict::Format('Core:DeletedObjectTip', $oRecord->Get('date'), $oRecord->Get('userinfo')); } - return ''.htmlentities($sName, ENT_QUOTES, 'UTF-8').''; + + return ''.utils::EscapeHtml($sName).''; } return $oObj->GetHyperLink(); } @@ -7307,14 +7290,11 @@ abstract class MetaModel $aSearches = array(); $aReplacements = array(); - foreach ($aParams as $sSearch => $replace) - { + foreach ($aParams as $sSearch => $replace) { // Some environment parameters are objects, we just need scalars - if (is_object($replace)) - { + if (is_object($replace)) { $iPos = strpos($sSearch, '->object()'); - if ($iPos !== false) - { + if ($iPos !== false) { // Expand the parameters for the object $sName = substr($sSearch, 0, $iPos); // Note: Capturing @@ -7322,63 +7302,67 @@ abstract class MetaModel // 2 - The arrow // 3 - The attribute code $aRegExps = array( - '/(\\$)'.$sName.'-(>|>)([^\\$]+)\\$/', // Support both syntaxes: $this->xxx$ or $this->xxx$ for HTML compatibility - '/(%24)'.$sName.'-(>|>)([^%24]+)%24/', // Support for urlencoded in HTML attributes (%20this->xxx%20) - ); - foreach($aRegExps as $sRegExp) - { - if(preg_match_all($sRegExp, $sInput, $aMatches)) - { - foreach($aMatches[3] as $idx => $sPlaceholderAttCode) - { - try - { - $sReplacement = $replace->GetForTemplate($sPlaceholderAttCode); - if($sReplacement !== null) - { - $aReplacements[] = $sReplacement; - $aSearches[] = $aMatches[1][$idx] . $sName . '-' . $aMatches[2][$idx] . $sPlaceholderAttCode . $aMatches[1][$idx]; - } - } - catch(Exception $e) - { - // No replacement will occur - } - } - } - } - } - else - { + '/(\\$)'.$sName.'-(>|>)([^\\$]+)\\$/', // Support both syntaxes: $this->xxx$ or $this->xxx$ for HTML compatibility + '/(%24)'.$sName.'-(>|>)([^%24]+)%24/', // Support for urlencoded in HTML attributes (%20this->xxx%20) + ); + foreach ($aRegExps as $sRegExp) { + if (preg_match_all($sRegExp, $sInput, $aMatches)) { + foreach ($aMatches[3] as $idx => $sPlaceholderAttCode) { + try { + $sReplacement = $replace->GetForTemplate($sPlaceholderAttCode); + if ($sReplacement !== null) { + $aReplacements[] = $sReplacement; + $aSearches[] = $aMatches[1][$idx].$sName.'-'.$aMatches[2][$idx].$sPlaceholderAttCode.$aMatches[1][$idx]; + } + } + catch (Exception $e) { + $aContext = [ + 'placeholder' => $sPlaceholderAttCode, + 'replace class' => get_class($replace), + ]; + if ($replace instanceof DBObject) { + $aContext['replace id'] = $replace->GetKey(); + } + IssueLog::Debug( + 'Invalid placeholder in notification, no replacement will occur!', + LogChannels::NOTIFICATIONS, + $aContext + ); + } + } + } + } + } else { continue; // Ignore this non-scalar value } - } - else - { + } else { $aRegExps = array( '/(\$)'.$sSearch.'\$/', // Support for regular placeholders (eg. $APP_URL$) '/(%24)'.$sSearch.'%24/', // Support for urlencoded in HTML attributes (eg. %24APP_URL%24) ); - foreach($aRegExps as $sRegExp) - { - if(preg_match_all($sRegExp, $sInput, $aMatches)) - { - foreach($aMatches[1] as $idx => $sDelimiter) - { - try - { - $aReplacements[] = (string) $replace; - $aSearches[] = $aMatches[1][$idx] . $sSearch . $aMatches[1][$idx]; + foreach ($aRegExps as $sRegExp) { + if (preg_match_all($sRegExp, $sInput, $aMatches)) { + foreach ($aMatches[1] as $idx => $sDelimiter) { + try { + $aReplacements[] = (string)$replace; + $aSearches[] = $aMatches[1][$idx].$sSearch.$aMatches[1][$idx]; } - catch(Exception $e) - { - // No replacement will occur + catch (Exception $e) { + IssueLog::Debug( + 'Invalid placeholder in notification, no replacement will occur !', + LogChannels::NOTIFICATIONS, + [ + 'placeholder' => $sPlaceholderAttCode, + 'replace' => $replace, + ] + ); } } } } } } + return str_replace($aSearches, $aReplacements, $sInput); } diff --git a/core/oql/oql-parser.php b/core/oql/oql-parser.php index 83fe29aa6..5bd6d1577 100644 --- a/core/oql/oql-parser.php +++ b/core/oql/oql-parser.php @@ -33,17 +33,19 @@ class OQLParser_yyToken implements ArrayAccess return $this->string; } - function offsetExists($offset) + function offsetExists($offset): bool { return isset($this->metadata[$offset]); } + // Return type mixed is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+ + #[\ReturnTypeWillChange] function offsetGet($offset) { return $this->metadata[$offset]; } - function offsetSet($offset, $value) + function offsetSet($offset, $value): void { if ($offset === null) { if (isset($value[0])) { @@ -66,7 +68,7 @@ class OQLParser_yyToken implements ArrayAccess } } - function offsetUnset($offset) + function offsetUnset($offset): void { unset($this->metadata[$offset]); } diff --git a/core/oql/oqlexception.class.inc.php b/core/oql/oqlexception.class.inc.php index f336bc4e3..81e771b27 100644 --- a/core/oql/oqlexception.class.inc.php +++ b/core/oql/oqlexception.class.inc.php @@ -58,22 +58,19 @@ class OQLException extends CoreException public function getHtmlDesc($sHighlightHtmlBegin = '', $sHighlightHtmlEnd = '') { - $sRet = htmlentities($this->m_MyIssue.", found '".$this->m_sUnexpected."' in: ", ENT_QUOTES, 'UTF-8'); - $sRet .= htmlentities(substr($this->m_sInput, 0, $this->m_iCol), ENT_QUOTES, 'UTF-8'); - $sRet .= $sHighlightHtmlBegin.htmlentities(substr($this->m_sInput, $this->m_iCol, strlen($this->m_sUnexpected)), ENT_QUOTES, 'UTF-8').$sHighlightHtmlEnd; - $sRet .= htmlentities(substr($this->m_sInput, $this->m_iCol + strlen($this->m_sUnexpected)), ENT_QUOTES, 'UTF-8'); + $sRet = utils::EscapeHtml($this->m_MyIssue.", found '".$this->m_sUnexpected."' in: "); + $sRet .= utils::EscapeHtml(substr($this->m_sInput, 0, $this->m_iCol)); + $sRet .= $sHighlightHtmlBegin.utils::EscapeHtml(substr($this->m_sInput, $this->m_iCol, strlen($this->m_sUnexpected))).$sHighlightHtmlEnd; + $sRet .= utils::EscapeHtml(substr($this->m_sInput, $this->m_iCol + strlen($this->m_sUnexpected))); - if (!is_null($this->m_aExpecting) && (count($this->m_aExpecting) > 0)) - { - if (count($this->m_aExpecting) < 30) - { + if (!is_null($this->m_aExpecting) && (count($this->m_aExpecting) > 0)) { + if (count($this->m_aExpecting) < 30) { $sExpectations = '{'.implode(', ', $this->m_aExpecting).'}'; - $sRet .= ", expecting ".htmlentities($sExpectations, ENT_QUOTES, 'UTF-8'); - } + $sRet .= ", expecting ".utils::EscapeHtml($sExpectations); + } $sSuggest = self::FindClosestString($this->m_sUnexpected, $this->m_aExpecting); - if (strlen($sSuggest) > 0) - { - $sRet .= ", I would suggest to use '$sHighlightHtmlBegin".htmlentities($sSuggest, ENT_QUOTES, 'UTF-8')."$sHighlightHtmlEnd'"; + if (strlen($sSuggest) > 0) { + $sRet .= ", I would suggest to use '$sHighlightHtmlBegin".utils::EscapeHtml($sSuggest)."$sHighlightHtmlEnd'"; } } diff --git a/core/ormStyle.class.inc.php b/core/ormStyle.class.inc.php index 8f3b02abf..dabbd59bd 100644 --- a/core/ormStyle.class.inc.php +++ b/core/ormStyle.class.inc.php @@ -50,7 +50,7 @@ class ormStyle */ public function HasMainColor(): bool { - return utils::StrLen($this->sMainColor) > 0; + return utils::IsNotNullOrEmptyString($this->sMainColor); } /** @@ -68,7 +68,7 @@ class ormStyle */ public function SetMainColor(?string $sMainColor) { - $this->sMainColor = (utils::StrLen($sMainColor) === 0) ? null : $sMainColor; + $this->sMainColor = utils::IsNullOrEmptyString($sMainColor) ? null : $sMainColor; return $this; } @@ -78,7 +78,7 @@ class ormStyle */ public function HasComplementaryColor(): bool { - return utils::StrLen($this->sComplementaryColor) > 0; + return utils::IsNotNullOrEmptyString($this->sComplementaryColor); } /** @@ -96,7 +96,7 @@ class ormStyle */ public function SetComplementaryColor(?string $sComplementaryColor) { - $this->sComplementaryColor = (utils::StrLen($sComplementaryColor) === 0) ? null : $sComplementaryColor; + $this->sComplementaryColor = utils::IsNullOrEmptyString($sComplementaryColor) ? null : $sComplementaryColor; return $this; } @@ -116,7 +116,7 @@ class ormStyle */ public function HasStyleClass(): bool { - return utils::StrLen($this->sStyleClass) > 0; + return utils::IsNotNullOrEmptyString($this->sStyleClass); } /** @@ -134,7 +134,7 @@ class ormStyle */ public function SetStyleClass(?string $sStyleClass) { - $this->sStyleClass = (utils::StrLen($sStyleClass) === 0) ? null : $sStyleClass; + $this->sStyleClass = utils::IsNullOrEmptyString($sStyleClass) ? null : $sStyleClass; return $this; } @@ -144,7 +144,7 @@ class ormStyle */ public function HasAltStyleClass(): bool { - return utils::StrLen($this->sAltStyleClass) > 0; + return utils::IsNotNullOrEmptyString($this->sAltStyleClass); } /** @@ -162,7 +162,7 @@ class ormStyle */ public function SetAltStyleClass(?string $sAltStyleClass) { - $this->sAltStyleClass = (utils::StrLen($sAltStyleClass) === 0) ? null : $sAltStyleClass; + $this->sAltStyleClass = utils::IsNullOrEmptyString($sAltStyleClass) ? null : $sAltStyleClass; return $this; } @@ -172,7 +172,7 @@ class ormStyle */ public function HasDecorationClasses(): bool { - return utils::StrLen($this->sDecorationClasses) > 0; + return utils::IsNotNullOrEmptyString($this->sDecorationClasses); } /** @@ -190,7 +190,7 @@ class ormStyle */ public function SetDecorationClasses(?string $sDecorationClasses) { - $this->sDecorationClasses = (utils::StrLen($sDecorationClasses) === 0) ? null : $sDecorationClasses; + $this->sDecorationClasses = utils::IsNullOrEmptyString($sDecorationClasses) ? null : $sDecorationClasses; return $this; } @@ -200,7 +200,7 @@ class ormStyle */ public function HasIcon(): bool { - return utils::StrLen($this->sIcon) > 0; + return utils::IsNotNullOrEmptyString($this->sIcon); } /** @@ -210,7 +210,7 @@ class ormStyle */ public function SetIcon(?string $sIcon) { - $this->sIcon = (utils::StrLen($sIcon) === 0) ? null : $sIcon; + $this->sIcon = utils::IsNullOrEmptyString($sIcon) ? null : $sIcon; return $this; } diff --git a/core/ormcaselog.class.inc.php b/core/ormcaselog.class.inc.php index 950ff0627..de90d241e 100644 --- a/core/ormcaselog.class.inc.php +++ b/core/ormcaselog.class.inc.php @@ -252,7 +252,7 @@ class ormCaseLog { if (!array_key_exists('format', $aIndex[$index]) || ($aIndex[$index]['format'] == static::ENUM_FORMAT_TEXT)) { $sCSSClass = 'caselog_entry'; - $sTextEntry = str_replace(array("\r\n", "\n", "\r"), "
", htmlentities($sTextEntry, ENT_QUOTES, 'UTF-8')); + $sTextEntry = str_replace(array("\r\n", "\n", "\r"), "
", utils::EscapeHtml($sTextEntry)); } else { @@ -292,19 +292,15 @@ class ormCaseLog { } // Process the case of an eventual remainder (quick migration of AttributeText fields) - if ($iPos < (strlen($this->m_sLog) - 1)) - { + if ($iPos < (strlen($this->m_sLog) - 1)) { $sTextEntry = substr($this->m_sLog, $iPos); - $sTextEntry = str_replace(array("\r\n", "\n", "\r"), "
", htmlentities($sTextEntry, ENT_QUOTES, 'UTF-8')); + $sTextEntry = str_replace(array("\r\n", "\n", "\r"), "
", utils::EscapeHtml($sTextEntry)); - if (count($this->m_aIndex) == 0) - { + if (count($this->m_aIndex) == 0) { $sHtml .= '
'; $sHtml .= $sTextEntry; $sHtml .= '
'; - } - else - { + } else { $sHtml .= '
'; $sHtml .= Dict::S('UI:CaseLog:InitialValue'); $sHtml .= '
'; @@ -327,24 +323,18 @@ class ormCaseLog { $sHtml = '

', - 'UI:WelcomeMenu:Text'=> '
Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!
+ 'UI:WelcomeMenu:Text'=> '
Felicidades, se encuentra en '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!
-
This version features a brand new modern and accessible backoffice design.
+
Esta versión cuenta con un moderno diseño accesible y receptivo.
-
We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them. -We hope you’ll enjoy this version as much as we enjoyed imagining and creating it.
+
Mantuvimos en '.ITOP_APPLICATION.' las funciones bĂĄsicas que le gustan y se modernizaron. +Esperamos distrute de esta versiĂłn tanto como nosotros la imaginamos y creamos.
-
Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.
~~', +
Configure las preferencias de '.ITOP_APPLICATION.' para una experiencia personalizada.
', 'UI:WelcomeMenu:AllOpenRequests' => 'Requerimientos Abiertos: %1$d', 'UI:WelcomeMenu:MyCalls' => 'Mis Requerimientos', 'UI:WelcomeMenu:OpenIncidents' => 'Incidentes Abiertos: %1$d', @@ -389,17 +389,17 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Button:Logoff' => 'Cerrar SesiĂłn', 'UI:Button:GlobalSearch' => 'Buscar', 'UI:Button:Search' => 'Buscar', - 'UI:Button:Clear' => ' Clear ~~', - 'UI:Button:SearchInHierarchy' => 'Search in hierarchy~~', + 'UI:Button:Clear' => ' Limpiar', + 'UI:Button:SearchInHierarchy' => 'Buscar en JerarquĂ­a', 'UI:Button:Query' => 'Consultar', 'UI:Button:Ok' => 'Aceptar', 'UI:Button:Save' => 'Guardar', - 'UI:Button:SaveAnd' => 'Save and %1$s~~', + 'UI:Button:SaveAnd' => 'Guardar y %1$s', 'UI:Button:Cancel' => 'Cancelar', 'UI:Button:Close' => 'Cerrar', 'UI:Button:Apply' => 'Aplicar', - 'UI:Button:Send' => 'Send~~', - 'UI:Button:SendAnd' => 'Send and %1$s~~', + 'UI:Button:Send' => 'Enviar', + 'UI:Button:SendAnd' => 'Enviar y %1$s', 'UI:Button:Back' => '<< Anterior', 'UI:Button:Restart' => '|<< Reiniciar', 'UI:Button:Next' => 'Siguiente >>', @@ -422,19 +422,19 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Button:ChangePassword' => 'Cambiar Contraseña', 'UI:Button:ResetPassword' => 'Restablecer Contraseña', 'UI:Button:Insert' => 'Insertar', - 'UI:Button:More' => 'MĂĄs', + 'UI:Button:More' => 'Mas', 'UI:Button:Less' => 'Menos', - 'UI:Button:Wait' => 'Por favor espere mientras se actualizan los campos', + 'UI:Button:Wait' => 'Espere mientras se actualizan los campos', 'UI:Treeview:CollapseAll' => 'Contraer Todo', 'UI:Treeview:ExpandAll' => 'Expandir Todo', - 'UI:UserPref:DoNotShowAgain' => 'Do not show again~~', - 'UI:InputFile:NoFileSelected' => 'No File Selected~~', - 'UI:InputFile:SelectFile' => 'Select a file~~', + 'UI:UserPref:DoNotShowAgain' => 'No mostrar otra vez', + 'UI:InputFile:NoFileSelected' => 'NingĂșn Archivo seleccionado', + 'UI:InputFile:SelectFile' => 'Seleccionar un archivo', 'UI:SearchToggle' => 'Buscar', 'UI:ClickToCreateNew' => 'Crear %1$s', 'UI:SearchFor_Class' => 'Buscar %1$s', - 'UI:NoObjectToDisplay' => 'Ninguna InformaciĂłn por Visualizar.', + 'UI:NoObjectToDisplay' => 'Ninguna informaciĂłn por visualizar.', 'UI:Error:SaveFailed' => 'El objeto no puede ser guardado :', 'UI:Error:MandatoryTemplateParameter_object_id' => 'El parĂĄmetro object_id es obligatorio cuando link_attr es especificado. Verifique la definiciĂłn de la plantilla de visualizaciĂłn.', 'UI:Error:MandatoryTemplateParameter_target_attr' => 'El parĂĄmetro target_attr es obligatorio cuando link_attr es especificado. Verifique la definiciĂłn de la plantilla de visualizaciĂłn.', @@ -462,7 +462,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Error:ObjectsAlreadyDeleted' => 'Error: los objetos ya han sido borrados!', 'UI:Error:BulkDeleteNotAllowedOn_Class' => 'No esta autorizado a borrar un lote de de objetos de la clase %1$s', 'UI:Error:DeleteNotAllowedOn_Class' => 'No esta autorizado a borrar objetos del la clase %1$s', - 'UI:Error:ReadNotAllowedOn_Class' => 'You are not allowed to view objects of class %1$s~~', + 'UI:Error:ReadNotAllowedOn_Class' => 'No tiene permitido visualizar objetos de la clase %1$s', 'UI:Error:BulkModifyNotAllowedOn_Class' => 'No esta autorizado a actualizar un lote de de objetos de la clase %1$s', 'UI:Error:ObjectAlreadyCloned' => 'Error: el objeto ha sido previamente duplicado!', 'UI:Error:ObjectAlreadyCreated' => 'Error: el objeto ha sido previamente creado!', @@ -471,8 +471,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Error:InvalidDashboard' => 'Error: Dashboard invĂĄlido', 'UI:Error:MaintenanceMode' => 'La aplicaciĂłn se encuentra actualmente en mantenimiento', 'UI:Error:MaintenanceTitle' => 'Mantenimiento', - 'UI:Error:InvalidToken' => 'Error: the requested operation has already been performed (CSRF token not found)~~', - + 'UI:Error:InvalidToken' => 'Error: La operaciĂłn solicitada ya se habia realizado (CSRF token not found)', 'UI:Error:SMTP:UnknownVendor' => 'OAuth SMTP provider %1$s does not exist (email_transport_smtp.oauth.provider)~~', 'UI:GroupBy:Count' => 'Cuenta', @@ -501,8 +500,8 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Loading' => 'Cargando', 'UI:Menu:Actions' => 'Acciones', 'UI:Menu:OtherActions' => 'Otras Acciones', - 'UI:Menu:Transitions' => 'Transitions~~', - 'UI:Menu:OtherTransitions' => 'Other Transitions~~', + 'UI:Menu:Transitions' => 'Transiciones', + 'UI:Menu:OtherTransitions' => 'Otras Transiciones', 'UI:Menu:New' => 'Nuevo', 'UI:Menu:Add' => 'Agregar', 'UI:Menu:Manage' => 'Administrar', @@ -542,7 +541,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Login:ForgotPwdForm+' => ITOP_APPLICATION_SHORT.' puede enviarle un correo en el cual encontrarĂĄ las instrucciones a seguir para restablecer su contraseña.', 'UI:Login:ResetPassword' => 'Enviar Ahora', 'UI:Login:ResetPwdFailed' => 'Error al enviar correo-e: %1$s', - 'UI:Login:SeparatorOr' => 'Or~~', + 'UI:Login:SeparatorOr' => 'O', 'UI:ResetPwd-Error-WrongLogin' => '\'%1$s\' no es un usuario vĂĄlido', 'UI:ResetPwd-Error-NotPossible' => 'Cuentas externas no permiten restablecimiento de contraseña.', @@ -631,7 +630,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:CSVImport:CommentsAndHeader' => 'Comentarios y encabezado', 'UI:CSVImport:SelectClass' => 'Seleccione la clase a importar:', 'UI:CSVImport:AdvancedMode' => 'Modo Avanzado', - 'UI:CSVImport:AdvancedMode+' => 'En modo avanzado el "id" (clave primaria) de los objetos puede ser usado para actualizar y renombrar objetos.Sin embargo, la columna "id" (si esta presente) solo puede ser usado como criterio de busqueda y no puede ser combinado con ningun otro criterio de busqueda.', + 'UI:CSVImport:AdvancedMode+' => 'En modo avanzado el "id" (clave primaria) de los objetos puede ser usado para actualizar y renombrar objetos. Sin embargo, la columna "id" (si esta presente) solo puede ser usado como criterio de bĂșsqueda y no puede ser combinado con ningun otro criterio de bĂșsqueda.', 'UI:CSVImport:SelectAClassFirst' => 'Para configurar el mapeo, primero seleccione un clase.', 'UI:CSVImport:HeaderFields' => 'Campos', 'UI:CSVImport:HeaderMappings' => 'Mapeo', @@ -690,34 +689,34 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:CSVExport:LostChars' => 'Errores de CĂłdigo de Caracteres', 'UI:CSVExport:LostChars+' => 'El archivo descargado serĂĄ codificado a %1$s. '.ITOP_APPLICATION_SHORT.' detectĂł alguos caracteres que no son compatibles con este formato. Esos caracteres serĂĄn reemplazados por un sustituto (ejem.: caracteres sin acento), o serĂĄn descartados. Puede copiar/pegar datos desde su navegador de internet. Alternativamente, puede contactar al administrador para cambiar el cĂłdigo de caracteres (Ver parĂĄmetro \'csv_file_default_charset\').', - 'UI:Audit:Title' => ITOP_APPLICATION_SHORT.' - Auditoria a CMDB', - 'UI:Audit:InteractiveAudit' => 'Auditoria Interactiva', - 'UI:Audit:HeaderAuditRule' => 'Reglas de Auditoria', + 'UI:Audit:Title' => ITOP_APPLICATION_SHORT.' - AuditorĂ­a a CMDB', + 'UI:Audit:InteractiveAudit' => 'AuditorĂ­a Interactiva', + 'UI:Audit:HeaderAuditRule' => 'Reglas de AuditorĂ­a', 'UI:Audit:HeaderNbObjects' => '# Objetos', 'UI:Audit:HeaderNbErrors' => '# Errores', 'UI:Audit:PercentageOk' => '% Ok', - 'UI:Audit:OqlError' => 'OQL Error~~', - 'UI:Audit:Error:ValueNA' => 'n/a~~', - 'UI:Audit:ErrorIn_Rule' => 'Error in Rule~~', + 'UI:Audit:OqlError' => 'Error OQL', + 'UI:Audit:Error:ValueNA' => 'N/A', + 'UI:Audit:ErrorIn_Rule' => 'Error en Regla', 'UI:Audit:ErrorIn_Rule_Reason' => 'Error de OQL en la Regla %1$s: %2$s.', - 'UI:Audit:ErrorIn_Category' => 'Error in Category~~', + 'UI:Audit:ErrorIn_Category' => 'Error en CategorĂ­a', 'UI:Audit:ErrorIn_Category_Reason' => 'Error de OQL en la CategorĂ­a %1$s: %2$s.', - 'UI:Audit:AuditErrors' => 'Audit Errors~~', - 'UI:Audit:Dashboard:ObjectsAudited' => 'Objects audited~~', - 'UI:Audit:Dashboard:ObjectsInError' => 'Objects in errors~~', - 'UI:Audit:Dashboard:ObjectsValidated' => 'Objects validated~~', - 'UI:Audit:AuditCategory:Subtitle' => '%1$s errors ouf of %2$s - %3$s%%~~', + 'UI:Audit:AuditErrors' => 'Errores de AuditorĂ­a', + 'UI:Audit:Dashboard:ObjectsAudited' => 'Objetos Auditados', + 'UI:Audit:Dashboard:ObjectsInError' => 'Objetos con Error', + 'UI:Audit:Dashboard:ObjectsValidated' => 'Objetos VĂĄlidos', + 'UI:Audit:AuditCategory:Subtitle' => '%1$s errores de %2$s - %3$s%%', 'UI:RunQuery:Title' => ITOP_APPLICATION_SHORT.' - EvaluaciĂłn de consultas OQL', 'UI:RunQuery:QueryExamples' => 'Explorador de Consultas', - 'UI:RunQuery:QueryResults' => 'Query Results~~', + 'UI:RunQuery:QueryResults' => 'Resultados de Consulta', 'UI:RunQuery:HeaderPurpose' => 'PropĂłsito', 'UI:RunQuery:HeaderPurpose+' => 'ExplicaciĂłn acerca de la consulta', 'UI:RunQuery:HeaderOQLExpression' => 'ExpresiĂłn OQL', 'UI:RunQuery:HeaderOQLExpression+' => 'La consulta en sintĂĄxis OQL', 'UI:RunQuery:ExpressionToEvaluate' => 'ExpresiĂłn a evaluar: ', - 'UI:RunQuery:QueryArguments' => 'Query Arguments~~', + 'UI:RunQuery:QueryArguments' => 'Argumentos de Consulta', 'UI:RunQuery:MoreInfo' => 'MĂĄs informaciĂłn acerca de la consulta: ', 'UI:RunQuery:DevelopedQuery' => 'ExpresiĂłn de consulta rediseñada: ', 'UI:RunQuery:SerializedFilter' => 'Filtro de serializaciĂłn: ', @@ -729,7 +728,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Query:UrlForExcel' => 'URL para usarse en consultas web de MS-Excel', 'UI:Query:UrlV1' => 'La lista de campos se ha dejado sin especificaciĂłn. La pĂĄgina export-V2.php no puede ser invocada sin estĂĄ informaciĂłn. Por lo tanto, el URL sugerido abajo apunta a la pĂĄgina legada: export.php. Esta versiĂłn legada de exportaciĂłn tiene la siguiente limitaciĂłn: la lista de campos exportados puede variar, dependiendo del formato de salida y el modelo de datos de '.ITOP_APPLICATION_SHORT.'. Desea garantizar que la lista de columnas exportadas permanenzcan estables durante la ejecuciĂłn, entonces debe especificar un valor para el atributo "Campos" y utilice la pĂĄgina export-V2.php.', 'UI:Schema:Title' => 'Esquema de Objetos en '.ITOP_APPLICATION_SHORT, - 'UI:Schema:TitleForClass' => 'Esquema de %1$s~~', + 'UI:Schema:TitleForClass' => 'Esquema de %1$s', 'UI:Schema:CategoryMenuItem' => 'Categoria %1$s', 'UI:Schema:Relationships' => 'Relaciones', 'UI:Schema:AbstractClass' => 'Clase Abstracta: NingĂșn objeto de esta clase puede ser representado.', @@ -796,9 +795,9 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Schema:Attribute/Filter' => 'Filtro', 'UI:Schema:DefaultNullValue' => 'Nulo por OmisiĂłn : "%1$s"', 'UI:LinksWidget:Autocomplete+' => 'Escriba los primeros 3 caracteres...', - 'UI:Edit:SearchQuery' => 'Select a predefined query~~', + 'UI:Edit:SearchQuery' => 'Selecciona una consulta predefinida', 'UI:Edit:TestQuery' => 'Consulta de Prueba', - 'UI:Combo:SelectValue' => '--- seleccione un valor ---', + 'UI:Combo:SelectValue' => '--- Seleccione un valor ---', 'UI:Label:SelectedObjects' => 'Objetos seleccionados: ', 'UI:Label:AvailableObjects' => 'Objetos disponibles: ', 'UI:Link_Class_Attributes' => '%1$s atributos', @@ -808,7 +807,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:ManageObjectsOf_Class_LinkedWith_Class_Instance' => 'Administrar %1$s objetos vinculados con %2$s: %3$s', 'UI:AddLinkedObjectsOf_Class' => 'Agregar %1$s', 'UI:RemoveLinkedObjectsOf_Class' => 'Eliminar Seleccionados', - 'UI:Message:EmptyList:UseAdd' => 'La lista esta vacĂ­a, use el botĂłn "Agregar" para añadir elementos.', + 'UI:Message:EmptyList:UseAdd' => 'La lista estĂĄ vacĂ­a, use el botĂłn "Crear ..." para añadir elementos.', 'UI:Message:EmptyList:UseSearchForm' => 'Use la forma arriba para buscar objetos a ser agregados.', 'UI:Wizard:FinalStepTitle' => 'Paso Final: ConfirmaciĂłn', 'UI:Title:DeletionOf_Object' => 'Borrado de %1$s', @@ -909,29 +908,32 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:UserManagement:Action:BulkDelete+' => 'eliminaciĂłn masiva de objetos', 'UI:UserManagement:Action:Stimuli' => 'Stimuli', 'UI:UserManagement:Action:Stimuli+' => 'Acciones (compound) permitidas', - 'UI:UserManagement:Action' => 'Action~~', - 'UI:UserManagement:Action+' => 'Action performed by the user~~', - 'UI:UserManagement:TitleActions' => 'Actions~~', - 'UI:UserManagement:Permission' => 'Permission~~', - 'UI:UserManagement:Permission+' => 'User\'s permissions~~', - 'UI:UserManagement:Attributes' => 'Attributes~~', - 'UI:UserManagement:ActionAllowed:Yes' => 'Yes~~', - 'UI:UserManagement:ActionAllowed:No' => 'No~~', - 'UI:UserManagement:AdminProfile+' => 'Administrators have full read/write access to all objects in the database.~~', + 'UI:UserManagement:Action' => 'AcciĂłn', + 'UI:UserManagement:Action+' => 'AcciĂłn ejecutada por el usuario', + 'UI:UserManagement:TitleActions' => 'Acciones', + 'UI:UserManagement:Permission' => 'Permisos', + 'UI:UserManagement:Permission+' => 'Permisos de usuario', + 'UI:UserManagement:Attributes' => 'Atributos', + 'UI:UserManagement:ActionAllowed:Yes' => 'Si', + 'UI:UserManagement:ActionAllowed:No' => 'No', + 'UI:UserManagement:AdminProfile+' => 'Los administradores tienen acceso total de lectura/escritura para todos los objetos en la base de datos.', 'UI:UserManagement:NoLifeCycleApplicable' => 'N/A', 'UI:UserManagement:NoLifeCycleApplicable+' => 'No se ha definido ciclo de vida para esta clase', 'UI:UserManagement:GrantMatrix' => 'Matriz de Acceso', + 'UI:UserManagement:LinkBetween_User_And_Profile' => 'Vinculo entre %1$s y %2$s', + 'UI:UserManagement:LinkBetween_User_And_Org' => 'VĂ­nculo entre %1$s y %2$s', 'Menu:AdminTools' => 'Herramientas Administrativas',// Duplicated into itop-welcome-itil (will be removed from here...) 'Menu:AdminTools+' => 'Herramientas Administrativas',// Duplicated into itop-welcome-itil (will be removed from here...) 'Menu:AdminTools?' => 'Herramientas accesibles sĂłlo a usuarios con Perfil de administrador',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:SystemTools' => 'System~~', + 'Menu:SystemTools' => 'Sistema', 'UI:ChangeManagementMenu' => 'Control de Cambios', 'UI:ChangeManagementMenu+' => '', 'UI:ChangeManagementMenu:Title' => 'Resumen de Cambios', 'UI-ChangeManagementMenu-ChangesByType' => 'Cambios por Tipo', 'UI-ChangeManagementMenu-ChangesByStatus' => 'Cambios por Estatus', + 'UI-ChangeManagementMenu-ChangesByWorkgroup' => 'Cambios por Grupo de Trabajo', 'UI-ChangeManagementMenu-ChangesNotYetAssigned' => 'Cambios No Asignados AĂșn', 'UI:ConfigurationManagementMenu' => 'AdministraciĂłn de la ConfiguraciĂłn', @@ -960,7 +962,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI-ChangeManagementOverview-ChangeWithOutage' => 'Interrupciones de Servicios debida a Cambios', 'UI:ServiceMgmtMenuOverview:Title' => 'Panel de Control para AdministraciĂłn de Servicios', - 'UI-ServiceManagementOverview-CustomerContractToRenew' => 'Contratos de Clientes a ser Renovados en 30 dĂ­as', + 'UI-ServiceManagementOverview-CustomerContractToRenew' => 'Acuerdos con Clientes a ser Renovados en 30 dĂ­as', 'UI-ServiceManagementOverview-ProviderContractToRenew' => 'Contratos de Proveedores a ser Renovados en 30 dĂ­as', 'UI:ContactsMenu' => 'Contactos', @@ -970,17 +972,17 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI-ContactsMenu-ContactsByType' => 'Contactos por Tipo', 'UI-ContactsMenu-ContactsByStatus' => 'Contactos por Estatus', - 'Menu:CSVImportMenu' => 'Importar CSV',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:CSVImportMenu+' => 'CreaciĂłn o ActualizaciĂłn MĂĄsiva',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:CSVImportMenu' => 'Importar CSV', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:CSVImportMenu+' => 'CreaciĂłn o ActualizaciĂłn MĂĄsiva', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:DataModelMenu' => 'Modelo de Datos',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:DataModelMenu+' => 'Resumen del Modelo de Datos',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:DataModelMenu' => 'Modelo de Datos', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:DataModelMenu+' => 'Resumen del Modelo de Datos', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:ExportMenu' => 'Exportar',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:ExportMenu+' => 'Exportar los Resultados de Cualquier Consulta en HTML, CSV o XML',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:ExportMenu' => 'Exportar', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:ExportMenu+' => 'Exportar los Resultados de Cualquier Consulta en HTML, CSV o XML', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:NotificationsMenu' => 'Notificaciones',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:NotificationsMenu+' => 'ConfiguraciĂłn de las Notificaciones',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:NotificationsMenu' => 'Notificaciones', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:NotificationsMenu+' => 'ConfiguraciĂłn de las Notificaciones', // Duplicated into itop-welcome-itil (will be removed from here...) 'UI:NotificationsMenu:Title' => 'ConfiguraciĂłn de las Notificaciones', 'UI:NotificationsMenu:Help' => 'Ayuda', 'UI:NotificationsMenu:HelpContent' => '

En '.ITOP_APPLICATION_SHORT.' las notificaciones son completamente personalizables. EstĂĄn basadas en dos conjuntos de objetos: Disparadores y Acciones.

@@ -994,62 +996,58 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating

-Las Acciones define the actions to be performed when the triggers execute. For now there are only two kind of actions: -

    -
  1. Sending an email message: Such actions also define the template to be used for sending the email as well as the other parameters of the message like the recipients, importance, etc.
    +Las Acciones definen las acciones a ser ejecutadas cuando los disparadores se ejecutan, por ahora los tipos de acciĂłn son +
      +
    1. Enviar un mensaje de correo: Dichas acciones también definen la plantilla que se utilizarå para enviar el correo electrónico, así como los demås paråmetros del mensaje, como los destinatarios, la importancia, etc.
      Una pĂĄgina especial:
      email.test.php estĂĄ disponible para probar y diagnosticar su configuraciĂłn de correo de PHP.
    2. -
    3. Outgoing webhooks: Allow integration with a third-party application by sending structured data to a defined URL.
    4. +
    5. Webhooks de Salida: permite la integraciĂłn con una aplicaciĂłn de terceros mediante el envĂ­o de datos estructurados a una URL definida.

    Para ser ejecutadas, las acciones deben estar asociadas con los disparadores. -Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", esto especifica en que orden se ejecutaran las acciones.

    ~~', +Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", esto especifica en que orden se ejecutaran las acciones.

    ', 'UI:NotificationsMenu:Triggers' => 'Disparadores', 'UI:NotificationsMenu:AvailableTriggers' => 'Disparadores disponibles', 'UI:NotificationsMenu:OnCreate' => 'Cuando un objeto es creado', 'UI:NotificationsMenu:OnStateEnter' => 'Cuando un objeto entra a un estado especĂ­fico', 'UI:NotificationsMenu:OnStateLeave' => 'Cuando un objeto sale de un estado especĂ­fico', 'UI:NotificationsMenu:Actions' => 'Acciones', - 'UI:NotificationsMenu:Actions:ActionEmail' => 'Email actions~~', - 'UI:NotificationsMenu:Actions:ActionWebhook' => 'Webhook actions (outgoing integrations)~~', - 'UI:NotificationsMenu:Actions:Action' => 'Other actions~~', + 'UI:NotificationsMenu:Actions:ActionEmail' => 'Acciones correo electrĂłnico', + 'UI:NotificationsMenu:Actions:ActionWebhook' => 'Acciones Webhook (Integraciones salientes)', + 'UI:NotificationsMenu:Actions:Action' => 'Otras acciones', 'UI:NotificationsMenu:AvailableActions' => 'Acciones Disponibles', 'Menu:TagAdminMenu' => 'ConfiguraciĂłn de Etiquetas', - 'Menu:TagAdminMenu+' => 'GestiĂłn de valores de Etiquetas', + 'Menu:TagAdminMenu+' => 'AdministraciĂłn de valores de Etiquetas', 'UI:TagAdminMenu:Title' => 'ConfiguraciĂłn de Etiquetas', 'UI:TagAdminMenu:NoTags' => 'No hay campos Etiquetas configurados', 'UI:TagSetFieldData:Error' => 'Error: %1$s', - 'Menu:AuditCategories' => 'Auditar CategorĂ­as',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:AuditCategories+' => 'Auditar CategorĂ­as',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:Notifications:Title' => 'Auditar CategorĂ­as',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:AuditCategories' => 'Auditar CategorĂ­as', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:AuditCategories+' => 'Auditar CategorĂ­as', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:Notifications:Title' => 'Auditar CategorĂ­as', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:RunQueriesMenu' => 'Ejecutar Consultas',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:RunQueriesMenu+' => 'Ejecutar Cualquier Consulta',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:RunQueriesMenu' => 'Ejecutar Consultas', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:RunQueriesMenu+' => 'Ejecutar Cualquier Consulta', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:QueryMenu' => 'Libreta de Consultas',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:QueryMenu+' => 'Libreta de Consultas',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:QueryMenu' => 'Libreta de Consultas', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:QueryMenu+' => 'Libreta de Consultas', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:DataAdministration' => 'AdministraciĂłn de Datos',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:DataAdministration+' => 'AdministraciĂłn de Datos',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:DataAdministration' => 'AdministraciĂłn de Datos', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:DataAdministration+' => 'AdministraciĂłn de Datos', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UniversalSearchMenu' => 'BĂșsqueda Universal',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UniversalSearchMenu+' => 'Buscar cualquier cosa',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UniversalSearchMenu' => 'BĂșsqueda Universal', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UniversalSearchMenu+' => 'Buscar cualquier cosa', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UserManagementMenu' => 'AdministraciĂłn de Usuarios',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UserManagementMenu+' => 'AdministraciĂłn de Usuarios',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UserManagementMenu' => 'AdministraciĂłn de Usuarios', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UserManagementMenu+' => 'AdministraciĂłn de Usuarios', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:ProfilesMenu' => 'Perfiles',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:ProfilesMenu+' => 'Perfiles',// Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:ProfilesMenu:Title' => 'Perfiles', - // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:ProfilesMenu' => 'Perfiles', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:ProfilesMenu+' => 'Perfiles', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:ProfilesMenu:Title' => 'Perfiles', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UserAccountsMenu' => 'Cuentas de Usuario', - // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UserAccountsMenu+' => 'Cuentas de Usuario', - // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:UserAccountsMenu:Title' => 'Cuentas de Usuario', - // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UserAccountsMenu' => 'Cuentas de Usuario', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UserAccountsMenu+' => 'Cuentas de Usuario', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:UserAccountsMenu:Title' => 'Cuentas de Usuario', // Duplicated into itop-welcome-itil (will be removed from here...) 'UI:iTopVersion:Short' => '%1$s versiĂłn %2$s', 'UI:iTopVersion:Long' => '%1$s versiĂłn %2$s-%3$s compilada en %4$s', @@ -1178,10 +1176,10 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:ArchiveMode:Banner+' => 'Objetos archivados son visibles, y ninguna modificaciĂłn es permitida', 'UI:FavoriteOrganizations' => 'Mi OrganizaciĂłn Favorita', 'UI:FavoriteOrganizations+' => 'Verifique en la siguiente lista de Organizaciones, la que necesite ver en los menues para un rĂĄpido acceso. Nota, esto no es una configuraciĂłn de seguridad, elementos de cualquier OrganizaciĂłn son visibles y pueden ser accesados mediante la selecciĂłn de "Todas las Organizaciones" en la lista del menĂș.', - 'UI:FavoriteLanguage' => 'Idioma de la Interfaz de Usuario~~', + 'UI:FavoriteLanguage' => 'Idioma de la Interfaz de Usuario', 'UI:Favorites:SelectYourLanguage' => 'Seleccione su Idioma Predeterminado', 'UI:FavoriteOtherSettings' => 'Otras Configuraciones', - 'UI:Favorites:Default_X_ItemsPerPage' => 'Tamaño Predeterminado de Listas: %1$s elementos por pĂĄgina~~', + 'UI:Favorites:Default_X_ItemsPerPage' => 'Tamaño Predeterminado de Listas: %1$s elementos por pĂĄgina', 'UI:Favorites:ShowObsoleteData' => 'Mostrar datos Obsoletos', 'UI:Favorites:ShowObsoleteData+' => 'Mostrar datos obsoletos en resultados de bĂșsqueda y listas de elementos seleccionables', 'UI:NavigateAwayConfirmationMessage' => 'Cualquier modificaciĂłn serĂĄ descartada.', @@ -1204,13 +1202,13 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:ConfigureThisList' => 'Configurar Lista', 'UI:ListConfigurationTitle' => 'ConfiguraciĂłn de Lista', 'UI:ColumnsAndSortOrder' => 'Columnas y Ordenamiento:', - 'UI:UseDefaultSettings' => 'Usar ConfiguraciĂłn por OmisiĂłn', + 'UI:UseDefaultSettings' => 'Usar ConfiguraciĂłn predeterminada', 'UI:UseSpecificSettings' => 'Usar la Siguiente ConfiguraciĂłn:', - 'UI:Display_X_ItemsPerPage_prefix' => 'Desplegar %1$s elementos por pĂĄgina', - 'UI:Display_X_ItemsPerPage_suffix' => 'elementos por pĂĄgina', + 'UI:Display_X_ItemsPerPage_prefix' => 'Desplegar ', + 'UI:Display_X_ItemsPerPage_suffix' => ' elementos por pĂĄgina', 'UI:UseSavetheSettings' => 'Guardar Configuraciones', 'UI:OnlyForThisList' => 'SĂłlo esta Lista', - 'UI:ForAllLists' => 'Defecto en todas las listas', + 'UI:ForAllLists' => 'Predeterminado en todas las listas', 'UI:ExtKey_AsLink' => '%1$s (Liga)', 'UI:ExtKey_AsFriendlyName' => '%1$s (Nombre ComĂșn)', 'UI:ExtField_AsRemoteField' => '%1$s (%2$s)', @@ -1220,16 +1218,16 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:OQL:UnknownClassAndFix' => 'Clase Desconocida "%1$s". Puede usar "%2$s" en su lugar.', 'UI:OQL:UnknownClassNoFix' => 'Clase Desconocida "%1$s"', - 'UI:Dashboard:EditCustom' => 'Editar esta PĂĄgina', - 'UI:Dashboard:CreateCustom' => 'Create a custom version...~~', - 'UI:Dashboard:DeleteCustom' => 'Regresar a VersiĂłn Original', - 'UI:Dashboard:RevertConfirm' => 'Todos los cambios realizados a la versiĂłn original se perderĂĄn. Por favor confime que quiere hacer esto.', - 'UI:ExportDashBoard' => 'Exportar a un Archivo', - 'UI:ImportDashBoard' => 'Importar de un Archivo', - 'UI:ImportDashboardTitle' => 'Importar de un Archivo', - 'UI:ImportDashboardText' => 'Seleccione el Archivo de Panel de Control a Importar:', - 'UI:Dashboard:Actions' => 'Dashboard actions~~', - 'UI:Dashboard:NotUpToDateUntilContainerSaved' => 'This dashboard displays information that does not include the on-going changes.~~', + 'UI:Dashboard:EditCustom' => 'Editar versiĂłn personalizada...', + 'UI:Dashboard:CreateCustom' => 'Crear versiĂłn personalizada...', + 'UI:Dashboard:DeleteCustom' => 'Borrar versiĂłn personalizada...', + 'UI:Dashboard:RevertConfirm' => 'Todos los cambios realizados a la versiĂłn original se perderan. Por favor confirmar que desea hacer esto.', + 'UI:ExportDashBoard' => 'Exportar a un archivo', + 'UI:ImportDashBoard' => 'Importar de un archivo', + 'UI:ImportDashboardTitle' => 'Importar de un archivo', + 'UI:ImportDashboardText' => 'Seleccione el archivo de Panel de Control a importar:', + 'UI:Dashboard:Actions' => 'Acciones en Panel de Control', + 'UI:Dashboard:NotUpToDateUntilContainerSaved' => 'Este panel de control muestra informaciĂłn que no incluye los cambios en curso', 'UI:DashletCreation:Title' => 'Crear Dashlet', @@ -1242,8 +1240,8 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:DashboardEdit:AutoReload' => 'ActualizaciĂłn AutomĂĄtica', 'UI:DashboardEdit:AutoReloadSec' => 'IntervĂĄlo de ActualizaciĂłn AutomĂĄtica (segundos)', 'UI:DashboardEdit:AutoReloadSec+' => 'El intervĂĄlo mĂ­nimo es de %1$d segundos', - 'UI:DashboardEdit:Revert' => 'Revert~~', - 'UI:DashboardEdit:Apply' => 'Apply~~', + 'UI:DashboardEdit:Revert' => 'Revertir', + 'UI:DashboardEdit:Apply' => 'Aplicar', 'UI:DashboardEdit:Layout' => 'DistribuciĂłn', 'UI:DashboardEdit:Properties' => 'Propiedades', @@ -1380,13 +1378,13 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'Month-10-Short' => 'Oct', 'Month-11-Short' => 'Nov', 'Month-12-Short' => 'Dic', - 'Calendar-FirstDayOfWeek' => '0',// 0 = Sunday, 1 = Monday, etc... + 'Calendar-FirstDayOfWeek' => '0', // 0 = Sunday, 1 = Monday, etc... 'UI:Menu:ShortcutList' => 'Crear Acceso RĂĄpido', 'UI:ShortcutRenameDlg:Title' => 'Renombrar Acceso RĂĄpido', 'UI:ShortcutListDlg:Title' => 'Crear Acceso RĂĄpido para la Lista', 'UI:ShortcutDelete:Confirm' => 'Por favor conforme que desea Eliminar el/los Acceso(s) RĂĄpido(s)', - 'Menu:MyShortcuts' => 'Mis Accesos RĂĄpidos',// Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:MyShortcuts' => 'Mis Accesos RĂĄpidos', // Duplicated into itop-welcome-itil (will be removed from here...) 'Class:Shortcut' => 'Acceso RĂĄpido', 'Class:Shortcut+' => 'Acceso RĂĄpido', 'Class:Shortcut/Attribute:name' => 'Nombre', @@ -1444,7 +1442,7 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:About:Licenses' => 'Licencias', 'UI:About:InstallationOptions' => 'Opciones de InstalaciĂłn', 'UI:About:ManualExtensionSource' => 'ExtensiĂłn', - 'UI:About:Extension_Version' => 'VersiĂłn: %1$s~~', + 'UI:About:Extension_Version' => 'VersiĂłn: %1$s', 'UI:About:RemoteExtensionSource' => 'Fuente', 'UI:DisconnectedDlgMessage' => 'EstĂĄ desconectado. Debe identificarse para continuar usando la aplicaciĂłn.', @@ -1467,7 +1465,7 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:CurrentObjectIsLockedBy_User' => 'El objeto estĂĄ bloqueado debido a que estĂĄ siendo modificado por %1$s.', 'UI:CurrentObjectIsLockedBy_User_Explanation' => 'El objeto estĂĄ siendo modificado por %1$s. Sus modificaciones no pueden ser guardadas debeido a que serĂĄn re-escritas.', - 'UI:CurrentObjectIsSoftLockedBy_User' => 'The object is currently being modified by %1$s. You\'ll be able to submit your modifications once they have finished.~~', + 'UI:CurrentObjectIsSoftLockedBy_User' => 'El objeto se encuentra modificado por %1$s. PodrĂĄ guardar sus modificaciones cuando el otro usuario termine.', 'UI:CurrentObjectLockExpired' => 'El bloqueo que prevenia modificaciones concurrentes ha expirado', 'UI:CurrentObjectLockExpired_Explanation' => 'TEl bloqueo que prevenia modificaciones concurrentes ha expirado. Sus modificaiones no pueden ser guardadas debido a que otros usuario tiene el permiso para modificar este objeto.', 'UI:ConcurrentLockKilled' => 'El bloqueo que prevenia modificaciones concurrentes ha sido eliminado.', @@ -1485,7 +1483,7 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:ToggleFullScreen' => 'Cambiar Maximizar / Minimizar', 'UI:Button:ResetImage' => 'Recuperar imĂĄgen previa', 'UI:Button:RemoveImage' => 'Remover imĂĄgen', - 'UI:Button:UploadImage' => 'Upload an image from the disk~~', + 'UI:Button:UploadImage' => 'Cargar una imagen del disco', 'UI:UploadNotSupportedInThisMode' => 'La modificaciĂłn de imĂĄgenes o archivos no estĂĄ soportado en este modo.', 'UI:Button:RemoveDocument' => 'Remover documento', @@ -1503,9 +1501,9 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:Search:AddCriteria:List:RecentlyUsed:Placeholder' => 'Ninguno todavĂ­a', // - Criteria header actions - 'UI:Search:Criteria:Toggle' => 'Minimize / Expand~~', - 'UI:Search:Criteria:Remove' => 'Remove~~', - 'UI:Search:Criteria:Locked' => 'Locked~~', + 'UI:Search:Criteria:Toggle' => 'Minimizar / Expandir', + 'UI:Search:Criteria:Remove' => 'Remover', + 'UI:Search:Criteria:Locked' => 'Bloquear', // - Criteria titles // - Default widget @@ -1567,12 +1565,12 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:Search:Criteria:Operator:String:EndsWith' => 'Termina con', 'UI:Search:Criteria:Operator:String:RegExp' => 'Exp. Regular', // - Numeric widget - 'UI:Search:Criteria:Operator:Numeric:Equals' => 'Igual',// => '=', - 'UI:Search:Criteria:Operator:Numeric:GreaterThan' => 'Mayor',// => '>', - 'UI:Search:Criteria:Operator:Numeric:GreaterThanOrEquals' => 'Mayor / igual',// > '>=', - 'UI:Search:Criteria:Operator:Numeric:LessThan' => 'Menor',// => '<', - 'UI:Search:Criteria:Operator:Numeric:LessThanOrEquals' => 'Menor / igual',// > '<=', - 'UI:Search:Criteria:Operator:Numeric:Different' => 'Diferente',// => '≠', + 'UI:Search:Criteria:Operator:Numeric:Equals' => 'Igual', // => '=', + 'UI:Search:Criteria:Operator:Numeric:GreaterThan' => 'Mayor', // => '>', + 'UI:Search:Criteria:Operator:Numeric:GreaterThanOrEquals' => 'Mayor / igual', // > '>=', + 'UI:Search:Criteria:Operator:Numeric:LessThan' => 'Menor', // => '<', + 'UI:Search:Criteria:Operator:Numeric:LessThanOrEquals' => 'Menor / igual', // > '<=', + 'UI:Search:Criteria:Operator:Numeric:Different' => 'Diferente', // => '≠', // - Tag Set Widget 'UI:Search:Criteria:Operator:TagSet:Matches' => 'Coincidencias', @@ -1603,7 +1601,7 @@ Cuando se asocien con un disparador, cada acciĂłn recibe un nĂșmero de "orden", 'UI:Search:Criteria:Raw:Filtered' => 'Filtrado', 'UI:Search:Criteria:Raw:FilteredOn' => 'Filtrado en %1$s', - 'UI:StateChanged' => 'State changed~~', + 'UI:StateChanged' => 'Estado cambiado', )); // @@ -1632,7 +1630,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array( // Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array( 'UI:Newsroom:NoNewMessage' => 'Sin Mensajes', - 'UI:Newsroom:XNewMessage' => '%1$s new message(s)~~', + 'UI:Newsroom:XNewMessage' => '%1$s nuevo(s) mensaje(s)', 'UI:Newsroom:MarkAllAsRead' => 'Marcar todos los mensajes como leĂ­dos', 'UI:Newsroom:ViewAllMessages' => 'Ver todos los mensajes', 'UI:Newsroom:Preferences' => 'Preferencia de Notificaciones', @@ -1676,16 +1674,16 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array( 'Menu:UserAccountsMenu' => 'Cuentas de Usuario', 'Menu:UserAccountsMenu+' => 'Cuentas de Usuario', 'Menu:UserAccountsMenu:Title' => 'Cuentas de Usuario', - 'Menu:MyShortcuts' => 'Mis Accesos RĂĄpidos', - 'Menu:UserManagement' => 'GestiĂłn de usuarios', - 'Menu:Queries' => 'Consultas', - 'Menu:ConfigurationTools' => 'ConfiguraciĂłn', + 'Menu:MyShortcuts' => 'Mis Accesos RĂĄpidos', + 'Menu:UserManagement' => 'AdministraciĂłn de usuarios', + 'Menu:Queries' => 'Consultas', + 'Menu:ConfigurationTools' => 'ConfiguraciĂłn', )); // Additional language entries not present in English dict Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array( - 'UI:Toggle:StandardDashboard' => 'Standard~~', - 'UI:Toggle:CustomDashboard' => 'Custom~~', - 'UI:Dashboard:Edit' => 'Editar esta PĂĄgina', - 'UI:Dashboard:Revert' => 'Regresar a VersiĂłn Original', + 'UI:Toggle:StandardDashboard' => 'EstĂĄndar', + 'UI:Toggle:CustomDashboard' => 'Personalizado', + 'UI:Dashboard:Edit' => 'Editar esta PĂĄgina', + 'UI:Dashboard:Revert' => 'Regresar a VersiĂłn Original', )); diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php index 40d1c721f..71840c677 100644 --- a/dictionaries/fr.dictionary.itop.core.php +++ b/dictionaries/fr.dictionary.itop.core.php @@ -519,9 +519,9 @@ Dict::Add('FR FR', 'French', 'Français', array( 'Class:ActionEmail' => 'Notification par mĂ©l', 'Class:ActionEmail+' => '', 'Class:ActionEmail/Attribute:status+' => 'Cet Ă©tat dĂ©finit qui va ĂȘtre notifiĂ©: le \'Destinataire de test\', tous les destinataires (A, Copie and Copie CachĂ©e) ou personne', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Seul le destinataire de test est notifiĂ© ', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'Tous les destinataires (A, Copie and Copie CachĂ©e) sont notifiĂ©s', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'La notification n\'est pas envoyĂ©e', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Seul le destinataire de test est notifiĂ© ', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'Tous les destinataires (A, Copie and Copie CachĂ©e) sont notifiĂ©s', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'La notification n\'est pas envoyĂ©e', 'Class:ActionEmail/Attribute:test_recipient' => 'Destinataire de test', 'Class:ActionEmail/Attribute:test_recipient+' => '', 'Class:ActionEmail/Attribute:from' => 'De (mĂ©l)', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 619b64abb..e36507466 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -348,7 +348,7 @@ Dict::Add('FR FR', 'French', 'Français', array(

    Tous ces modules peuvent ĂȘtre installĂ©s sĂ©parĂ©ment, Ă  votre rythme.

    ', - 'UI:WelcomeMenu:RightBlock' => '

    '.ITOP_APPLICATION_SHORT.' a été conçu pour les fournisseurs de service, il permet à vos équipes IT de gérer facilement de multiples clients et organisations. + 'UI:WelcomeMenu:RightBlock' => '

    ITOP_APPLICATION_SHORT a été conçu pour les fournisseurs de service, il permet à vos équipes IT de gérer facilement de multiples clients et organisations.

      iTop fournit un riche ensemble de processus mĂ©tier pour:
    • Augmenter l\'efficacitĂ© de la gestion de votre SI
    • Accroitre la performance de vos Ă©quipes d\'exploitation
    • @@ -467,7 +467,7 @@ Nous espĂ©rons que vous aimerez cette version autant que nous avons eu du plaisi 'UI:Error:MaintenanceTitle' => 'Maintenance', 'UI:Error:InvalidToken' => 'Erreur: l\'opĂ©ration a dĂ©jĂ  Ă©tĂ© effectuĂ©e (CSRF token not found)', - 'UI:Error:SMTP:UnknownVendor' => 'Le provider SMTP Oauth 2.0 %1$s n\'existe pas', + 'UI:Error:SMTP:UnknownVendor' => 'Le provider SMTP OAuth 2.0 %1$s n\'existe pas', 'UI:GroupBy:Count' => 'Nombre', 'UI:GroupBy:Count+' => 'Nombre d\'Ă©lĂ©ments', diff --git a/dictionaries/hu.dictionary.itop.core.php b/dictionaries/hu.dictionary.itop.core.php index 888b6b749..d7c567697 100755 --- a/dictionaries/hu.dictionary.itop.core.php +++ b/dictionaries/hu.dictionary.itop.core.php @@ -519,9 +519,9 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array( 'Class:ActionEmail' => 'E-mail Ă©rtesĂ­tĂ©s', 'Class:ActionEmail+' => '', 'Class:ActionEmail/Attribute:status+' => 'This status drives who will be notified: just the Test recipient, all (To, cc and Bcc) or no-one~~', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Only the Test recipient is notified~~', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'All To, Cc and Bcc emails are notified~~', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'The email notification will not be sent~~', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Only the Test recipient is notified~~', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'All To, Cc and Bcc emails are notified~~', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'The email notification will not be sent~~', 'Class:ActionEmail/Attribute:test_recipient' => 'Teszt cĂ­mzett', 'Class:ActionEmail/Attribute:test_recipient+' => '', 'Class:ActionEmail/Attribute:from' => 'FeladĂł~~', diff --git a/dictionaries/it.dictionary.itop.core.php b/dictionaries/it.dictionary.itop.core.php index 641142ac2..6df05fc87 100644 --- a/dictionaries/it.dictionary.itop.core.php +++ b/dictionaries/it.dictionary.itop.core.php @@ -521,9 +521,9 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array( 'Class:ActionEmail' => 'Email di notifica', 'Class:ActionEmail+' => '', 'Class:ActionEmail/Attribute:status+' => 'This status drives who will be notified: just the Test recipient, all (To, cc and Bcc) or no-one~~', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Only the Test recipient is notified~~', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'All To, Cc and Bcc emails are notified~~', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'The email notification will not be sent~~', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Only the Test recipient is notified~~', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'All To, Cc and Bcc emails are notified~~', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'The email notification will not be sent~~', 'Class:ActionEmail/Attribute:test_recipient' => 'Test destinatario', 'Class:ActionEmail/Attribute:test_recipient+' => '', 'Class:ActionEmail/Attribute:from' => 'Da~~', diff --git a/dictionaries/ja.dictionary.itop.core.php b/dictionaries/ja.dictionary.itop.core.php index c235ecf67..48b1c6308 100644 --- a/dictionaries/ja.dictionary.itop.core.php +++ b/dictionaries/ja.dictionary.itop.core.php @@ -519,9 +519,9 @@ Dict::Add('JA JP', 'Japanese', 'æ—„æœŹèȘž', array( 'Class:ActionEmail' => 'ăƒĄăƒŒăƒ«é€šçŸ„', 'Class:ActionEmail+' => '', 'Class:ActionEmail/Attribute:status+' => 'This status drives who will be notified: just the Test recipient, all (To, cc and Bcc) or no-one~~', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Only the Test recipient is notified~~', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'All To, Cc and Bcc emails are notified~~', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'The email notification will not be sent~~', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Only the Test recipient is notified~~', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'All To, Cc and Bcc emails are notified~~', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'The email notification will not be sent~~', 'Class:ActionEmail/Attribute:test_recipient' => 'テă‚čăƒˆăƒŹă‚·ăƒ”', 'Class:ActionEmail/Attribute:test_recipient+' => 'çŠ¶æ…‹ăŒăƒ†ă‚čトぼ栮搈ぼ漛慈', 'Class:ActionEmail/Attribute:from' => 'From~~', diff --git a/dictionaries/nl.dictionary.itop.core.php b/dictionaries/nl.dictionary.itop.core.php index 4fceeb12e..ad9891a78 100644 --- a/dictionaries/nl.dictionary.itop.core.php +++ b/dictionaries/nl.dictionary.itop.core.php @@ -22,7 +22,7 @@ * http://www.linprofs.com * * @author Hipska (2018, 2019) - * @author Jeffrey Bostoen - (2019 - 2020) + * @author Jeffrey Bostoen (2019 - 2022) * * @copyright Copyright (C) 2010-2021 Combodo SARL * @licence http://opensource.org/licenses/AGPL-3.0 @@ -41,7 +41,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Core:AttributeLinkedSet' => 'Reeks van objecten', 'Core:AttributeLinkedSet+' => 'Elke soort objecten van dezelfde klasse of subklasse', - 'Core:AttributeLinkedSetDuplicatesFound' => 'Duplicates in the \'%1$s\' field : %2$s~~', + 'Core:AttributeLinkedSetDuplicatesFound' => 'Dubbele records in het \'%1$s\' veld : %2$s', 'Core:AttributeDashboard' => 'Dashboard', 'Core:AttributeDashboard+' => '', @@ -239,14 +239,14 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:CMDBChange/Attribute:date+' => 'De datum en tijd waarop de aanpassingen zijn waargenomen ', 'Class:CMDBChange/Attribute:userinfo' => 'Info', 'Class:CMDBChange/Attribute:userinfo+' => 'Info over wie/wat (bv. welke service) de aanpassing heeft doorgevoerd', - 'Class:CMDBChange/Attribute:origin/Value:interactive' => 'User interaction in the GUI~~', - 'Class:CMDBChange/Attribute:origin/Value:csv-import.php' => 'CSV import script~~', - 'Class:CMDBChange/Attribute:origin/Value:csv-interactive' => 'CSV import in the GUI~~', - 'Class:CMDBChange/Attribute:origin/Value:email-processing' => 'Email processing~~', - 'Class:CMDBChange/Attribute:origin/Value:synchro-data-source' => 'Synchro. data source~~', - 'Class:CMDBChange/Attribute:origin/Value:webservice-rest' => 'REST/JSON webservices~~', - 'Class:CMDBChange/Attribute:origin/Value:webservice-soap' => 'SOAP webservices~~', - 'Class:CMDBChange/Attribute:origin/Value:custom-extension' => 'By an extension~~', + 'Class:CMDBChange/Attribute:origin/Value:interactive' => 'Gebruikersinteractie in de GUI', + 'Class:CMDBChange/Attribute:origin/Value:csv-import.php' => 'CSV import script', + 'Class:CMDBChange/Attribute:origin/Value:csv-interactive' => 'CSV import in de GUI', + 'Class:CMDBChange/Attribute:origin/Value:email-processing' => 'Verwerking e-mail', + 'Class:CMDBChange/Attribute:origin/Value:synchro-data-source' => 'Synchro. databron', + 'Class:CMDBChange/Attribute:origin/Value:webservice-rest' => 'REST/JSON webservices', + 'Class:CMDBChange/Attribute:origin/Value:webservice-soap' => 'SOAP webservices', + 'Class:CMDBChange/Attribute:origin/Value:custom-extension' => 'Via een extensie', )); // @@ -507,7 +507,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:Action/Attribute:trigger_list+' => 'Triggers gelinkt aan deze actie', 'Class:Action/Attribute:finalclass' => 'Type', 'Class:Action/Attribute:finalclass+' => '', - 'Action:WarningNoTriggerLinked' => 'Warning, no trigger is linked to the action. It will not be active until it has at least 1.~~', + 'Action:WarningNoTriggerLinked' => 'Opgelet: er is geen trigger gelinkt aan deze actie. Zonder minstens 1 actieve trigger zal de actie nooit uitgevoerd worden.', )); // @@ -527,9 +527,9 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:ActionEmail' => 'E-mailmelding', 'Class:ActionEmail+' => '', 'Class:ActionEmail/Attribute:status+' => 'Status bepaalt wie op de hoogte zal gesteld worden: enkel de testontvanger, iedereen (Aan, CC en BCC) of niemand', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Enkel de testontvanger zal op de hoogte gesteld worden', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'Alle Aan, CC en BCC bestemingen zullen op de hoogte gesteld worden', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'De e-mailmelding zal niet verstuurd worden', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Enkel de testontvanger zal op de hoogte gesteld worden', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'Alle Aan, CC en BCC bestemingen zullen op de hoogte gesteld worden', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'De e-mailmelding zal niet verstuurd worden', 'Class:ActionEmail/Attribute:test_recipient' => 'Testontvanger', 'Class:ActionEmail/Attribute:test_recipient+' => 'Bestemming als de status op "Test" staat', 'Class:ActionEmail/Attribute:from' => 'Van (e-mail)', @@ -587,7 +587,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:TriggerOnObject/Attribute:target_class' => 'Toegepast op klasse', 'Class:TriggerOnObject/Attribute:target_class+' => '', 'Class:TriggerOnObject/Attribute:filter' => 'Filter', - 'Class:TriggerOnObject/Attribute:filter+' => 'Limit the object list (of the target class) which will activate the trigger~~', + 'Class:TriggerOnObject/Attribute:filter+' => 'Beperk de objecten (van de opgegeven klasse) die de trigger zullen activeren.', 'TriggerOnObject:WrongFilterQuery' => 'Verkeerde filter-query: %1$s', 'TriggerOnObject:WrongFilterClass' => 'De filter-query moet verwijzen naar objecten van klasse "%1$s"', )); @@ -664,10 +664,10 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( // Dict::Add('NL NL', 'Dutch', 'Nederlands', array( - 'Class:TriggerOnObjectMention' => 'Trigger (on object mention)~~', - 'Class:TriggerOnObjectMention+' => 'Trigger on mention (@xxx) of an object of [a child class of] the given class in a log attribute~~', - 'Class:TriggerOnObjectMention/Attribute:mentioned_filter' => 'Mentioned filter~~', - 'Class:TriggerOnObjectMention/Attribute:mentioned_filter+' => 'Limit the list of mentioned objects which will activate the trigger. If empty, any mentioned object (of any class) will activate it.~~', + 'Class:TriggerOnObjectMention' => 'Trigger (bij vermelden van object)', + 'Class:TriggerOnObjectMention+' => 'Trigger bij vermelden (@xxx) van een object van de opgegeven klasse (of subklasse ervan) in een log', + 'Class:TriggerOnObjectMention/Attribute:mentioned_filter' => 'Filter', + 'Class:TriggerOnObjectMention/Attribute:mentioned_filter+' => 'Beperk de lijst van vermelde objecten die de trigger zullen activeren. Indien leeg, zullen alle objecten (van eender welke klasse) de trigger activeren.', )); // @@ -1097,8 +1097,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:AsyncTask/Attribute:last_error+' => '', 'Class:AsyncTask/Attribute:last_attempt' => 'Laatste poging', 'Class:AsyncTask/Attribute:last_attempt+' => '', - 'Class:AsyncTask:InvalidConfig_Class_Keys' => 'Invalid format for the configuration of "async_task_retries[%1$s]". Expecting an array with the following keys: %2$s~~', - 'Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys' => 'Invalid format for the configuration of "async_task_retries[%1$s]": unexpected key "%2$s". Expecting only the following keys: %3$s~~', + 'Class:AsyncTask:InvalidConfig_Class_Keys' => 'Ongeldig formaat bij de configuratie van "async_tasks_retries[%1$s]". Er wordt een Array verwacht met de volgende sleutels: %2$s', + 'Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys' => 'Ongeldig formaat bij de configuratie van "async_tasks_retries[%1$s]": onverwachte sleutel "%2$s". Enkel deze sleutels worden verwacht: %3$s', )); // diff --git a/dictionaries/nl.dictionary.itop.ui.php b/dictionaries/nl.dictionary.itop.ui.php index 1f6abbfab..9381d81c1 100644 --- a/dictionaries/nl.dictionary.itop.ui.php +++ b/dictionaries/nl.dictionary.itop.ui.php @@ -112,7 +112,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:User/Attribute:language/Value:FR FR+' => 'Frans (Frankrijk)', 'Class:User/Attribute:profile_list' => 'Profielen', 'Class:User/Attribute:profile_list+' => 'Rollen waarmee rechten verleend zijn aan deze account.', - 'Class:User/Attribute:allowed_org_list' => 'Mijn organisaties', + 'Class:User/Attribute:allowed_org_list' => 'Toegestane organisaties', 'Class:User/Attribute:allowed_org_list+' => 'De eindgebruiker heeft toestemming om data te bekijken van de gerelateerde organisaties. Als er geen organisatie is opgegeven, heeft de persoon toegang tot data van alle organisaties.', 'Class:User/Attribute:status' => 'Status', 'Class:User/Attribute:status+' => 'De gebruikersaccount kan in- of uitgeschakeld zijn.', @@ -121,10 +121,10 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Class:User/Error:LoginMustBeUnique' => 'Login moet uniek zijn - "%1s" is al in gebruik', 'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Minstens één profiel moet toegewezen zijn aan deze gebruiker', - 'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~', - 'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~', - 'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~', - 'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~', + 'Class:User/Error:ProfileNotAllowed' => 'Profiel "%1$s" kan niet toegevoegd worden omdat het de toegang tot de backoffice zou ontzeggen.', + 'Class:User/Error:StatusChangeIsNotAllowed' => 'Je kan de status voor je eigen gebruikersaccount niet wijzigen.', + 'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'De toegestande organisaties moeten minstens de organisatie bevatten waartoe de gebruikersaccount behoort.', + 'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'De huidige lijst van profielen heeft niet voldoende toegangsrechten (gebruikersaccount zijn niet meer wijzigbaar).', 'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Minstens één organisatie moet toegewezen zijn aan deze gebruiker', 'Class:User/Error:OrganizationNotAllowed' => 'Organisatie is niet toegestaan.', 'Class:User/Error:UserOrganizationNotAllowed' => 'De gebruikersaccount behoort niet tot de organisaties waar je zelf rechten voor hebt.', @@ -368,14 +368,14 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
    • Het beheren van het belangrijkste middel: documentatie.

    ', - 'UI:WelcomeMenu:Text'=> '
    Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!
    + 'UI:WelcomeMenu:Text'=> '
    Proficiat, je werkt nu met '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!
    -
    This version features a brand new modern and accessible backoffice design.
    +
    Deze versie heeft een volledig nieuw, modern en toegankelijk uiterlijk.
    -
    We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them. -We hope you’ll enjoy this version as much as we enjoyed imagining and creating it.
    +
    De belangrijkste en meest vertrouwde '.ITOP_APPLICATION.' functies hebben we behouden en een modern jasje gegeven. +We hopen dat je even hard van deze versie geniet als dat we zelf ervan hebben genoten om het te ontwerpen.
    -
    Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.
    ~~', +
    Wijzig je '.ITOP_APPLICATION.'-voorkeuren voor een gepersonaliseerde ervaring.
    ', 'UI:WelcomeMenu:AllOpenRequests' => 'Open aanvragen: %1$d', 'UI:WelcomeMenu:MyCalls' => 'Mijn aanvragen', 'UI:WelcomeMenu:OpenIncidents' => 'Open incidenten: %1$d', @@ -383,8 +383,8 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:WelcomeMenu:MyIncidents' => 'Aan mij toegewezen incidenten', 'UI:AllOrganizations' => ' Alle Organisaties ', 'UI:YourSearch' => 'Jouw zoekopdracht', - 'UI:LoggedAsMessage' => 'Ingelogd als %1$s (%2$s)~~', - 'UI:LoggedAsMessage+Admin' => 'Ingelogd als %1$s (%2$s, Beheerder)~~', + 'UI:LoggedAsMessage' => 'Ingelogd als %1$s (%2$s)', + 'UI:LoggedAsMessage+Admin' => 'Ingelogd als %1$s (%2$s, Beheerder)', 'UI:Button:Logoff' => 'Log uit', 'UI:Button:GlobalSearch' => 'Zoek', 'UI:Button:Search' => ' Zoek ', @@ -423,7 +423,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Button:Insert' => 'Invoegen', 'UI:Button:More' => 'Meer', 'UI:Button:Less' => 'Minder', - 'UI:Button:Wait' => 'Please wait while updating fields~~', + 'UI:Button:Wait' => 'Even geduld terwijl de velden vernieuwd worden', 'UI:Treeview:CollapseAll' => 'Alles inklappen', 'UI:Treeview:ExpandAll' => 'Alles uitklappen', 'UI:UserPref:DoNotShowAgain' => 'Niet meer opnieuw tonen', @@ -470,7 +470,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Error:InvalidDashboard' => 'Fout: ongeldig dashboard', 'UI:Error:MaintenanceMode' => 'Toepassing is momenteel in onderhoud', 'UI:Error:MaintenanceTitle' => 'Onderhoud', - 'UI:Error:InvalidToken' => 'Error: the requested operation has already been performed (CSRF token not found)~~', + 'UI:Error:InvalidToken' => 'Fout: de gevraagde bewerking werd al uitgevoerd (CSRF token niet gevonden)', 'UI:Error:SMTP:UnknownVendor' => 'OAuth SMTP provider %1$s does not exist (email_transport_smtp.oauth.provider)~~', @@ -705,18 +705,18 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Audit:Dashboard:ObjectsAudited' => 'Gecontroleerde objecten', 'UI:Audit:Dashboard:ObjectsInError' => 'Foutieve objecten', 'UI:Audit:Dashboard:ObjectsValidated' => 'Gevalideerde objecten', - 'UI:Audit:AuditCategory:Subtitle' => '%1$s errors ouf of %2$s - %3$s%%~~', + 'UI:Audit:AuditCategory:Subtitle' => '%1$s fouten van de %2$s - %3$s%%', 'UI:RunQuery:Title' => ITOP_APPLICATION_SHORT.' - Evaluatie van OQL-query', 'UI:RunQuery:QueryExamples' => 'Voorbeelden van query\'s', - 'UI:RunQuery:QueryResults' => 'Query Results~~', + 'UI:RunQuery:QueryResults' => 'Query-resultaten', 'UI:RunQuery:HeaderPurpose' => 'Doel', 'UI:RunQuery:HeaderPurpose+' => 'Uitleg over de query', 'UI:RunQuery:HeaderOQLExpression' => 'OQL-expressie', 'UI:RunQuery:HeaderOQLExpression+' => 'De query in OQL syntax', 'UI:RunQuery:ExpressionToEvaluate' => 'Expressie om te evalueren: ', - 'UI:RunQuery:QueryArguments' => 'Query Arguments~~', + 'UI:RunQuery:QueryArguments' => 'Query-argumenten', 'UI:RunQuery:MoreInfo' => 'Meer informatie over de query: ', 'UI:RunQuery:DevelopedQuery' => 'Herschreven query-expressie: ', 'UI:RunQuery:SerializedFilter' => 'Geserialiseerde filter: ', @@ -728,7 +728,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Query:UrlForExcel' => 'URL om te gebruiken voor MS Excel-webquery\'s', 'UI:Query:UrlV1' => 'De lijst van velden is leeg gelaten. De pagina export-V2.php kan niet aangeroepen worden zonder deze informatie.Daarom verwijst de onderstaande link naar de oude export-pagina: export.php. Deze verouderde versie heeft enkele beperkingen: de lijst van geĂ«xporteerde velden kan verschillen afhankelijk van het gekozen export-formaat en het datamodel van '.ITOP_APPLICATION_SHORT.'. Als je wil dat de lijst van geĂ«xporteerde kolommen hetzelfde blijft over lange tijd, dan moet je een waarde opgeven voor het attribuut "Velden" en de pagina export-V2.php gebruiken.', 'UI:Schema:Title' => ITOP_APPLICATION_SHORT.' objecten-schema', - 'UI:Schema:TitleForClass' => '%1$s schema~~', + 'UI:Schema:TitleForClass' => '%1$s schema', 'UI:Schema:CategoryMenuItem' => 'Categorie %1$s', 'UI:Schema:Relationships' => 'Relaties', 'UI:Schema:AbstractClass' => 'Abstracte klasse: objecten van deze klasse kunnen niet worden geĂŻnstantieerd.', @@ -795,7 +795,7 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating 'UI:Schema:Attribute/Filter' => 'Filter', 'UI:Schema:DefaultNullValue' => 'Standaardwaarde null : "%1$s"', 'UI:LinksWidget:Autocomplete+' => 'Typ de eerste 3 karakters...', - 'UI:Edit:SearchQuery' => 'Select a predefined query~~', + 'UI:Edit:SearchQuery' => 'Kies een vooraf gedefinieerde query', 'UI:Edit:TestQuery' => 'Test query', 'UI:Combo:SelectValue' => '--- selecteer een waarde ---', 'UI:Label:SelectedObjects' => 'Geselecteerde objecten: ', @@ -994,24 +994,24 @@ We hope you’ll enjoy this version as much as we enjoyed imagining and creating

-Acties define the actions to be performed when the triggers execute. For now there are only two kind of actions: +Acties definieer de acties die uitgevoerd moeten worden als de triggers geactiveerd worden. Er zijn momenteel 2 soorten standaardacties:

    -
  1. Sending an email message: Such actions also define the template to be used for sending the email as well as the other parameters of the message like the recipients, importance, etc.
    +
  2. Stuur een e-mail: Bij deze acties definieer je een sjabloon voor het bericht en ook parameters zoals ontvanger(s), prioriteit, enz.
    Een speciale testpagina (email.test.php) is beschikbaar voor het testen en oplossen van eventuele problemen met jouw PHP e-mailconfiguratie.
  3. -
  4. Outgoing webhooks: Allow integration with a third-party application by sending structured data to a defined URL.
  5. +
  6. Webhooks: Staat toe om te integreren met toepassingen van derde partijen, door gestructureerde data te sturen naar een URL.

Acties moeten gekoppeld zijn aan triggers. -Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt in welke volgorde de acties moeten worden uitgevoerd.

~~', +Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt in welke volgorde de acties moeten worden uitgevoerd.

', 'UI:NotificationsMenu:Triggers' => 'Triggers', 'UI:NotificationsMenu:AvailableTriggers' => 'Beschikbare triggers', 'UI:NotificationsMenu:OnCreate' => 'Wanneer een object is aangemaakt', 'UI:NotificationsMenu:OnStateEnter' => 'Wanneer een object een bepaalde fase intreedt', 'UI:NotificationsMenu:OnStateLeave' => 'Wanneer een object een bepaalde fase uittreedt', 'UI:NotificationsMenu:Actions' => 'Acties', - 'UI:NotificationsMenu:Actions:ActionEmail' => 'Email actions~~', - 'UI:NotificationsMenu:Actions:ActionWebhook' => 'Webhook actions (outgoing integrations)~~', - 'UI:NotificationsMenu:Actions:Action' => 'Other actions~~', + 'UI:NotificationsMenu:Actions:ActionEmail' => 'Email acties', + 'UI:NotificationsMenu:Actions:ActionWebhook' => 'Webhook acties (uitgaande integraties)', + 'UI:NotificationsMenu:Actions:Action' => 'Andere acties', 'UI:NotificationsMenu:AvailableActions' => 'Beschikbare acties', 'Menu:TagAdminMenu' => 'Tags-configuratie', @@ -1055,8 +1055,8 @@ Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt 'UI:iTopVersion:Long' => '%1$s versie %2$s-%3$s uitgegeven op %4$s', 'UI:PropertiesTab' => 'Eigenschappen', - 'UI:OpenDocumentInNewWindow_' => 'Open~~', - 'UI:DownloadDocument_' => 'Download~~', + 'UI:OpenDocumentInNewWindow_' => 'Open', + 'UI:DownloadDocument_' => 'Download', 'UI:Document:NoPreview' => 'Er is geen voorbeeld beschikbaar voor dit soort document', 'UI:Download-CSV' => 'Download %1$s', @@ -1178,7 +1178,7 @@ Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt 'UI:ArchiveMode:Banner+' => 'Gearchiveerde objecten zijn zichtbaar, maar kunnen niet worden aangepast', 'UI:FavoriteOrganizations' => 'Favoriete organisaties', 'UI:FavoriteOrganizations+' => 'Duid in onderstaande lijst de organisaties aan die je wilt zien in de keuzelijst voor een snelle toegang. Dit is geen beveiligingsinstelling; objecten van elke organisatie zijn nog steed zichtbaar en toegankelijk door "Alle Organisaties" te selecteren in de keuzelijst.', - 'UI:FavoriteLanguage' => 'Taal van de gebruikersinterface~~', + 'UI:FavoriteLanguage' => 'Taal van de gebruikersinterface', 'UI:Favorites:SelectYourLanguage' => 'Selecteer jouw taal', 'UI:FavoriteOtherSettings' => 'Overige instellingen', 'UI:Favorites:Default_X_ItemsPerPage' => 'Standaardlengte: %1$s items per pagina', @@ -1220,16 +1220,16 @@ Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt 'UI:OQL:UnknownClassAndFix' => 'Onbekende klasse "%1$s". Je zou "%2$s" kunnen proberen.', 'UI:OQL:UnknownClassNoFix' => 'Onbekende klasse "%1$s"', - 'UI:Dashboard:EditCustom' => 'Edit custom version...~~', - 'UI:Dashboard:CreateCustom' => 'Create a custom version...~~', - 'UI:Dashboard:DeleteCustom' => 'Delete custom version...~~', + 'UI:Dashboard:EditCustom' => 'Bewerk aangepaste versie...', + 'UI:Dashboard:CreateCustom' => 'Maak aangepaste versie...', + 'UI:Dashboard:DeleteCustom' => 'Verwijder aangepaste versie...', 'UI:Dashboard:RevertConfirm' => 'Alle bewerkingen die zijn gemaakt aan de originele versie zullen verloren gaan. Bevestig dat je wilt doorgaan.', 'UI:ExportDashBoard' => 'Exporteer naar een bestand', 'UI:ImportDashBoard' => 'Importeer vanuit een bestand', 'UI:ImportDashboardTitle' => 'Importeer vanuit een bestand', 'UI:ImportDashboardText' => 'Selecteer een bestand van het dashboard om te importeren:', 'UI:Dashboard:Actions' => 'Dashboard acties', - 'UI:Dashboard:NotUpToDateUntilContainerSaved' => 'This dashboard displays information that does not include the on-going changes.~~', + 'UI:Dashboard:NotUpToDateUntilContainerSaved' => 'Dit dashboard toont informatie die nog geen rekening houdt met de wijzigingen die nu gemaakt worden.', 'UI:DashletCreation:Title' => 'Maak een nieuwe Dashlet aan', @@ -1242,8 +1242,8 @@ Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt 'UI:DashboardEdit:AutoReload' => 'Automatisch vernieuwen', 'UI:DashboardEdit:AutoReloadSec' => 'Interval voor het automatisch vernieuwen (seconden)', 'UI:DashboardEdit:AutoReloadSec+' => 'Het toegestane minimum is 5 seconden', - 'UI:DashboardEdit:Revert' => 'Revert~~', - 'UI:DashboardEdit:Apply' => 'Apply~~', + 'UI:DashboardEdit:Revert' => 'Herstel', + 'UI:DashboardEdit:Apply' => 'Opslaan', 'UI:DashboardEdit:Layout' => 'Layout', 'UI:DashboardEdit:Properties' => 'Eigenschappen van dashboard', @@ -1502,9 +1502,9 @@ Bij die koppeling wordt aan elke actie een volgorde-nummer gegeven. Dit bepaalt 'UI:Search:AddCriteria:List:RecentlyUsed:Placeholder' => 'Nog geen.', // - Criteria header actions - 'UI:Search:Criteria:Toggle' => 'Minimize / Expand~~', - 'UI:Search:Criteria:Remove' => 'Remove~~', - 'UI:Search:Criteria:Locked' => 'Locked~~', + 'UI:Search:Criteria:Toggle' => 'Klap in / uit', + 'UI:Search:Criteria:Remove' => 'Verwijder', + 'UI:Search:Criteria:Locked' => 'Vergrendeld', // - Criteria titles // - Default widget @@ -1663,8 +1663,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Menu:Notifications:Title' => 'AuditcategorieĂ«n', 'Menu:RunQueriesMenu' => 'Query\'s uitvoeren', 'Menu:RunQueriesMenu+' => 'Voer een query uit', - 'Menu:QueryMenu' => 'Favoriete query\'s', - 'Menu:QueryMenu+' => 'Favoriete query\'s', + 'Menu:QueryMenu' => 'Voorgedefinieerde query\'s', + 'Menu:QueryMenu+' => 'Voorgedefinieerde query\'s', 'Menu:UniversalSearchMenu' => 'Globale zoekopdracht', 'Menu:UniversalSearchMenu+' => 'Zoek in alle data...', 'Menu:UserManagementMenu' => 'Gebruikersbeheer', diff --git a/dictionaries/pl.dictionary.itop.core.php b/dictionaries/pl.dictionary.itop.core.php index 0b80789c3..279a62c2a 100644 --- a/dictionaries/pl.dictionary.itop.core.php +++ b/dictionaries/pl.dictionary.itop.core.php @@ -520,9 +520,9 @@ Dict::Add('PL PL', 'Polish', 'Polski', array( 'Class:ActionEmail' => 'Powiadomienie e-mail', 'Class:ActionEmail+' => '', 'Class:ActionEmail/Attribute:status+' => 'Ten status decyduje o tym, kto zostanie powiadomiony: tylko odbiorca testowy, wszyscy (Do, DW i UDW) lub nikt', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Powiadomiony zostanie tylko odbiorca testowy', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'Wszystkie e-maile "Do", "DW" i "UDW" są powiadamiane', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'Powiadomienie e-mail nie zostanie wysƂane', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Powiadomiony zostanie tylko odbiorca testowy', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'Wszystkie e-maile "Do", "DW" i "UDW" są powiadamiane', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'Powiadomienie e-mail nie zostanie wysƂane', 'Class:ActionEmail/Attribute:test_recipient' => 'Odbiorca testowy', 'Class:ActionEmail/Attribute:test_recipient+' => 'Miejsce docelowe w przypadku, gdy status jest ustawiony na "Test"', 'Class:ActionEmail/Attribute:from' => 'Z', diff --git a/dictionaries/pt_br.dictionary.itop.core.php b/dictionaries/pt_br.dictionary.itop.core.php index a2bf053a2..5cb8420b1 100644 --- a/dictionaries/pt_br.dictionary.itop.core.php +++ b/dictionaries/pt_br.dictionary.itop.core.php @@ -26,27 +26,27 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:DeletedObjectTip' => 'O objeto foi excluĂ­do em %1$s (%2$s)', 'Core:UnknownObjectLabel' => 'Objeto nĂŁo encontrado (classe: %1$s, id: %2$d)', - 'Core:UnknownObjectTip' => 'O objeto nĂŁo pode ser encontrado. Ele pode ter sido eliminado hĂĄ algum tempo e o log foi removido desde entĂŁo.', + 'Core:UnknownObjectTip' => 'O objeto nĂŁo pode ser encontrado. Ele pode ter sido eliminado hĂĄ algum tempo e o log foi removido desde entĂŁo', 'Core:UniquenessDefaultError' => 'Regra de exclusividade \'%1$s\' com erro', - 'Core:CheckConsistencyError' => 'Consistency rules not followed: %1$s~~', - 'Core:CheckValueError' => 'Unexpected value for attribute \'%1$s\' (%2$s) : %3$s~~', + 'Core:CheckConsistencyError' => 'Regras de consistĂȘncia nĂŁo seguidas: %1$s', + 'Core:CheckValueError' => 'Valor inesperado para o atributo \'%1$s\' (%2$s) : %3$s~~', - 'Core:AttributeLinkedSet' => 'Array de objetos', - 'Core:AttributeLinkedSet+' => 'Qualquer tipo de objetos da mesma classe ou subclasses', + 'Core:AttributeLinkedSet' => 'Array de objetos', + 'Core:AttributeLinkedSet+' => 'Quaisquer tipos de objetos da mesma classe ou subclasses', - 'Core:AttributeLinkedSetDuplicatesFound' => 'Duplicates in the \'%1$s\' field : %2$s~~', + 'Core:AttributeLinkedSetDuplicatesFound' => 'Duplicatas no campo \'%1$s\' : %2$s', - 'Core:AttributeDashboard' => 'Painel de controle', + 'Core:AttributeDashboard' => 'Painel do '.ITOP_APPLICATION_SHORT, 'Core:AttributeDashboard+' => '', 'Core:AttributePhoneNumber' => 'NĂșmero de telefone', 'Core:AttributePhoneNumber+' => '', - 'Core:AttributeObsolescenceDate' => 'ObsolescĂȘncia data', + 'Core:AttributeObsolescenceDate' => 'Data de obsolescĂȘncia', 'Core:AttributeObsolescenceDate+' => '', - 'Core:AttributeTagSet' => 'Lista de etiquetas', + 'Core:AttributeTagSet' => 'Lista de tags', 'Core:AttributeTagSet+' => '', 'Core:AttributeSet:placeholder' => 'clique para adicionar', 'Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromClass' => '%1$s (%2$s)', @@ -57,10 +57,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:AttributeCaseLog+' => '', 'Core:AttributeMetaEnum' => 'Enum Computado', - 'Core:AttributeMetaEnum+' => '', + 'Core:AttributeMetaEnum+' => 'Exibir Strings alfanumĂ©ricas computadas', 'Core:AttributeLinkedSetIndirect' => 'Array de objetos (N-N)', - 'Core:AttributeLinkedSetIndirect+' => 'Qualquer tipo de objetos [sub-classe] da mesma classe', + 'Core:AttributeLinkedSetIndirect+' => 'Qualquer tipo de objetos [subclasse] da mesma classe', 'Core:AttributeInteger' => 'Inteiro', 'Core:AttributeInteger+' => 'Valor numĂ©rico (nĂŁo pode ser negativo)', @@ -68,40 +68,40 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:AttributeDecimal' => 'Decimal', 'Core:AttributeDecimal+' => 'Valor decimal (nĂŁo pode ser negativo)', - 'Core:AttributeBoolean' => 'Boolean', + 'Core:AttributeBoolean' => 'Booleano', 'Core:AttributeBoolean+' => '', 'Core:AttributeBoolean/Value:null' => '', 'Core:AttributeBoolean/Value:yes' => 'Sim', 'Core:AttributeBoolean/Value:no' => 'NĂŁo', - 'Core:AttributeArchiveFlag' => 'Arquivar bandeira', + 'Core:AttributeArchiveFlag' => 'Flag de arquivamento', 'Core:AttributeArchiveFlag/Value:yes' => 'Sim', - 'Core:AttributeArchiveFlag/Value:yes+' => 'Este objeto Ă© visĂ­vel apenas no modo de arquivo', + 'Core:AttributeArchiveFlag/Value:yes+' => 'Este objeto Ă© visĂ­vel apenas no modo de arquivamento', 'Core:AttributeArchiveFlag/Value:no' => 'NĂŁo', 'Core:AttributeArchiveFlag/Label' => 'Arquivado', 'Core:AttributeArchiveFlag/Label+' => '', 'Core:AttributeArchiveDate/Label' => 'Data de arquivamento', 'Core:AttributeArchiveDate/Label+' => '', - 'Core:AttributeObsolescenceFlag' => 'Obsolescence flag~~', + 'Core:AttributeObsolescenceFlag' => 'Flag de obsolescĂȘncia', 'Core:AttributeObsolescenceFlag/Value:yes' => 'Sim', - 'Core:AttributeObsolescenceFlag/Value:yes+' => 'Este objeto Ă© excluĂ­do da anĂĄlise de impacto e oculto dos resultados de pesquisa', + 'Core:AttributeObsolescenceFlag/Value:yes+' => 'Este objeto serĂĄ excluĂ­do da anĂĄlise de impacto e ocultado dos resultados de pesquisa', 'Core:AttributeObsolescenceFlag/Value:no' => 'NĂŁo', 'Core:AttributeObsolescenceFlag/Label' => 'Obsoleto', - 'Core:AttributeObsolescenceFlag/Label+' => 'Computado dinamicamente em outros atributos', - 'Core:AttributeObsolescenceDate/Label' => 'ObsolescĂȘncia data', + 'Core:AttributeObsolescenceFlag/Label+' => 'Calculado dinamicamente com base em outros atributos do objeto', + 'Core:AttributeObsolescenceDate/Label' => 'Data de obsolescĂȘncia', 'Core:AttributeObsolescenceDate/Label+' => 'Data aproximada em que o objeto foi considerado obsoleto', 'Core:AttributeString' => 'String', - 'Core:AttributeString+' => 'SeqĂŒĂȘncia alfanumĂ©rica', + 'Core:AttributeString+' => 'SequĂȘncia alfanumĂ©rica', 'Core:AttributeClass' => 'Classe', 'Core:AttributeClass+' => '', - 'Core:AttributeApplicationLanguage' => 'Linguagem usuĂĄrio', - 'Core:AttributeApplicationLanguage+' => 'Linguagem e paĂ­s (EN US)', + 'Core:AttributeApplicationLanguage' => 'Idioma do usuĂĄrio', + 'Core:AttributeApplicationLanguage+' => 'Idioma e paĂ­s (por exemplo: EN US)', - 'Core:AttributeFinalClass' => 'Classe (auto)', + 'Core:AttributeFinalClass' => 'Classe (automĂĄtica)', 'Core:AttributeFinalClass+' => 'Classe real do objeto (criada automaticamente pelo sistema)', 'Core:AttributePassword' => 'Senha', @@ -116,28 +116,28 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:AttributeText+' => 'Cadeia de caracteres Multi-linha', 'Core:AttributeHTML' => 'HTML', - 'Core:AttributeHTML+' => 'HTML string', + 'Core:AttributeHTML+' => 'String HTML', - 'Core:AttributeEmailAddress' => 'Endereço email', + 'Core:AttributeEmailAddress' => 'Endereço de e-mail', 'Core:AttributeEmailAddress+' => '', 'Core:AttributeIPAddress' => 'Endereço IP', 'Core:AttributeIPAddress+' => '', 'Core:AttributeOQL' => 'OQL', - 'Core:AttributeOQL+' => 'ExpressĂŁo Object Query Langage', + 'Core:AttributeOQL+' => 'ExpressĂŁo Object Query Language (OQL)', 'Core:AttributeEnum' => 'Enum', - 'Core:AttributeEnum+' => 'Lista de prĂ©-definida seqĂŒĂȘncias alfanumĂ©ricas', + 'Core:AttributeEnum+' => 'Lista de sequĂȘncias alfanumĂ©ricas prĂ©-definidas', - 'Core:AttributeTemplateString' => 'Modelo string', - 'Core:AttributeTemplateString+' => 'Espaço reservado contendo string', + 'Core:AttributeTemplateString' => 'String do modelo', + 'Core:AttributeTemplateString+' => 'String de uma linha, contendo espaços reservados para dados do '.ITOP_APPLICATION_SHORT, - 'Core:AttributeTemplateText' => 'Template text', - 'Core:AttributeTemplateText+' => 'Texto contendo espaços reservados', + 'Core:AttributeTemplateText' => 'Texto do modelo', + 'Core:AttributeTemplateText+' => 'Texto contendo espaços reservados para dados do '.ITOP_APPLICATION_SHORT, - 'Core:AttributeTemplateHTML' => 'Modelo HTML', - 'Core:AttributeTemplateHTML+' => 'HTML contendo espaços reservados', + 'Core:AttributeTemplateHTML' => 'HTML do modelo', + 'Core:AttributeTemplateHTML+' => 'CĂłdigo HTML contendo espaços reservados para dados do '.ITOP_APPLICATION_SHORT, 'Core:AttributeDateTime' => 'Data/hora', 'Core:AttributeDateTime+' => 'Data e hora (ano-mĂȘs-dia hh:mm:ss)', @@ -172,38 +172,38 @@ Operadores:
[data,data]

', - 'Core:AttributeDeadline' => 'Tempo determinado', + 'Core:AttributeDeadline' => 'Prazo determinado', 'Core:AttributeDeadline+' => 'Data, apresentada relativamente ao tempo atual', 'Core:AttributeExternalKey' => 'Chave externa', 'Core:AttributeExternalKey+' => 'Chave externa (ou foreign)', 'Core:AttributeHierarchicalKey' => 'Chave hierĂĄrquica', - 'Core:AttributeHierarchicalKey+' => 'Chave externa (ou foreign) para o principal', + 'Core:AttributeHierarchicalKey+' => 'Chave externa (ou foreign key) para o objeto pai', 'Core:AttributeExternalField' => 'Campo externo', 'Core:AttributeExternalField+' => 'Campo mapeado para uma chave externa', 'Core:AttributeURL' => 'URL', - 'Core:AttributeURL+' => 'URL absoluto ou relativo como um texto', + 'Core:AttributeURL+' => 'URL absoluto ou relativo como texto', 'Core:AttributeBlob' => 'Blob', 'Core:AttributeBlob+' => 'Qualquer conteĂșdo binĂĄrio (documento)', - 'Core:AttributeOneWayPassword' => 'Uma forma de senha', - 'Core:AttributeOneWayPassword+' => 'Uma forma de senha encriptado', + 'Core:AttributeOneWayPassword' => 'Senha criptografada', + 'Core:AttributeOneWayPassword+' => 'Uma senha encriptada de uma sĂł via (one-way)', 'Core:AttributeTable' => 'Tabela', - 'Core:AttributeTable+' => 'Matriz indexada tem duas dimensĂ”es', + 'Core:AttributeTable+' => 'Matriz indexada com duas dimensĂ”es', 'Core:AttributePropertySet' => 'Propriedades', 'Core:AttributePropertySet+' => 'Lista de propriedades sem categoria (nome e valor)', 'Core:AttributeFriendlyName' => 'Nome amigĂĄvel', - 'Core:AttributeFriendlyName+' => 'Atributo criado automaticamente; o nome amigĂĄvel Ă© gerado depois de vĂĄrios atributos', + 'Core:AttributeFriendlyName+' => 'Atributo criado automaticamente; o nome amigĂĄvel Ă© baseado nos diferentes atributos do objeto', 'Core:FriendlyName-Label' => 'Nome amigĂĄvel', - 'Core:FriendlyName-Description' => 'Nome amigĂĄvel', + 'Core:FriendlyName-Description' => '', 'Core:AttributeTag' => 'Etiquetas', 'Core:AttributeTag+' => '', @@ -213,7 +213,7 @@ Operadores:
'Core:Context=Setup' => 'Setup', 'Core:Context=GUI:Console' => 'Console', 'Core:Context=CRON' => 'cron', - 'Core:Context=GUI:Portal' => 'Portal', + 'Core:Context=GUI:Portal' => 'Portal do usuĂĄrio', )); @@ -227,20 +227,20 @@ Operadores:
// Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChange' => 'Mudanças', - 'Class:CMDBChange+' => 'Rastreamento de mudanças', + 'Class:CMDBChange' => 'AlteraçÔes no CMDB', + 'Class:CMDBChange+' => 'Controle de mudanças no CMDB', 'Class:CMDBChange/Attribute:date' => 'Data', - 'Class:CMDBChange/Attribute:date+' => 'Data e hora em que as mudanças foram registrados', - 'Class:CMDBChange/Attribute:userinfo' => 'Mais InformaçÔes', - 'Class:CMDBChange/Attribute:userinfo+' => 'InformaçÔes solicitantes definidos', - 'Class:CMDBChange/Attribute:origin/Value:interactive' => 'User interaction in the GUI~~', - 'Class:CMDBChange/Attribute:origin/Value:csv-import.php' => 'CSV import script~~', - 'Class:CMDBChange/Attribute:origin/Value:csv-interactive' => 'CSV import in the GUI~~', - 'Class:CMDBChange/Attribute:origin/Value:email-processing' => 'Email processing~~', - 'Class:CMDBChange/Attribute:origin/Value:synchro-data-source' => 'Synchro. data source~~', - 'Class:CMDBChange/Attribute:origin/Value:webservice-rest' => 'REST/JSON webservices~~', - 'Class:CMDBChange/Attribute:origin/Value:webservice-soap' => 'SOAP webservices~~', - 'Class:CMDBChange/Attribute:origin/Value:custom-extension' => 'By an extension~~', + 'Class:CMDBChange/Attribute:date+' => 'Data e hora em que as alteraçÔes foram registradas', + 'Class:CMDBChange/Attribute:userinfo' => 'InformaçÔes adicionais', + 'Class:CMDBChange/Attribute:userinfo+' => 'InformaçÔes definidas pelos solicitantes', + 'Class:CMDBChange/Attribute:origin/Value:interactive' => 'Interação do usuĂĄrio (GUI)', + 'Class:CMDBChange/Attribute:origin/Value:csv-import.php' => 'Script de importação CSV', + 'Class:CMDBChange/Attribute:origin/Value:csv-interactive' => 'Importação de CSV interativa (GUI)', + 'Class:CMDBChange/Attribute:origin/Value:email-processing' => 'Processamento de e-mail', + 'Class:CMDBChange/Attribute:origin/Value:synchro-data-source' => 'Origem de dados Synchro', + 'Class:CMDBChange/Attribute:origin/Value:webservice-rest' => 'REST/JSON webservices', + 'Class:CMDBChange/Attribute:origin/Value:webservice-soap' => 'SOAP WebServices', + 'Class:CMDBChange/Attribute:origin/Value:custom-extension' => 'Por uma extensĂŁo', )); // @@ -248,19 +248,19 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOp' => 'OperaçÔes de mudanças', - 'Class:CMDBChangeOp+' => 'OperaçÔes de controle de mudança', - 'Class:CMDBChangeOp/Attribute:change' => 'Mudança', + 'Class:CMDBChangeOp' => 'OperaçÔes de alteração', + 'Class:CMDBChangeOp+' => 'OperaçÔes de controle de alteração', + 'Class:CMDBChangeOp/Attribute:change' => 'Alteração', 'Class:CMDBChangeOp/Attribute:change+' => '', 'Class:CMDBChangeOp/Attribute:date' => 'Data', - 'Class:CMDBChangeOp/Attribute:date+' => 'Data e hora da mudança', + 'Class:CMDBChangeOp/Attribute:date+' => 'Data e hora da alteração', 'Class:CMDBChangeOp/Attribute:userinfo' => 'UsuĂĄrio', - 'Class:CMDBChangeOp/Attribute:userinfo+' => 'Quem fez essa mudança', - 'Class:CMDBChangeOp/Attribute:objclass' => 'Classe objeto', + 'Class:CMDBChangeOp/Attribute:userinfo+' => 'Quem fez essa alteração', + 'Class:CMDBChangeOp/Attribute:objclass' => 'Classe do objeto', 'Class:CMDBChangeOp/Attribute:objclass+' => '', - 'Class:CMDBChangeOp/Attribute:objkey' => 'ID objeto', + 'Class:CMDBChangeOp/Attribute:objkey' => 'ID do objeto', 'Class:CMDBChangeOp/Attribute:objkey+' => '', - 'Class:CMDBChangeOp/Attribute:finalclass' => 'tipo', + 'Class:CMDBChangeOp/Attribute:finalclass' => 'Tipo', 'Class:CMDBChangeOp/Attribute:finalclass+' => '', )); @@ -269,8 +269,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOpCreate' => 'Criação do objeto', - 'Class:CMDBChangeOpCreate+' => 'Rastreamento de criação do objeto', + 'Class:CMDBChangeOpCreate' => 'Criação de objeto', + 'Class:CMDBChangeOpCreate+' => 'Controle de criação do objeto', )); // @@ -278,8 +278,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOpDelete' => 'Objeto excluĂ­do', - 'Class:CMDBChangeOpDelete+' => 'Rastreamento de exclusĂŁo do objeto', + 'Class:CMDBChangeOpDelete' => 'ExclusĂŁo de objeto', + 'Class:CMDBChangeOpDelete+' => 'Controle de exclusĂŁo do objeto', )); // @@ -287,10 +287,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOpSetAttribute' => 'Objeto alterado', - 'Class:CMDBChangeOpSetAttribute+' => 'Rastreamento alteração propriedade Objeto', + 'Class:CMDBChangeOpSetAttribute' => 'Alteração de propriedades', + 'Class:CMDBChangeOpSetAttribute+' => 'Controle de alteração de propriedades do objeto', 'Class:CMDBChangeOpSetAttribute/Attribute:attcode' => 'Atributo', - 'Class:CMDBChangeOpSetAttribute/Attribute:attcode+' => 'CĂłdigo da propriedade modificado', + 'Class:CMDBChangeOpSetAttribute/Attribute:attcode+' => 'CĂłdigo da propriedade modificada', )); // @@ -298,28 +298,28 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOpSetAttributeScalar' => 'Propriedade alterado', - 'Class:CMDBChangeOpSetAttributeScalar+' => 'Propriedades escalares objeto de controle de alteraçÔes', + 'Class:CMDBChangeOpSetAttributeScalar' => 'Alteração de propriedades escalares', + 'Class:CMDBChangeOpSetAttributeScalar+' => 'Controle de alteraçÔes de propriedades escalares do objeto', 'Class:CMDBChangeOpSetAttributeScalar/Attribute:oldvalue' => 'Valor anterior', - 'Class:CMDBChangeOpSetAttributeScalar/Attribute:oldvalue+' => 'valor anterior do atributo', + 'Class:CMDBChangeOpSetAttributeScalar/Attribute:oldvalue+' => 'Valor anterior do atributo', 'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue' => 'Novo valor', - 'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue+' => 'novo valor do atributo', + 'Class:CMDBChangeOpSetAttributeScalar/Attribute:newvalue+' => 'Novo valor do atributo', )); // Used by CMDBChangeOp... & derived classes Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Change:ObjectCreated' => 'Objeto criado', 'Change:ObjectDeleted' => 'Objeto excluĂ­do', 'Change:ObjectModified' => 'Objeto modificado', - 'Change:TwoAttributesChanged' => 'Edited %1$s and %2$s~~', - 'Change:ThreeAttributesChanged' => 'Edited %1$s, %2$s and 1 other~~', - 'Change:FourOrMoreAttributesChanged' => 'Edited %1$s, %2$s and %3$s others~~', - 'Change:AttName_SetTo_NewValue_PreviousValue_OldValue' => '%1$s configurado para %2$s (valor anterior: %3$s)', - 'Change:AttName_SetTo' => '%1$s configurado para %2$s', - 'Change:Text_AppendedTo_AttName' => '%1$s anexado ao %2$s', - 'Change:AttName_Changed_PreviousValue_OldValue' => '%1$s modificado, valor anterior: %2$s', - 'Change:AttName_Changed' => '%1$s modificado', - 'Change:AttName_EntryAdded' => '%1$s modificado, nova entrada adicionada: %2$s', - 'Change:State_Changed_NewValue_OldValue' => 'Changed from %2$s to %1$s~~', + 'Change:TwoAttributesChanged' => 'Modificado %1$s e %2$s', + 'Change:ThreeAttributesChanged' => 'Modificado %1$s, %2$s e 1 outro', + 'Change:FourOrMoreAttributesChanged' => 'Modificado %1$s, %2$s e %3$s outros', + 'Change:AttName_SetTo_NewValue_PreviousValue_OldValue' => '%1$s definido para %2$s (valor anterior: %3$s)', + 'Change:AttName_SetTo' => '%1$s definido para %2$s', + 'Change:Text_AppendedTo_AttName' => '%1$s anexado a(o) %2$s', + 'Change:AttName_Changed_PreviousValue_OldValue' => '%1$s modificado(a), valor anterior: %2$s', + 'Change:AttName_Changed' => '%1$s modificado(a)', + 'Change:AttName_EntryAdded' => '%1$s modificado(a), nova entrada adicionada: %2$s', + 'Change:State_Changed_NewValue_OldValue' => 'Modificado de %2$s para %1$s', 'Change:LinkSet:Added' => 'adicionado %1$s', 'Change:LinkSet:Removed' => 'excluĂ­do %1$s', 'Change:LinkSet:Modified' => 'modificado %1$s', @@ -330,10 +330,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOpSetAttributeBlob' => 'data mudança', - 'Class:CMDBChangeOpSetAttributeBlob+' => 'controle de alteraçÔes de dados', + 'Class:CMDBChangeOpSetAttributeBlob' => 'Alteração de conteĂșdo (Blob)', + 'Class:CMDBChangeOpSetAttributeBlob+' => 'Controle de alteraçÔes de conteĂșdo de dados (Blob)', 'Class:CMDBChangeOpSetAttributeBlob/Attribute:prevdata' => 'Valor anterior', - 'Class:CMDBChangeOpSetAttributeBlob/Attribute:prevdata+' => 'conteĂșdo anterior do atributo', + 'Class:CMDBChangeOpSetAttributeBlob/Attribute:prevdata+' => 'ConteĂșdo anterior do atributo', )); // @@ -341,10 +341,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:CMDBChangeOpSetAttributeText' => 'mudança texto', - 'Class:CMDBChangeOpSetAttributeText+' => 'controle de alteraçÔes de texto', + 'Class:CMDBChangeOpSetAttributeText' => 'Alteração de texto', + 'Class:CMDBChangeOpSetAttributeText+' => 'Controle de alteraçÔes de texto do objeto', 'Class:CMDBChangeOpSetAttributeText/Attribute:prevdata' => 'Valor anterior', - 'Class:CMDBChangeOpSetAttributeText/Attribute:prevdata+' => 'conteĂșdo anterior do atributo', + 'Class:CMDBChangeOpSetAttributeText/Attribute:prevdata+' => 'ConteĂșdo anterior do atributo', )); // @@ -352,14 +352,14 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:Event' => 'Evento registros', + 'Class:Event' => 'Registro de evento', 'Class:Event+' => 'Um evento interno do aplicativo', - 'Class:Event/Attribute:message' => 'Mensagens', - 'Class:Event/Attribute:message+' => 'pequena descrição deste evento', + 'Class:Event/Attribute:message' => 'Mensagem', + 'Class:Event/Attribute:message+' => 'Descrição curta deste evento', 'Class:Event/Attribute:date' => 'Data', - 'Class:Event/Attribute:date+' => 'data e hora em que as mudanças foram registradas', - 'Class:Event/Attribute:userinfo' => 'InformaçÔes usuĂĄrio', - 'Class:Event/Attribute:userinfo+' => 'identificação do usuĂĄrio que estava fazendo a ação que desencadeou este evento', + 'Class:Event/Attribute:date+' => 'Data e hora em que o evento foi registrado', + 'Class:Event/Attribute:userinfo' => 'InformaçÔes do usuĂĄrio', + 'Class:Event/Attribute:userinfo+' => 'Identificação do usuĂĄrio que estava executando a ação que desencadeou este evento', 'Class:Event/Attribute:finalclass' => 'Tipo', 'Class:Event/Attribute:finalclass+' => '', )); @@ -369,14 +369,14 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:EventNotification' => 'Evento notificação', - 'Class:EventNotification+' => 'Rastreamento de uma notificação que foi enviada', + 'Class:EventNotification' => 'Notificação de evento', + 'Class:EventNotification+' => 'Controle de notificaçÔes que foram enviadas', 'Class:EventNotification/Attribute:trigger_id' => 'Gatilho', - 'Class:EventNotification/Attribute:trigger_id+' => 'conta usuĂĄrio', - 'Class:EventNotification/Attribute:action_id' => 'usuĂĄrio', - 'Class:EventNotification/Attribute:action_id+' => 'conta usuĂĄrio', - 'Class:EventNotification/Attribute:object_id' => 'Id objeto', - 'Class:EventNotification/Attribute:object_id+' => 'Id objeto (classe definida pelo gatilho?)', + 'Class:EventNotification/Attribute:trigger_id+' => 'Conta de usuĂĄrio', + 'Class:EventNotification/Attribute:action_id' => 'UsuĂĄrio', + 'Class:EventNotification/Attribute:action_id+' => 'Conta de usuĂĄrio', + 'Class:EventNotification/Attribute:object_id' => 'ID do objeto', + 'Class:EventNotification/Attribute:object_id+' => 'ID do objeto (classe definida pelo gatilho?)', )); // @@ -384,20 +384,20 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:EventNotificationEmail' => 'Evento envio email', - 'Class:EventNotificationEmail+' => 'Rastreamento de um e-mail que foi enviado', + 'Class:EventNotificationEmail' => 'Evento de envio de e-mail', + 'Class:EventNotificationEmail+' => 'Controle de e-mails que foram enviados', 'Class:EventNotificationEmail/Attribute:to' => 'Para', - 'Class:EventNotificationEmail/Attribute:to+' => '', + 'Class:EventNotificationEmail/Attribute:to+' => 'Endereço(s) de e-mail do(s) destinatĂĄrio(s)', 'Class:EventNotificationEmail/Attribute:cc' => 'CC', - 'Class:EventNotificationEmail/Attribute:cc+' => '', + 'Class:EventNotificationEmail/Attribute:cc+' => 'Endereço(s) de e-mail do(s) destinarĂĄio(s) com cĂłpia', 'Class:EventNotificationEmail/Attribute:bcc' => 'CCO', - 'Class:EventNotificationEmail/Attribute:bcc+' => '', + 'Class:EventNotificationEmail/Attribute:bcc+' => 'Endereço(s) de e-mail do(s) destinatĂĄrio(s) com cĂłpia oculta', 'Class:EventNotificationEmail/Attribute:from' => 'De', - 'Class:EventNotificationEmail/Attribute:from+' => 'Remetente da mensagem', + 'Class:EventNotificationEmail/Attribute:from+' => 'Remetente do e-mail', 'Class:EventNotificationEmail/Attribute:subject' => 'Assunto', - 'Class:EventNotificationEmail/Attribute:subject+' => '', + 'Class:EventNotificationEmail/Attribute:subject+' => 'TĂ­tulo do e-mail', 'Class:EventNotificationEmail/Attribute:body' => 'Corpo', - 'Class:EventNotificationEmail/Attribute:body+' => '', + 'Class:EventNotificationEmail/Attribute:body+' => 'ConteĂșdo do e-mail', 'Class:EventNotificationEmail/Attribute:attachments' => 'Anexos', 'Class:EventNotificationEmail/Attribute:attachments+' => '', )); @@ -407,21 +407,21 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:EventIssue' => 'Evento entrega', - 'Class:EventIssue+' => 'Rastreamento de entrega (aviso, erro, etc.)', + 'Class:EventIssue' => 'Evento de entrega', + 'Class:EventIssue+' => 'Controle de entrega (aviso, erro, etc.)', 'Class:EventIssue/Attribute:issue' => 'Entrega', 'Class:EventIssue/Attribute:issue+' => 'O que aconteceu', 'Class:EventIssue/Attribute:impact' => 'Impacto', 'Class:EventIssue/Attribute:impact+' => 'Quais sĂŁo as consequĂȘncias', 'Class:EventIssue/Attribute:page' => 'PĂĄgina', - 'Class:EventIssue/Attribute:page+' => 'HTTP ponto de entrada', - 'Class:EventIssue/Attribute:arguments_post' => 'Argumentos postados', + 'Class:EventIssue/Attribute:page+' => 'Ponto de entrada HTTP', + 'Class:EventIssue/Attribute:arguments_post' => 'Argumentos POST', 'Class:EventIssue/Attribute:arguments_post+' => 'Argumentos HTTP POST', 'Class:EventIssue/Attribute:arguments_get' => 'Argumentos URL', 'Class:EventIssue/Attribute:arguments_get+' => 'Argumentos HTTP GET', - 'Class:EventIssue/Attribute:callstack' => 'Quantidade solicitaçÔes', - 'Class:EventIssue/Attribute:callstack+' => 'Quantidade de solicitaçÔes', - 'Class:EventIssue/Attribute:data' => 'Dado', + 'Class:EventIssue/Attribute:callstack' => 'Quantidade de solicitaçÔes', + 'Class:EventIssue/Attribute:callstack+' => '', + 'Class:EventIssue/Attribute:data' => 'Dados', 'Class:EventIssue/Attribute:data+' => 'Mais informaçÔes', )); @@ -431,34 +431,34 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:EventWebService' => 'Evento Web service', - 'Class:EventWebService+' => 'Rastreamento de uma solicitação de serviço web', - 'Class:EventWebService/Attribute:verb' => 'Verbo', + 'Class:EventWebService+' => 'Controle de uma solicitação de WebService', + 'Class:EventWebService/Attribute:verb' => 'Verb', 'Class:EventWebService/Attribute:verb+' => 'Nome da operação', 'Class:EventWebService/Attribute:result' => 'Resultado', - 'Class:EventWebService/Attribute:result+' => 'Sucesso/fracasso geral', - 'Class:EventWebService/Attribute:log_info' => 'Log informação', - 'Class:EventWebService/Attribute:log_info+' => 'Resultado log informação', + 'Class:EventWebService/Attribute:result+' => 'Sucesso/erro geral', + 'Class:EventWebService/Attribute:log_info' => 'Log de resultado', + 'Class:EventWebService/Attribute:log_info+' => '', 'Class:EventWebService/Attribute:log_warning' => 'Log de alerta', - 'Class:EventWebService/Attribute:log_warning+' => 'Resultado log de alerta', + 'Class:EventWebService/Attribute:log_warning+' => '', 'Class:EventWebService/Attribute:log_error' => 'Log de erro', - 'Class:EventWebService/Attribute:log_error+' => 'Resultado log de erro', - 'Class:EventWebService/Attribute:data' => 'Dado', - 'Class:EventWebService/Attribute:data+' => 'Resultado dado', + 'Class:EventWebService/Attribute:log_error+' => '', + 'Class:EventWebService/Attribute:data' => 'Dados', + 'Class:EventWebService/Attribute:data+' => 'Mais informaçÔes', )); Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:EventRestService' => 'Chamada REST/JSON', - 'Class:EventRestService+' => 'Rastreio de uma chamada de serviço REST/JSON', - 'Class:EventRestService/Attribute:operation' => 'Operation', - 'Class:EventRestService/Attribute:operation+' => 'Argument \'operation\'', + 'Class:EventRestService+' => 'Controle de uma chamada de serviço REST/JSON', + 'Class:EventRestService/Attribute:operation' => 'Operação', + 'Class:EventRestService/Attribute:operation+' => 'Argumento \'operation\'', 'Class:EventRestService/Attribute:version' => 'VersĂŁo', - 'Class:EventRestService/Attribute:version+' => 'Argument \'version\'', + 'Class:EventRestService/Attribute:version+' => 'Argumento \'version\'', 'Class:EventRestService/Attribute:json_input' => 'Input', 'Class:EventRestService/Attribute:json_input+' => 'Argumento \'json_data\'', - 'Class:EventRestService/Attribute:code' => 'Code', + 'Class:EventRestService/Attribute:code' => 'CĂłdigo', 'Class:EventRestService/Attribute:code+' => 'CĂłdigo de resultado', - 'Class:EventRestService/Attribute:json_output' => 'Response', - 'Class:EventRestService/Attribute:json_output+' => 'Resposta HTTP (json)', + 'Class:EventRestService/Attribute:json_output' => 'Resposta', + 'Class:EventRestService/Attribute:json_output+' => 'Resposta HTTP (JSON)', 'Class:EventRestService/Attribute:provider' => 'Provedor', 'Class:EventRestService/Attribute:provider+' => 'Classe PHP implementando a operação esperada', )); @@ -468,14 +468,14 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:EventLoginUsage' => 'Login utilizado', - 'Class:EventLoginUsage+' => 'ConexĂŁo com a aplicação', + 'Class:EventLoginUsage' => 'Logins', + 'Class:EventLoginUsage+' => 'ConexĂ”es com a aplicação', 'Class:EventLoginUsage/Attribute:user_id' => 'Login', 'Class:EventLoginUsage/Attribute:user_id+' => '', - 'Class:EventLoginUsage/Attribute:contact_name' => 'Nome usuĂĄrio', + 'Class:EventLoginUsage/Attribute:contact_name' => 'Nome de usuĂĄrio', 'Class:EventLoginUsage/Attribute:contact_name+' => '', - 'Class:EventLoginUsage/Attribute:contact_email' => 'Email usuĂĄrio', - 'Class:EventLoginUsage/Attribute:contact_email+' => 'Endereço email deste usuĂĄrio', + 'Class:EventLoginUsage/Attribute:contact_email' => 'E-mail do usuĂĄrio', + 'Class:EventLoginUsage/Attribute:contact_email+' => 'Endereço de e-mail deste usuĂĄrio', )); // @@ -484,24 +484,24 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:Action' => 'Ação personalizada', - 'Class:Action+' => 'Ação definida pelo usuĂĄrio', + 'Class:Action+' => 'AçÔes definidas pelo usuĂĄrio', 'Class:Action/Attribute:name' => 'Nome', 'Class:Action/Attribute:name+' => '', 'Class:Action/Attribute:description' => 'Descrição', 'Class:Action/Attribute:description+' => '', 'Class:Action/Attribute:status' => 'Status', - 'Class:Action/Attribute:status+' => 'Em produção ou ?', - 'Class:Action/Attribute:status/Value:test' => 'sendo testado', + 'Class:Action/Attribute:status+' => 'Ativo ou ?', + 'Class:Action/Attribute:status/Value:test' => 'Em homologação', 'Class:Action/Attribute:status/Value:test+' => '', - 'Class:Action/Attribute:status/Value:enabled' => 'Em produção', + 'Class:Action/Attribute:status/Value:enabled' => 'Ativo', 'Class:Action/Attribute:status/Value:enabled+' => '', 'Class:Action/Attribute:status/Value:disabled' => 'Inativo', 'Class:Action/Attribute:status/Value:disabled+' => '', 'Class:Action/Attribute:trigger_list' => 'Gatilhos relacionados', - 'Class:Action/Attribute:trigger_list+' => 'Gatilhos ligados a esta ação', + 'Class:Action/Attribute:trigger_list+' => 'Gatilhos associadas Ă  esta ação', 'Class:Action/Attribute:finalclass' => 'Tipo', 'Class:Action/Attribute:finalclass+' => '', - 'Action:WarningNoTriggerLinked' => 'Warning, no trigger is linked to the action. It will not be active until it has at least 1.~~', + 'Action:WarningNoTriggerLinked' => 'Aviso, nenhum gatilho estĂĄ associado Ă  ação. NĂŁo serĂĄ ativo atĂ© que esta ação tenha pelo menos um gatilho associado', )); // @@ -518,39 +518,39 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:ActionEmail' => 'Notificação email', - 'Class:ActionEmail+' => '', - 'Class:ActionEmail/Attribute:status+' => 'This status drives who will be notified: just the Test recipient, all (To, cc and Bcc) or no-one~~', - 'Class:ActionEmail/Attribute:status/Value:test+' => 'Only the Test recipient is notified~~', - 'Class:ActionEmail/Attribute:status/Value:enabled+' => 'All To, Cc and Bcc emails are notified~~', - 'Class:ActionEmail/Attribute:status/Value:disabled+' => 'The email notification will not be sent~~', - 'Class:ActionEmail/Attribute:test_recipient' => 'Testar destinatĂĄrio', - 'Class:ActionEmail/Attribute:test_recipient+' => 'DestinatĂĄrio em caso o estado estĂĄ definido como "Teste"', - 'Class:ActionEmail/Attribute:from' => 'De~~', - 'Class:ActionEmail/Attribute:from+' => 'SerĂĄ enviado para o cabeçalho de email~~', - 'Class:ActionEmail/Attribute:from_label' => 'From (label)~~', - 'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~', - 'Class:ActionEmail/Attribute:reply_to' => 'Responder para~~', - 'Class:ActionEmail/Attribute:reply_to+' => 'SerĂĄ enviado para o cabeçalho de email~~', - 'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~', - 'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~', + 'Class:ActionEmail' => 'Notificação via E-mail', + 'Class:ActionEmail+' => 'Lista de NotificaçÔes via E-mail', + 'Class:ActionEmail/Attribute:status+' => 'Esse status especifica quem serĂĄ notificado: apenas o destinatĂĄrio do Teste, todos (Para, CC e CCO) ou ninguĂ©m', + 'Class:ActionEmail/Attribute:status/Value:test' => 'Apenas o destinatĂĄrio de teste Ă© notificado', + 'Class:ActionEmail/Attribute:status/Value:enabled' => 'Todos os endereços de e-mails dos campos Para, CC e CCO sĂŁo notificados', + 'Class:ActionEmail/Attribute:status/Value:disabled' => 'A notificação de e-mail nĂŁo serĂĄ enviada', + 'Class:ActionEmail/Attribute:test_recipient' => 'DestinatĂĄrio de teste', + 'Class:ActionEmail/Attribute:test_recipient+' => 'DestinatĂĄrio caso o status esteja definido como "teste"', + 'Class:ActionEmail/Attribute:from' => 'De', + 'Class:ActionEmail/Attribute:from+' => 'Endereço de e-mail do remetente enviado no cabeçalho do e-mail', + 'Class:ActionEmail/Attribute:from_label' => 'De (campo)', + 'Class:ActionEmail/Attribute:from_label+' => 'Nome de exibição enviado no cabeçalho do e-mail', + 'Class:ActionEmail/Attribute:reply_to' => 'Responder para', + 'Class:ActionEmail/Attribute:reply_to+' => 'Endereço de e-mail enviado no cabeçalho do e-mail', + 'Class:ActionEmail/Attribute:reply_to_label' => 'Responder para (campo)', + 'Class:ActionEmail/Attribute:reply_to_label+' => 'Nome de exibição enviado no cabeçalho do e-mail', 'Class:ActionEmail/Attribute:to' => 'Para', - 'Class:ActionEmail/Attribute:to+' => 'DestinatĂĄrio para o email', + 'Class:ActionEmail/Attribute:to+' => 'Endereço(s) de e-mail do(s) destinatĂĄrio(s)', 'Class:ActionEmail/Attribute:cc' => 'CC', - 'Class:ActionEmail/Attribute:cc+' => '', + 'Class:ActionEmail/Attribute:cc+' => 'Endereço(s) de e-mail do(s) destinarĂĄio(s) com cĂłpia', 'Class:ActionEmail/Attribute:bcc' => 'CCO', - 'Class:ActionEmail/Attribute:bcc+' => '', - 'Class:ActionEmail/Attribute:subject' => 'assunto', - 'Class:ActionEmail/Attribute:subject+' => 'TĂ­tulo do email', - 'Class:ActionEmail/Attribute:body' => 'corpo', - 'Class:ActionEmail/Attribute:body+' => 'ConteĂșdo do email', - 'Class:ActionEmail/Attribute:importance' => 'importĂąncia', - 'Class:ActionEmail/Attribute:importance+' => 'Flag importĂąncia', - 'Class:ActionEmail/Attribute:importance/Value:low' => 'baixo', + 'Class:ActionEmail/Attribute:bcc+' => 'Endereço(s) de e-mail do(s) destinatĂĄrio(s) com cĂłpia oculta', + 'Class:ActionEmail/Attribute:subject' => 'Assunto', + 'Class:ActionEmail/Attribute:subject+' => 'TĂ­tulo do e-mail', + 'Class:ActionEmail/Attribute:body' => 'Corpo', + 'Class:ActionEmail/Attribute:body+' => 'ConteĂșdo do e-mail', + 'Class:ActionEmail/Attribute:importance' => 'Prioridade', + 'Class:ActionEmail/Attribute:importance+' => '', + 'Class:ActionEmail/Attribute:importance/Value:low' => 'Baixa', 'Class:ActionEmail/Attribute:importance/Value:low+' => '', - 'Class:ActionEmail/Attribute:importance/Value:normal' => 'normal', + 'Class:ActionEmail/Attribute:importance/Value:normal' => 'Normal', 'Class:ActionEmail/Attribute:importance/Value:normal+' => '', - 'Class:ActionEmail/Attribute:importance/Value:high' => 'alto', + 'Class:ActionEmail/Attribute:importance/Value:high' => 'Alta', 'Class:ActionEmail/Attribute:importance/Value:high+' => '', )); @@ -562,13 +562,13 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:Trigger' => 'Gatilho', 'Class:Trigger+' => 'Manipulador de eventos personalizado', 'Class:Trigger/Attribute:description' => 'Descrição', - 'Class:Trigger/Attribute:description+' => 'uma linha descrição', + 'Class:Trigger/Attribute:description+' => 'Uma descrição curta', 'Class:Trigger/Attribute:action_list' => 'AçÔes desencadeadas', - 'Class:Trigger/Attribute:action_list+' => 'AçÔes executadas quando o gatilho Ă© ativado', + 'Class:Trigger/Attribute:action_list+' => 'AçÔes executadas quando o gatilho Ă© acionado', 'Class:Trigger/Attribute:finalclass' => 'Tipo', 'Class:Trigger/Attribute:finalclass+' => '', 'Class:Trigger/Attribute:context' => 'Contexto', - 'Class:Trigger/Attribute:context+' => 'Contexto para permitir o gatilho ser ativado', + 'Class:Trigger/Attribute:context+' => 'Contexto para permitir o acionamento do gatilho', )); // @@ -581,7 +581,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:TriggerOnObject/Attribute:target_class' => 'Classe alvo', 'Class:TriggerOnObject/Attribute:target_class+' => '', 'Class:TriggerOnObject/Attribute:filter' => 'Filtro', - 'Class:TriggerOnObject/Attribute:filter+' => 'Limit the object list (of the target class) which will activate the trigger~~', + 'Class:TriggerOnObject/Attribute:filter+' => 'Limita a lista de objetos (da classe de destino) que irĂĄ ativar o gatilho', 'TriggerOnObject:WrongFilterQuery' => 'Consulta de filtro incorreta: %1$s', 'TriggerOnObject:WrongFilterClass' => 'A consulta de filtro deve retornar objetos da classe \\"%1$s\\"', )); @@ -591,8 +591,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnPortalUpdate' => 'Gatilho (quando atualizado a partir do portal)', - 'Class:TriggerOnPortalUpdate+' => 'Gatilho de uma atualização do usuĂĄrio final a partir do portal', + 'Class:TriggerOnPortalUpdate' => 'Gatilho (quando atualizado a partir do portal do usuĂĄrio)', + 'Class:TriggerOnPortalUpdate+' => 'Gatilho acionado a partir de uma atualização do usuĂĄrio final atravĂ©s do portal do usuĂĄrio', )); // @@ -600,9 +600,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnStateChange' => 'Gatilho (na mudança de estado)', - 'Class:TriggerOnStateChange+' => 'Gatilho de mudança do estado do objeto', - 'Class:TriggerOnStateChange/Attribute:state' => 'State', + 'Class:TriggerOnStateChange' => 'Gatilho (na mudança de status)', + 'Class:TriggerOnStateChange+' => 'Gatilho de mudança de status do objeto', + 'Class:TriggerOnStateChange/Attribute:state' => 'Status', 'Class:TriggerOnStateChange/Attribute:state+' => '', )); @@ -611,8 +611,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnStateEnter' => 'Gatilho (ao entrar em um estado)', - 'Class:TriggerOnStateEnter+' => 'Gatilho de mudança do estado do objeto - entrando', + 'Class:TriggerOnStateEnter' => 'Gatilho (ao entrar em um status)', + 'Class:TriggerOnStateEnter+' => 'Gatilho de mudança de status do objeto - entrada', )); // @@ -620,8 +620,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnStateLeave' => 'Gatilho (para sair de um estado)', - 'Class:TriggerOnStateLeave+' => 'Gatilho de mudança do estado do objeto - saindo', + 'Class:TriggerOnStateLeave' => 'Gatilho (ao sair de um status)', + 'Class:TriggerOnStateLeave+' => 'Gatilho de mudança de status do objeto - saĂ­da', )); // @@ -630,7 +630,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:TriggerOnObjectCreate' => 'Gatilho (na criação do objeto)', - 'Class:TriggerOnObjectCreate+' => 'Gatilho de criação do objeto de [a classe filha] determinada classe', + 'Class:TriggerOnObjectCreate+' => 'Gatilho de criação de objeto de [uma classe filha] de determinada classe', )); // @@ -638,8 +638,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnObjectDelete' => 'Trigger (na exclusĂŁo de objetos)', - 'Class:TriggerOnObjectDelete+' => 'Trigger na exclusĂŁo de objeto de [uma classe filho] da classe dada', + 'Class:TriggerOnObjectDelete' => 'Gatilho (na exclusĂŁo de objetos)', + 'Class:TriggerOnObjectDelete+' => 'Gatilho na exclusĂŁo de objeto de [uma classe filha] de determinada classe', )); // @@ -647,8 +647,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnObjectUpdate' => 'Trigger (na atualização do objeto)', - 'Class:TriggerOnObjectUpdate+' => 'Trigger na atualização de objeto de [uma classe filho] da classe dada', + 'Class:TriggerOnObjectUpdate' => 'Gatilho (na atualização do objeto)', + 'Class:TriggerOnObjectUpdate+' => 'Gatilho na atualização de objeto de [uma classe filha] de uma determinada classe', 'Class:TriggerOnObjectUpdate/Attribute:target_attcodes' => 'Campos de destino', 'Class:TriggerOnObjectUpdate/Attribute:target_attcodes+' => '', )); @@ -658,10 +658,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnObjectMention' => 'Trigger (on object mention)~~', - 'Class:TriggerOnObjectMention+' => 'Trigger on mention (@xxx) of an object of [a child class of] the given class in a log attribute~~', - 'Class:TriggerOnObjectMention/Attribute:mentioned_filter' => 'Mentioned filter~~', - 'Class:TriggerOnObjectMention/Attribute:mentioned_filter+' => 'Limit the list of mentioned objects which will activate the trigger. If empty, any mentioned object (of any class) will activate it.~~', + 'Class:TriggerOnObjectMention' => 'Gatilho (na menção do objeto)', + 'Class:TriggerOnObjectMention+' => 'Gatilho em menção (@xxx) de um objeto de [uma classe filha] de uma determinada classe em um atributo de log', + 'Class:TriggerOnObjectMention/Attribute:mentioned_filter' => 'Filtro de mençÔes', + 'Class:TriggerOnObjectMention/Attribute:mentioned_filter+' => 'Limita a lista de objetos mencionados que ativarĂŁo o gatilho. Se vazio, qualquer objeto mencionado (de qualquer classe) irĂĄ ativĂĄ-lo', )); // @@ -669,11 +669,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:TriggerOnThresholdReached' => 'Gatilho (na atingimento de limite)', - 'Class:TriggerOnThresholdReached+' => 'Gatilho de limite do cronĂŽmetro atingido', + 'Class:TriggerOnThresholdReached' => 'Gatilho (no alcance do limite)', + 'Class:TriggerOnThresholdReached+' => 'Gatilho no alcance do limite do cronĂŽmetro', 'Class:TriggerOnThresholdReached/Attribute:stop_watch_code' => 'CronĂŽmetro', 'Class:TriggerOnThresholdReached/Attribute:stop_watch_code+' => '', - 'Class:TriggerOnThresholdReached/Attribute:threshold_index' => 'Entrada', + 'Class:TriggerOnThresholdReached/Attribute:threshold_index' => 'Limite', 'Class:TriggerOnThresholdReached/Attribute:threshold_index+' => '', )); @@ -682,8 +682,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:lnkTriggerAction' => 'AçÔes/Gatilho', - 'Class:lnkTriggerAction+' => 'Ligação entre um Gatilho e uma Ação', + 'Class:lnkTriggerAction' => 'Ação/Gatilho', + 'Class:lnkTriggerAction+' => 'Link Gatilho / Ação', 'Class:lnkTriggerAction/Attribute:action_id' => 'Ação', 'Class:lnkTriggerAction/Attribute:action_id+' => 'Ação a ser executada', 'Class:lnkTriggerAction/Attribute:action_name' => 'Ação', @@ -708,30 +708,30 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:SynchroDataSource/Attribute:user_id' => 'UsuĂĄrio', 'Class:SynchroDataSource/Attribute:notify_contact_id' => 'Contato para notificação', 'Class:SynchroDataSource/Attribute:notify_contact_id+' => 'Contato para notificar em caso de erro', - 'Class:SynchroDataSource/Attribute:url_icon' => 'Icones hiperlink', - 'Class:SynchroDataSource/Attribute:url_icon+' => 'Hiperlink de uma pequena imagem representando o aplicativo com o qual o iTop Ă© sincronizado', - 'Class:SynchroDataSource/Attribute:url_application' => 'Hiperlink aplicativo', - 'Class:SynchroDataSource/Attribute:url_application+' => 'Hiperlink para o objeto na aplicação externa com a qual o iTop Ă© sincronizado (se aplicĂĄvel). As substituiçÔes possĂ­veis: $this->attribute$ e $replica->primary_key$', - 'Class:SynchroDataSource/Attribute:reconciliation_policy' => 'PolĂ­tica reconciliação', - 'Class:SynchroDataSource/Attribute:full_load_periodicity' => 'Intervalo da carga plena', - 'Class:SynchroDataSource/Attribute:full_load_periodicity+' => 'A recarga completa de todos os dados devem ocorrer pelo menos tĂŁo frequentemente como especificado aqui', + 'Class:SynchroDataSource/Attribute:url_icon' => 'Ícone de Hiperlink', + 'Class:SynchroDataSource/Attribute:url_icon+' => 'Hiperlink de uma pequena imagem representando o aplicativo com o qual o '.ITOP_APPLICATION_SHORT.' Ă© sincronizado', + 'Class:SynchroDataSource/Attribute:url_application' => 'Hiperlink de aplicativo', + 'Class:SynchroDataSource/Attribute:url_application+' => 'Hiperlink para o objeto na aplicação externa com a qual o '.ITOP_APPLICATION_SHORT.' Ă© sincronizado (se aplicĂĄvel). As substituiçÔes possĂ­veis: $this->attribute$ e $replica->primary_key$', + 'Class:SynchroDataSource/Attribute:reconciliation_policy' => 'PolĂ­tica de reconciliação', + 'Class:SynchroDataSource/Attribute:full_load_periodicity' => 'Intervalo de obsolescĂȘncia programada', + 'Class:SynchroDataSource/Attribute:full_load_periodicity+' => 'Um objeto Ă© considerado obsoleto se nĂŁo aparecer nos dados alĂ©m desse tempo', 'Class:SynchroDataSource/Attribute:action_on_zero' => 'Ação sobre zero', 'Class:SynchroDataSource/Attribute:action_on_zero+' => 'Medidas tomadas quando a busca retorna nenhum objeto', 'Class:SynchroDataSource/Attribute:action_on_one' => 'Ação em um', - 'Class:SynchroDataSource/Attribute:action_on_one+' => 'Medidas tomadas quando a busca retorna exatamente um objeto', + 'Class:SynchroDataSource/Attribute:action_on_one+' => 'Medidas tomadas quando a busca retorna exatamente um Ășnico objeto', 'Class:SynchroDataSource/Attribute:action_on_multiple' => 'Ação em muitos', 'Class:SynchroDataSource/Attribute:action_on_multiple+' => 'Medidas tomadas quando a busca retorna mais de um objeto', 'Class:SynchroDataSource/Attribute:user_delete_policy' => 'UsuĂĄrios permitidos', 'Class:SynchroDataSource/Attribute:user_delete_policy+' => 'Quem tem permissĂŁo para excluir objetos sincronizados', 'Class:SynchroDataSource/Attribute:delete_policy/Value:never' => 'NinguĂ©m', - 'Class:SynchroDataSource/Attribute:delete_policy/Value:depends' => 'Somente Administradores', - 'Class:SynchroDataSource/Attribute:delete_policy/Value:always' => 'Todos os usuĂĄrios permitidos', + 'Class:SynchroDataSource/Attribute:delete_policy/Value:depends' => 'Somente administradores', + 'Class:SynchroDataSource/Attribute:delete_policy/Value:always' => 'Todos os usuĂĄrios', 'Class:SynchroDataSource/Attribute:delete_policy_update' => 'Regras de atualização', 'Class:SynchroDataSource/Attribute:delete_policy_update+' => 'Sintaxe: nome_do_campo:valor; ...', - 'Class:SynchroDataSource/Attribute:delete_policy_retention' => 'Duração de retenção', - 'Class:SynchroDataSource/Attribute:delete_policy_retention+' => 'Quanto tempo um objeto obsoleto Ă© mantida antes de ser excluĂ­do', - 'Class:SynchroDataSource/Attribute:database_table_name' => 'Tabela de dados', - 'Class:SynchroDataSource/Attribute:database_table_name+' => 'Nome da tabela para armazenar os dados de sincronização. Se for deixado vazio, um nome padrĂŁo serĂĄ computado.', + 'Class:SynchroDataSource/Attribute:delete_policy_retention' => 'Duração da retenção', + 'Class:SynchroDataSource/Attribute:delete_policy_retention+' => 'Quanto tempo um objeto obsoleto Ă© mantido antes de ser excluĂ­do', + 'Class:SynchroDataSource/Attribute:database_table_name' => 'Tabela do banco de dados', + 'Class:SynchroDataSource/Attribute:database_table_name+' => 'Nome da tabela para armazenar os dados de sincronização. Se for deixado vazio, um nome padrĂŁo serĂĄ computado', 'SynchroDataSource:Description' => 'Descrição', 'SynchroDataSource:Reconciliation' => 'Pesquisa & reconciliação', 'SynchroDataSource:Deletion' => 'Regras de exclusĂŁo', @@ -752,12 +752,12 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:SynchroUpdate:Yes' => 'Sim', 'Core:SynchroUpdate:No' => 'NĂŁo', 'Core:Synchro:LastestStatus' => 'Último Status', - 'Core:Synchro:History' => 'HistĂłrico sincronização', - 'Core:Synchro:NeverRun' => 'Este sincronismo nunca foi executado. Sem registo ainda.', - 'Core:Synchro:SynchroEndedOn_Date' => 'A Ășltima sincronização terminou em %1$s.', - 'Core:Synchro:SynchroRunningStartedOn_Date' => 'A sincronização começou em %1$s ainda estĂĄ em execução...', - 'Menu:DataSources' => 'Fontes de dados de sincronização', // Duplicated into itop-welcome-itil (will be removed from here...) - 'Menu:DataSources+' => 'Todas fontes de dados de sincronização', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Core:Synchro:History' => 'HistĂłrico de sincronização', + 'Core:Synchro:NeverRun' => 'Esta sincronização nunca foi executada. Sem registro ainda', + 'Core:Synchro:SynchroEndedOn_Date' => 'A Ășltima sincronização terminou em %1$s', + 'Core:Synchro:SynchroRunningStartedOn_Date' => 'A sincronização iniciou em %1$s ainda estĂĄ em execução...', + 'Menu:DataSources' => 'Fontes de Sincronização de Dados', // Duplicated into itop-welcome-itil (will be removed from here...) + 'Menu:DataSources+' => 'Lista de Fontes de Sincronização de Dados', // Duplicated into itop-welcome-itil (will be removed from here...) 'Core:Synchro:label_repl_ignored' => 'Ignoradas (%1$s)', 'Core:Synchro:label_repl_disappeared' => 'Desaparecido (%1$s)', 'Core:Synchro:label_repl_existing' => 'Saindo (%1$s)', @@ -774,17 +774,17 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:Synchro:label_obj_created' => 'Criado (%1$s)', 'Core:Synchro:label_obj_new_errors' => 'Erros (%1$s)', 'Core:SynchroLogTitle' => '%1$s - %2$s', - 'Core:Synchro:Nb_Replica' => 'Replica processado: %1$s', + 'Core:Synchro:Nb_Replica' => 'RĂ©plica processada: %1$s', 'Core:Synchro:Nb_Class:Objects' => '%1$s: %2$s', - 'Class:SynchroDataSource/Error:AtLeastOneReconciliationKeyMustBeSpecified' => 'Pelo menos uma chave de reconciliação deve ser especificado, ou a polĂ­tica de reconciliação deve ser a de usar a chave primĂĄria.', - 'Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified' => 'Um perĂ­odo de retenção excluir deve ser especificado, jĂĄ que objetos devem ser excluĂ­dos depois de ser marcado como obsoleto.', - 'Class:SynchroDataSource/Error:DeletePolicyUpdateMustBeSpecified' => 'Objetos obsoletos devem ser atualizados, mas nenhuma atualização Ă© especificado.', - 'Class:SynchroDataSource/Error:DataTableAlreadyExists' => 'A tabela %1$s jĂĄ existe na base de dados. Por favor, use um outro nome para a tabela de dados sincronizada.', + 'Class:SynchroDataSource/Error:AtLeastOneReconciliationKeyMustBeSpecified' => 'Pelo menos uma chave de reconciliação deve ser especificada, ou a polĂ­tica de reconciliação deve ser a de usar a chave primĂĄria', + 'Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified' => 'Um perĂ­odo de retenção de exclusĂŁo deve ser especificado, jĂĄ que objetos devem ser excluĂ­dos depois de serem marcados como obsoletos', + 'Class:SynchroDataSource/Error:DeletePolicyUpdateMustBeSpecified' => 'Objetos obsoletos devem ser atualizados, mas nenhuma polĂ­tica de atualização foi especificada', + 'Class:SynchroDataSource/Error:DataTableAlreadyExists' => 'A tabela "%1$s" jĂĄ existe no banco de dados. Por favor, use um outro nome para a tabela de dados sincronizada', 'Core:SynchroReplica:PublicData' => 'Dados pĂșblicos', - 'Core:SynchroReplica:PrivateDetails' => 'Detalhes privado', + 'Core:SynchroReplica:PrivateDetails' => 'Detalhes privados', 'Core:SynchroReplica:BackToDataSource' => 'Voltar para a fonte de dados sincronização: %1$s', - 'Core:SynchroReplica:ListOfReplicas' => 'Lista de replica', - 'Core:SynchroAttExtKey:ReconciliationById' => 'Id (chave primĂĄria)', + 'Core:SynchroReplica:ListOfReplicas' => 'Lista de rĂ©plica', + 'Core:SynchroAttExtKey:ReconciliationById' => 'ID (chave primĂĄria)', 'Core:SynchroAtt:attcode' => 'Atributo', 'Core:SynchroAtt:attcode+' => 'Campo do objeto', 'Core:SynchroAtt:reconciliation' => 'Reconciliação?', @@ -793,38 +793,38 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:SynchroAtt:update+' => 'Usado para atualizar o objeto', 'Core:SynchroAtt:update_policy' => 'PolĂ­tica de atualização', 'Core:SynchroAtt:update_policy+' => 'Comportamento do campo atualizado', - 'Core:SynchroAtt:reconciliation_attcode' => 'Chave reconciliação', - 'Core:SynchroAtt:reconciliation_attcode+' => 'CĂłdigo atributo para a reconciliação chave externa', + 'Core:SynchroAtt:reconciliation_attcode' => 'Chave de reconciliação', + 'Core:SynchroAtt:reconciliation_attcode+' => 'CĂłdigo de atributo para a reconciliação de chave externa', 'Core:SyncDataExchangeComment' => '(Sincronização dado)', 'Core:Synchro:ListOfDataSources' => 'Lista de fontes de dados:', 'Core:Synchro:LastSynchro' => 'Última sincronização:', 'Core:Synchro:ThisObjectIsSynchronized' => 'Este objeto Ă© sincronizado com uma fonte de dados externa', - 'Core:Synchro:TheObjectWasCreatedBy_Source' => 'O objeto foi criado pela fonte de dados externa %1$s', - 'Core:Synchro:TheObjectCanBeDeletedBy_Source' => 'O objeto nĂŁo pode ser excluĂ­do pela fonte de dados externa %1$s', - 'Core:Synchro:TheObjectCannotBeDeletedByUser_Source' => 'VocĂȘ nĂŁo pode excluir o objeto porque Ă© propriedade de uma fonte de dados externa %1$s', + 'Core:Synchro:TheObjectWasCreatedBy_Source' => 'O objeto foi criado pela fonte de dados externa "%1$s"', + 'Core:Synchro:TheObjectCanBeDeletedBy_Source' => 'O objeto nĂŁo pode ser excluĂ­do pela fonte de dados externa "%1$s"', + 'Core:Synchro:TheObjectCannotBeDeletedByUser_Source' => 'VocĂȘ nĂŁo pode excluir o objeto porque Ă© propriedade de uma fonte de dados externa "%1$s"', 'TitleSynchroExecution' => 'Execução da sincronização', - 'Class:SynchroDataSource:DataTable' => 'Tabela base de dados: %1$s', - 'Core:SyncDataSourceObsolete' => 'A fonte de dados Ă© marcado como obsoleto. Operação cancelada.', - 'Core:SyncDataSourceAccessRestriction' => 'Adminstradores ou apenas o usuĂĄrio especificado na fonte de dados pode executar esta operação. Operação cancelada.', - 'Core:SyncTooManyMissingReplicas' => 'Todos os registros foram intocado por algum tempo (todos os objetos podem ser apagados). Verifique se o processo que grava na tabela de sincronização ainda estĂĄ em execução. Operação cancelada.', - 'Core:SyncSplitModeCLIOnly' => 'A sincronização pode ser executado em pedaços sĂł se for executado em modo CLI', - 'Core:Synchro:ListReplicas_AllReplicas_Errors_Warnings' => '%1$s replicas, %2$s erro(s), %3$s alerta(s).', - 'Core:SynchroReplica:TargetObject' => 'Objeto(s) sincronizado(s): %1$s', - 'Class:AsyncSendEmail' => 'Email (assĂ­ncrono)', + 'Class:SynchroDataSource:DataTable' => 'Tabela do banco de dados: "%1$s"', + 'Core:SyncDataSourceObsolete' => 'A fonte de dados estĂĄ marcada como obsoleta. Operação cancelada', + 'Core:SyncDataSourceAccessRestriction' => 'Adminstradores ou apenas o usuĂĄrio especificado na fonte de dados pode executar esta operação. Operação cancelada', + 'Core:SyncTooManyMissingReplicas' => 'Todos os registros estĂŁo intocados a algum tempo (todos os objetos podem ser apagados). Verifique se o processo que grava na tabela de sincronização ainda estĂĄ em execução. Operação cancelada', + 'Core:SyncSplitModeCLIOnly' => 'A sincronização pode ser executada em pedaços sĂł se for executada em modo CLI', + 'Core:Synchro:ListReplicas_AllReplicas_Errors_Warnings' => '%1$s rĂ©plica(s), %2$s erro(s), %3$s alerta(s)', + 'Core:SynchroReplica:TargetObject' => 'Objeto sincronizado: %1$s', + 'Class:AsyncSendEmail' => 'E-mail (assĂ­ncrono)', 'Class:AsyncSendEmail/Attribute:to' => 'Para', 'Class:AsyncSendEmail/Attribute:subject' => 'Assunto', 'Class:AsyncSendEmail/Attribute:body' => 'Corpo', 'Class:AsyncSendEmail/Attribute:header' => 'Cabeçalho', - 'Class:CMDBChangeOpSetAttributeOneWayPassword' => 'Senha criptograda', + 'Class:CMDBChangeOpSetAttributeOneWayPassword' => 'Senha criptografada', 'Class:CMDBChangeOpSetAttributeOneWayPassword/Attribute:prev_pwd' => 'Valor anterior', 'Class:CMDBChangeOpSetAttributeEncrypted' => 'Campo criptografado', 'Class:CMDBChangeOpSetAttributeEncrypted/Attribute:prevstring' => 'Valor anterior', - 'Class:CMDBChangeOpSetAttributeCaseLog' => 'Caso Log', + 'Class:CMDBChangeOpSetAttributeCaseLog' => 'Case Log~~', 'Class:CMDBChangeOpSetAttributeCaseLog/Attribute:lastentry' => 'Última entrada', - 'Class:SynchroDataSource' => 'Fonte de dados sincronização', - 'Class:SynchroDataSource/Attribute:status/Value:implementation' => 'Implementação', + 'Class:SynchroDataSource' => 'Fonte de Sincronização de Dados', + 'Class:SynchroDataSource/Attribute:status/Value:implementation' => 'Em homologação', 'Class:SynchroDataSource/Attribute:status/Value:obsolete' => 'Obsoleto', - 'Class:SynchroDataSource/Attribute:status/Value:production' => 'Produção', + 'Class:SynchroDataSource/Attribute:status/Value:production' => 'Em produção', 'Class:SynchroDataSource/Attribute:scope_restriction' => 'Restrição de escopo', 'Class:SynchroDataSource/Attribute:reconciliation_policy/Value:use_attributes' => 'Use os atributos', 'Class:SynchroDataSource/Attribute:reconciliation_policy/Value:use_primary_key' => 'Use o campo primary_key', @@ -834,76 +834,76 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:SynchroDataSource/Attribute:action_on_one/Value:update' => 'Atualizar', 'Class:SynchroDataSource/Attribute:action_on_multiple/Value:create' => 'Criar', 'Class:SynchroDataSource/Attribute:action_on_multiple/Value:error' => 'Erro', - 'Class:SynchroDataSource/Attribute:action_on_multiple/Value:take_first' => 'TPegue o primeiro (acaso?)', - 'Class:SynchroDataSource/Attribute:delete_policy' => 'PolĂ­tica exclusĂŁo', + 'Class:SynchroDataSource/Attribute:action_on_multiple/Value:take_first' => 'Pegue o primeiro (ao acaso?)', + 'Class:SynchroDataSource/Attribute:delete_policy' => 'PolĂ­tica de exclusĂŁo', 'Class:SynchroDataSource/Attribute:delete_policy/Value:delete' => 'Excluir', 'Class:SynchroDataSource/Attribute:delete_policy/Value:ignore' => 'Ignorar', 'Class:SynchroDataSource/Attribute:delete_policy/Value:update' => 'Atualizar', - 'Class:SynchroDataSource/Attribute:delete_policy/Value:update_then_delete' => 'Atualize quando excluĂ­do', - 'Class:SynchroDataSource/Attribute:attribute_list' => 'Listar atributos', + 'Class:SynchroDataSource/Attribute:delete_policy/Value:update_then_delete' => 'Atualizar entĂŁo Excluir', + 'Class:SynchroDataSource/Attribute:attribute_list' => 'Exibir atributos', 'Class:SynchroDataSource/Attribute:user_delete_policy/Value:administrators' => 'Somente administradores', - 'Class:SynchroDataSource/Attribute:user_delete_policy/Value:everybody' => 'PermissĂŁo total para excluir esses objetos', + 'Class:SynchroDataSource/Attribute:user_delete_policy/Value:everybody' => 'Todos os usuĂĄrios', 'Class:SynchroDataSource/Attribute:user_delete_policy/Value:nobody' => 'NinguĂ©m', - 'Class:SynchroAttribute' => 'Atributo sincronização', + 'Class:SynchroAttribute' => 'Atributo de sincronização', 'Class:SynchroAttribute/Attribute:sync_source_id' => 'Fonte de dados', - 'Class:SynchroAttribute/Attribute:attcode' => 'CĂłdigo atributo', + 'Class:SynchroAttribute/Attribute:attcode' => 'CĂłdigo do atributo', 'Class:SynchroAttribute/Attribute:update' => 'Atualizar', 'Class:SynchroAttribute/Attribute:reconcile' => 'Reconciliar', - 'Class:SynchroAttribute/Attribute:update_policy' => 'PolĂ­tica atualizar', - 'Class:SynchroAttribute/Attribute:update_policy/Value:master_locked' => 'Trancado', - 'Class:SynchroAttribute/Attribute:update_policy/Value:master_unlocked' => 'Destrancado', - 'Class:SynchroAttribute/Attribute:update_policy/Value:write_if_empty' => 'Iniciando se vazio', + 'Class:SynchroAttribute/Attribute:update_policy' => 'PolĂ­tica de atualização', + 'Class:SynchroAttribute/Attribute:update_policy/Value:master_locked' => 'Slave', + 'Class:SynchroAttribute/Attribute:update_policy/Value:master_unlocked' => 'Master', + 'Class:SynchroAttribute/Attribute:update_policy/Value:write_if_empty' => 'Atualizar se vazio', 'Class:SynchroAttribute/Attribute:finalclass' => 'Classe', - 'Class:SynchroAttExtKey' => 'Atributo sincronização (ExtKey)', - 'Class:SynchroAttExtKey/Attribute:reconciliation_attcode' => 'Atributo reconciliação', - 'Class:SynchroAttLinkSet' => 'Atributo sincronização (Linkset)', + 'Class:SynchroAttExtKey' => 'Atributo de sincronização (ExtKey)', + 'Class:SynchroAttExtKey/Attribute:reconciliation_attcode' => 'Atributo de reconciliação', + 'Class:SynchroAttLinkSet' => 'Atributo de sincronização (Linkset)', 'Class:SynchroAttLinkSet/Attribute:row_separator' => 'Separador de linhas', - 'Class:SynchroAttLinkSet/Attribute:attribute_separator' => 'Separador atributos', - 'Class:SynchroLog' => 'Log sincronização', - 'Class:SynchroLog/Attribute:sync_source_id' => 'Fonte de dados sincronização', - 'Class:SynchroLog/Attribute:start_date' => 'Data inĂ­cio', + 'Class:SynchroAttLinkSet/Attribute:attribute_separator' => 'Separador de atributos', + 'Class:SynchroLog' => 'Log de sincronização', + 'Class:SynchroLog/Attribute:sync_source_id' => 'Fonte de sincronização de dados', + 'Class:SynchroLog/Attribute:start_date' => 'Data de inĂ­cio', 'Class:SynchroLog/Attribute:end_date' => 'Data final', 'Class:SynchroLog/Attribute:status' => 'Status', - 'Class:SynchroLog/Attribute:status/Value:completed' => 'Completado', + 'Class:SynchroLog/Attribute:status/Value:completed' => 'Finalizado', 'Class:SynchroLog/Attribute:status/Value:error' => 'Erro', - 'Class:SynchroLog/Attribute:status/Value:running' => 'Ainda estĂĄ em execução', - 'Class:SynchroLog/Attribute:stats_nb_replica_seen' => 'NĂșmero rĂ©plica vista', - 'Class:SynchroLog/Attribute:stats_nb_replica_total' => 'NĂșmero rĂ©plica total', - 'Class:SynchroLog/Attribute:stats_nb_obj_deleted' => 'NĂșmero objeto(s) excluĂ­do(s)', - 'Class:SynchroLog/Attribute:stats_nb_obj_deleted_errors' => 'NĂșmero de erros enquanto excluindo', - 'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted' => 'NĂșmero objeto(s) obsoleto(s)', - 'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted_errors' => 'NĂșmero de erros enquanto obsoletos', - 'Class:SynchroLog/Attribute:stats_nb_obj_created' => 'NĂșmero objeto(s) criado(s)', - 'Class:SynchroLog/Attribute:stats_nb_obj_created_errors' => 'NĂșmero de erros enquanto criando', - 'Class:SynchroLog/Attribute:stats_nb_obj_updated' => 'NĂșmero objeto(s) atualizado(s)', - 'Class:SynchroLog/Attribute:stats_nb_obj_updated_errors' => 'NĂșmero de erros enquanto atualizando', - 'Class:SynchroLog/Attribute:stats_nb_replica_reconciled_errors' => 'NĂșmero de erros durante reconciliação', - 'Class:SynchroLog/Attribute:stats_nb_replica_disappeared_no_action' => 'NĂșmero rĂ©plica desaparecida', - 'Class:SynchroLog/Attribute:stats_nb_obj_new_updated' => 'NĂșmero objetos atualizados', - 'Class:SynchroLog/Attribute:stats_nb_obj_new_unchanged' => 'NĂșmero objetos inalterados', + 'Class:SynchroLog/Attribute:status/Value:running' => 'Em execução', + 'Class:SynchroLog/Attribute:stats_nb_replica_seen' => 'NĂșmero rĂ©plica vista~~', + 'Class:SynchroLog/Attribute:stats_nb_replica_total' => 'NĂșmero rĂ©plica total~~', + 'Class:SynchroLog/Attribute:stats_nb_obj_deleted' => 'NĂșmero de objeto(s) excluĂ­do(s)', + 'Class:SynchroLog/Attribute:stats_nb_obj_deleted_errors' => 'NĂșmero de erros durante a exclusĂŁo', + 'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted' => 'NĂșmero de objeto(s) obsoleto(s)', + 'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted_errors' => 'NĂșmero de erros durante a obsolescĂȘncia', + 'Class:SynchroLog/Attribute:stats_nb_obj_created' => 'NĂșmero de objeto(s) criado(s)', + 'Class:SynchroLog/Attribute:stats_nb_obj_created_errors' => 'NĂșmero de erros durante a criação', + 'Class:SynchroLog/Attribute:stats_nb_obj_updated' => 'NĂșmero de objeto(s) atualizado(s)', + 'Class:SynchroLog/Attribute:stats_nb_obj_updated_errors' => 'NĂșmero de erros durante a atualização', + 'Class:SynchroLog/Attribute:stats_nb_replica_reconciled_errors' => 'NĂșmero de erros durante a reconciliação', + 'Class:SynchroLog/Attribute:stats_nb_replica_disappeared_no_action' => 'NĂșmero de rĂ©plicas desaparecidas', + 'Class:SynchroLog/Attribute:stats_nb_obj_new_updated' => 'NĂșmero de objetos atualizados', + 'Class:SynchroLog/Attribute:stats_nb_obj_new_unchanged' => 'NĂșmero de objetos inalterados', 'Class:SynchroLog/Attribute:last_error' => 'Últimos erros', 'Class:SynchroLog/Attribute:traces' => 'Rastrear', - 'Class:SynchroReplica' => 'RĂ©plica sincronização', + 'Class:SynchroReplica' => 'Sincronização de rĂ©plica', 'Class:SynchroReplica/Attribute:sync_source_id' => 'Fonte de dados', - 'Class:SynchroReplica/Attribute:dest_id' => 'Objeto destino (ID)', - 'Class:SynchroReplica/Attribute:dest_class' => 'Tipo destino', + 'Class:SynchroReplica/Attribute:dest_id' => 'Objeto de destino (ID)', + 'Class:SynchroReplica/Attribute:dest_class' => 'Tipo de destino', 'Class:SynchroReplica/Attribute:status_last_seen' => 'Visto pela Ășltima vez', 'Class:SynchroReplica/Attribute:status' => 'Status', 'Class:SynchroReplica/Attribute:status/Value:modified' => 'Modificado', 'Class:SynchroReplica/Attribute:status/Value:new' => 'Novo', 'Class:SynchroReplica/Attribute:status/Value:obsolete' => 'Obsoleto', - 'Class:SynchroReplica/Attribute:status/Value:orphan' => 'OrfĂŁo', + 'Class:SynchroReplica/Attribute:status/Value:orphan' => 'ÓrfĂŁo', 'Class:SynchroReplica/Attribute:status/Value:synchronized' => 'Sincronizado', 'Class:SynchroReplica/Attribute:status_dest_creator' => 'Objeto criado?', 'Class:SynchroReplica/Attribute:status_last_error' => 'Último Erro', 'Class:SynchroReplica/Attribute:status_last_warning' => 'Alertas', - 'Class:SynchroReplica/Attribute:info_creation_date' => 'Data criação', + 'Class:SynchroReplica/Attribute:info_creation_date' => 'Data de criação', 'Class:SynchroReplica/Attribute:info_last_modified' => 'Última data modificação', - 'Class:appUserPreferences' => 'PreferĂȘncia de usuĂĄrio', + 'Class:appUserPreferences' => 'PreferĂȘncias de usuĂĄrio', 'Class:appUserPreferences/Attribute:userid' => 'UsuĂĄrio', 'Class:appUserPreferences/Attribute:preferences' => 'PreferĂȘncias', - 'Core:ExecProcess:Code1' => 'Comando errado ou comando terminou com erros (por exemplo, nome do script errado)', - 'Core:ExecProcess:Code255' => 'PHP erro (parsing, or runtime)', + 'Core:ExecProcess:Code1' => 'Comando incorreto ou comando terminou com erros (por exemplo, nome do script errado)', + 'Core:ExecProcess:Code255' => 'Erro PHP (parsing, ou runtime)', // Attribute Duration 'Core:Duration_Seconds' => '%1$ds', @@ -918,7 +918,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Bulk export 'Core:BulkExport:MissingParameter_Param' => 'ParĂąmetro ausente \\"%1$s\\"', - 'Core:BulkExport:InvalidParameter_Query' => 'Valor invĂĄlido para o parĂąmetro \\"query\\". NĂŁo hĂĄ nenhum Phrasebook de consulta correspondente ao id: \\"%1$s\\".', + 'Core:BulkExport:InvalidParameter_Query' => 'Valor invĂĄlido para o parĂąmetro \\"query\\". NĂŁo hĂĄ nenhum entrada no livro de consultas correspondente ao ID: \\"%1$s\\"', 'Core:BulkExport:ExportFormatPrompt' => 'Formato de exportação:', 'Core:BulkExportOf_Class' => '%1$s Export', 'Core:BulkExport:ClickHereToDownload_FileName' => 'Clique aqui para baixar %1$s', @@ -928,44 +928,44 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:BulkExport:CSVFormat' => 'Valores separados por vĂ­rgula (*.csv)', 'Core:BulkExport:XLSXFormat' => 'Excel 2007 ou mais recente (*.xlsx)', 'Core:BulkExport:PDFFormat' => 'Documento PDF (*.pdf)', - 'Core:BulkExport:DragAndDropHelp' => 'Arrastar e soltar os cabeçalhos das colunas para organizar as colunas. Visualização de %1$s linhas. NĂșmero total de linhas para exportar: %2$s.', + 'Core:BulkExport:DragAndDropHelp' => 'Segure e arraste os cabeçalhos das colunas para organizar as colunas. Visualização de %1$s linha(s). NĂșmero total de linhas para exportar: %2$s', 'Core:BulkExport:EmptyPreview' => 'Selecione as colunas a serem exportadas da lista acima', 'Core:BulkExport:ColumnsOrder' => 'Ordem das colunas', - 'Core:BulkExport:AvailableColumnsFrom_Class' => 'Colunas disponĂ­veis de %1$s', - 'Core:BulkExport:NoFieldSelected' => 'Selecione pelo menos uma coluna para ser exportada', - 'Core:BulkExport:CheckAll' => 'Check All~~', - 'Core:BulkExport:UncheckAll' => 'Desmarque tudo', + 'Core:BulkExport:AvailableColumnsFrom_Class' => 'Colunas disponĂ­veis de(a) %1$s', + 'Core:BulkExport:NoFieldSelected' => 'Selecione pelo menos uma coluna para exportar', + 'Core:BulkExport:CheckAll' => 'Marcar todos', + 'Core:BulkExport:UncheckAll' => 'Desmarcar todos', 'Core:BulkExport:ExportCancelledByUser' => 'Exportação cancelada pelo usuĂĄrio', - 'Core:BulkExport:CSVOptions' => 'CSV Options', - 'Core:BulkExport:CSVLocalization' => 'Localização', + 'Core:BulkExport:CSVOptions' => 'OpçÔes de exportação CSV', + 'Core:BulkExport:CSVLocalization' => 'Codificação de caracteres:', 'Core:BulkExport:PDFOptions' => 'OpçÔes de PDF', 'Core:BulkExport:PDFPageFormat' => 'Formato da pĂĄgina', - 'Core:BulkExport:PDFPageSize' => 'Tamanho da pĂĄgina:', + 'Core:BulkExport:PDFPageSize' => 'Tamanho da pĂĄgina', 'Core:BulkExport:PageSize-A4' => 'A4', 'Core:BulkExport:PageSize-A3' => 'A3', 'Core:BulkExport:PageSize-Letter' => 'Carta', - 'Core:BulkExport:PDFPageOrientation' => 'Orientação de PĂĄgina:', - 'Core:BulkExport:PageOrientation-L' => 'Landscape~~', - 'Core:BulkExport:PageOrientation-P' => 'Portrait~~', + 'Core:BulkExport:PDFPageOrientation' => 'Orientação da PĂĄgina', + 'Core:BulkExport:PageOrientation-L' => 'Paisagem', + 'Core:BulkExport:PageOrientation-P' => 'Retrato', 'Core:BulkExport:XMLFormat' => 'Arquivo XML (*.xml)', 'Core:BulkExport:XMLOptions' => 'OpçÔes XML', 'Core:BulkExport:SpreadsheetFormat' => 'Formato HTML de planilha (*.html)', 'Core:BulkExport:SpreadsheetOptions' => 'OpçÔes de planilha', - 'Core:BulkExport:OptionNoLocalize' => 'CĂłdigo de exportação em vez de Label', - 'Core:BulkExport:OptionLinkSets' => 'Incluir objetos vinculados', + 'Core:BulkExport:OptionNoLocalize' => 'Usar CĂłdigo de exportação ao invĂ©s do TĂ­tulo dos objetos', + 'Core:BulkExport:OptionLinkSets' => 'Incluir objetos associados', 'Core:BulkExport:OptionFormattedText' => 'Preservar formatação de texto', 'Core:BulkExport:ScopeDefinition' => 'Definição dos objetos a exportar', - 'Core:BulkExportLabelOQLExpression' => 'OQL Query:~~', - 'Core:BulkExportLabelPhrasebookEntry' => 'Query Phrasebook Entry:~~', - 'Core:BulkExportMessageEmptyOQL' => 'Por favor insira uma consulta OQL vĂĄlida.', - 'Core:BulkExportMessageEmptyPhrasebookEntry' => 'Por favor, selecione uma entrada de livro de frases vĂĄlida.', + 'Core:BulkExportLabelOQLExpression' => 'Consulta OQL:', + 'Core:BulkExportLabelPhrasebookEntry' => 'Entrada do livro de consultas:', + 'Core:BulkExportMessageEmptyOQL' => 'Por favor, insira uma consulta OQL vĂĄlida', + 'Core:BulkExportMessageEmptyPhrasebookEntry' => 'Por favor, selecione uma entrada vĂĄlida do livro de consultas', 'Core:BulkExportQueryPlaceholder' => 'Digite uma consulta OQL aqui ...', - 'Core:BulkExportCanRunNonInteractive' => 'Clique aqui para executar a exportação no modo nĂŁo interativo.', - 'Core:BulkExportLegacyExport' => 'Clique aqui para acessar a exportação legada.', + 'Core:BulkExportCanRunNonInteractive' => 'Clique aqui para executar a exportação no modo nĂŁo interativo', + 'Core:BulkExportLegacyExport' => 'Clique aqui para acessar a exportação legada', 'Core:BulkExport:XLSXOptions' => 'OpçÔes do Excel', - 'Core:BulkExport:TextFormat' => 'Campos de texto contendo alguma marcação HTML', + 'Core:BulkExport:TextFormat' => 'Campos de texto contendo cĂłdigos HTML', 'Core:BulkExport:DateTimeFormat' => 'Formato de data e hora', - 'Core:BulkExport:DateTimeFormatDefault_Example' => 'Formato padrĂŁo (%1$s), por ex. %2$s', + 'Core:BulkExport:DateTimeFormatDefault_Example' => 'Formato padrĂŁo (%1$s), por exemplo: %2$s', 'Core:BulkExport:DateTimeFormatCustom_Format' => 'Formato personalizado: %1$s', 'Core:BulkExport:PDF:PageNumber' => 'PĂĄgina %1$s', 'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero) @@ -982,9 +982,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:DateTime:Placeholder_A' => 'AM/PM', // AM/PM (uppercase) 'Core:DateTime:Placeholder_i' => 'mm', // minutes, 2 digits: 00..59 'Core:DateTime:Placeholder_s' => 'ss', // seconds, 2 digits 00..59 - 'Core:Validator:Default' => 'Formato errado', + 'Core:Validator:Default' => 'Formato invĂĄlido', 'Core:Validator:Mandatory' => 'Por favor, preencha este campo', - 'Core:Validator:MustBeInteger' => 'Deve ser um inteiro', + 'Core:Validator:MustBeInteger' => 'Deve ser um nĂșmero inteiro', 'Core:Validator:MustSelectOne' => 'Por favor, selecione um', )); @@ -1001,18 +1001,18 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:TagSetFieldData/Attribute:label+' => 'RĂłtulo exibido', 'Class:TagSetFieldData/Attribute:description' => 'Descrição', 'Class:TagSetFieldData/Attribute:description+' => '', - 'Class:TagSetFieldData/Attribute:finalclass' => 'Tag class~~', + 'Class:TagSetFieldData/Attribute:finalclass' => 'Classe da etiqueta', 'Class:TagSetFieldData/Attribute:obj_class' => 'Classe de objeto', - 'Class:TagSetFieldData/Attribute:obj_attcode' => 'CĂłdigo de campo', + 'Class:TagSetFieldData/Attribute:obj_attcode' => 'CĂłdigo de atributo', - 'Core:TagSetFieldData:ErrorDeleteUsedTag' => 'Tags usadas nĂŁo podem ser deletadas', - 'Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel' => 'Tags cĂłdigos ou rĂłtulos devem ser Ășnicos', - 'Core:TagSetFieldData:ErrorTagCodeSyntax' => 'O cĂłdigo de tags deve conter entre 3 e %1$d caracteres alfanumĂ©ricos', + 'Core:TagSetFieldData:ErrorDeleteUsedTag' => 'Tags em uso nĂŁo podem ser deletadas', + 'Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel' => 'O cĂłdigo de tag ou rĂłtulo devem ser Ășnicos', + 'Core:TagSetFieldData:ErrorTagCodeSyntax' => 'O cĂłdigo de tag deve conter entre 3 e %1$d caracteres alfanumĂ©ricos', 'Core:TagSetFieldData:ErrorTagCodeReservedWord' => 'O cĂłdigo de tag escolhido Ă© uma palavra reservada', - 'Core:TagSetFieldData:ErrorTagLabelSyntax' => 'O rĂłtulo de etiquetas nĂŁo deve conter \'%1$s\'nem estar vazio', - 'Core:TagSetFieldData:ErrorCodeUpdateNotAllowed' => 'Tags CĂłdigo nĂŁo pode ser alterado quando usado', - 'Core:TagSetFieldData:ErrorClassUpdateNotAllowed' => 'Tags "Object Class" nĂŁo pode ser alterado', - 'Core:TagSetFieldData:ErrorAttCodeUpdateNotAllowed' => 'Tags "CĂłdigo do atributo" nĂŁo pode ser alterado', + 'Core:TagSetFieldData:ErrorTagLabelSyntax' => 'O rĂłtulo da tag nĂŁo deve conter \'%1$s\' nem estar vazio', + 'Core:TagSetFieldData:ErrorCodeUpdateNotAllowed' => 'Tags de cĂłdigo nĂŁo podem ser alteradas quando em uso', + 'Core:TagSetFieldData:ErrorClassUpdateNotAllowed' => 'Tags de "Classe de Objeto" nĂŁo podem ser alteradas', + 'Core:TagSetFieldData:ErrorAttCodeUpdateNotAllowed' => 'Tags de "CĂłdigo do atributo" nĂŁo podem ser alteradas', 'Core:TagSetFieldData:WhereIsThisTagTab' => 'Uso de tags (%1$d)', 'Core:TagSetFieldData:NoEntryFound' => 'Nenhuma entrada encontrada para esta tag', )); @@ -1021,7 +1021,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Class: DBProperty // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:DBProperty' => 'Propriedade do DB', + 'Class:DBProperty' => 'Propriedades do DB', 'Class:DBProperty+' => '', 'Class:DBProperty/Attribute:name' => 'Nome', 'Class:DBProperty/Attribute:name+' => '', @@ -1029,9 +1029,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:DBProperty/Attribute:description+' => '', 'Class:DBProperty/Attribute:value' => 'Valor', 'Class:DBProperty/Attribute:value+' => '', - 'Class:DBProperty/Attribute:change_date' => 'Data de mudança', + 'Class:DBProperty/Attribute:change_date' => 'Data de alteração', 'Class:DBProperty/Attribute:change_date+' => '', - 'Class:DBProperty/Attribute:change_comment' => 'Alterar comentĂĄrio', + 'Class:DBProperty/Attribute:change_comment' => 'Editar comentĂĄrio', 'Class:DBProperty/Attribute:change_comment+' => '', )); @@ -1039,27 +1039,27 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Class: BackgroundTask // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:BackgroundTask' => 'Tarefa de fundo', + 'Class:BackgroundTask' => 'Tarefas de fundo', 'Class:BackgroundTask+' => '', - 'Class:BackgroundTask/Attribute:class_name' => 'Nome da turma', + 'Class:BackgroundTask/Attribute:class_name' => 'Nome da classe', 'Class:BackgroundTask/Attribute:class_name+' => '', - 'Class:BackgroundTask/Attribute:first_run_date' => 'Primeira data de execução', + 'Class:BackgroundTask/Attribute:first_run_date' => 'Data da primeira execução', 'Class:BackgroundTask/Attribute:first_run_date+' => '', - 'Class:BackgroundTask/Attribute:latest_run_date' => 'Data de execução mais recente', + 'Class:BackgroundTask/Attribute:latest_run_date' => 'Data da execução mais recente', 'Class:BackgroundTask/Attribute:latest_run_date+' => '', - 'Class:BackgroundTask/Attribute:next_run_date' => 'PrĂłxima data de execução', + 'Class:BackgroundTask/Attribute:next_run_date' => 'Data da prĂłxima execução', 'Class:BackgroundTask/Attribute:next_run_date+' => '', - 'Class:BackgroundTask/Attribute:total_exec_count' => 'Total exec. conte', + 'Class:BackgroundTask/Attribute:total_exec_count' => 'NĂșmero total de execuçÔes', 'Class:BackgroundTask/Attribute:total_exec_count+' => '', - 'Class:BackgroundTask/Attribute:latest_run_duration' => 'Duração de execução mais recente', + 'Class:BackgroundTask/Attribute:latest_run_duration' => 'Duração da execução mais recente', 'Class:BackgroundTask/Attribute:latest_run_duration+' => '', - 'Class:BackgroundTask/Attribute:min_run_duration' => 'Min. duração de execução', + 'Class:BackgroundTask/Attribute:min_run_duration' => 'Duração mĂ­n. de execução', 'Class:BackgroundTask/Attribute:min_run_duration+' => '', - 'Class:BackgroundTask/Attribute:max_run_duration' => 'Max. duração de execução', + 'Class:BackgroundTask/Attribute:max_run_duration' => 'Duração mĂĄx. de execução', 'Class:BackgroundTask/Attribute:max_run_duration+' => '', 'Class:BackgroundTask/Attribute:average_run_duration' => 'Duração mĂ©dia de execução', 'Class:BackgroundTask/Attribute:average_run_duration+' => '', - 'Class:BackgroundTask/Attribute:running' => 'Correndo', + 'Class:BackgroundTask/Attribute:running' => 'Em execução', 'Class:BackgroundTask/Attribute:running+' => '', 'Class:BackgroundTask/Attribute:status' => 'Status', 'Class:BackgroundTask/Attribute:status+' => '', @@ -1069,30 +1069,30 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Class: AsyncTask // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:AsyncTask' => 'AssĂ­ncrono. tarefa', + 'Class:AsyncTask' => 'Tarefa assĂ­ncrona', 'Class:AsyncTask+' => '', - 'Class:AsyncTask/Attribute:created' => 'Criado', + 'Class:AsyncTask/Attribute:created' => 'Criada', 'Class:AsyncTask/Attribute:created+' => '', - 'Class:AsyncTask/Attribute:started' => 'Iniciado', + 'Class:AsyncTask/Attribute:started' => 'Iniciada', 'Class:AsyncTask/Attribute:started+' => '', - 'Class:AsyncTask/Attribute:planned' => 'Planejado', + 'Class:AsyncTask/Attribute:planned' => 'Planejada', 'Class:AsyncTask/Attribute:planned+' => '', 'Class:AsyncTask/Attribute:event_id' => 'Evento', 'Class:AsyncTask/Attribute:event_id+' => '', - 'Class:AsyncTask/Attribute:finalclass' => 'Aula final', + 'Class:AsyncTask/Attribute:finalclass' => 'Classe final', 'Class:AsyncTask/Attribute:finalclass+' => '', - 'Class:AsyncTask/Attribute:status' => 'Status~~', + 'Class:AsyncTask/Attribute:status' => 'Status', 'Class:AsyncTask/Attribute:status+' => '', - 'Class:AsyncTask/Attribute:remaining_retries' => 'Remaining retries~~', + 'Class:AsyncTask/Attribute:remaining_retries' => 'Tentativas restantes', 'Class:AsyncTask/Attribute:remaining_retries+' => '', - 'Class:AsyncTask/Attribute:last_error_code' => 'Last error code~~', + 'Class:AsyncTask/Attribute:last_error_code' => 'Último cĂłdigo de erro', 'Class:AsyncTask/Attribute:last_error_code+' => '', - 'Class:AsyncTask/Attribute:last_error' => 'Last error~~', + 'Class:AsyncTask/Attribute:last_error' => 'Último erro', 'Class:AsyncTask/Attribute:last_error+' => '', - 'Class:AsyncTask/Attribute:last_attempt' => 'Last attempt~~', + 'Class:AsyncTask/Attribute:last_attempt' => 'Última tentativa', 'Class:AsyncTask/Attribute:last_attempt+' => '', - 'Class:AsyncTask:InvalidConfig_Class_Keys' => 'Invalid format for the configuration of "async_task_retries[%1$s]". Expecting an array with the following keys: %2$s~~', - 'Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys' => 'Invalid format for the configuration of "async_task_retries[%1$s]": unexpected key "%2$s". Expecting only the following keys: %3$s~~', + 'Class:AsyncTask:InvalidConfig_Class_Keys' => 'Formato invĂĄlido para a configuração de "async_task_retries[%1$s]". Esperando um array com as seguintes chaves: %2$s', + 'Class:AsyncTask:InvalidConfig_Class_InvalidKey_Keys' => 'Formato invĂĄlido para a configuração de "async_task_retries[%1$s]": chave inesperada "%2$s". Esperando somente as seguintes chaves: %3$s', )); // @@ -1100,7 +1100,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:AbstractResource' => 'Recurso abstrato', + 'Class:AbstractResource' => 'Recurso Abstrato', 'Class:AbstractResource+' => '', )); @@ -1109,7 +1109,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:ResourceAdminMenu' => 'Recurso Admin Menu', + 'Class:ResourceAdminMenu' => 'Recurso Menu de Administração', 'Class:ResourceAdminMenu+' => '', )); @@ -1118,7 +1118,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:ResourceRunQueriesMenu' => 'Menu de consultas de execução de recursos', + 'Class:ResourceRunQueriesMenu' => 'Recurso Livro de Consultas', 'Class:ResourceRunQueriesMenu+' => '', )); @@ -1127,7 +1127,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:ResourceSystemMenu' => 'Resource System Menu~~', + 'Class:ResourceSystemMenu' => 'Menu de Recursos do Sistema', 'Class:ResourceSystemMenu+' => '', )); diff --git a/dictionaries/pt_br.dictionary.itop.ui.php b/dictionaries/pt_br.dictionary.itop.ui.php index 2cdd156bb..58099b866 100644 --- a/dictionaries/pt_br.dictionary.itop.ui.php +++ b/dictionaries/pt_br.dictionary.itop.ui.php @@ -15,7 +15,7 @@ // Class: AuditCategory // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:AuditCategory' => 'Categoria Auditoria', + 'Class:AuditCategory' => 'Categoria de Auditoria', 'Class:AuditCategory+' => 'Uma seção dentro da auditoria', 'Class:AuditCategory/Attribute:name' => 'Nome', 'Class:AuditCategory/Attribute:name+' => 'Nome curto para esta categoria', @@ -23,8 +23,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:AuditCategory/Attribute:description+' => 'Longa descrição para esta categoria de auditoria', 'Class:AuditCategory/Attribute:definition_set' => 'Definir Regra', 'Class:AuditCategory/Attribute:definition_set+' => 'ExpressĂŁo OQL que define o conjunto de objetos para auditoria', - 'Class:AuditCategory/Attribute:rules_list' => 'Regras Auditoria', - 'Class:AuditCategory/Attribute:rules_list+' => 'Regra auditoria para essa categoria', + 'Class:AuditCategory/Attribute:rules_list' => 'Regras de Auditoria', + 'Class:AuditCategory/Attribute:rules_list+' => 'Regra de auditoria para essa categoria', )); // @@ -32,23 +32,23 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:AuditRule' => 'Regra de auditoria', + 'Class:AuditRule' => 'Regra de Auditoria', 'Class:AuditRule+' => 'Uma regra para verificar se uma determinada categoria de Auditoria', 'Class:AuditRule/Attribute:name' => 'Nome', 'Class:AuditRule/Attribute:name+' => 'Nome curto para esta regra', 'Class:AuditRule/Attribute:description' => 'Descrição', 'Class:AuditRule/Attribute:description+' => 'Descrição longa para essa regra', - 'Class:TagSetFieldData/Attribute:finalclass' => 'Tag class~~', - 'Class:TagSetFieldData/Attribute:obj_class' => 'Classe de objeto', - 'Class:TagSetFieldData/Attribute:obj_attcode' => 'CĂłdigo de campo', + 'Class:TagSetFieldData/Attribute:finalclass' => 'Classe da tag', + 'Class:TagSetFieldData/Attribute:obj_class' => 'Classe do objeto', + 'Class:TagSetFieldData/Attribute:obj_attcode' => 'CĂłdigo do campo', 'Class:AuditRule/Attribute:query' => 'Executar consulta', 'Class:AuditRule/Attribute:query+' => 'Executar a expressĂŁo OQL', 'Class:AuditRule/Attribute:valid_flag' => 'Objetos vĂĄlidos?', 'Class:AuditRule/Attribute:valid_flag+' => 'Verdadeiro se a regra retornar o objeto vĂĄlido, falso caso contrĂĄrio', 'Class:AuditRule/Attribute:valid_flag/Value:true' => 'Verdadeiro', - 'Class:AuditRule/Attribute:valid_flag/Value:true+' => 'Verdadeiro', + 'Class:AuditRule/Attribute:valid_flag/Value:true+' => '', 'Class:AuditRule/Attribute:valid_flag/Value:false' => 'Falso', - 'Class:AuditRule/Attribute:valid_flag/Value:false+' => 'Falso', + 'Class:AuditRule/Attribute:valid_flag/Value:false+' => '', 'Class:AuditRule/Attribute:category_id' => 'Categoria', 'Class:AuditRule/Attribute:category_id+' => 'A categoria para esta regra', 'Class:AuditRule/Attribute:category_name' => 'Categoria', @@ -63,19 +63,19 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:Query' => 'Consulta', 'Class:Query+' => 'Uma consulta Ă© um conjunto de dados definido de uma forma dinĂąmica', 'Class:Query/Attribute:name' => 'Nome', - 'Class:Query/Attribute:name+' => 'Identificar a consulta', + 'Class:Query/Attribute:name+' => 'Identificação da consulta', 'Class:Query/Attribute:description' => 'Descrição', - 'Class:Query/Attribute:description+' => 'Descrição longa para a consulta (finalidade, uso, etc)', - 'Class:Query/Attribute:is_template' => 'Template for OQL fields~~', - 'Class:Query/Attribute:is_template+' => 'Usable as source for recipient OQL in Notifications~~', - 'Class:Query/Attribute:is_template/Value:yes' => 'Yes~~', - 'Class:Query/Attribute:is_template/Value:no' => 'No~~', + 'Class:Query/Attribute:description+' => 'Descrição longa para a consulta (finalidade, uso, etc.)', + 'Class:Query/Attribute:is_template' => 'Template para campos OQL', + 'Class:Query/Attribute:is_template+' => 'UtilizĂĄvel como origem para o DestinatĂĄrio OQL em NotificaçÔes', + 'Class:Query/Attribute:is_template/Value:yes' => 'Sim', + 'Class:Query/Attribute:is_template/Value:no' => 'NĂŁo', 'Class:QueryOQL/Attribute:fields' => 'Campos', - 'Class:QueryOQL/Attribute:fields+' => 'VĂ­rgula separando a lista de atributos (ou alias.attribute) para exportar.', + 'Class:QueryOQL/Attribute:fields+' => 'Lista separada por vĂ­rgulas de atributos (ou alias.attribute) para exportar', 'Class:QueryOQL' => 'Consulta OQL', - 'Class:QueryOQL+' => 'Uma consulta baseada no Object Query Language OQL', + 'Class:QueryOQL+' => 'Uma consulta baseada no Object Query Language (OQL)', 'Class:QueryOQL/Attribute:oql' => 'ExpressĂŁo', - 'Class:QueryOQL/Attribute:oql+' => 'ExpressĂŁo OQL', + 'Class:QueryOQL/Attribute:oql+' => 'ExpressĂŁo Object Query Language (OQL)', )); ////////////////////////////////////////////////////////////////////// @@ -89,46 +89,46 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:User' => 'UsuĂĄrio', - 'Class:User+' => 'Login', + 'Class:User+' => '', 'Class:User/Attribute:finalclass' => 'Tipo de conta', 'Class:User/Attribute:finalclass+' => '', - 'Class:User/Attribute:contactid' => 'Contato (pessoa)', - 'Class:User/Attribute:contactid+' => 'Dados pessoais a partir dos dados do negĂłcio', + 'Class:User/Attribute:contactid' => 'Pessoa', + 'Class:User/Attribute:contactid+' => '', 'Class:User/Attribute:org_id' => 'Organização', - 'Class:User/Attribute:org_id+' => 'Organization of the associated person~~', - 'Class:User/Attribute:last_name' => 'Último nome', - 'Class:User/Attribute:last_name+' => 'Nome do contato correspondente', + 'Class:User/Attribute:org_id+' => 'Organização Ă  qual esse usuĂĄrio pertence', + 'Class:User/Attribute:last_name' => 'Sobrenome', + 'Class:User/Attribute:last_name+' => 'Último nome do usuĂĄrio correspondente', 'Class:User/Attribute:first_name' => 'Primeiro nome', - 'Class:User/Attribute:first_name+' => 'Primeiro nome do contato correspondente', - 'Class:User/Attribute:email' => 'Email', - 'Class:User/Attribute:email+' => 'Email do contato correspondente', + 'Class:User/Attribute:first_name+' => 'Primeiro nome do usuĂĄrio correspondente', + 'Class:User/Attribute:email' => 'E-mail', + 'Class:User/Attribute:email+' => 'Endereço de e-mail do usuĂĄrio correspondente', 'Class:User/Attribute:login' => 'Login', - 'Class:User/Attribute:login+' => 'String de identificação do usuĂĄrio', - 'Class:User/Attribute:language' => 'Linguagem', - 'Class:User/Attribute:language+' => 'Linguagem usuĂĄrio', - 'Class:User/Attribute:language/Value:EN US' => 'English', - 'Class:User/Attribute:language/Value:EN US+' => 'English (U.S.)', - 'Class:User/Attribute:language/Value:FR FR' => 'French', - 'Class:User/Attribute:language/Value:FR FR+' => 'French (France)', + 'Class:User/Attribute:login+' => 'Login de acesso ao '.ITOP_APPLICATION_SHORT, + 'Class:User/Attribute:language' => 'Idioma', + 'Class:User/Attribute:language+' => 'Idioma do usuĂĄrio correspondente', + 'Class:User/Attribute:language/Value:EN US' => 'InglĂȘs', + 'Class:User/Attribute:language/Value:EN US+' => 'InglĂȘs (E.U.A.)', + 'Class:User/Attribute:language/Value:FR FR' => 'FrancĂȘs', + 'Class:User/Attribute:language/Value:FR FR+' => 'FrancĂȘs (França)', 'Class:User/Attribute:profile_list' => 'Perfil', - 'Class:User/Attribute:profile_list+' => 'Regras, permissĂ”es de direito para essa pessoa', + 'Class:User/Attribute:profile_list+' => 'PermissĂ”es de acesso para esse usuĂĄrio', 'Class:User/Attribute:allowed_org_list' => 'OrganizaçÔes permitidas', - 'Class:User/Attribute:allowed_org_list+' => 'O usuĂĄrio estĂĄ permitido ver as informaçÔes para a(s) organização(Ă”es) abaixo. Se nenhuma organização for especificada, nĂŁo hĂĄ restrição.', + 'Class:User/Attribute:allowed_org_list+' => 'O usuĂĄrio tem permissĂŁo de ver as informaçÔes para a(s) organização(Ă”es) abaixo. Se nenhuma organização for especificada, nĂŁo hĂĄ restrição', 'Class:User/Attribute:status' => 'Status', - 'Class:User/Attribute:status+' => 'Se a conta de usuĂĄrio estĂĄ habilitada ou desabilitada.', - 'Class:User/Attribute:status/Value:enabled' => 'Ativado', - 'Class:User/Attribute:status/Value:disabled' => 'Desativado', + 'Class:User/Attribute:status+' => 'Se a conta de usuĂĄrio estĂĄ habilitada ou desabilitada', + 'Class:User/Attribute:status/Value:enabled' => 'Ativa', + 'Class:User/Attribute:status/Value:disabled' => 'Desativada', 'Class:User/Error:LoginMustBeUnique' => 'Login Ă© Ășnico - "%1s" jĂĄ estĂĄ ativo', - 'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Pelo menos um perfil deve ser atribuĂ­do a esse usuĂĄrio.', - 'Class:User/Error:ProfileNotAllowed' => 'Profile "%1$s" cannot be added it will deny the access to backoffice~~', - 'Class:User/Error:StatusChangeIsNotAllowed' => 'Changing status is not allowed for your own User~~', - 'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'Allowed organizations must contain User organization~~', - 'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'The current list of profiles does not give sufficient access rights (Users are not modifiable anymore)~~', - 'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Pelo menos uma organização deve ser atribuĂ­da a este usuĂĄrio.', - 'Class:User/Error:OrganizationNotAllowed' => 'Organização nĂŁo permitida.', - 'Class:User/Error:UserOrganizationNotAllowed' => 'A conta de usuĂĄrio nĂŁo pertence Ă s suas organizaçÔes permitidas.', - 'Class:User/Error:PersonIsMandatory' => 'O contato Ă© obrigatĂłrio.', + 'Class:User/Error:AtLeastOneProfileIsNeeded' => 'Pelo menos um perfil deve ser atribuĂ­do a esse usuĂĄrio', + 'Class:User/Error:ProfileNotAllowed' => 'O perfil "%1$s" nĂŁo pode ser adicionado, ele negarĂĄ o acesso ao backoffice', + 'Class:User/Error:StatusChangeIsNotAllowed' => 'Alterar o status da conta nĂŁo Ă© permitido para o seu prĂłprio usuĂĄrio', + 'Class:User/Error:AllowedOrgsMustContainUserOrg' => 'As organizaçÔes permitidas devem conter apenas usuĂĄrios pertencentes a organização', + 'Class:User/Error:CurrentProfilesHaveInsufficientRights' => 'A lista atual de perfis nĂŁo fornece permissĂ”es de acesso suficientes (os usuĂĄrios nĂŁo sĂŁo mais modificĂĄveis)', + 'Class:User/Error:AtLeastOneOrganizationIsNeeded' => 'Pelo menos uma organização deve ser atribuĂ­da a esse usuĂĄrio', + 'Class:User/Error:OrganizationNotAllowed' => 'Organização nĂŁo permitida', + 'Class:User/Error:UserOrganizationNotAllowed' => 'A conta de usuĂĄrio nĂŁo pertence Ă s suas organizaçÔes permitidas', + 'Class:User/Error:PersonIsMandatory' => 'O contato Ă© obrigatĂłrio', 'Class:UserInternal' => 'UsuĂĄrio Interno', 'Class:UserInternal+' => 'UsuĂĄrio definido dentro do '.ITOP_APPLICATION_SHORT, )); @@ -138,12 +138,12 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:URP_Profiles' => 'Perfis', - 'Class:URP_Profiles+' => 'Perfil do usuĂĄrio', + 'Class:URP_Profiles' => 'Perfil', + 'Class:URP_Profiles+' => 'Perfil do UsuĂĄrio', 'Class:URP_Profiles/Attribute:name' => 'Nome', 'Class:URP_Profiles/Attribute:name+' => '', 'Class:URP_Profiles/Attribute:description' => 'Descrição', - 'Class:URP_Profiles/Attribute:description+' => 'uma linha descrição', + 'Class:URP_Profiles/Attribute:description+' => 'Uma descrição curta', 'Class:URP_Profiles/Attribute:user_list' => 'UsuĂĄrios', 'Class:URP_Profiles/Attribute:user_list+' => 'Pessoas que possuem esse perfil', )); @@ -153,14 +153,14 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:URP_Dimensions' => 'dimensĂŁo', - 'Class:URP_Dimensions+' => 'dimensĂŁo de aplicação (definição silos)', + 'Class:URP_Dimensions' => 'DimensĂŁo', + 'Class:URP_Dimensions+' => 'DimensĂŁo de aplicação (definição de silos)', 'Class:URP_Dimensions/Attribute:name' => 'Nome', 'Class:URP_Dimensions/Attribute:name+' => '', 'Class:URP_Dimensions/Attribute:description' => 'Descrição', - 'Class:URP_Dimensions/Attribute:description+' => 'uma linha descrição', + 'Class:URP_Dimensions/Attribute:description+' => 'Uma descrição curta', 'Class:URP_Dimensions/Attribute:type' => 'Tipo', - 'Class:URP_Dimensions/Attribute:type+' => 'nome classe ou tipo dado (unidade projeção)', + 'Class:URP_Dimensions/Attribute:type+' => 'Nome da classe ou tipo de dado (unidade de mapeamento)', )); // @@ -168,19 +168,19 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:URP_UserProfile' => 'UsuĂĄrio para perfil', - 'Class:URP_UserProfile+' => 'Perfil usuĂĄrio', + 'Class:URP_UserProfile' => 'Perfil de UsuĂĄrio', + 'Class:URP_UserProfile+' => 'Perfil de UsuĂĄrio', 'Class:URP_UserProfile/Name' => 'Link entre %1$s e %2$s', 'Class:URP_UserProfile/Attribute:userid' => 'UsuĂĄrio', - 'Class:URP_UserProfile/Attribute:userid+' => 'Conta usuĂĄrio', + 'Class:URP_UserProfile/Attribute:userid+' => 'Conta de usuĂĄrio', 'Class:URP_UserProfile/Attribute:userlogin' => 'Login', - 'Class:URP_UserProfile/Attribute:userlogin+' => 'Login', + 'Class:URP_UserProfile/Attribute:userlogin+' => '', 'Class:URP_UserProfile/Attribute:profileid' => 'Perfil', 'Class:URP_UserProfile/Attribute:profileid+' => 'Perfil utilizado', 'Class:URP_UserProfile/Attribute:profile' => 'Perfil', - 'Class:URP_UserProfile/Attribute:profile+' => 'Nome perfil', + 'Class:URP_UserProfile/Attribute:profile+' => 'Nome do perfil', 'Class:URP_UserProfile/Attribute:reason' => 'Função', - 'Class:URP_UserProfile/Attribute:reason+' => 'Explicação por que esta pessoa teve ter esse perfil', + 'Class:URP_UserProfile/Attribute:reason+' => 'Explicação por que esta pessoa deve ter essa função', )); // @@ -189,19 +189,19 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:URP_UserOrg' => 'Organização usuĂĄrio', + 'Class:URP_UserOrg' => 'Organização do usuĂĄrio', 'Class:URP_UserOrg+' => 'OrganizaçÔes permitidas', 'Class:URP_UserOrg/Name' => 'Link entre %1$s e %2$s', - 'Class:URP_UserOrg/Attribute:userid' => 'UsĂĄrio', - 'Class:URP_UserOrg/Attribute:userid+' => 'Conta usuĂĄrio', + 'Class:URP_UserOrg/Attribute:userid' => 'UsuĂĄrio', + 'Class:URP_UserOrg/Attribute:userid+' => 'Conta de usuĂĄrio', 'Class:URP_UserOrg/Attribute:userlogin' => 'Login', - 'Class:URP_UserOrg/Attribute:userlogin+' => 'Login', + 'Class:URP_UserOrg/Attribute:userlogin+' => '', 'Class:URP_UserOrg/Attribute:allowed_org_id' => 'Organização', 'Class:URP_UserOrg/Attribute:allowed_org_id+' => 'Organização permitida', 'Class:URP_UserOrg/Attribute:allowed_org_name' => 'Organização', 'Class:URP_UserOrg/Attribute:allowed_org_name+' => 'Organização permitida', 'Class:URP_UserOrg/Attribute:reason' => 'Função', - 'Class:URP_UserOrg/Attribute:reason+' => 'explicação por que essa pessoa Ă© permitida ver as informaçÔes da organização abaixo', + 'Class:URP_UserOrg/Attribute:reason+' => 'Explicação por que essa pessoa tem permissĂŁo para ver os dados pertencentes com essa organização', )); // @@ -209,18 +209,18 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( // Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( - 'Class:URP_ProfileProjection' => 'profile_projection', - 'Class:URP_ProfileProjection+' => 'profile projections', + 'Class:URP_ProfileProjection' => 'Mapeamentos de Perfil', + 'Class:URP_ProfileProjection+' => '', 'Class:URP_ProfileProjection/Attribute:dimensionid' => 'DimensĂŁo', - 'Class:URP_ProfileProjection/Attribute:dimensionid+' => 'DimensĂŁo aplicação', + 'Class:URP_ProfileProjection/Attribute:dimensionid+' => 'DimensĂŁo de aplicação', 'Class:URP_ProfileProjection/Attribute:dimension' => 'DimensĂŁo', - 'Class:URP_ProfileProjection/Attribute:dimension+' => 'DimensĂŁo aplicação', + 'Class:URP_ProfileProjection/Attribute:dimension+' => 'DimensĂŁo de aplicação', 'Class:URP_ProfileProjection/Attribute:profileid' => 'Perfil', 'Class:URP_ProfileProjection/Attribute:profileid+' => 'Perfil utilizado', 'Class:URP_ProfileProjection/Attribute:profile' => 'Perfil', - 'Class:URP_ProfileProjection/Attribute:profile+' => 'Nome perfil', - 'Class:URP_ProfileProjection/Attribute:value' => 'Valor de expressĂŁo', - 'Class:URP_ProfileProjection/Attribute:value+' => 'ExpressĂŁo OQL (usando $ user) | constante | | + cĂłdigo de atributo', + 'Class:URP_ProfileProjection/Attribute:profile+' => 'Nome do perfil', + 'Class:URP_ProfileProjection/Attribute:value' => 'Valor da expressĂŁo', + 'Class:URP_ProfileProjection/Attribute:value+' => 'ExpressĂŁo OQL (usando $user) | constante | | +cĂłdigo de atributo', 'Class:URP_ProfileProjection/Attribute:attribute' => 'Atributo', 'Class:URP_ProfileProjection/Attribute:attribute+' => 'CĂłdigo de atributo alvo (opcional)', )); @@ -237,7 +237,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:URP_ClassProjection/Attribute:dimension' => 'DimensĂŁo', 'Class:URP_ClassProjection/Attribute:dimension+' => 'DimensĂŁo aplicação', 'Class:URP_ClassProjection/Attribute:class' => 'Classe', - 'Class:URP_ClassProjection/Attribute:class+' => 'Classe alvoTarget class', + 'Class:URP_ClassProjection/Attribute:class+' => 'Classe alvo', 'Class:URP_ClassProjection/Attribute:value' => 'ExpressĂŁo de valor', 'Class:URP_ClassProjection/Attribute:value+' => 'ExpressĂŁo OQL (usando $ user) | constante | | + cĂłdigo de atributo', 'Class:URP_ClassProjection/Attribute:attribute' => 'Atributo', @@ -260,11 +260,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:URP_ActionGrant/Attribute:permission' => 'PermissĂ”es', 'Class:URP_ActionGrant/Attribute:permission+' => 'Permitido ou nĂŁo permitido?', 'Class:URP_ActionGrant/Attribute:permission/Value:yes' => 'Sim', - 'Class:URP_ActionGrant/Attribute:permission/Value:yes+' => 'Sim', + 'Class:URP_ActionGrant/Attribute:permission/Value:yes+' => '', 'Class:URP_ActionGrant/Attribute:permission/Value:no' => 'NĂŁo', - 'Class:URP_ActionGrant/Attribute:permission/Value:no+' => 'NĂŁo', + 'Class:URP_ActionGrant/Attribute:permission/Value:no+' => '', 'Class:URP_ActionGrant/Attribute:action' => 'Ação', - 'Class:URP_ActionGrant/Attribute:action+' => 'operaçÔes a realizar em determinada classe', + 'Class:URP_ActionGrant/Attribute:action+' => 'OperaçÔes a realizar em determinada classe', )); // @@ -273,7 +273,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:URP_StimulusGrant' => 'stimulus_permission', - 'Class:URP_StimulusGrant+' => 'permissĂ”es de Incentivo do ciclo de vida do objeto', + 'Class:URP_StimulusGrant+' => 'PermissĂ”es de estĂ­mulo do ciclo de vida do objeto', 'Class:URP_StimulusGrant/Attribute:profileid' => 'Perfil', 'Class:URP_StimulusGrant/Attribute:profileid+' => 'Perfil utilizado', 'Class:URP_StimulusGrant/Attribute:profile' => 'Perfil', @@ -283,11 +283,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:URP_StimulusGrant/Attribute:permission' => 'PermissĂŁo', 'Class:URP_StimulusGrant/Attribute:permission+' => 'Permitido ou nĂŁo permitido?', 'Class:URP_StimulusGrant/Attribute:permission/Value:yes' => 'Sim', - 'Class:URP_StimulusGrant/Attribute:permission/Value:yes+' => 'Sim', + 'Class:URP_StimulusGrant/Attribute:permission/Value:yes+' => '', 'Class:URP_StimulusGrant/Attribute:permission/Value:no' => 'NĂŁo', - 'Class:URP_StimulusGrant/Attribute:permission/Value:no+' => 'NĂŁo', - 'Class:URP_StimulusGrant/Attribute:stimulus' => 'Incentivo', - 'Class:URP_StimulusGrant/Attribute:stimulus+' => 'CĂłdigo incentivo', + 'Class:URP_StimulusGrant/Attribute:permission/Value:no+' => '', + 'Class:URP_StimulusGrant/Attribute:stimulus' => 'EstĂ­mulo', + 'Class:URP_StimulusGrant/Attribute:stimulus+' => 'CĂłdigo do estĂ­mulo', )); // @@ -296,11 +296,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:URP_AttributeGrant' => 'attribute_permission', - 'Class:URP_AttributeGrant+' => 'PermissĂ”es no nĂ­vel de atributos', - 'Class:URP_AttributeGrant/Attribute:actiongrantid' => 'Ação permissĂŁo', - 'Class:URP_AttributeGrant/Attribute:actiongrantid+' => 'Ação permissĂŁo', + 'Class:URP_AttributeGrant+' => 'PermissĂ”es a nĂ­vel de atributos', + 'Class:URP_AttributeGrant/Attribute:actiongrantid' => 'ConcessĂŁo de permissĂŁo', + 'Class:URP_AttributeGrant/Attribute:actiongrantid+' => 'ConcessĂŁo de permissĂŁo', 'Class:URP_AttributeGrant/Attribute:attcode' => 'Atributo', - 'Class:URP_AttributeGrant/Attribute:attcode+' => 'CĂłdigo atributo', + 'Class:URP_AttributeGrant/Attribute:attcode+' => 'CĂłdigo do atributo', )); // @@ -311,7 +311,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Class:UserDashboard+' => '', 'Class:UserDashboard/Attribute:user_id' => 'UsuĂĄrio', 'Class:UserDashboard/Attribute:user_id+' => '', - 'Class:UserDashboard/Attribute:menu_code' => 'CĂłdigo de menu', + 'Class:UserDashboard/Attribute:menu_code' => 'CĂłdigo do menu', 'Class:UserDashboard/Attribute:menu_code+' => '', 'Class:UserDashboard/Attribute:contents' => 'ConteĂșdo', 'Class:UserDashboard/Attribute:contents+' => '', @@ -335,70 +335,70 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'BooleanLabel:yes' => 'Sim', 'BooleanLabel:no' => 'NĂŁo', - 'UI:Login:Title' => ITOP_APPLICATION_SHORT.' login', - 'Menu:WelcomeMenu' => 'Bem-vindo ao '.ITOP_APPLICATION_SHORT, // Duplicated into itop-welcome-itil (will be removed from here...) + 'UI:Login:Title' => 'Login no '.ITOP_APPLICATION_SHORT, + 'Menu:WelcomeMenu' => 'PĂĄgina inicial do '.ITOP_APPLICATION_SHORT, // Duplicated into itop-welcome-itil (will be removed from here...) 'Menu:WelcomeMenu+' => 'Bem-vindo ao '.ITOP_APPLICATION_SHORT, // Duplicated into itop-welcome-itil (will be removed from here...) 'Menu:WelcomeMenuPage' => 'Bem-vindo ao '.ITOP_APPLICATION_SHORT, // Duplicated into itop-welcome-itil (will be removed from here...) 'Menu:WelcomeMenuPage+' => 'Bem-vindo ao '.ITOP_APPLICATION_SHORT, // Duplicated into itop-welcome-itil (will be removed from here...) 'UI:WelcomeMenu:Title' => 'Bem-vindo ao '.ITOP_APPLICATION_SHORT, - 'UI:WelcomeMenu:LeftBlock' => '

iTop é um completo, OpenSource, portal de operação IT.

-