mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 18:48:51 +02:00
N°3649 - Activity panel: Add notifications
This commit is contained in:
@@ -24,6 +24,7 @@ use AttributeDateTime;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
use DateTime;
|
||||
use UserRights;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* Class ActivityEntry
|
||||
@@ -46,6 +47,8 @@ class ActivityEntry extends UIBlock
|
||||
public const DEFAULT_TYPE = 'generic';
|
||||
/** @var string DEFAULT_DECORATION_CLASSES */
|
||||
public const DEFAULT_DECORATION_CLASSES = 'fas fa-fw fa-mortar-pestle';
|
||||
/** @var string Relative URL (from the app. root) to the default author picture URL */
|
||||
public const DEFAULT_AUTHOR_PICTURE_REL_URL = 'images/icons/icons8-music-robot.svg';
|
||||
|
||||
/** @var string $sType Type of entry, used for filtering (eg. case log, edits, transition, ...) */
|
||||
protected $sType;
|
||||
@@ -209,17 +212,20 @@ class ActivityEntry extends UIBlock
|
||||
|
||||
// Set friendlyname to whatever we have in case $sAuthorLogin is not a valid login (deleted user, cron, ...)
|
||||
$iAuthorId = UserRights::GetUserId($this->sAuthorLogin);
|
||||
if(empty($iAuthorId) === true)
|
||||
{
|
||||
// - Friendlyname
|
||||
if (true === empty($iAuthorId)) {
|
||||
$this->sAuthorFriendlyname = $this->sAuthorLogin;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO 3.0.0: Check that this does not return '' when author is the CRON or an extension.
|
||||
} else {
|
||||
$this->sAuthorFriendlyname = UserRights::GetUserFriendlyName($this->sAuthorLogin);
|
||||
}
|
||||
// - Initials
|
||||
$this->sAuthorInitials = UserRights::GetUserInitials($this->sAuthorLogin);
|
||||
// - Picture
|
||||
$this->sAuthorPictureAbsUrl = UserRights::GetContactPictureAbsUrl($this->sAuthorLogin, false);
|
||||
if ((null === $this->sAuthorPictureAbsUrl) && (ITOP_APPLICATION_SHORT === $this->sAuthorLogin)) {
|
||||
$this->sAuthorPictureAbsUrl = utils::GetAbsoluteUrlAppRoot().static::DEFAULT_AUTHOR_PICTURE_REL_URL;
|
||||
}
|
||||
|
||||
$this->bIsFromCurrentUser = UserRights::GetUserId($this->sAuthorLogin) === UserRights::GetUserId();
|
||||
|
||||
return $this;
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry;
|
||||
use AttributeDateTime;
|
||||
use CMDBChangeOp;
|
||||
use DateTime;
|
||||
use DBObject;
|
||||
use EventNotification;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use ReflectionClass;
|
||||
@@ -47,11 +49,10 @@ class ActivityEntryFactory
|
||||
*/
|
||||
public static function MakeFromCmdbChangeOp(CMDBChangeOp $oChangeOp)
|
||||
{
|
||||
$sFactoryFqcn = static::GetCmdbChangeOpFactoryClass($oChangeOp);
|
||||
$sFactoryFqcn = static::GetFactoryClass($oChangeOp, 'CMDBChangeOp');
|
||||
|
||||
// If no factory found, throw an exception as the developer most likely forgot to create it
|
||||
if(empty($sFactoryFqcn))
|
||||
{
|
||||
if (empty($sFactoryFqcn)) {
|
||||
throw new Exception('No factory found for '.get_class($oChangeOp).', did you forgot to create one?');
|
||||
}
|
||||
|
||||
@@ -89,36 +90,57 @@ class ActivityEntryFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FQCN of the best fitted factory for the $oChangeOp. If none found, null will be returned.
|
||||
* Make an ActivityEntry entry (for ActivityPanel) based on the $oEvent
|
||||
*
|
||||
* @param \CMDBChangeOp $oChangeOp
|
||||
* @param \EventNotification $oEvent
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\ActivityEntry
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function MakeFromEventNotification(EventNotification $oEvent)
|
||||
{
|
||||
$sFactoryFqcn = static::GetFactoryClass($oEvent, 'EventNotification');
|
||||
|
||||
// If no factory found, throw an exception as the developer most likely forgot to create it
|
||||
if (empty($sFactoryFqcn)) {
|
||||
throw new Exception('No factory found for '.get_class($oEvent).', did you forgot to create one?');
|
||||
}
|
||||
|
||||
/** @var \Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\NotificationEntry $oEntry */
|
||||
/** @noinspection PhpUndefinedMethodInspection Call static method from the $sFactoryFqcn class */
|
||||
$oEntry = $sFactoryFqcn::MakeFromEventNotification($oEvent);
|
||||
|
||||
return $oEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FQCN of the best fitted factory for the $oObject / $sObjectType tuple. If none found, null will be returned.
|
||||
*
|
||||
* @param \DBObject $oObject
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected static function GetCmdbChangeOpFactoryClass(CMDBChangeOp $oChangeOp)
|
||||
protected static function GetFactoryClass(DBObject $oObject, string $sObjectType)
|
||||
{
|
||||
// Classes to search a factory for
|
||||
$aClassesTree = [get_class($oChangeOp)];
|
||||
$aClassesTree = [get_class($oObject)];
|
||||
|
||||
// Add parent classes to tree if not a root class
|
||||
$aParentClasses = class_parents($oChangeOp);
|
||||
if(is_array($aParentClasses))
|
||||
{
|
||||
$aParentClasses = class_parents($oObject);
|
||||
if (is_array($aParentClasses)) {
|
||||
$aClassesTree = array_merge($aClassesTree, array_values($aParentClasses));
|
||||
}
|
||||
|
||||
$sFactoryFqcn = null;
|
||||
foreach($aClassesTree as $sClass)
|
||||
{
|
||||
// Warning: This will replace all occurrences of 'CMDBChangeOp' which can be an issue on classes using this
|
||||
foreach ($aClassesTree as $sClass) {
|
||||
// Warning: This will replace all occurrences of $sObjectType (eg. 'CMDBChangeOp', 'EventNotification', ...) which can be an issue on classes using this
|
||||
// We used the case sensitive search to limit this issue.
|
||||
$sSimplifiedClass = (new ReflectionClass($sClass))->getShortName();
|
||||
$sFactoryFqcnToTry = __NAMESPACE__ . '\\CMDBChangeOp\\' . $sSimplifiedClass . 'Factory';
|
||||
$sFactoryFqcnToTry = __NAMESPACE__.'\\'.$sObjectType.'\\'.$sSimplifiedClass.'Factory';
|
||||
|
||||
// Stop at the first factory found
|
||||
if(class_exists($sFactoryFqcnToTry))
|
||||
{
|
||||
if (class_exists($sFactoryFqcnToTry)) {
|
||||
$sFactoryFqcn = $sFactoryFqcnToTry;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 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
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\EventNotification;
|
||||
|
||||
|
||||
/**
|
||||
* Class EventNotificationEmailFactory
|
||||
*
|
||||
* Factory for EventNotificationEmail events
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @package Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\EventNotification
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class EventNotificationEmailFactory extends EventNotificationFactory
|
||||
{
|
||||
/** @inheritDoc */
|
||||
public const DEFAULT_DECORATION_CLASSES = 'fas fa-fw fa-envelope';
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 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
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\EventNotification;
|
||||
|
||||
|
||||
use AttributeDateTime;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\NotificationEntry;
|
||||
use DateTime;
|
||||
use EventNotification;
|
||||
|
||||
/**
|
||||
* Class EventNotificationFactory
|
||||
*
|
||||
* Default factory for EventNotification events
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @package Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\EventNotification
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class EventNotificationFactory
|
||||
{
|
||||
/** @var string Used to overload the type from the NotificationEntry */
|
||||
public const DEFAULT_TYPE = NotificationEntry::DEFAULT_TYPE;
|
||||
/** @var string Used to overload the decoration classes from the NotificationEntry */
|
||||
public const DEFAULT_DECORATION_CLASSES = NotificationEntry::DEFAULT_DECORATION_CLASSES;
|
||||
|
||||
/**
|
||||
* Make an ActivityEntry from the iEventNotification $oEvent
|
||||
*
|
||||
* @param \EventNotification $oEvent
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry\NotificationEntry
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function MakeFromEventNotification(EventNotification $oEvent)
|
||||
{
|
||||
$oDateTime = DateTime::createFromFormat(AttributeDateTime::GetInternalFormat(), $oEvent->Get('date'));
|
||||
|
||||
// Author login is hardcoded:
|
||||
// - Adding a user_id column to the event tables like for the CMDBChangeOp could be erro prone during migration as those tables are huge.
|
||||
// - Marking events as created by the app. is good enough as the user triggering it as no power over it, it cannot avoid it.
|
||||
$sAuthorLogin = ITOP_APPLICATION_SHORT;
|
||||
|
||||
$oEntry = new NotificationEntry($oDateTime, $sAuthorLogin, $oEvent->Get('action_id_friendlyname'), $oEvent->Get('message'));
|
||||
$oEntry->SetType(static::DEFAULT_TYPE)
|
||||
->SetDecorationClasses(static::DEFAULT_DECORATION_CLASSES);
|
||||
|
||||
return $oEntry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 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
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry;
|
||||
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Class NotificationEntry
|
||||
*
|
||||
* @internal
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @package Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityEntry
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class NotificationEntry extends ActivityEntry
|
||||
{
|
||||
// Overloaded constants
|
||||
public const BLOCK_CODE = 'ibo-notification-entry';
|
||||
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/layouts/activity-panel/activity-entry/notification-entry';
|
||||
|
||||
public const DEFAULT_TYPE = 'edits';
|
||||
public const DEFAULT_DECORATION_CLASSES = 'fas fa-fw fa-bell';
|
||||
|
||||
/** @var string Title of the entry, usually the linked action title */
|
||||
protected $sTitle;
|
||||
/** @var string Message of the entry, usually it's status */
|
||||
protected $sMessage;
|
||||
|
||||
/**
|
||||
* NotificationEntry constructor.
|
||||
*
|
||||
* @param \DateTime $oDateTime
|
||||
* @param string $sAuthorLogin
|
||||
* @param string $sTitle
|
||||
* @param string $sMessage
|
||||
* @param string|null $sId
|
||||
*
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function __construct(DateTime $oDateTime, string $sAuthorLogin, string $sTitle, string $sMessage, ?string $sId = null)
|
||||
{
|
||||
parent::__construct($oDateTime, $sAuthorLogin, null, $sId);
|
||||
|
||||
$this->SetTitle($sTitle);
|
||||
$this->SetMessage($sMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sTitle
|
||||
*
|
||||
* @param string $sTitle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetTitle(string $sTitle)
|
||||
{
|
||||
$this->sTitle = $sTitle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sTitle
|
||||
* @return string
|
||||
*/
|
||||
public function GetTitle(): string
|
||||
{
|
||||
return $this->sTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sMessage
|
||||
*
|
||||
* @param string $sMessage
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetMessage(string $sMessage)
|
||||
{
|
||||
$this->sMessage = $sMessage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see static::$sMessage
|
||||
* @return string
|
||||
*/
|
||||
public function GetMessage(): string
|
||||
{
|
||||
return $this->sMessage;
|
||||
}
|
||||
}
|
||||
@@ -45,11 +45,11 @@ class ActivityPanelFactory
|
||||
/**
|
||||
* Make an activity panel for an object details layout, meaning that it should contain the case logs and the activity.
|
||||
*
|
||||
* @param \DBObject $oObject
|
||||
* @param string $sMode Mode the object is being displayed (view, edit, create, ...), default is view.
|
||||
*
|
||||
* @see cmdbAbstractObject::ENUM_OBJECT_MODE_XXX
|
||||
*
|
||||
* @param \DBObject $oObject
|
||||
* @param string $sMode Mode the object is being displayed (view, edit, create, ...), default is view.
|
||||
*
|
||||
* @return \Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityPanel
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
@@ -124,14 +124,41 @@ class ActivityPanelFactory
|
||||
$oActivityPanel->AddEntry($oEntry);
|
||||
|
||||
// Set previous edits entry
|
||||
if($oEntry instanceof EditsEntry)
|
||||
{
|
||||
if ($oEntry instanceof EditsEntry) {
|
||||
$oPreviousEditsEntry = $oEntry;
|
||||
}
|
||||
}
|
||||
|
||||
$iPreviousChangeId = $iChangeId;
|
||||
}
|
||||
unset($oChangesSet);
|
||||
|
||||
// Retrieving notification events for cmdbAbstractObject only
|
||||
if ($oObject instanceof cmdbAbstractObject) {
|
||||
$aRelatedTriggersIDs = $oObject->GetRelatedTriggersIDs();
|
||||
|
||||
// Protection for classes which have no related trigger
|
||||
if (false === empty($aRelatedTriggersIDs)) {
|
||||
// - Prepare query to retrieve events
|
||||
$oNotifEventsSearch = DBObjectSearch::FromOQL('SELECT EN FROM EventNotification AS EN JOIN Action AS A ON EN.action_id = A.id WHERE EN.trigger_id IN (:triggers_ids) AND EN.object_id = :object_id');
|
||||
$oNotifEventsSet = new DBObjectSet($oNotifEventsSearch, ['id' => false], ['triggers_ids' => $aRelatedTriggersIDs, 'object_id' => $iObjId]);
|
||||
$oNotifEventsSet->SetLimit(MetaModel::GetConfig()->Get('max_history_length'));
|
||||
|
||||
/** @var \EventNotification $oNotifEvent */
|
||||
while ($oNotifEvent = $oNotifEventsSet->Fetch()) {
|
||||
try {
|
||||
$oEntry = ActivityEntryFactory::MakeFromEventNotification($oNotifEvent);
|
||||
}
|
||||
catch (Exception $oException) {
|
||||
IssueLog::Debug(static::class.': Could not create entry from EventNotification: '.$oException->getMessage());
|
||||
continue;
|
||||
}
|
||||
|
||||
$oActivityPanel->AddEntry($oEntry);
|
||||
}
|
||||
unset($oNotifEventsSet);
|
||||
}
|
||||
}
|
||||
|
||||
return $oActivityPanel;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user