Bläddra i källkod

Productivity enhancement: apply directly the 'next_action' when creating or modifying an object with a life-cycle !

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1434 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 14 år sedan
förälder
incheckning
aa06c315db
2 ändrade filer med 148 tillägg och 13 borttagningar
  1. 69 1
      application/cmdbabstract.class.inc.php
  2. 79 12
      pages/UI.php

+ 69 - 1
application/cmdbabstract.class.inc.php

@@ -1717,7 +1717,26 @@ EOF
 			$sButtons .= "<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n";
 		}
 
-
+		$aTransitions = $this->EnumTransitions();
+		if (count($aTransitions))
+		{
+			$oSetToCheckRights = DBObjectSet::FromObject($this);
+			$aStimuli = Metamodel::EnumStimuli($sClass);
+			foreach($aTransitions as $sStimulusCode => $aTransitionDef)
+			{
+				$iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSetToCheckRights) : UR_ALLOWED_NO;
+				switch($iActionAllowed)
+				{
+					case UR_ALLOWED_YES:
+					$sButtons .= "<button type=\"submit\" name=\"next_action\" value=\"{$sStimulusCode}\" class=\"action\"><span>".$aStimuli[$sStimulusCode]->GetLabel()."</span></button>\n";
+					break;
+					
+					default:
+					// Do nothing
+				}
+			}
+		}
+				
 		$bDisplayActionsAtTop = MetaModel::GetConfig()->Get('display_actions_at_top');
 		$iTransactionId = utils::GetNewTransactionId();
 		$oPage->SetTransactionId($iTransactionId);
@@ -2530,5 +2549,54 @@ EOF
 			$oPage->add('</fieldset>');
 		}
 	}
+	
+	public function GetExpectedAttributes($sCurrentState, $sStimulus, $bOnlyNewOnes)
+	{
+		$aTransitions = $this->EnumTransitions();
+		$aStimuli = MetaModel::EnumStimuli(get_class($this));
+		if (!isset($aTransitions[$sStimulus]))
+		{
+			// Invalid stimulus
+			throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel()));
+		}
+		$aTransition = $aTransitions[$sStimulus];
+		$sTargetState = $aTransition['target_state'];
+		$aTargetStates = MetaModel::EnumStates(get_class($this));
+		$aTargetState = $aTargetStates[$sTargetState];
+		$aCurrentState = $aTargetStates[$this->GetState()];
+		$aExpectedAttributes = $aTargetState['attribute_list'];
+		$aCurrentAttributes = $aCurrentState['attribute_list'];
+
+		$aComputedAttributes = array();
+		foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
+		{
+			if (!array_key_exists($sAttCode, $aCurrentAttributes))
+			{
+				$aComputedAttributes[$sAttCode] = $iExpectCode;
+			}
+			else
+			{
+				if ( !($aCurrentAttributes[$sAttCode] & (OPT_ATT_HIDDEN|OPT_ATT_READONLY)) )
+				{
+					$iExpectCode = $iExpectCode & ~(OPT_ATT_MUSTPROMPT|OPT_ATT_MUSTCHANGE); // Already prompted/changed, reset the flags
+				}
+				//TODO: better check if the attribute is not *null*
+				if ( ($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) != ''))
+				{
+					$iExpectCode = $iExpectCode & ~(OPT_ATT_MANDATORY); // If the attribute is present, then no need to request its presence
+				}
+
+				$aComputedAttributes[$sAttCode] = $iExpectCode;								
+			}
+
+			$aComputedAttributes[$sAttCode] = $aComputedAttributes[$sAttCode] & ~(OPT_ATT_READONLY|OPT_ATT_HIDDEN); // Don't care about this form now
+
+			if ($aComputedAttributes[$sAttCode] == 0)
+			{
+				unset($aComputedAttributes[$sAttCode]);
+			}
+		}
+		return $aComputedAttributes;
+	}
 }
 ?>

+ 79 - 12
pages/UI.php

