mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
313 lines
10 KiB
PHP
313 lines
10 KiB
PHP
<?php
|
|
/*
|
|
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
|
* @license http://opensource.org/licenses/AGPL-3.0
|
|
*/
|
|
|
|
namespace Combodo\iTop\Controller\Links;
|
|
|
|
use AjaxPage;
|
|
use cmdbAbstractObject;
|
|
use Combodo\iTop\Application\Helper\FormHelper;
|
|
use Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory;
|
|
use Combodo\iTop\Controller\AbstractController;
|
|
use Combodo\iTop\Service\Links\LinkSetModel;
|
|
use Combodo\iTop\Service\Router\Router;
|
|
use Combodo\iTop\Service\Base\ObjectRepository;
|
|
use Dict;
|
|
use Exception;
|
|
use JsonPage;
|
|
use CoreException;
|
|
use DBObject;
|
|
use MetaModel;
|
|
use UserRights;
|
|
use utils;
|
|
|
|
/**
|
|
* Class LinkSetController
|
|
*
|
|
* @internal
|
|
* @since 3.1.0
|
|
* @package Combodo\iTop\Controller
|
|
*/
|
|
class LinkSetController extends AbstractController
|
|
{
|
|
public const ROUTE_NAMESPACE = 'linkset';
|
|
|
|
/**
|
|
* OperationDeleteLinkedObject.
|
|
*
|
|
* @return JsonPage
|
|
* @throws \CoreException
|
|
*/
|
|
public function OperationDeleteLinkedObject(): JsonPage
|
|
{
|
|
if (!$this->IsHandlingXmlHttpRequest()) {
|
|
throw new CoreException('LinksetController can only be called in ajax.');
|
|
}
|
|
|
|
$oPage = new JsonPage();
|
|
$sErrorMessage = null;
|
|
$bOperationSuccess = false;
|
|
|
|
// retrieve parameters
|
|
$sLinkedObjectClass = utils::ReadParam('linked_object_class', '', false, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
|
$sLinkedObjectObjectKey = utils::ReadParam('linked_object_key', 0, false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
$sTransactionId = utils::ReadParam('transaction_id', null, false, utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID);
|
|
|
|
// check transaction id
|
|
if (utils::IsTransactionValid($sTransactionId, false)) {
|
|
try {
|
|
$oDeletionPlan = MetaModel::GetObject($sLinkedObjectClass, $sLinkedObjectObjectKey)->DBDelete();
|
|
$bOperationSuccess = (count($oDeletionPlan->GetIssues()) === 0);
|
|
if (!$bOperationSuccess) {
|
|
$sErrorMessage = json_encode($oDeletionPlan->GetIssues());
|
|
}
|
|
}
|
|
catch (Exception $e) {
|
|
$sErrorMessage = $e->getMessage();
|
|
}
|
|
} else {
|
|
$sErrorMessage = 'invalid transaction id';
|
|
}
|
|
$oPage->SetData([
|
|
'success' => $bOperationSuccess,
|
|
'error_message' => $sErrorMessage,
|
|
]);
|
|
|
|
return $oPage;
|
|
}
|
|
|
|
/**
|
|
* OperationDetachLinkedObject.
|
|
*
|
|
* @return \JsonPage
|
|
* @throws \CoreException
|
|
*/
|
|
public function OperationDetachLinkedObject(): JsonPage
|
|
{
|
|
if (!$this->IsHandlingXmlHttpRequest()) {
|
|
throw new CoreException('LinksetController can only be called in ajax.');
|
|
}
|
|
|
|
$oPage = new JsonPage();
|
|
$sErrorMessage = null;
|
|
$bOperationSuccess = false;
|
|
|
|
// retrieve parameters
|
|
$sLinkedObjectClass = utils::ReadParam('linked_object_class', '', false, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
|
$sLinkedObjectKey = utils::ReadParam('linked_object_key', 0, false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
$sExternalKeyAttCode = utils::ReadParam('external_key_att_code', null, false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
$sTransactionId = utils::ReadParam('transaction_id', null, false, utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID);
|
|
|
|
// check transaction id
|
|
if (utils::IsTransactionValid($sTransactionId, false)) {
|
|
try {
|
|
$oLinkedObject = MetaModel::GetObject($sLinkedObjectClass, $sLinkedObjectKey);
|
|
$oLinkedObject->Set($sExternalKeyAttCode, null);
|
|
$oLinkedObject->DBWrite();
|
|
$bOperationSuccess = true;
|
|
}
|
|
catch (Exception $e) {
|
|
$sErrorMessage = $e->getMessage();
|
|
}
|
|
} else {
|
|
$sErrorMessage = 'invalid transaction id';
|
|
}
|
|
$oPage->SetData([
|
|
'success' => $bOperationSuccess,
|
|
'error_message' => $sErrorMessage,
|
|
]);
|
|
|
|
return $oPage;
|
|
}
|
|
|
|
/**
|
|
* @return \AjaxPage Create edit form in its webpage
|
|
* @throws \ApplicationException
|
|
* @throws \ArchivedObjectException
|
|
* @throws \CoreException
|
|
* @throws \SecurityException
|
|
*/
|
|
public function OperationCreateLinkedObject(): AjaxPage
|
|
{
|
|
if (!$this->IsHandlingXmlHttpRequest()) {
|
|
throw new CoreException('LinksetController can only be called in ajax.');
|
|
}
|
|
|
|
$oRouter = Router::GetInstance();
|
|
$oPage = new AjaxPage('');
|
|
|
|
$sProposedRealClass = utils::ReadParam('class', '', false, 'class');
|
|
$sAttCode = utils::ReadParam('att_code', '', false, 'raw');
|
|
$sClass = utils::ReadParam('host_class', '', false, 'class');
|
|
$sId = utils::ReadParam('host_id', '', false, 'integer');
|
|
|
|
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
|
|
// and that the current user is allowed to create objects of this class
|
|
$sRealClass = '';
|
|
|
|
$aSubClasses = MetaModel::EnumChildClasses($sProposedRealClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
|
|
$aPossibleClasses = array();
|
|
foreach ($aSubClasses as $sCandidateClass) {
|
|
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) {
|
|
if ($sCandidateClass == $sProposedRealClass) {
|
|
$sRealClass = $sProposedRealClass;
|
|
}
|
|
$aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass);
|
|
}
|
|
}
|
|
|
|
// Only one of the subclasses can be instantiated...
|
|
if (count($aPossibleClasses) == 1) {
|
|
$aKeys = array_keys($aPossibleClasses);
|
|
$sRealClass = $aKeys[0];
|
|
}
|
|
if ($sRealClass != '') {
|
|
$oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
|
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
|
|
$aFieldFlags = array($sExtKeyToMe => OPT_ATT_READONLY);
|
|
$oObj = DBObject::MakeDefaultInstance($sRealClass);
|
|
|
|
$oSourceObj = MetaModel::GetObject($sClass, $sId);
|
|
|
|
$oObj->Set($sExtKeyToMe, $sId);
|
|
$aPrefillParam = array('source_obj' => $oSourceObj);
|
|
$oObj->PrefillForm('creation_from_editinplace', $aPrefillParam);
|
|
// We display this form in a modal, once we submit (in ajax) we probably want to only close the modal
|
|
$sFormOnSubmitJsCode =
|
|
<<<JS
|
|
event.preventDefault();
|
|
if(bOnSubmitForm === true)
|
|
{
|
|
let oForm = $(this);
|
|
let sUrl = oForm.attr('action');
|
|
let sPosting = $.post( sUrl, oForm.serialize());
|
|
|
|
/* Alerts the results */
|
|
sPosting.done(function(data) {
|
|
// fire event
|
|
oForm.trigger('itop.form.submitted', [data]);
|
|
if(data.success !== undefined && data.success === true) {
|
|
oForm.closest('[data-role="ibo-modal"]').dialog('close');
|
|
}
|
|
else {
|
|
/* We're not in submit anymore */
|
|
window.bInSubmit = false;
|
|
oForm.attr('data-form-state', 'default');
|
|
/* Display error popup */
|
|
CombodoModal.OpenErrorModal(data.data.error_message);
|
|
}
|
|
});
|
|
}
|
|
JS;
|
|
|
|
|
|
// Form title
|
|
/** @var \AttributeLinkedSet $oLinksetDef */
|
|
$oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
|
$oHostObj = MetaModel::GetObject($sClass, $sId);
|
|
$sFormTitle = $oLinksetDef->SearchSpecificLabel('UI:Links:Add:Modal:Title', '', true,
|
|
MetaModel::GetName($sClass),
|
|
$oHostObj->Get('friendlyname'),
|
|
$oLinksetDef->GetLabel(),
|
|
MetaModel::GetName(LinkSetModel::GetTargetClass($oLinksetDef)));
|
|
|
|
$aExtraParams = [
|
|
'noRelations' => true,
|
|
'hide_transitions' => true,
|
|
'formPrefix' => $sAttCode,
|
|
'fieldsFlags' => $aFieldFlags,
|
|
'forceFieldsSubmission' => [
|
|
$sExtKeyToMe,
|
|
],
|
|
'form_title' => $sFormTitle,
|
|
'custom_button' => \Dict::S('UI:Button:Add'),
|
|
'js_handlers' => [
|
|
'form_on_submit' => $sFormOnSubmitJsCode,
|
|
'cancel_button_on_click' =>
|
|
<<<JS
|
|
function() {
|
|
$(this).closest('[data-role="ibo-modal"]').dialog('close');
|
|
};
|
|
JS
|
|
,
|
|
],
|
|
];
|
|
|
|
// Remove blob edition from creation form @see N°5863 to allow blob edition in modal context
|
|
FormHelper::DisableAttributeBlobInputs($sRealClass, $aExtraParams);
|
|
|
|
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, $oObj, array(), $aExtraParams);
|
|
}
|
|
else
|
|
{
|
|
// - We'll let the user select a class if multiple classes are available
|
|
$oClassForm = FormUIBlockFactory::MakeStandard();
|
|
|
|
// - When the user submit, redo the same request but with a real class
|
|
|
|
$sCurrentParameters = json_encode([
|
|
'att_code' => $sAttCode,
|
|
'host_class' => $sClass,
|
|
'host_id' => $sId]);
|
|
$sCurrentUrl = $oRouter->GenerateUrl('linkset.create_linked_object');
|
|
$oClassForm->SetOnSubmitJsCode(
|
|
<<<JS
|
|
let me = this;
|
|
let aParam = $sCurrentParameters;
|
|
aParam['class'] = $(this).find('[name="class"]').val();
|
|
let sPosting = $.post('$sCurrentUrl', aParam);
|
|
sPosting.done(function(data){
|
|
$(me).closest('[data-role="ibo-modal"]').html(data);
|
|
});
|
|
return false;
|
|
JS
|
|
);
|
|
|
|
// - Add a select and a button to validate the form
|
|
$oClassForm->AddSubBlock(cmdbAbstractObject::DisplayBlockSelectClassToCreate($sProposedRealClass, MetaModel::GetName($sProposedRealClass), $aPossibleClasses));
|
|
|
|
$oPage->AddUiBlock($oClassForm);
|
|
}
|
|
|
|
return $oPage;
|
|
}
|
|
|
|
/**
|
|
* OperationGetRemoteObject.
|
|
*
|
|
* @return JsonPage
|
|
*/
|
|
public function OperationGetRemoteObject(): JsonPage
|
|
{
|
|
$oPage = new JsonPage();
|
|
$bSuccess = true;
|
|
$aObjectData = null;
|
|
|
|
// Retrieve query params
|
|
$sObjectClass = utils::ReadParam('linked_object_class', '', false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
$sObjectKey = utils::ReadParam('linked_object_key', '', false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
$sRemoteClass = utils::ReadParam('remote_class', null, false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
$sRemoteExtKey = utils::ReadParam('external_key_att_code', null, false, utils::ENUM_SANITIZATION_FILTER_STRING);
|
|
|
|
// Retrieve object
|
|
try {
|
|
$oObject = MetaModel::GetObject($sObjectClass, $sObjectKey);
|
|
$sLinkKey = $oObject->GetKey();
|
|
if (!utils::IsNullOrEmptyString($sRemoteExtKey)) {
|
|
$oObject = MetaModel::GetObject($sRemoteClass, $oObject->Get($sRemoteExtKey));
|
|
}
|
|
$aObjectData = ObjectRepository::ConvertObjectToArray($oObject, $sObjectClass);
|
|
$aObjectData['link_keys'] = [$sObjectKey];
|
|
}
|
|
catch (Exception $e) {
|
|
$bSuccess = false;
|
|
}
|
|
|
|
return $oPage->SetData([
|
|
'object' => $aObjectData,
|
|
'success' => $bSuccess,
|
|
]);
|
|
}
|
|
} |