Compare commits

...

13 Commits

Author SHA1 Message Date
Pierre Goiffon
180da03f08 N°2980 Fix backup not executed anymore
Regression introduced by #89
2020-05-05 09:00:40 +02:00
Eric
f92a980b4d N°2974 - Fix Global Search doesn't search in external field.
For External Field, allow the search also for FriendlyNames.
2020-05-04 18:13:18 +02:00
Eric
843798505a N°2974 - Fix Global Search doesn't search in external field
The IsSearchable() check was wrong for some attributes
2020-05-04 11:40:02 +02:00
Pierre Goiffon
96d888fcf3 N°2968 fix email-reply notification not updated
- add a specific container for attachments list, upload button and #attachment_plugin hidden input is outside of it
- refactor code between abstract class and implementation, add some comments
- now refreshes only the attachment list instead of the whole content
2020-04-28 17:47:20 +02:00
Pierre Goiffon
1904bfdba6 css-variables : update to 2.7.0-2 2020-04-21 16:35:41 +02:00
Eric
1b2d3d1e84 N°2952 - Provisioning for hybrid auth fails
Changed Origin for change to an allowed value
2020-04-21 11:59:48 +02:00
Eric Espié
1f750bb12d N°2902 Fix alias renaming when already exists in one OQL of an UNION
The legacy impl is not modified
2020-04-20 14:59:56 +02:00
Eric
5b60ec9edf N°2919 - Dashboard - Fix dashboard not saved
the sanitization was too strong. Some names can contain ':'
2020-04-10 18:11:36 +02:00
Eric
c1a7a36896 Compatibility with MySQL 5.6 2020-04-06 09:02:06 +02:00
Eric
15e5e21a89 Compatibility with MySQL 5.6 2020-04-01 17:37:55 +02:00
Molkobain
30034d381b Update version number to 2.7.0-1 2020-03-31 09:47:37 +02:00
Molkobain
986eb90546 N°2893 - Fix DataModel Viewer not supporting special chars in class name (eg. ") 2020-03-31 09:40:31 +02:00
Pierre Goiffon
84968ff550 Merge remote-tracking branch 'origin/release/2.7.0' 2020-03-26 08:50:14 +01:00
11 changed files with 94 additions and 49 deletions

View File

@@ -790,12 +790,13 @@ class LoginWebPage extends NiceWebPage
$oPerson = null; $oPerson = null;
try try
{ {
$sOrigin = 'External User provisioning'; CMDBObject::SetTrackOrigin('custom-extension');
$sInfo = 'External User provisioning';
if (isset($_SESSION['login_mode'])) if (isset($_SESSION['login_mode']))
{ {
$sOrigin .= " ({$_SESSION['login_mode']})"; $sInfo .= " ({$_SESSION['login_mode']})";
} }
CMDBObject::SetTrackOrigin($sOrigin); CMDBObject::SetTrackInfo($sInfo);
$oPerson = MetaModel::NewObject('Person'); $oPerson = MetaModel::NewObject('Person');
$oPerson->Set('first_name', $sFirstName); $oPerson->Set('first_name', $sFirstName);
@@ -843,6 +844,14 @@ class LoginWebPage extends NiceWebPage
$oUser = null; $oUser = null;
try try
{ {
CMDBObject::SetTrackOrigin('custom-extension');
$sInfo = 'External User provisioning';
if (isset($_SESSION['login_mode']))
{
$sInfo .= " ({$_SESSION['login_mode']})";
}
CMDBObject::SetTrackInfo($sInfo);
$oUser = MetaModel::GetObjectByName('UserExternal', $sAuthUser, false); $oUser = MetaModel::GetObjectByName('UserExternal', $sAuthUser, false);
if (is_null($oUser)) if (is_null($oUser))
{ {

View File

@@ -156,7 +156,7 @@ abstract class AttributeDefinition
*/ */
public function IsSearchable() public function IsSearchable()
{ {
return static::SEARCH_WIDGET_TYPE != static::SEARCH_WIDGET_TYPE_RAW; return $this->GetSearchType() != static::SEARCH_WIDGET_TYPE_RAW;
} }
/** @var string */ /** @var string */
@@ -7015,6 +7015,15 @@ class AttributeExternalField extends AttributeDefinition
return self::SEARCH_WIDGET_TYPE_RAW; return self::SEARCH_WIDGET_TYPE_RAW;
} }
function IsSearchable()
{
if ($this->IsFriendlyName())
{
return true;
}
return parent::IsSearchable();
}
public static function ListExpectedParams() public static function ListExpectedParams()
{ {
return array_merge(parent::ListExpectedParams(), array("extkey_attcode", "target_attcode")); return array_merge(parent::ListExpectedParams(), array("extkey_attcode", "target_attcode"));

View File

@@ -82,7 +82,8 @@ interface iScheduledProcess extends iProcess
* *
* Other info (module name and time default value) should be provided using a method that needs to be implemented. * Other info (module name and time default value) should be provided using a method that needs to be implemented.
* *
* @since 2.7.0 * @since 2.7.0 PR #89
* @since 2.7.0-2 N°2580 Fix {@link GetNextOccurrence} returning wrong value
*/ */
abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
{ {
@@ -191,7 +192,8 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
} }
$oNow = new DateTime(); $oNow = new DateTime();
$iNextPos = false; $iNextPos = false;
for ($iDay = $oNow->format('N'); $iDay <= 7; $iDay++) $sDay = $oNow->format('N');
for ($iDay = (int) $sDay; $iDay <= 7; $iDay++)
{ {
$iNextPos = array_search($iDay, $aDays, true); $iNextPos = array_search($iDay, $aDays, true);
if ($iNextPos !== false) if ($iNextPos !== false)

View File

@@ -223,9 +223,9 @@ class DBObjectSearch extends DBSearch
public function RenameAlias($sOldName, $sNewName) public function RenameAlias($sOldName, $sNewName)
{ {
$bFound = false; $bFound = false;
if (array_key_exists($sOldName, $this->m_aClasses)) if (!array_key_exists($sOldName, $this->m_aClasses))
{ {
$bFound = true; return false;
} }
if (array_key_exists($sNewName, $this->m_aClasses)) if (array_key_exists($sNewName, $this->m_aClasses))
{ {

View File

@@ -131,7 +131,7 @@ class SQLUnionQuery extends SQLQuery
if ($bGetCount) if ($bGetCount)
{ {
$sSelects = "({$sLimitStart}".implode(" {$sLimit}{$sLimitEnd}{$sLineSep} UNION{$sLineSep} {$sLimitStart}", $aSelects)." {$sLimit}{$sLimitEnd})"; $sSelects = "{$sLimitStart}".implode(" {$sLimit}{$sLimitEnd}{$sLineSep} UNION{$sLineSep} {$sLimitStart}", $aSelects)." {$sLimit}{$sLimitEnd}";
$sFrom = "({$sLineSep}{$sSelects}{$sLineSep}) as __selects__"; $sFrom = "({$sLineSep}{$sSelects}{$sLineSep}) as __selects__";
$sSQL = "SELECT COUNT(*) AS COUNT FROM (SELECT$sLineSep 1 $sLineSep FROM {$sFrom}{$sLineSep}) AS _union_alderaan_"; $sSQL = "SELECT COUNT(*) AS COUNT FROM (SELECT$sLineSep 1 $sLineSep FROM {$sFrom}{$sLineSep}) AS _union_alderaan_";
} }

View File

@@ -17,7 +17,7 @@
*/ */
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0 // Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.7.0"; $version: "v2.7.0-2";
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css $approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
// Base colors // Base colors

View File

@@ -46,7 +46,7 @@ function RenderAttachments(ajax_page $oPage, $iTransactionId)
: AttachmentPlugIn::IsReadonlyState($oObject, $oObject->GetState(), AttachmentPlugIn::ENUM_GUI_BACKOFFICE); : AttachmentPlugIn::IsReadonlyState($oObject, $oObject->GetState(), AttachmentPlugIn::ENUM_GUI_BACKOFFICE);
if ($bEditMode && !$bIsReadOnlyState) if ($bEditMode && !$bIsReadOnlyState)
{ {
$oAttachmentsRenderer->RenderEditAttachmentsList($aAttachmentsDeleted); $oAttachmentsRenderer->AddAttachmentsListContent(true, $aAttachmentsDeleted);
} }
else else
{ {

View File

@@ -69,6 +69,14 @@ abstract class AbstractAttachmentsRenderer
*/ */
const MAX_SIZE_FOR_PREVIEW = 500000; const MAX_SIZE_FOR_PREVIEW = 500000;
/**
* Attachments list container HTML id, that must be generated in {@link RenderEditAttachmentsList}
*
* @since 2.7.0-2 N°2968 ajax buttons (on especially the #attachment_plugin hidden input) should not be refreshed
* so we are refreshing only the content of this container
*/
const ATTACHMENTS_LIST_CONTAINER_ID = 'AttachmentsListContainer';
/** @var \WebPage */ /** @var \WebPage */
protected $oPage; protected $oPage;
/** /**
@@ -129,13 +137,38 @@ abstract class AbstractAttachmentsRenderer
} }
/** /**
* Can be overriden to change display order, but must generate an HTML container of ID {@link ATTACHMENTS_LIST_CONTAINER_ID} for JS refresh.
*
* @param int[] $aAttachmentsDeleted Attachments id that should be deleted after form submission * @param int[] $aAttachmentsDeleted Attachments id that should be deleted after form submission
* *
* @return string * @return void will print using {@link oPage}
*/ */
abstract public function RenderEditAttachmentsList($aAttachmentsDeleted = array()); public function RenderEditAttachmentsList($aAttachmentsDeleted = array())
{
$this->AddUploadButton();
abstract public function RenderViewAttachmentsList(); $this->oPage->add('<div id="'.self::ATTACHMENTS_LIST_CONTAINER_ID.'">');
$this->AddAttachmentsListContent(true, $aAttachmentsDeleted);
$this->oPage->add('</div>');
}
/**
* Generates the attachments list content
*
* @param bool $bWithDeleteButton
* @param array $aAttachmentsDeleted
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
abstract public function AddAttachmentsListContent($bWithDeleteButton, $aAttachmentsDeleted = array());
public function RenderViewAttachmentsList()
{
$this->AddAttachmentsListContent(false, array());
}
protected function AddUploadButton() protected function AddUploadButton()
{ {
@@ -154,9 +187,9 @@ abstract class AbstractAttachmentsRenderer
$this->oPage->add_ready_script( $this->oPage->add_ready_script(
<<<JS <<<JS
function RefreshAttachmentsDisplay() function RefreshAttachmentsDisplay(dataUpload)
{ {
var sContentNode = '#AttachmentsContent', var sContentNode = '#AttachmentsContent>div#AttachmentsListContainer',
aAttachmentsDeletedHiddenInputs = $('table.attachmentsList>tbody>tr[id^="display_attachment_"]>td input[name="removed_attachments[]"]'), aAttachmentsDeletedHiddenInputs = $('table.attachmentsList>tbody>tr[id^="display_attachment_"]>td input[name="removed_attachments[]"]'),
aAttachmentsDeletedIds = aAttachmentsDeletedHiddenInputs.map(function() { return $(this).val() }).toArray(); aAttachmentsDeletedIds = aAttachmentsDeletedHiddenInputs.map(function() { return $(this).val() }).toArray();
$(sContentNode).block(); $(sContentNode).block();
@@ -172,6 +205,8 @@ abstract class AbstractAttachmentsRenderer
function(data) { function(data) {
$(sContentNode).html(data); $(sContentNode).html(data);
$(sContentNode).unblock(); $(sContentNode).unblock();
$('#attachment_plugin').trigger('add_attachment', [dataUpload.result.att_id, dataUpload.result.msg, false]);
} }
); );
} }
@@ -181,7 +216,17 @@ abstract class AbstractAttachmentsRenderer
formData: { operation: 'add', temp_id: '$this->sTransactionId', obj_class: '$sClass' }, formData: { operation: 'add', temp_id: '$this->sTransactionId', obj_class: '$sClass' },
dataType: 'json', dataType: 'json',
pasteZone: null, // Don't accept files via Chrome's copy/paste pasteZone: null, // Don't accept files via Chrome's copy/paste
done: RefreshAttachmentsDisplay, done: function(e, data) {
if(typeof(data.result.error) != 'undefined')
{
if(data.result.error !== '')
{
alert(data.result.error);
return;
}
}
RefreshAttachmentsDisplay(data);
},
send: function(e, data){ send: function(e, data){
// Don't send attachment if size is greater than PHP post_max_size, otherwise it will break the request and all its parameters (\$_REQUEST, \$_POST, ...) // Don't send attachment if size is greater than PHP post_max_size, otherwise it will break the request and all its parameters (\$_REQUEST, \$_POST, ...)
// Note: We loop on the files as the data structures is an array but in this case, we only upload 1 file at a time. // Note: We loop on the files as the data structures is an array but in this case, we only upload 1 file at a time.
@@ -325,16 +370,7 @@ JS;
*/ */
class TableDetailsAttachmentsRenderer extends AbstractAttachmentsRenderer class TableDetailsAttachmentsRenderer extends AbstractAttachmentsRenderer
{ {
/** public function AddAttachmentsListContent($bWithDeleteButton, $aAttachmentsDeleted = array())
* @param bool $bWithDeleteButton
* @param array $aAttachmentsDeleted
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
private function AddAttachmentsTable($bWithDeleteButton, $aAttachmentsDeleted = array())
{ {
if ($this->GetAttachmentsCount() === 0) if ($this->GetAttachmentsCount() === 0)
{ {
@@ -522,22 +558,4 @@ JS
HTML HTML
); );
} }
/**
* @inheritDoc
*/
public function RenderEditAttachmentsList($aAttachmentsDeleted = array())
{
$this->AddUploadButton();
$this->AddAttachmentsTable(true, $aAttachmentsDeleted);
}
/**
* @inheritDoc
*/
public function RenderViewAttachmentsList()
{
$this->AddAttachmentsTable(false);
}
} }

View File

@@ -1197,7 +1197,7 @@ EOF
break; break;
case 'dashboard_editor': case 'dashboard_editor':
$sId = utils::ReadParam('id', '', false, 'element_identifier'); $sId = utils::ReadParam('id', '', false, 'context_param');
$aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data'); $aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data');
$aExtraParams['dashboard_div_id'] = utils::Sanitize($sId, '', 'element_identifier'); $aExtraParams['dashboard_div_id'] = utils::Sanitize($sId, '', 'element_identifier');
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data'); $sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');

View File

@@ -309,12 +309,18 @@ EOF
$aRootClasses[$sClassName] = MetaModel::GetName($sClassName); $aRootClasses[$sClassName] = MetaModel::GetName($sClassName);
} }
$sLabelClassName = MetaModel::GetName($sClassName); $sLabelClassName = MetaModel::GetName($sClassName);
//Fetch classes names for autocomplete purpose //Fetch classes names for autocomplete purpose
// - Encode as JSON to escape quotes and other characters
$sClassLabelAndCodeAsJSON = json_encode("$sLabelClassName ($sClassName)");
$sClassLabelAsJSON = json_encode($sLabelClassName);
$sClassCodeAsJSON = json_encode($sClassName);
// - Push to autocomplete
$oPage->add_script( $oPage->add_script(
<<<EOF <<<EOF
autocompleteClassLabelAndCode.push("$sLabelClassName ($sClassName)"); autocompleteClassLabelAndCode.push($sClassLabelAndCodeAsJSON);
autocompleteClassLabel.push("$sLabelClassName"); autocompleteClassLabel.push($sClassLabelAsJSON);
autocompleteClassCode.push("$sClassName"); autocompleteClassCode.push($sClassCodeAsJSON);
EOF EOF
); );
} }

View File

@@ -341,6 +341,7 @@ class OQLToSQLTest extends ItopDataTestCase
); );
$aData = array( $aData = array(
"SELECT UNION 5.6" => array("SELECT `Organization` AS `Organization` WHERE ((`Organization`.`status` != 'inactive') AND (`Organization`.`id` = '1')) UNION SELECT `Organization` AS `Organization` WHERE ((`Organization`.`id` = '1') AND (`Organization`.`id` = '1'))", array(), array(), array(), null, null, 3, 0),
"SELECT WebServer 150" => array("SELECT `WebServer` FROM WebServer AS `WebServer` WHERE 1", array(), array(), $aAttToLoad150, null, null, 3, 0), "SELECT WebServer 150" => array("SELECT `WebServer` FROM WebServer AS `WebServer` WHERE 1", array(), array(), $aAttToLoad150, null, null, 3, 0),
"SELECT WebServer 151" => array("SELECT `WebServer` FROM WebServer AS `WebServer` WHERE 1", array(), array(), array(), null, null, 3, 0), "SELECT WebServer 151" => array("SELECT `WebServer` FROM WebServer AS `WebServer` WHERE 1", array(), array(), array(), null, null, 3, 0),
"SELECT L JOIN 176" => array("SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1", unserialize('a:1:{s:14:"L.friendlyname";b:1;}'), array(), null, null, 3, 0), "SELECT L JOIN 176" => array("SELECT `L` FROM Location AS `L` JOIN Person AS `P` ON `P`.location_id = `L`.id WHERE 1", unserialize('a:1:{s:14:"L.friendlyname";b:1;}'), array(), null, null, 3, 0),