@@ -354,6 +354,52 @@ EOF
 }
 
 /**
+ * Apply the 'next-action' to the given object or redirect to the page that prompts for additional information if needed
+ * @param $oP WebPage The page for the output
+ * @param $oObj CMDBObject The object to process
+ * @param $sNextAction string The code of the stimulus for the 'action' (i.e. Transition) to apply
+ * @param $oMyChange CMDBChange The change used to log the modifications or null is none is available (a new one will be created)
+ */
+function ApplyNextAction(Webpage $oP, CMDBObject $oObj, $sNextAction, $oMyChange)
+{
+	// Here handle the apply stimulus
+	$aTransitions = $oObj->EnumTransitions();
+	$aStimuli = MetaModel::EnumStimuli(get_class($oObj));
+	if (!isset($aTransitions[$sNextAction]))
+	{
+		// Invalid stimulus
+		throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sNextAction, $oObj->GetName(), $oObj->GetStateLabel()));
+	}
+	// Get the list of missing mandatory fields for the target state, considering only the changes from the previous form (i.e don't prompt twice)
+	$aExpectedAttributes = $oObj->GetExpectedAttributes($oObj->GetState(), $sNextAction, true /* $bOnlyNewOnes */);
+	
+	if (count($aExpectedAttributes) == 0)
+	{
+		// If all the mandatory fields are already present, just apply the transition silently...
+		if ($oObj->ApplyStimulus($sNextAction))
+		{
+			if ($oMyChange == null)
+			{
+				$oMyChange = MetaModel::NewObject("CMDBChange");
+				$oMyChange->Set("date", time());
+				$sUserString = CMDBChange::GetCurrentUserName();
+				$oMyChange->Set("userinfo", $sUserString);
+				$iChangeId = $oMyChange->DBInsert();							
+			}
+			$oObj->DBUpdateTracked($oMyChange);
+		}
+		$oObj->DisplayDetails($oP);
+	}
+	else
+	{
+		// redirect to the 'stimulus' action
+		$oAppContext = new ApplicationContext();
+//echo "<p>Missing Attributes <pre>".print_r($aExpectedAttributes, true)."</pre></p>\n";
+		
+		$oP->add_header('Location: '.utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=stimulus&class='.get_class($oObj).'&stimulus='.$sNextAction.'&id='.$oObj->getKey().'&'.$oAppContext->GetForLink());
+	}
+}
+/**
  * Displays the details of an object
  * @param $oP WebPage Page for the output
  * @param $sClass string The name of the class of the object
@@ -1172,6 +1218,7 @@ EOF
 			}
 			else
 			{
+				$oMyChange = null;
 				$oObj->UpdateObjectFromPostedForm();
 
 				if (!$oObj->IsModified())
@@ -1217,7 +1264,16 @@ EOF
 			if ($bDisplayDetails)
 			{
 				$oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey()); //Workaround: reload the object so that the linkedset are displayed properly
-				$oObj->DisplayDetails($oP);
+				$sNextAction = utils::ReadPostedParam('next_action', '');
+				if (!empty($sNextAction))
+				{
+					ApplyNextAction($oP, $oObj, $sNextAction, $oMyChange);
+				}
+				else
+				{
+					// Nothing more to do
+					$oObj->DisplayDetails($oP);
+				}
 			}
 		break;
 
@@ -1324,7 +1380,18 @@ EOF
 				utils::RemoveTransaction($sTransactionId);
 				$oP->set_title(Dict::S('UI:PageTitle:ObjectCreated'));
 				$oP->add("<h1>".Dict::Format('UI:Title:Object_Of_Class_Created', $oObj->GetName(), $sClassLabel)."</h1>\n");
-				$oObj->DisplayDetails($oP);
+				$oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey()); //Workaround: reload the object so that the linkedset are displayed properly
+
+				$sNextAction = utils::ReadPostedParam('next_action', '');
+				if (!empty($sNextAction))
+				{
+					ApplyNextAction($oP, $oObj, $sNextAction, $oMyChange);
+				}
+				else
+				{
+					// Nothing more to do
+					$oObj->DisplayDetails($oP);
+				}
 			}
 			else
 			{
@@ -1902,16 +1969,16 @@ EOF
 				}
 				if (count($aErrors) == 0)
 				{
-				if ($oObj->ApplyStimulus($sStimulus))
-				{
-					$oMyChange = MetaModel::NewObject("CMDBChange");
-					$oMyChange->Set("date", time());
-					$sUserString = CMDBChange::GetCurrentUserName();
-					$oMyChange->Set("userinfo", $sUserString);
-					$iChangeId = $oMyChange->DBInsert();
-					$oObj->DBUpdateTracked($oMyChange);
-					$oP->p(Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()));
-				}
+					if ($oObj->ApplyStimulus($sStimulus))
+					{
+						$oMyChange = MetaModel::NewObject("CMDBChange");
+						$oMyChange->Set("date", time());
+						$sUserString = CMDBChange::GetCurrentUserName();
+						$oMyChange->Set("userinfo", $sUserString);
+						$iChangeId = $oMyChange->DBInsert();
+						$oObj->DBUpdateTracked($oMyChange);
+						$oP->p(Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()));
+					}
 					else
 					{
 						$oP->p(Dict::S('UI:FailedToApplyStimuli'));