diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php
index 63655d79a..87eace0ae 100644
--- a/application/applicationextension.inc.php
+++ b/application/applicationextension.inc.php
@@ -308,6 +308,37 @@ interface iPopupMenuExtension
* $param is null
*/
const MENU_USER_ACTIONS = 5;
+ /**
+ * Insert an item into the Action menu on an object details page in the portal
+ *
+ * $param is an array('portal_id' => $sPortalId, 'object' => $oObject) containing the portal id and a DBObject instance (the object currently displayed)
+ */
+ const PORTAL_OBJDETAILS_ACTIONS = 7;
+
+ /**
+ * Insert an item into the Actions menu of a list in the portal
+ * Note: This is not implemented yet !
+ *
+ * $param is an array('portal_id' => $sPortalId, 'object_set' => $oSet) containing DBObjectSet containing the list of objects
+ * @todo
+ */
+ const PORTAL_OBJLIST_ACTIONS = 6;
+ /**
+ * Insert an item into the user menu of the portal
+ * Note: This is not implemented yet !
+ *
+ * $param is the portal id
+ * @todo
+ */
+ const PORTAL_USER_ACTIONS = 8;
+ /**
+ * Insert an item into the navigation menu of the portal
+ * Note: This is not implemented yet !
+ *
+ * $param is the portal id
+ * @todo
+ */
+ const PORTAL_MENU_ACTIONS = 9;
/**
* Get the list of items to be added to a menu.
@@ -334,17 +365,21 @@ abstract class ApplicationPopupMenuItem
protected $sUID;
/** @ignore */
protected $sLabel;
+ /** @ignore */
+ protected $aCssClasses;
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
- * @param string $sLabel The display label of the menu (must be localized)
- */
+ * @param string $sLabel The display label of the menu (must be localized)
+ * @param array $aCssClasses The CSS classes to add to the menu
+ */
public function __construct($sUID, $sLabel)
{
$this->sUID = $sUID;
$this->sLabel = $sLabel;
+ $this->aCssClasses = array();
}
/**
@@ -368,6 +403,35 @@ abstract class ApplicationPopupMenuItem
{
return $this->sLabel;
}
+
+ /**
+ * Get the CSS classes
+ *
+ * @return array
+ * @ignore
+ */
+ public function GetCssClasses()
+ {
+ return $this->aCssClasses;
+ }
+
+ /**
+ * @param $aCssClasses
+ */
+ public function SetCssClasses($aCssClasses)
+ {
+ $this->aCssClasses = $aCssClasses;
+ }
+
+ /**
+ * Adds a CSS class to the CSS classes that will be put on the menu item
+ *
+ * @param $sCssClass
+ */
+ public function AddCssClass($sCssClass)
+ {
+ $this->aCssClasses[] = $sCssClass;
+ }
/**
* Returns the components to create a popup menu item in HTML
@@ -415,7 +479,7 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
/** @ignore */
public function GetMenuItem()
{
- return array ('label' => $this->GetLabel(), 'url' => $this->sURL, 'target' => $this->sTarget);
+ return array ('label' => $this->GetLabel(), 'url' => $this->sURL, 'target' => $this->sTarget, 'css_classes' => $this->aCssClasses);
}
}
@@ -451,7 +515,7 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
public function GetMenuItem()
{
// Note: the semicolumn is a must here!
- return array ('label' => $this->GetLabel(), 'onclick' => $this->sJSCode.'; return false;', 'url' => '#');
+ return array ('label' => $this->GetLabel(), 'onclick' => $this->sJSCode.'; return false;', 'url' => '#', 'css_classes' => $this->aCssClasses);
}
/** @ignore */
@@ -483,10 +547,34 @@ class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
/** @ignore */
public function GetMenuItem()
{
- return array ('label' => '
', 'url' => '');
+ return array ('label' => '', 'url' => '', 'css_classes' => $this->aCssClasses);
}
}
+/**
+ * Class for adding an item as a button that browses to the given URL
+ *
+ * @package Extensibility
+ * @api
+ * @since 2.0
+ */
+class URLButtonItem extends URLPopupMenuItem
+{
+
+}
+
+/**
+ * Class for adding an item as a button that runs some JS code
+ *
+ * @package Extensibility
+ * @api
+ * @since 2.0
+ */
+class JSButtonItem extends JSPopupMenuItem
+{
+
+}
+
/**
* Implement this interface to add content to any iTopWebPage
*
diff --git a/application/webpage.class.inc.php b/application/webpage.class.inc.php
index cd85fe705..149cb3277 100644
--- a/application/webpage.class.inc.php
+++ b/application/webpage.class.inc.php
@@ -734,7 +734,7 @@ class WebPage implements Page
{
foreach ($aActions as $aAction)
{
- $sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : "";
+ $sClass = isset($aAction['css_classes']) ? ' class="'.implode(' ', $aAction['css_classes']).'"' : '';
$sOnClick = isset($aAction['onclick']) ? ' onclick="'.htmlspecialchars($aAction['onclick'], ENT_QUOTES, "UTF-8").'"' : '';
$sTarget = isset($aAction['target']) ? " target=\"{$aAction['target']}\"" : "";
if (empty($aAction['url']))
diff --git a/datamodels/2.x/itop-portal-base/portal/src/controllers/objectcontroller.class.inc.php b/datamodels/2.x/itop-portal-base/portal/src/controllers/objectcontroller.class.inc.php
index b0dccf400..a42c45a3c 100644
--- a/datamodels/2.x/itop-portal-base/portal/src/controllers/objectcontroller.class.inc.php
+++ b/datamodels/2.x/itop-portal-base/portal/src/controllers/objectcontroller.class.inc.php
@@ -43,6 +43,9 @@ use \cmdbAbstractObject;
use \AttributeEnum;
use \AttributeFinalClass;
use \UserRights;
+use \iPopupMenuExtension;
+use \URLButtonItem;
+use \JSButtonItem;
use \Combodo\iTop\Portal\Helper\ApplicationHelper;
use \Combodo\iTop\Portal\Helper\SecurityHelper;
use \Combodo\iTop\Portal\Helper\ContextManipulatorHelper;
@@ -101,10 +104,13 @@ class ObjectController extends AbstractController
// 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))
- );
+ $oModifyButton = new URLButtonItem(
+ 'modify_object',
+ Dict::S('UI:Menu:Modify'),
+ $oApp['url_generator']->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId))
+ );
+ // Putting this one first
+ $aData['form']['buttons']['links'][] = $oModifyButton->GetMenuItem();
}
// Preparing response
@@ -467,7 +473,9 @@ class ObjectController extends AbstractController
// Preparing transitions only if we are currently going through one
$aFormData['buttons'] = array(
- 'transitions' => array()
+ 'transitions' => array(),
+ 'actions' => array(),
+ 'links' => array(),
);
if ($sMode !== 'apply_stimulus')
{
@@ -482,6 +490,25 @@ class ObjectController extends AbstractController
$aFormData['buttons']['transitions'][$sStimulusCode] = $aStimuli[$sStimulusCode]->GetLabel();
}
}
+
+ // Add plugins buttons
+ foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
+ {
+ foreach($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJDETAILS_ACTIONS, array('portal_id' => $oApp['combodo.portal.instance.id'], 'object' => $oObject)) as $oMenuItem)
+ {
+ if (is_object($oMenuItem))
+ {
+ if($oMenuItem instanceof JSButtonItem)
+ {
+ $aFormData['buttons']['actions'][] = $oMenuItem->GetMenuItem() + array('js_files' => $oMenuItem->GetLinkedScripts());
+ }
+ elseif($oMenuItem instanceof URLButtonItem)
+ {
+ $aFormData['buttons']['links'][] = $oMenuItem->GetMenuItem();
+ }
+ }
+ }
+ }
}
// Preparing callback urls
$aCallbackUrls = $oApp['context_manipulator']->GetCallbackUrls($oApp, $aActionRules, $oObject, $bModal);
@@ -1499,5 +1526,3 @@ class ObjectController extends AbstractController
}
}
-
-?>
\ No newline at end of file
diff --git a/datamodels/2.x/itop-portal-base/portal/src/views/bricks/object/mode_create.html.twig b/datamodels/2.x/itop-portal-base/portal/src/views/bricks/object/mode_create.html.twig
index 5f2875802..608da60f4 100644
--- a/datamodels/2.x/itop-portal-base/portal/src/views/bricks/object/mode_create.html.twig
+++ b/datamodels/2.x/itop-portal-base/portal/src/views/bricks/object/mode_create.html.twig
@@ -21,6 +21,13 @@