1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357 |
- <?php
- // Copyright (C) 2010-2015 Combodo SARL
- //
- // This file is part of iTop.
- //
- // 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.
- //
- // iTop is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with iTop. If not, see <http://www.gnu.org/licenses/>
- namespace Combodo\iTop\Portal\Controller;
- use \Silex\Application;
- use \Symfony\Component\HttpFoundation\Request;
- use \Symfony\Component\HttpFoundation\Response;
- use \Symfony\Component\HttpFoundation\RedirectResponse;
- use \Symfony\Component\HttpKernel\HttpKernelInterface;
- use \Exception;
- use \FileUploadException;
- use \utils;
- use \Dict;
- use \IssueLog;
- use \MetaModel;
- use \DBSearch;
- use \DBObjectSearch;
- use \BinaryExpression;
- use \FieldExpression;
- use \VariableExpression;
- use \ListExpression;
- use \ScalarExpression;
- use \DBObjectSet;
- use \cmdbAbstractObject;
- use \UserRights;
- use \Combodo\iTop\Portal\Helper\ApplicationHelper;
- use \Combodo\iTop\Portal\Helper\SecurityHelper;
- use \Combodo\iTop\Portal\Helper\ContextManipulatorHelper;
- use \Combodo\iTop\Portal\Form\ObjectFormManager;
- use \Combodo\iTop\Renderer\Bootstrap\BsFormRenderer;
- /**
- * Controller to handle basic view / edit / create of cmdbAbstractObject
- */
- class ObjectController extends AbstractController
- {
- const ENUM_MODE_VIEW = 'view';
- const ENUM_MODE_EDIT = 'edit';
- const ENUM_MODE_CREATE = 'create';
- const DEFAULT_COUNT_PER_PAGE_LIST = 10;
- /**
- * Displays an cmdbAbstractObject if the connected user is allowed to.
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sObjectClass (Class must be instance of cmdbAbstractObject)
- * @param string $sObjectId
- * @return Response
- */
- public function ViewAction(Request $oRequest, Application $oApp, $sObjectClass, $sObjectId)
- {
- // Checking parameters
- if ($sObjectClass === '' || $sObjectId === '')
- {
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : sObjectClass and sObjectId expected, "' . $sObjectClass . '" and "' . $sObjectId . '" given.');
- $oApp->abort(500, Dict::Format('UI:Error:2ParametersMissing', 'class', 'id'));
- }
- // Checking security layers
- if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $sObjectClass, $sObjectId))
- {
- IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' not allowed to read ' . $sObjectClass . '::' . $sObjectId . ' object.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // Retrieving object
- $oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
- if ($oObject === null)
- {
- // We should never be there as the secuirty helper makes sure that the object exists, but just in case.
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : Could not load object ' . $sObjectClass . '::' . $sObjectId . '.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- $aData = array('sMode' => 'view');
- $aData['form'] = $this->HandleForm($oRequest, $oApp, $aData['sMode'], $sObjectClass, $sObjectId);
- $aData['form']['title'] = Dict::Format('Brick:Portal:Object:Form:View:Title', MetaModel::GetName($sObjectClass), $oObject->GetName());
- // Add an edit button if user is allowed
- if (SecurityHelper::IsActionAllowed($oApp, UR_ACTION_MODIFY, $sObjectClass, $sObjectId))
- {
- $aData['form']['buttons']['links'][] = array(
- 'label' => Dict::S('UI:Menu:Modify'),
- 'url' => $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId))
- );
- }
- // Preparing response
- if ($oRequest->isXmlHttpRequest())
- {
- // We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
- if ($oRequest->request->get('operation') === null)
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
- }
- else
- {
- $oResponse = $oApp->json($aData);
- }
- }
- else
- {
- // Adding brick if it was passed
- $sBrickId = $oRequest->get('sBrickId');
- if ($sBrickId !== null)
- {
- $oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
- if ($oBrick !== null)
- {
- $aData['oBrick'] = $oBrick;
- }
- }
- $aData['sPageTitle'] = $aData['form']['title'];
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/layout.html.twig', $aData);
- }
- return $oResponse;
- }
- public function EditAction(Request $oRequest, Application $oApp, $sObjectClass, $sObjectId)
- {
- // Checking parameters
- if ($sObjectClass === '' || $sObjectId === '')
- {
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : sObjectClass and sObjectId expected, "' . $sObjectClass . '" and "' . $sObjectId . '" given.');
- $oApp->abort(500, Dict::Format('UI:Error:2ParametersMissing', 'class', 'id'));
- }
-
- // Checking security layers
- // Warning : This is a dirty quick fix to allow editing its own contact information
- $bAllowWrite = ($sObjectClass === 'Person' && $sObjectId == UserRights::GetContactId());
- if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_MODIFY, $sObjectClass, $sObjectId) && !$bAllowWrite)
- {
- IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' not allowed to modify ' . $sObjectClass . '::' . $sObjectId . ' object.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // Retrieving object
- $oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
- if ($oObject === null)
- {
- // We should never be there as the secuirty helper makes sure that the object exists, but just in case.
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : Could not load object ' . $sObjectClass . '::' . $sObjectId . '.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- $aData = array('sMode' => 'edit');
- $aData['form'] = $this->HandleForm($oRequest, $oApp, $aData['sMode'], $sObjectClass, $sObjectId);
- $aData['form']['title'] = Dict::Format('Brick:Portal:Object:Form:Edit:Title', MetaModel::GetName($sObjectClass), $aData['form']['object_name']);
- // Preparing response
- if ($oRequest->isXmlHttpRequest())
- {
- // We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
- if ($oRequest->request->get('operation') === null)
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
- }
- else
- {
- $oResponse = $oApp->json($aData);
- }
- }
- else
- {
- // Adding brick if it was passed
- $sBrickId = $oRequest->get('sBrickId');
- if ($sBrickId !== null)
- {
- $oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
- if ($oBrick !== null)
- {
- $aData['oBrick'] = $oBrick;
- }
- }
- $aData['sPageTitle'] = $aData['form']['title'];
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/layout.html.twig', $aData);
- }
- return $oResponse;
- }
- /**
- * Creates an cmdbAbstractObject of the $sObjectClass
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sObjectClass
- * @return Response
- */
- public function CreateAction(Request $oRequest, Application $oApp, $sObjectClass)
- {
- // Checking security layers
- if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_CREATE, $sObjectClass))
- {
- IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' not allowed to create ' . $sObjectClass . ' object.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- $aData = array('sMode' => 'create');
- $aData['form'] = $this->HandleForm($oRequest, $oApp, $aData['sMode'], $sObjectClass);
- $aData['form']['title'] = Dict::Format('Brick:Portal:Object:Form:Create:Title', MetaModel::GetName($sObjectClass));
- // Preparing response
- if ($oRequest->isXmlHttpRequest())
- {
- // We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
- if ($oRequest->request->get('operation') === null)
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
- }
- else
- {
- $oResponse = $oApp->json($aData);
- }
- }
- else
- {
- // Adding brick if it was passed
- $sBrickId = $oRequest->get('sBrickId');
- if ($sBrickId !== null)
- {
- $oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
- if ($oBrick !== null)
- {
- $aData['oBrick'] = $oBrick;
- }
- }
- $aData['sPageTitle'] = $aData['form']['title'];
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/layout.html.twig', $aData);
- }
- return $oResponse;
- }
- /**
- * Creates an cmdbAbstractObject of a class determined by the method encoded in $sEncodedMethodName.
- * This method use an origin DBObject in order to determine the created cmdbAbstractObject.
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sObjectClass Class of the origin object
- * @param string $sObjectId ID of the origin object
- * @param string $sEncodedMethodName Base64 encoded factory method name
- * @return Response
- */
- public function CreateFromFactoryAction(Request $oRequest, Application $oApp, $sObjectClass, $sObjectId, $sEncodedMethodName)
- {
- $sMethodName = base64_decode($sEncodedMethodName);
-
- // Checking that the factory method is valid
- if (!is_callable($sMethodName))
- {
- IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Invalid factory method "' . $sMethodName . '" used when creating an object.');
- $oApp->abort(500, 'Invalid factory method "' . $sMethodName . '" used when creating an object');
- }
-
- // Retrieving origin object
- $oOriginObject = MetaModel::GetObject($sObjectClass, $sObjectId);
-
- // Retrieving target object (We check if the method is a simple function or if it's part of a class in which case only static function are supported)
- if (!strpos($sMethodName, '::'))
- {
- $sTargetObject = $sMethodName($oOriginObject);
- }
- else
- {
- $aMethodNameParts = explode('::', $sMethodName);
- $sTargetObject = $aMethodNameParts[0]::$aMethodNameParts[1]($oOriginObject);
- }
- // Preparing redirection
- // - Route
- $aRouteParams = array(
- 'sObjectClass' => get_class($sTargetObject)
- );
- $sRedirectRoute = $oApp['url_generator']->generate('p_object_create', $aRouteParams);
- // - Request
- $oSubRequest = Request::create($sRedirectRoute, 'GET', $oRequest->query->all(), $oRequest->cookies->all(), array(), $oRequest->server->all());
- return $oApp->handle($oSubRequest, HttpKernelInterface::SUB_REQUEST, true);
- }
- /**
- * Applies a stimulus $sStimulus on an cmdbAbstractObject
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sObjectClass
- * @param string $sObjectId
- * @param string $sStimulusCode
- * @return Response
- */
- public function ApplyStimulusAction(Request $oRequest, Application $oApp, $sObjectClass, $sObjectId, $sStimulusCode)
- {
- // Checking parameters
- if ($sObjectClass === '' || $sObjectId === '' || $sStimulusCode === '')
- {
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : sObjectClass, sObjectId and $sStimulusCode expected, "' . $sObjectClass . '", "' . $sObjectId . '" and "' . $sStimulusCode . '" given.');
- $oApp->abort(500, Dict::Format('UI:Error:3ParametersMissing', 'class', 'id', 'stimulus'));
- }
- // Checking security layers
- // TODO : This should call the stimulus check in the security helper
- // if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_MODIFY, $sObjectClass, $sObjectId))
- // {
- // $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- // }
-
- // Retrieving object
- $oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */);
- if ($oObject === null)
- {
- // We should never be there as the secuirty helper makes sure that the object exists, but just in case.
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : Could not load object ' . $sObjectClass . '::' . $sObjectId . '.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // Preparing a dedicated form for the stimulus application
- $aFormProperties = array(
- 'id' => 'apply-stimulus',
- 'type' => 'static',
- 'fields' => array(),
- 'layout' => null
- );
- // Checking which fields need to be prompt
- $aTransitions = MetaModel::EnumTransitions($sObjectClass, $oObject->GetState());
- $aTargetStates = MetaModel::EnumStates($sObjectClass);
- $aTargetState = $aTargetStates[$aTransitions[$sStimulusCode]['target_state']];
- $aExpectedAttributes = $aTargetState['attribute_list'];
- foreach ($aExpectedAttributes as $sAttCode => $iFlags)
- {
- if (($iFlags & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
- (($iFlags & OPT_ATT_MANDATORY) && ($oObject->Get($sAttCode) == '')))
- {
- $aFormProperties['fields'][$sAttCode] = array();
- // Settings flags for the field
- if ($iFlags & OPT_ATT_MUSTCHANGE)
- $aFormProperties['fields'][$sAttCode]['must_change'] = true;
- if ($iFlags & OPT_ATT_MUSTPROMPT)
- $aFormProperties['fields'][$sAttCode]['must_prompt'] = true;
- if (($iFlags & OPT_ATT_MANDATORY) && ($oObject->Get($sAttCode) == ''))
- $aFormProperties['fields'][$sAttCode]['mandatory'] = true;
- }
- }
- // Adding target_state to current_values
- $oRequest->request->set('apply_stimulus', array('code' => $sStimulusCode));
- $aData = array('sMode' => 'apply_stimulus');
- $aData['form'] = $this->HandleForm($oRequest, $oApp, $aData['sMode'], $sObjectClass, $sObjectId, $aFormProperties);
- $aData['form']['title'] = Dict::Format('Brick:Portal:Object:Form:Stimulus:Title');
- $aData['form']['validation']['redirection'] = array(
- 'url' => $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId))
- );
- // Preparing response
- if ($oRequest->isXmlHttpRequest())
- {
- // We have to check whether the 'operation' parameter is defined or not in order to know if the form is required via ajax (to be displayed as a modal dialog) or if it's a lifecycle call from a existing form.
- if ($oRequest->request->get('operation') === null)
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
- }
- else
- {
- $oResponse = $oApp->json($aData);
- }
- }
- else
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/layout.html.twig', $aData);
- }
- return $oResponse;
- }
- public static function HandleForm(Request $oRequest, Application $oApp, $sMode, $sObjectClass, $sObjectId = null, $aFormProperties = null)
- {
- $aFormData = array();
- $oRequestParams = $oRequest->request;
- $sOperation = $oRequestParams->get('operation');
- $bModal = ($oRequest->isXmlHttpRequest() && ($oRequest->request->get('operation') === null) );
- // - Retrieve form properties
- if ($aFormProperties === null)
- {
- $aFormProperties = ApplicationHelper::GetLoadedFormFromClass($oApp, $sObjectClass, $sMode);
- }
- // - Create and
- if ($sOperation === null)
- {
- // Retrieving action rules
- //
- // Note : The action rules must be a base64-encoded JSON object, this is just so users are tempted to changes values.
- // But it would not be a security issue as it only presets values in the form.
- $sActionRulesToken = $oRequest->get('ar_token');
- $aActionRules = ($sActionRulesToken !== null) ? ContextManipulatorHelper::DecodeRulesToken($sActionRulesToken) : array();
-
- // Preparing object
- if ($sObjectId === null)
- {
- // Create new UserRequest
- $oObject = MetaModel::NewObject($sObjectClass);
- // Retrieve action rules information to auto-fill the form if available
- // Preparing object
- $oApp['context_manipulator']->PrepareObject($aActionRules, $oObject);
- }
- else
- {
- $oObject = MetaModel::GetObject($sObjectClass, $sObjectId);
- }
- // Preparing transitions only if we are currently going through one
- $aFormData['buttons'] = array(
- 'transitions' => array()
- );
- if ($sMode !== 'apply_stimulus')
- {
- $oSetToCheckRights = DBObjectSet::FromObject($oObject);
- $aStimuli = Metamodel::EnumStimuli($sObjectClass);
- foreach ($oObject->EnumTransitions() as $sStimulusCode => $aTransitionDef)
- {
- $iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sObjectClass, $sStimulusCode, $oSetToCheckRights) : UR_ALLOWED_NO;
- // Careful, $iAction is an integer whereas UR_ALLOWED_YES is a boolean, therefore we can't use a '===' operator.
- if ($iActionAllowed == UR_ALLOWED_YES)
- {
- $aFormData['buttons']['transitions'][$sStimulusCode] = $aStimuli[$sStimulusCode]->GetLabel();
- }
- }
- }
- // Preparing callback urls
- $aCallbackUrls = $oApp['context_manipulator']->GetCallbackUrls($oApp, $aActionRules, $oObject, $bModal);
- $aFormData['submit_callback'] = $aCallbackUrls['submit'];
- $aFormData['cancel_callback'] = $aCallbackUrls['cancel'];
- // Preparing renderer
- // Note : We might need to distinguish form & renderer endpoints
- if (in_array($sMode, array('create', 'edit', 'view')))
- {
- $sFormEndpoint = $oApp['url_generator']->generate('p_object_' . $sMode, array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId));
- }
- else
- {
- $sFormEndpoint = $_SERVER['REQUEST_URI'];
- }
- $oFormRenderer = new BsFormRenderer();
- $oFormRenderer->SetEndpoint($sFormEndpoint);
- $oFormManager = new ObjectFormManager();
- $oFormManager->SetApplication($oApp)
- ->SetObject($oObject)
- ->SetMode($sMode)
- ->SetActionRulesToken($sActionRulesToken)
- ->SetRenderer($oFormRenderer)
- ->SetFormProperties($aFormProperties)
- ->Build();
-
- // Check the number of editable fields
- $aFormData['editable_fields_count'] = $oFormManager->GetForm()->GetEditableFieldCount();
- }
- else
- {
- // Update / Submit / Cancel
- $sFormManagerClass = $oRequestParams->get('formmanager_class');
- $sFormManagerData = $oRequestParams->get('formmanager_data');
- if ($sFormManagerClass === null || $sFormManagerData === null)
- {
- IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameters formmanager_class and formamanager_data must be defined.');
- $oApp->abort(500, 'Parameters formmanager_class and formmanager_data must be defined.');
- }
- $oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
- $oFormManager->SetApplication($oApp);
-
- // Applying action rules if present
- if (($oFormManager->GetActionRulesToken() !== null) && ($oFormManager->GetActionRulesToken() !== ''))
- {
- $aActionRules = ContextManipulatorHelper::DecodeRulesToken($oFormManager->GetActionRulesToken());
- $oObj = $oFormManager->GetObject();
- $oApp['context_manipulator']->PrepareObject($aActionRules, $oObj);
- $oFormManager->SetObject($oObj);
- }
-
- switch ($sOperation)
- {
- case 'submit':
- // Applying modification to object
- $aFormData['validation'] = $oFormManager->OnSubmit(array('currentValues' => $oRequestParams->get('current_values'), 'attachmentIds' => $oRequest->get('attachment_ids'), 'formProperties' => $aFormProperties, 'applyStimulus' => $oRequestParams->get('apply_stimulus')));
- if ($aFormData['validation']['valid'] === true)
- {
- // Note : We don't use $sObjectId there as it can be null if we are creating a new one. Instead we use the id from the created object once it has been seralized
- // Check if stimulus has to be applied
- $sStimulusCode = ($oRequestParams->get('stimulus_code') !== null && $oRequestParams->get('stimulus_code') !== '') ? $oRequestParams->get('stimulus_code') : null;
- if ($sStimulusCode !== null)
- {
- $aFormData['validation']['redirection'] = array(
- 'url' => $oApp['url_generator']->generate('p_object_apply_stimulus', array('sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey(), 'sStimulusCode' => $sStimulusCode)),
- 'ajax' => true
- );
- }
- // Otherwise, we show the object if there is no default
- else
- {
- // $aFormData['validation']['redirection'] = array(
- // 'alternative_url' => $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey()))
- // );
- }
- }
- break;
- case 'update':
- $oFormManager->OnUpdate(array('currentValues' => $oRequestParams->get('current_values'), 'formProperties' => $aFormProperties));
- break;
- case 'cancel':
- $oFormManager->OnCancel();
- break;
- }
- }
-
- // Preparing field_set data
- $aFieldSetData = array(
- //'fields_list' => $oFormManager->GetRenderer()->Render(), // GLA : This should be done just after in the if statement.
- 'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
- 'form_path' => $oFormManager->GetForm()->GetId()
- );
- // Preparing fields list regarding the operation
- if ($sOperation === 'update')
- {
- $aRequestedFields = $oRequestParams->get('requested_fields');
- $sFormPath = $oRequestParams->get('form_path');
- // Checking if the update was on a subform, if so we need to make the rendering for that part only
- if ($sFormPath !== null && $sFormPath !== $oFormManager->GetForm()->GetId())
- {
- $oSubForm = $oFormManager->GetForm()->FindSubForm($sFormPath);
- $oSubFormRenderer = new BsFormRenderer($oSubForm);
- $oSubFormRenderer->SetEndpoint($oFormManager->GetRenderer()->GetEndpoint());
- $aFormData['updated_fields'] = $oSubFormRenderer->Render($aRequestedFields);
- }
- else
- {
- $aFormData['updated_fields'] = $oFormManager->GetRenderer()->Render($aRequestedFields);
- }
- }
- else
- {
- $aFieldSetData['fields_list'] = $oFormManager->GetRenderer()->Render();
- }
- // Preparing form data
- $aFormData['id'] = $oFormManager->GetForm()->GetId();
- $aFormData['transaction_id'] = $oFormManager->GetForm()->GetTransactionId();
- $aFormData['formmanager_class'] = $oFormManager->GetClass();
- $aFormData['formmanager_data'] = $oFormManager->ToJSON();
- $aFormData['renderer'] = $oFormManager->GetRenderer();
- $aFormData['object_name'] = $oFormManager->GetObject()->GetName();
- $aFormData['fieldset'] = $aFieldSetData;
- return $aFormData;
- }
- /**
- * Handles the autocomplete search
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sTargetAttCode Attribute code of the host object pointing to the Object class to search
- * @param string $sHostObjectClass Class name of the host object
- * @param string $sHostObjectId Id of the host object
- * @return Response
- */
- public function SearchAutocompleteAction(Request $oRequest, Application $oApp, $sTargetAttCode, $sHostObjectClass, $sHostObjectId = null)
- {
- $aData = array(
- 'results' => array(
- 'count' => 0,
- 'items' => array()
- )
- );
- // Parsing parameters from request payload
- parse_str($oRequest->getContent(), $aRequestContent);
- // Checking parameters
- if (!isset($aRequestContent['sQuery']))
- {
- IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameter sQuery missing.');
- $oApp->abort(500, Dict::Format('UI:Error:ParameterMissing', 'sQuery'));
- }
- // Retrieving parameters
- $sQuery = $aRequestContent['sQuery'];
- // Checking security layers
- if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $sHostObjectClass, $sHostObjectId))
- {
- IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : Could not load object ' . $sHostObjectClass . '::' . $sHostObjectId . '.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // Retrieving host object for future DBSearch parameters
- if ($sHostObjectId !== null)
- {
- $oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId);
- }
- else
- {
- $oHostObject = MetaModel::NewObject($sHostObjectClass);
- // Retrieving action rules
- //
- // Note : The action rules must be a base64-encoded JSON object, this is just so users are tempted to changes values.
- // But it would not be a security issue as it only presets values in the form.
- $sActionRulesToken = $oRequest->get('ar_token');
- $aActionRules = ($sActionRulesToken !== null) ? ContextManipulatorHelper::DecodeRulesToken($sActionRulesToken) : array();
- // Preparing object
- $oApp['context_manipulator']->PrepareObject($aActionRules, $oHostObject);
- }
- // Updating host object with form data / values
- $sFormManagerClass = $aRequestContent['formmanager_class'];
- $sFormManagerData = $aRequestContent['formmanager_data'];
- if ($sFormManagerClass !== null && $sFormManagerData !== null)
- {
- $oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
- $oFormManager->SetApplication($oApp);
- $oFormManager->SetObject($oHostObject);
- // Applying action rules if present
- if (($oFormManager->GetActionRulesToken() !== null) && ($oFormManager->GetActionRulesToken() !== ''))
- {
- $aActionRules = ContextManipulatorHelper::DecodeRulesToken($oFormManager->GetActionRulesToken());
- $oObj = $oFormManager->GetObject();
- $oApp['context_manipulator']->PrepareObject($aActionRules, $oObj);
- $oFormManager->SetObject($oObj);
- }
-
- // Updating host object
- $oFormManager->OnUpdate(array('currentValues' => $aRequestContent['current_values']));
- $oHostObject = $oFormManager->GetObject();
- }
- // Building search query
- // - Retrieving target object class from attcode
- $oTargetAttDef = MetaModel::GetAttributeDef($sHostObjectClass, $sTargetAttCode);
- $sTargetObjectClass = $oTargetAttDef->GetTargetClass();
- // - Base query from meta model
- $oSearch = DBSearch::FromOQL($oTargetAttDef->GetValuesDef()->GetFilterExpression());
- // - Adding query condition
- $oSearch->AddConditionExpression(new BinaryExpression(new FieldExpression('friendlyname', $oSearch->GetClassAlias()), 'LIKE', new VariableExpression('ac_query')));
- // - Intersecting with scope constraints
- $oSearch = $oSearch->Intersect($oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sTargetObjectClass, UR_ACTION_READ));
-
- // Retrieving results
- // - Preparing object set
- $oSet = new DBObjectSet($oSearch, array(), array('this' => $oHostObject, 'ac_query' => '%' . $sQuery . '%'));
- $oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array('friendlyname')));
- // Note : This limit is also used in the field renderer by typeahead to determine how many suggestions to display
- $oSet->SetLimit($oTargetAttDef->GetMaximumComboLength()); // TODO : Is this the right limit value ? We might want to use another parameter
- // - Retrieving objects
- while ($oItem = $oSet->Fetch())
- {
- $aData['results']['items'][] = array('id' => $oItem->GetKey(), 'name' => html_entity_decode($oItem->GetName(), ENT_QUOTES, 'UTF-8'));
- $aData['results']['count'] ++;
- }
- // Preparing response
- if ($oRequest->isXmlHttpRequest())
- {
- $oResponse = $oApp->json($aData);
- }
- else
- {
- $oResponse = $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- return $oResponse;
- }
- /**
- * Handles the regular (table) search from an attribute
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sTargetAttCode Attribute code of the host object pointing to the Object class to search
- * @param string $sHostObjectClass Class name of the host object
- * @param string $sHostObjectId Id of the host object
- * @return Response
- */
- public function SearchFromAttributeAction(Request $oRequest, Application $oApp, $sTargetAttCode, $sHostObjectClass, $sHostObjectId = null)
- {
- $aData = array(
- 'sMode' => 'search_regular',
- 'sTargetAttCode' => $sTargetAttCode,
- 'sHostObjectClass' => $sHostObjectClass,
- 'sHostObjectId' => $sHostObjectId,
- 'sActionRulesToken' => $oRequest->get('ar_token')
- );
- // Checking security layers
- if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $sHostObjectClass, $sHostObjectId))
- {
- IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' not allowed to read ' . $sHostObjectClass . '::' . $sHostObjectId . ' object.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // Retrieving host object for future DBSearch parameters
- if ($sHostObjectId !== null)
- {
- $oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId);
- }
- else
- {
- $oHostObject = MetaModel::NewObject($sHostObjectClass);
- // Retrieving action rules
- //
- // Note : The action rules must be a base64-encoded JSON object, this is just so users are tempted to changes values.
- // But it would not be a security issue as it only presets values in the form.
- $aActionRules = ($aData['sActionRulesToken'] !== null) ? ContextManipulatorHelper::DecodeRulesToken($aData['sActionRulesToken']) : array();
- // Preparing object
- $oApp['context_manipulator']->PrepareObject($aActionRules, $oHostObject);
- }
- // Updating host object with form data / values
- $oRequestParams = $oRequest->request;
- $sFormManagerClass = $oRequestParams->get('formmanager_class');
- $sFormManagerData = $oRequestParams->get('formmanager_data');
- if ($sFormManagerClass !== null && $sFormManagerData !== null)
- {
- $oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
- $oFormManager->SetApplication($oApp);
- $oFormManager->SetObject($oHostObject);
- // Applying action rules if present
- if (($oFormManager->GetActionRulesToken() !== null) && ($oFormManager->GetActionRulesToken() !== ''))
- {
- $aActionRules = ContextManipulatorHelper::DecodeRulesToken($oFormManager->GetActionRulesToken());
- $oObj = $oFormManager->GetObject();
- $oApp['context_manipulator']->PrepareObject($aActionRules, $oObj);
- $oFormManager->SetObject($oObj);
- }
-
- // Updating host object
- $oFormManager->OnUpdate(array('currentValues' => $oRequestParams->get('current_values')));
- $oHostObject = $oFormManager->GetObject();
- }
-
- // Retrieving request parameters
- $iPageNumber = ($oRequest->get('iPageNumber') !== null) ? $oRequest->get('iPageNumber') : 1;
- $iCountPerPage = ($oRequest->get('iCountPerPage') !== null) ? $oRequest->get('iCountPerPage') : static::DEFAULT_COUNT_PER_PAGE_LIST;
- $bInitalPass = ($oRequest->get('draw') === null) ? true : false;
- $sQuery = $oRequest->get('sSearchValue');
- $sFormPath = $oRequest->get('sFormPath');
- $sFieldId = $oRequest->get('sFieldId');
- $aObjectIdsToIgnore = $oRequest->get('aObjectIdsToIgnore');
- // Building search query
- // - Retrieving target object class from attcode
- $oTargetAttDef = MetaModel::GetAttributeDef($sHostObjectClass, $sTargetAttCode);
- if ($oTargetAttDef->IsExternalKey())
- {
- $sTargetObjectClass = $oTargetAttDef->GetTargetClass();
- }
- elseif ($oTargetAttDef->IsLinkSet())
- {
- if (!$oTargetAttDef->IsIndirect())
- {
- $sTargetObjectClass = $oTargetAttDef->GetLinkedClass();
- }
- else
- {
- $oRemoteAttDef = MetaModel::GetAttributeDef($oTargetAttDef->GetLinkedClass(), $oTargetAttDef->GetExtKeyToRemote());
- $sTargetObjectClass = $oRemoteAttDef->GetTargetClass();
- }
- }
- else
- {
- throw new Exception('Search from attribute can only apply on AttributeExternalKey or AttributeLinkedSet objects, ' . get_class($oTargetAttDef) . ' given.');
- }
-
- // - Retrieving class attribute list
- $aAttCodes = MetaModel::FlattenZList(MetaModel::GetZListItems($sTargetObjectClass, 'list'));
- // - Adding friendlyname attribute to the list is not already in it
- $sTitleAttCode = MetaModel::GetFriendlyNameAttributeCode($sTargetObjectClass);
- if (!in_array($sTitleAttCode, $aAttCodes))
- {
- $aAttCodes = array_merge(array($sTitleAttCode), $aAttCodes);
- }
- // - Retrieving scope search
- $oScopeSearch = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sTargetObjectClass, UR_ACTION_READ);
- $aInternalParams = array();
- if ($oScopeSearch === null)
- {
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' has no scope query for ' . $sTargetObjectClass . ' class.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // - Base query from meta model
- if ($oTargetAttDef->IsExternalKey())
- {
- $oSearch = DBSearch::FromOQL($oTargetAttDef->GetValuesDef()->GetFilterExpression());
- }
- elseif ($oTargetAttDef->IsLinkSet())
- {
- $oSearch = $oScopeSearch;
- }
- // - Filtering objects to ignore
- if (($aObjectIdsToIgnore !== null) && (is_array($aObjectIdsToIgnore)))
- {
- //$oSearch->AddConditionExpression('id', $aObjectIdsToIgnore, 'NOT IN');
- $aExpressions = array();
- foreach ($aObjectIdsToIgnore as $sObjectIdToIgnore)
- {
- $aExpressions[] = new ScalarExpression($sObjectIdToIgnore);
- }
- $oSearch->AddConditionExpression(new BinaryExpression(new FieldExpression('id', $oSearch->GetClassAlias()), 'NOT IN', new ListExpression($aExpressions)));
- }
- // - Adding query condition
- $aInternalParams['this'] = $oHostObject;
- if ($sQuery !== null)
- {
- $oFullExpr = null;
- for ($i = 0; $i < count($aAttCodes); $i++)
- {
- // Checking if the current attcode is an external key in order to search on the friendlyname
- $oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $aAttCodes[$i]);
- $sAttCode = (!$oAttDef->IsExternalKey()) ? $aAttCodes[$i] : $aAttCodes[$i] . '_friendlyname';
- // Building expression for the current attcode
- $oBinExpr = new BinaryExpression(new FieldExpression($sAttCode, $oSearch->GetClassAlias()), 'LIKE', new VariableExpression('re_query'));
- // Adding expression to the full expression (all attcodes)
- if ($i === 0)
- {
- $oFullExpr = $oBinExpr;
- }
- else
- {
- $oFullExpr = new BinaryExpression($oFullExpr, 'OR', $oBinExpr);
- }
- }
- // Adding full expression to the search object
- $oSearch->AddConditionExpression($oFullExpr);
- $aInternalParams['re_query'] = '%' . $sQuery . '%';
- }
- // - Intersecting with scope constraints
- $oSearch = $oSearch->Intersect($oScopeSearch);
- // Retrieving results
- // - Preparing object set
- $oSet = new DBObjectSet($oSearch, array(), $aInternalParams);
- $oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => $aAttCodes));
- $oSet->SetLimit($iCountPerPage, $iCountPerPage * ($iPageNumber - 1));
- // - Retrieving columns properties
- $aColumnProperties = array();
- foreach ($aAttCodes as $sAttCode)
- {
- $oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $sAttCode);
- $aColumnProperties[$sAttCode] = array(
- 'title' => $oAttDef->GetLabel()
- );
- }
- // - Retrieving objects
- $aItems = array();
- while ($oItem = $oSet->Fetch())
- {
- $aItemProperties = array(
- 'id' => $oItem->GetKey(),
- 'name' => $oItem->GetName(),
- 'attributes' => array()
- );
- foreach ($aAttCodes as $sAttCode)
- {
- if ($sAttCode !== 'id')
- {
- $aAttProperties = array(
- 'att_code' => $sAttCode
- );
- $oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $sAttCode);
- if ($oAttDef->IsExternalKey())
- {
- $aAttProperties['value'] = $oItem->Get($sAttCode . '_friendlyname');
- // Checking if we can view the object
- if ((SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $oAttDef->GetTargetClass(), $oItem->Get($sAttCode))))
- {
- $aAttProperties['url'] = $oApp['url_generator']->generate('p_object_view', array('sObjectClass' => $oAttDef->GetTargetClass(), 'sObjectId' => $oItem->GetKey()));
- }
- }
- else
- {
- $aAttProperties['value'] = $oAttDef->GetValueLabel($oItem->Get($sAttCode));
- }
- $aItemProperties['attributes'][$sAttCode] = $aAttProperties;
- }
- }
- $aItems[] = $aItemProperties;
- }
-
- // Preparing response
- if ($bInitalPass)
- {
- $aData = $aData + array(
- 'form' => array(
- 'id' => 'object_search_form_' . time(),
- 'title' => Dict::Format('Brick:Portal:Object:Search:Regular:Title', $oTargetAttDef->GetLabel(), MetaModel::GetName($sTargetObjectClass))
- ),
- 'aColumnProperties' => json_encode($aColumnProperties),
- 'aResults' => array(
- 'aItems' => json_encode($aItems),
- 'iCount' => count($aItems)
- ),
- 'bMultipleSelect' => $oTargetAttDef->IsLinkSet(),
- 'aSource' => array(
- 'sFormPath' => $sFormPath,
- 'sFieldId' => $sFieldId,
- 'aObjectIdsToIgnore' => $aObjectIdsToIgnore,
- 'sFormManagerClass' => $sFormManagerClass,
- 'sFormManagerData' => $sFormManagerData
- )
- );
- if ($oRequest->isXmlHttpRequest())
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
- }
- else
- {
- //$oResponse = $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/layout.html.twig', $aData);
- }
- }
- else
- {
- $aData = $aData + array(
- 'levelsProperties' => $aColumnProperties,
- 'data' => $aItems,
- 'recordsTotal' => $oSet->Count(),
- 'recordsFiltered' => $oSet->Count()
- );
- $oResponse = $oApp->json($aData);
- }
- return $oResponse;
- }
- /**
- * Handles the hierarchical search from an attribute
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @param string $sTargetAttCode Attribute code of the host object pointing to the Object class to search
- * @param string $sHostObjectClass Class name of the host object
- * @param string $sHostObjectId Id of the host object
- * @return Response
- */
- public function SearchHierarchyAction(Request $oRequest, Application $oApp, $sTargetAttCode, $sHostObjectClass, $sHostObjectId = null)
- {
- $aData = array(
- 'sMode' => 'search_hierarchy',
- 'sTargetAttCode' => $sTargetAttCode,
- 'sHostObjectClass' => $sHostObjectClass,
- 'sHostObjectId' => $sHostObjectId
- );
- // Checking security layers
- if (!SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $sHostObjectClass, $sHostObjectId))
- {
- IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' not allowed to read ' . $sHostObjectClass . '::' . $sHostObjectId . ' object.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // Retrieving host object for future DBSearch parameters
- if ($sHostObjectId !== null)
- {
- $oHostObject = MetaModel::GetObject($sHostObjectClass, $sHostObjectId);
- }
- else
- {
- $oHostObject = MetaModel::NewObject($sHostObjectClass);
- }
- // Retrieving request parameters
- $bInitalPass = ($oRequest->get('draw') === null) ? true : false;
- $sQuery = $oRequest->get('sSearchValue'); // Note : Not used yet
- $sFormPath = $oRequest->get('sFormPath');
- $sFieldId = $oRequest->get('sFieldId');
- // Building search query
- // - Retrieving target object class from attcode
- $oTargetAttDef = MetaModel::GetAttributeDef($sHostObjectClass, $sTargetAttCode);
- if ($oTargetAttDef->IsExternalKey())
- {
- $sTargetObjectClass = $oTargetAttDef->GetTargetClass();
- }
- elseif ($oTargetAttDef->IsLinkSet())
- {
- if (!$oTargetAttDef->IsIndirect())
- {
- $sTargetObjectClass = $oTargetAttDef->GetLinkedClass();
- }
- else
- {
- $oRemoteAttDef = MetaModel::GetAttributeDef($oTargetAttDef->GetLinkedClass(), $oTargetAttDef->GetExtKeyToRemote());
- $sTargetObjectClass = $oRemoteAttDef->GetTargetClass();
- }
- }
- else
- {
- throw new Exception('Search by hierarchy can only apply on AttributeExternalKey or AttributeLinkedSet objects, ' . get_class($oTargetAttDef) . ' given.');
- }
- // // - Retrieving class attribute list
- // $aAttCodes = MetaModel::FlattenZList(MetaModel::GetZListItems($sTargetObjectClass, 'list'));
- // // - Adding friendlyname attribute to the list is not already in it
- // $sTitleAttrCode = MetaModel::GetFriendlyNameAttributeCode($sTargetObjectClass);
- // if (!in_array($sTitleAttrCode, $aAttCodes))
- // {
- // $aAttCodes = array_merge(array($sTitleAttrCode), $aAttCodes);
- // }
- // - Retrieving scope search
- $oScopeSearch = $oApp['scope_validator']->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sTargetObjectClass, UR_ACTION_READ);
- if ($oScopeSearch === null)
- {
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' has no scope query for ' . $sTargetObjectClass . ' class.');
- $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- }
- // - Base query from meta model
- if ($oTargetAttDef->IsExternalKey())
- {
- $oSearch = DBSearch::FromOQL($oTargetAttDef->GetValuesDef()->GetFilterExpression());
- }
- // elseif ($oTargetAttDef->IsLinkSet())
- else
- {
- $oSearch = $oScopeSearch;
- }
- // // - Adding query condition
- $aInternalParams = array('this' => $oHostObject);
- // if ($sQuery !== null)
- // {
- // for ($i = 0; $i < count($aAttCodes); $i++)
- // {
- // // Checking if the current attcode is an external key in order to search on the friendlyname
- // $oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $aAttCodes[$i]);
- // $sAttCode = (!$oAttDef->IsExternalKey()) ? $aAttCodes[$i] : $aAttCodes[$i] . '_friendlyname';
- // // Building expression for the current attcode
- // $oBinExpr = new BinaryExpression(new FieldExpression($sAttCode, $oSearch->GetClassAlias()), 'LIKE', new VariableExpression('re_query'));
- // // Adding expression to the full expression (all attcodes)
- // if ($i === 0)
- // {
- // $oFullExpr = $oBinExpr;
- // }
- // else
- // {
- // $oFullExpr = new BinaryExpression($oFullExpr, 'OR', $oBinExpr);
- // }
- // }
- // // Adding full expression to the search object
- // $oSearch->AddConditionExpression($oFullExpr);
- // $aInternalParams['re_query'] = '%' . $sQuery . '%';
- // }
- // - Intersecting with scope constraints
- $oSearch = $oSearch->Intersect($oScopeSearch);
- // Retrieving results
- // - Preparing object set
- $oSet = new DBObjectSet($oSearch, array(), $aInternalParams);
- $oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array('friendlyname')));
- // $oSet->SetLimit($iCountPerPage, $iCountPerPage * ($iPageNumber - 1));
- // // - Retrieving columns properties
- // $aColumnProperties = array();
- // foreach ($aAttCodes as $sAttCode)
- // {
- // $oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $sAttCode);
- // $aColumnProperties[$sAttCode] = array(
- // 'title' => $oAttDef->GetLabel()
- // );
- // }
- // - Retrieving objects
- $aItems = array();
- while ($oItem = $oSet->Fetch())
- {
- $aItemProperties = array(
- 'id' => $oItem->GetKey(),
- 'name' => $oItem->GetName(),
- 'attributes' => array()
- );
- // foreach ($aAttCodes as $sAttCode)
- // {
- // if ($sAttCode !== 'id')
- // {
- // $aAttProperties = array(
- // 'att_code' => $sAttCode
- // );
- //
- // $oAttDef = MetaModel::GetAttributeDef($sTargetObjectClass, $sAttCode);
- // if ($oAttDef->IsExternalKey())
- // {
- // $aAttProperties['value'] = $oItem->Get($sAttCode . '_friendlyname');
- // // Checking if we can view the object
- // if ((SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $oAttDef->GetTargetClass(), $oItem->Get($sAttCode))))
- // {
- // $aAttProperties['url'] = $oApp['url_generator']->generate('p_object_view', array('sObjectClass' => $oAttDef->GetTargetClass(), 'sObjectId' => $oItem->GetKey()));
- // }
- // }
- // else
- // {
- // $aAttProperties['value'] = $oAttDef->GetValueLabel($oItem->Get($sAttCode));
- // }
- //
- // $aItemProperties['attributes'][$sAttCode] = $aAttProperties;
- // }
- // }
- $aItems[] = $aItemProperties;
- }
- // Preparing response
- if ($bInitalPass)
- {
- $aData = $aData + array(
- 'form' => array(
- 'id' => 'object_search_form_' . time(),
- 'title' => Dict::Format('Brick:Portal:Object:Search:Hierarchy:Title', $oTargetAttDef->GetLabel(), MetaModel::GetName($sTargetObjectClass))
- ),
- 'aResults' => array(
- 'aItems' => json_encode($aItems),
- 'iCount' => count($aItems)
- ),
- 'aSource' => array(
- 'sFormPath' => $sFormPath,
- 'sFieldId' => $sFieldId
- )
- );
- if ($oRequest->isXmlHttpRequest())
- {
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/modal.html.twig', $aData);
- }
- else
- {
- //$oResponse = $oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
- $oResponse = $oApp['twig']->render('itop-portal-base/portal/src/views/bricks/object/layout.html.twig', $aData);
- }
- }
- else
- {
- $aData = $aData + array(
- 'levelsProperties' => $aColumnProperties,
- 'data' => $aItems
- );
- $oResponse = $oApp->json($aData);
- }
- return $oResponse;
- }
- /**
- * Handles attachment add/remove on an object
- *
- * Note : This is inspired from itop-attachment/ajax.attachment.php
- *
- * @param Request $oRequest
- * @param Application $oApp
- */
- public function AttachmentAction(Request $oRequest, Application $oApp, $sOperation = null)
- {
- $aData = array(
- 'att_id' => 0,
- 'preview' => false,
- 'msg' => ''
- );
- // Retrieving sOperation from request only if it wasn't forced (determined by the route)
- if ($sOperation === null)
- {
- $sOperation = $oRequest->get('operation');
- }
- switch ($sOperation)
- {
- case 'add':
- $sFieldName = $oRequest->get('field_name');
- $sObjectClass = $oRequest->get('object_class');
- $sTempId = $oRequest->get('temp_id');
- if (($sObjectClass === null) || ($sTempId === null))
- {
- $aData['error'] = Dict::Format('UI:Error:2ParametersMissing', 'object_class', 'temp_id');
- }
- else
- {
- try
- {
- $oDocument = utils::ReadPostedDocument($sFieldName);
- $oAttachment = MetaModel::NewObject('Attachment');
- $oAttachment->Set('expire', time() + 3600); // one hour...
- $oAttachment->Set('temp_id', $sTempId);
- $oAttachment->Set('item_class', $sObjectClass);
- $oAttachment->SetDefaultOrgId();
- $oAttachment->Set('contents', $oDocument);
- $iAttId = $oAttachment->DBInsert();
- $aData['msg'] = htmlentities($oDocument->GetFileName(), ENT_QUOTES, 'UTF-8');
- // TODO : Change icon location when itop-attachment is refactored
- //$aData['icon'] = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($oDoc->GetFileName());
- $aData['icon'] = utils::GetAbsoluteUrlAppRoot() . 'env-' . utils::GetCurrentEnvironment() . '/itop-attachments/icons/image.png';
- $aData['att_id'] = $iAttId;
- $aData['preview'] = $oDocument->IsPreviewAvailable() ? 'true' : 'false';
- }
- catch (FileUploadException $e)
- {
- $aData['error'] = $e->GetMessage();
- }
- }
- $oResponse = $oApp->json($aData);
- break;
- case 'download':
- $sAttachmentId = $oRequest->get('sAttachmentId');
- $sAttachmentUrl = utils::GetAbsoluteUrlAppRoot() . ATTACHMENT_DOWNLOAD_URL . $sAttachmentId;
- $oResponse = new RedirectResponse($sAttachmentUrl);
- break;
- default:
- $oApp->abort(403);
- break;
- }
- return $oResponse;
- }
- /**
- * Returns a json response containing an array of objects informations.
- *
- * The service must be given 3 parameters :
- * - sObjectClass : The class of objects to retrieve information from
- * - aObjectIds : An array of object ids
- * - aObjectAttCodes : An array of attribute codes to retrieve
- *
- * @param Request $oRequest
- * @param Application $oApp
- * @return Response
- */
- public function GetInformationsAsJsonAction(Request $oRequest, Application $oApp)
- {
- $aData = array();
- // Retrieving parameters
- $sObjectClass = $oRequest->Get('sObjectClass');
- $aObjectIds = $oRequest->Get('aObjectIds');
- $aObjectAttCodes = $oRequest->Get('aObjectAttCodes');
- if ($sObjectClass === null || $aObjectIds === null || $aObjectAttCodes === null)
- {
- IssueLog::Info(__METHOD__ . ' at line ' . __LINE__ . ' : sObjectClass, sObjectId and aObjectAttCodes expected, "' . $sObjectClass . '", "' . $sObjectId . '" given.');
- $oApp->abort(500, 'Invalid request data, some informations are missing');
- }
- // Checking that id is in the AttCodes
- if (!in_array('id', $aObjectAttCodes))
- {
- $aObjectAttCodes = array_merge(array('id'), $aObjectAttCodes);
- }
- // Retrieving attributes definitions
- $aAttDefs = array();
- foreach ($aObjectAttCodes as $sObjectAttCode)
- {
- if ($sObjectAttCode === 'id')
- continue;
- $aAttDefs[$sObjectAttCode] = MetaModel::GetAttributeDef($sObjectClass, $sObjectAttCode);
- }
-
- // Building the search
- $oSearch = DBObjectSearch::FromOQL("SELECT " . $sObjectClass . " WHERE id IN ('" . implode("','", $aObjectIds) . "')");
- $oSet = new DBObjectSet($oSearch);
- $oSet->OptimizeColumnLoad($aObjectAttCodes);
- // Retrieving objects
- while ($oObject = $oSet->Fetch())
- {
- $aObjectData = array(
- 'id' => $oObject->GetKey(),
- 'attributes' => array()
- );
- foreach ($aAttDefs as $oAttDef)
- {
- $aAttData = array(
- 'att_code' => $oAttDef->GetCode()
- );
- if ($oAttDef->IsExternalKey())
- {
- $aAttData['value'] = $oObject->Get($oAttDef->GetCode() . '_friendlyname');
- if (SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $oAttDef->GetTargetClass()))
- {
- $aAttData['url'] = $oApp['url_generator']->generate('p_object_view', array('sObjectClass' => $oAttDef->GetTargetClass(), 'sObjectId' => $oObject->Get($oAttDef->GetCode())));
- }
- }
- elseif ($oAttDef->IsLinkSet())
- {
- // We skip it
- continue;
- }
- else
- {
- $aAttData['value'] = $oAttDef->GetValueLabel($oObject->Get($oAttDef->GetCode()));
- }
- $aObjectData['attributes'][$oAttDef->GetCode()] = $aAttData;
- }
- $aData['items'][] = $aObjectData;
- }
- return $oApp->json($aData);
- }
- }
- ?>
|