mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°642 Portal: Flags on transition
SVN:trunk[4774]
This commit is contained in:
@@ -332,11 +332,10 @@ class ObjectController extends AbstractController
|
||||
}
|
||||
|
||||
// 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'));
|
||||
// }
|
||||
if(!SecurityHelper::IsStimulusAllowed($oApp, $sStimulusCode, $sObjectClass))
|
||||
{
|
||||
$oApp->abort(404, Dict::S('UI:ObjectDoesNotExist'));
|
||||
}
|
||||
|
||||
// Retrieving object
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, false /* MustBeFound */, $oApp['scope_validator']->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
|
||||
@@ -349,34 +348,54 @@ class ObjectController extends AbstractController
|
||||
|
||||
// Retrieving request parameters
|
||||
$sOperation = $oRequest->request->get('operation');
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieving form properties
|
||||
$aStimuliForms = ApplicationHelper::GetLoadedFormFromClass($oApp, $sObjectClass, 'apply_stimulus');
|
||||
if(array_key_exists($sStimulusCode, $aStimuliForms))
|
||||
{
|
||||
$aFormProperties = $aStimuliForms[$sStimulusCode];
|
||||
}
|
||||
// Or preparing a default form for the stimulus application
|
||||
else
|
||||
{
|
||||
$aFormProperties = array(
|
||||
'id' => 'apply-stimulus',
|
||||
'type' => 'static',
|
||||
'fields' => array(),
|
||||
'layout' => null
|
||||
);
|
||||
}
|
||||
|
||||
// Adding stimulus code to form
|
||||
$aFormProperties['stimulus_code'] = $sStimulusCode;
|
||||
|
||||
// Checking which fields need to be prompt
|
||||
// $aTransitions = MetaModel::EnumTransitions($sObjectClass, $oObject->GetState());
|
||||
// $aTargetStates = MetaModel::EnumStates($sObjectClass);
|
||||
// $aTargetState = $aTargetStates[$aTransitions[$sStimulusCode]['target_state']];
|
||||
// $aExpectedAttributes = $oObject->GetTransitionAttributes($sStimulusCode /*, current state*/);
|
||||
// IssueLog::Info($oObject->GetState());
|
||||
// IssueLog::Info(print_r($aExpectedAttributes, true));
|
||||
// foreach ($aExpectedAttributes as $sAttCode => $iFlags)
|
||||
// {
|
||||
// if (($iFlags & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
|
||||
// (($iFlags & OPT_ATT_MANDATORY) && ($oObject->Get($sAttCode) == '')))
|
||||
// {
|
||||
// if(!isset($aFormProperties['fields'][$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;
|
||||
// }
|
||||
// }
|
||||
// IssueLog::Info(print_r($aFormProperties['fields'], true));
|
||||
// Adding target_state to current_values
|
||||
$oRequest->request->set('apply_stimulus', array('code' => $sStimulusCode));
|
||||
|
||||
@@ -487,12 +506,6 @@ class ObjectController extends AbstractController
|
||||
$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();
|
||||
// }
|
||||
if(SecurityHelper::IsStimulusAllowed($oApp, $sStimulusCode, $sObjectClass, $oSetToCheckRights))
|
||||
{
|
||||
$aFormData['buttons']['transitions'][$sStimulusCode] = $aStimuli[$sStimulusCode]->GetLabel();
|
||||
@@ -555,12 +568,6 @@ class ObjectController extends AbstractController
|
||||
->SetRenderer($oFormRenderer)
|
||||
->SetFormProperties($aFormProperties);
|
||||
|
||||
if ($sMode === 'apply_stimulus')
|
||||
{
|
||||
$aEditFormProperties = ApplicationHelper::GetLoadedFormFromClass($oApp, $sObjectClass, ObjectFormManager::ENUM_MODE_APPLY_STIMULUS);
|
||||
$oFormManager->MergeFormProperties($aEditFormProperties);
|
||||
}
|
||||
|
||||
$oFormManager->Build();
|
||||
|
||||
// Check the number of editable fields
|
||||
|
||||
@@ -260,6 +260,16 @@ class ObjectFormManager extends FormManager
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the form manager is handling a transition form instead of a state form.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsTransitionForm()
|
||||
{
|
||||
return ($this->sMode === static::ENUM_MODE_APPLY_STIMULUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON string from the current object including :
|
||||
* - formobject_class
|
||||
@@ -314,16 +324,16 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$iFieldFlags = $iFieldFlags | OPT_ATT_SLAVE;
|
||||
}
|
||||
// Checking if field should be must prompt
|
||||
// Checking if field should be must_change
|
||||
if (isset($aOptions['must_change']) && ($aOptions['must_change'] === true))
|
||||
{
|
||||
$iFieldFlags = $iFieldFlags | OPT_ATT_MUSTCHANGE;
|
||||
}
|
||||
// Checking if field should be must prompt
|
||||
if (isset($aOptions['must_prompt']) && ($aOptions['must_prompt'] === true))
|
||||
{
|
||||
$iFieldFlags = $iFieldFlags | OPT_ATT_MUSTPROMPT;
|
||||
}
|
||||
// Checking if field should be must_change
|
||||
if (isset($aOptions['must_change']) && ($aOptions['must_change'] === true))
|
||||
{
|
||||
$iFieldFlags = $iFieldFlags | OPT_ATT_MUSTCHANGE;
|
||||
}
|
||||
// Checking if field should be hidden
|
||||
if (isset($aOptions['hidden']) && ($aOptions['hidden'] === true))
|
||||
{
|
||||
@@ -438,10 +448,24 @@ class ObjectFormManager extends FormManager
|
||||
// Also, retrieving mandatory attributes from metamodel to be able to complete the form with them if necessary
|
||||
if ($this->aFormProperties['type'] !== 'static')
|
||||
{
|
||||
foreach (MetaModel::ListAttributeDefs($sObjectClass) as $sAttCode => $oAttDef)
|
||||
if($this->IsTransitionForm())
|
||||
{
|
||||
$aDatamodelAttCodes = $this->oObject->GetTransitionAttributes($this->aFormProperties['stimulus_code']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aDatamodelAttCodes = MetaModel::ListAttributeDefs($sObjectClass);
|
||||
}
|
||||
|
||||
foreach ($aDatamodelAttCodes as $sAttCode => $value)
|
||||
{
|
||||
// Retrieving object flags
|
||||
if ($this->oObject->IsNew())
|
||||
if ($this->IsTransitionForm())
|
||||
{
|
||||
// Retrieving only mandatory flag from DM when on a transition
|
||||
$iFieldFlags = $value & OPT_ATT_MANDATORY;
|
||||
}
|
||||
elseif ($this->oObject->IsNew())
|
||||
{
|
||||
$iFieldFlags = $this->oObject->GetInitialStateAttributeFlags($sAttCode);
|
||||
}
|
||||
@@ -454,7 +478,9 @@ class ObjectFormManager extends FormManager
|
||||
// - only if the field if it's in fields list
|
||||
if (array_key_exists($sAttCode, $aFieldsAtts))
|
||||
{
|
||||
$aFieldsAtts[$sAttCode] = $aFieldsAtts[$sAttCode] | $iFieldFlags;
|
||||
if($this->IsTransitionForm()) {
|
||||
$aFieldsAtts[$sAttCode] = $aFieldsAtts[$sAttCode] | $iFieldFlags;
|
||||
}
|
||||
}
|
||||
// - or it is mandatory and has no value
|
||||
if ((($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY) && ($this->oObject->Get($sAttCode) === ''))
|
||||
@@ -493,12 +519,19 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
// - Else if it's mandatory and has no value, we force it as mandatory
|
||||
elseif ((($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY) && $oAttDef->IsNull($this->oObject->Get($sAttCode)))
|
||||
{
|
||||
$oField->SetMandatory(true);
|
||||
}
|
||||
// - Else if it wasn't mandatory or already had a value, and it's hidden, we force it as hidden
|
||||
// - Else if it's must change (transition), we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE && $this->IsTransitionForm())
|
||||
{
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
// - Else if it's must prompt (transition), we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT && $this->IsTransitionForm())
|
||||
{
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
// - Else if it wasn't mandatory or already had a value, and it's hidden, we force it as hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN)
|
||||
{
|
||||
$oField->SetHidden(true);
|
||||
@@ -507,23 +540,17 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
// - Else if it's must change, we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE)
|
||||
{
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
// - Else if it's must prompt, we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT)
|
||||
{
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal field
|
||||
}
|
||||
|
||||
// Finally, if it's mandatory and has no value, we force it as mandatory
|
||||
if ((($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY) && $oAttDef->IsNull($this->oObject->Get($sAttCode)))
|
||||
{
|
||||
$oField->SetMandatory(true);
|
||||
}
|
||||
|
||||
// Specific operation on field
|
||||
// - Field that require a transaction id
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\TextAreaField', 'Combodo\\iTop\\Form\\Field\\CaseLogField')))
|
||||
@@ -719,7 +746,11 @@ class ObjectFormManager extends FormManager
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
|
||||
$oForm->AddField($oField);
|
||||
// Adding attachements field in transition only if it is editable
|
||||
if(!$this->IsTransitionForm() || ($this->IsTransitionForm() && !$oField->GetReadOnly()) )
|
||||
{
|
||||
$oForm->AddField($oField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -728,87 +759,6 @@ class ObjectFormManager extends FormManager
|
||||
$this->oRenderer->SetForm($this->oForm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merging $this->aFormProperties with $aFormPropertiesToMerge. Merge only layout for now
|
||||
*
|
||||
* @param array $aFormPropertiesToMerge
|
||||
* @throws Exception
|
||||
*/
|
||||
public function MergeFormProperties($aFormPropertiesToMerge)
|
||||
{
|
||||
if ($aFormPropertiesToMerge['layout'] !== null)
|
||||
{
|
||||
// Checking if we need to render the template from twig to html in order to parse the fields
|
||||
if ($aFormPropertiesToMerge['layout']['type'] === 'twig')
|
||||
{
|
||||
// Creating sandbox twig env. to load and test the custom form template
|
||||
$oTwig = new \Twig_Environment(new \Twig_Loader_String());
|
||||
$sRendered = $oTwig->render($aFormPropertiesToMerge['layout']['content'], array('oRenderer' => $this->oRenderer, 'oObject' => $this->oObject));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRendered = $aFormPropertiesToMerge['layout']['content'];
|
||||
}
|
||||
|
||||
// Parsing rendered template to find the fields
|
||||
$oHtmlDocument = new \DOMDocument();
|
||||
$oHtmlDocument->loadHTML('<root>' . $sRendered . '</root>');
|
||||
|
||||
// Adding fields to the list
|
||||
$oXPath = new \DOMXPath($oHtmlDocument);
|
||||
foreach ($oXPath->query('//div[@class="form_field"][@data-field-id]') as $oFieldNode)
|
||||
{
|
||||
$sFieldId = $oFieldNode->getAttribute('data-field-id');
|
||||
$sFieldFlags = $oFieldNode->getAttribute('data-field-flags');
|
||||
// $iFieldFlags = OPT_ATT_NORMAL;
|
||||
|
||||
// // Checking if field has form_path, if not, we add it
|
||||
// if (!$oFieldNode->hasAttribute('data-form-path'))
|
||||
// {
|
||||
// $oFieldNode->setAttribute('data-form-path', $oForm->GetId());
|
||||
// }
|
||||
// Merging only fields that are already in the form
|
||||
if (array_key_exists($sFieldId, $this->aFormProperties['fields']))
|
||||
{
|
||||
// Settings field flags from the data-field-flags attribute
|
||||
foreach (explode(' ', $sFieldFlags) as $sFieldFlag)
|
||||
{
|
||||
if ($sFieldFlag !== '')
|
||||
{
|
||||
$sConst = 'OPT_ATT_' . strtoupper(str_replace('_', '', $sFieldFlag));
|
||||
if (defined($sConst))
|
||||
{
|
||||
switch ($sConst)
|
||||
{
|
||||
case 'OPT_ATT_SLAVE':
|
||||
case 'OPT_ATT_HIDDEN':
|
||||
if (!array_key_exists($sFieldId, $this->aFormProperties['fields']))
|
||||
{
|
||||
$this->aFormProperties['fields'][$sFieldId] = array();
|
||||
}
|
||||
$this->aFormProperties['fields'][$sFieldId]['hidden'] = true;
|
||||
break;
|
||||
case 'OPT_ATT_READONLY':
|
||||
if (!array_key_exists($sFieldId, $this->aFormProperties['fields']))
|
||||
{
|
||||
$this->aFormProperties['fields'][$sFieldId] = array();
|
||||
}
|
||||
$this->aFormProperties['fields'][$sFieldId]['read_only'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Flag "' . $sFieldFlag . '" is not valid for field [@data-field-id="' . $sFieldId . '"] in form[@id="' . $aFormPropertiesToMerge['id'] . '"]');
|
||||
throw new Exception('Flag "' . $sFieldFlag . '" is not valid for field [@data-field-id="' . $sFieldId . '"] in form[@id="' . $aFormPropertiesToMerge['id'] . '"]');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls all form fields OnCancel method in order to delegate them the cleanup;
|
||||
*
|
||||
|
||||
@@ -878,7 +878,8 @@ class ApplicationHelper
|
||||
}
|
||||
}
|
||||
|
||||
// Parsing availables modes for that form (view, edit, create)
|
||||
// Parsing availables modes for that form (view, edit, create, apply_stimulus)
|
||||
$aFormStimuli = array();
|
||||
if (($oFormNode->GetOptionalElement('modes') !== null) && ($oFormNode->GetOptionalElement('modes')->GetNodes('mode')->length > 0))
|
||||
{
|
||||
$aModes = array();
|
||||
@@ -892,10 +893,25 @@ class ApplicationHelper
|
||||
{
|
||||
throw new DOMFormatException('Mode tag must have an id attribute', null, null, $oFormNode);
|
||||
}
|
||||
|
||||
// If apply_stimulus mode, checking if stimuli are defined
|
||||
if ($oModeNode->getAttribute('id') === 'apply_stimulus')
|
||||
{
|
||||
$oStimuliNode = $oModeNode->GetOptionalElement('stimuli');
|
||||
if($oStimuliNode !== null)
|
||||
{
|
||||
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
|
||||
{
|
||||
$aFormStimuli[] = $oStimulusNode->getAttribute('id');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no mode was specified, we set it all but stimuli as it would have no sense that every transition forms
|
||||
// have as many fields displayed as a regular edit form for example.
|
||||
$aModes = array('view', 'edit', 'create');
|
||||
}
|
||||
|
||||
@@ -941,11 +957,6 @@ class ApplicationHelper
|
||||
}
|
||||
}
|
||||
}
|
||||
// // ... or a specified zlist
|
||||
// elseif ($oFormNode->GetOptionalElement('presentation') !== null)
|
||||
// {
|
||||
// // This is not implemented yet as it was rejected until futher notice.
|
||||
// }
|
||||
// ... or the default zlist
|
||||
else
|
||||
{
|
||||
@@ -953,6 +964,25 @@ class ApplicationHelper
|
||||
$aFields['fields'] = 'details';
|
||||
}
|
||||
|
||||
// Adding stimuli if explicitly defined
|
||||
if(in_array('apply_stimulus', $aModes))
|
||||
{
|
||||
// If stimuli are implicitly defined (empty tag), we define all those that have not already been by other forms.
|
||||
if(empty($aFormStimuli))
|
||||
{
|
||||
// Stimuli already declared
|
||||
$aDeclaredStimuli = array();
|
||||
if(array_key_exists($sFormClass, $aForms) && array_key_exists('apply_stimulus', $aForms[$sFormClass]))
|
||||
{
|
||||
$aDeclaredStimuli = array_keys($aForms[$sFormClass]['apply_stimulus']);
|
||||
}
|
||||
// All stimuli
|
||||
$aDatamodelStimuli = array_keys(MetaModel::EnumStimuli($sFormClass));
|
||||
// Missing stimuli
|
||||
$aFormStimuli = array_diff($aDatamodelStimuli, $aDeclaredStimuli);
|
||||
}
|
||||
}
|
||||
|
||||
// Parsing presentation
|
||||
if ($oFormNode->GetOptionalElement('twig') !== null)
|
||||
{
|
||||
@@ -975,7 +1005,18 @@ class ApplicationHelper
|
||||
$aForms[$sFormClass] = array();
|
||||
}
|
||||
|
||||
if (!isset($aForms[$sFormClass][$sMode]))
|
||||
if ($sMode === 'apply_stimulus')
|
||||
{
|
||||
foreach($aFormStimuli as $sFormStimulus)
|
||||
{
|
||||
if(!isset($aForms[$sFormClass][$sMode][$sFormStimulus]))
|
||||
{
|
||||
$aForms[$sFormClass][$sMode][$sFormStimulus] = $aFields;
|
||||
$aForms[$sFormClass][$sMode][$sFormStimulus]['id'] = 'apply_stimulus-'.$sFormClass.'-'.$sFormStimulus;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!isset($aForms[$sFormClass][$sMode]))
|
||||
{
|
||||
$aForms[$sFormClass][$sMode] = $aFields;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user