Trac #57 - Implemented beta version of email notifications (triggers and actions)

SVN:trunk[225]
This commit is contained in:
Romain Quetiez
2010-01-06 08:51:08 +00:00
parent 644d936c26
commit 5a15dcb849
9 changed files with 224 additions and 29 deletions

View File

@@ -16,7 +16,7 @@ class DisplayTemplate
public function Render(web_page $oPage, $aParams = array())
{
$this->ApplyParams($aParams);
$this->m_sTemplate = MetaModel::ApplyParams($this->m_sTemplate, $aParams);
$iStart = 0;
$iEnd = strlen($this->m_sTemplate);
$iCount = 0;
@@ -40,21 +40,6 @@ class DisplayTemplate
$oPage->add(substr($this->m_sTemplate, $iAfterTagPos));
}
/**
* Replaces all the parameters by the values passed in the hash array
*/
public function ApplyParams($aParams)
{
$aSearches = array();
$aReplacements = array();
foreach($aParams as $sSearch => $sReplace)
{
$aSearches[] = '$'.$sSearch.'$';
$aReplacements[] = $sReplace;
}
$this->m_sTemplate = str_replace($aSearches, $aReplacements, $this->m_sTemplate);
}
public function GetNextTag(&$iStartPos, &$iEndPos)
{
$iChunkStartPos = $iStartPos;

View File

@@ -200,7 +200,7 @@ class bizContact extends logRealObject
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalField("org_name", array("label"=>"Organization", "description"=>"Company / Department of the contact", "allowed_values"=>null, "extkey_attcode"=> 'org_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("email", array("label"=>"eMail", "description"=>"Email address", "allowed_values"=>null, "sql"=>"email", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEmailAddress("email", array("label"=>"eMail", "description"=>"Email address", "allowed_values"=>null, "sql"=>"email", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("phone", array("label"=>"Phone", "description"=>"Telephone", "allowed_values"=>null, "sql"=>"telephone", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("location_id", array("targetclass"=>"bizLocation", "label"=>"Location", "description"=>"Id of the location where the contact is located", "allowed_values"=>null, "sql"=>"location_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("location_name", array("label"=>"Location Name", "description"=>"Name of the location where the contact is located", "allowed_values"=>null, "extkey_attcode"=> 'location_id', "target_attcode"=>"name")));

View File

@@ -547,7 +547,7 @@ class AttributeString extends AttributeDBField
}
public function ScalarToSQL($value)
{
if (!is_string($value))
if (!is_string($value) && !is_null($value))
{
throw new CoreWarning('Expected the attribute value to be a string', array('found_type' => gettype($value), 'value' => $value, 'class' => $this->GetCode(), 'attribute' => $this->GetHostClass()));
}
@@ -615,6 +615,66 @@ class AttributeText extends AttributeString
}
}
/**
* Specialization of a string: email
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeEmailAddress extends AttributeString
{
public function GetTypeDesc() {return "Email address(es)";}
}
/**
* Specialization of a string: OQL expression
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeOQL extends AttributeString
{
public function GetTypeDesc() {return "OQL expression";}
}
/**
* Specialization of a string: template
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeTemplateString extends AttributeString
{
public function GetTypeDesc() {return "Template string";}
}
/**
* Specialization of a text: template
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeTemplateText extends AttributeText
{
public function GetTypeDesc() {return "Multiline template string";}
}
/**
* Map a enum column to an attribute
*

View File

@@ -37,9 +37,19 @@ require_once('dbobject.class.php');
require_once('dbobjectsearch.class.php');
require_once('dbobjectset.class.php');
// db change tracking data model
require_once('cmdbchange.class.inc.php');
require_once('cmdbchangeop.class.inc.php');
// customization data model
// Romain: temporary moved into application.inc.php (see explanations there)
//require_once('trigger.class.inc.php');
//require_once('action.class.inc.php');
// application log
// Romain: temporary moved into application.inc.php (see explanations there)
//require_once('event.class.inc.php');
require_once('csvparser.class.inc.php');
require_once('bulkchange.class.inc.php');

View File

@@ -289,6 +289,14 @@ class Config
fwrite($hFile, "\t'application' => array (\n");
fwrite($hFile, "\t\t'../application/menunode.class.inc.php',\n");
fwrite($hFile, "\t\t'../application/audit.rule.class.inc.php',\n");
// Romain - That's dirty, because those 3 classes are in fact part of the core
// but I needed those classes to be derived from cmdbAbstractObject
// (to be managed via the GUI) and this class in not really known from
// the core, PLUS I needed the includes to be there also for the setup
// to create the tables.
fwrite($hFile, "\t\t'../core/event.class.inc.php',\n");
fwrite($hFile, "\t\t'../core/action.class.inc.php',\n");
fwrite($hFile, "\t\t'../core/trigger.class.inc.php',\n");
fwrite($hFile, "\t\t// to be continued...\n");
fwrite($hFile, "\t),\n");
fwrite($hFile, "\t'business' => array (\n");

View File

@@ -611,7 +611,7 @@ abstract class DBObject
if (!empty($this->m_iKey) && ($this->m_iKey >= 0))
{
// Add it to the list of fields to write
$aFieldsToWrite[] = MetaModel::DBGetKey($sTableClass);
$aFieldsToWrite[] = '`'.MetaModel::DBGetKey($sTableClass).'`';
$aValuesToWrite[] = CMDBSource::Quote($this->m_iKey);
}
@@ -622,7 +622,7 @@ abstract class DBObject
$aAttColumns = $oAttDef->GetSQLValues($this->m_aCurrValues[$sAttCode]);
foreach($aAttColumns as $sColumn => $sValue)
{
$aFieldsToWrite[] = $sColumn;
$aFieldsToWrite[] = "`$sColumn`";
$aValuesToWrite[] = CMDBSource::Quote($sValue);
}
}
@@ -803,7 +803,9 @@ abstract class DBObject
// Change the state before proceeding to the actions, this is necessary because an action might
// trigger another stimuli (alternative: push the stimuli into a queue)
$this->Set($sStateAttCode, $aTransitionDef['target_state']);
$sPreviousState = $this->Get($sStateAttCode);
$sNewState = $aTransitionDef['target_state'];
$this->Set($sStateAttCode, $sNewState);
// $aTransitionDef is an
// array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
@@ -824,9 +826,39 @@ abstract class DBObject
if (!$bRet) $bSuccess = false;
}
// Change state triggers...
$sClass = get_class($this);
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class='$sClass' AND t.state='$sPreviousState'"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class='$sClass' AND t.state='$sNewState'"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
return $bSuccess;
}
// Make standard context arguments
public function ToArgs($sArgName)
{
$aScalarArgs = array();
$aScalarArgs[$sArgName] = $this->GetKey();
$aScalarArgs[$sArgName.'->id'] = $this->GetKey();
$sClass = get_class($this);
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$aScalarArgs[$sArgName.'->'.$sAttCode] = $this->Get($sAttCode);
}
return $aScalarArgs;
}
// Return an empty set for the parent of all
public static function GetRelationQueries($sRelCode)
{

View File

@@ -1222,14 +1222,7 @@ abstract class MetaModel
{
if (self::IsValidObject($value))
{
$aScalarArgs[$sArgName] = $value->GetKey();
$aScalarArgs[$sArgName.'->id'] = $value->GetKey();
$sClass = get_class($value);
foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$aScalarArgs[$sArgName.'->'.$sAttCode] = $value->Get($sAttCode);
}
$aScalarArgs = array_merge($aScalarArgs, $value->ToArgs($sArgName));
}
else
{
@@ -2849,6 +2842,21 @@ abstract class MetaModel
return self::GetLabel($sLinkClass, $sAttCode);
}
/**
* Replaces all the parameters by the values passed in the hash array
*/
static public function ApplyParams($aInput, $aParams)
{
$aSearches = array();
$aReplacements = array();
foreach($aParams as $sSearch => $sReplace)
{
$aSearches[] = '$'.$sSearch.'$';
$aReplacements[] = $sReplace;
}
return str_replace($aSearches, $aReplacements, $aInput);
}
} // class MetaModel

View File

@@ -231,6 +231,16 @@ function DisplayLifecycle($oPage, $sClass)
}
/**
* Helper for the trigger
*/
function DisplayTriggers($oPage, $sClass)
{
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateChange WHERE target_class = '$sClass'"));
cmdbAbstractObject::DisplaySet($oPage, $oSet);
}
/**
* Display the list of classes from the business model
*/
@@ -402,6 +412,9 @@ function DisplayClassDetails($oPage, $sClass)
$oPage->SetCurrentTab('Lifecycle');
DisplayLifecycle($oPage, $sClass);
$oPage->SetCurrentTab('Triggers');
DisplayTriggers($oPage, $sClass);
$oPage->SetCurrentTab();
$oPage->SetCurrentTabContainer();
}

View File

@@ -918,4 +918,83 @@ text-align:left;
<parent_id>0</parent_id>
<user_id>0</user_id>
</menuNode>
<menuNode id="500">
<name>Customization</name>
<label>Customization</label>
<hyperlink>UI.php</hyperlink>
<icon_path></icon_path>
<template></template>
<type>administrator</type>
<rank>2</rank>
<parent_id>1</parent_id>
<user_id>0</user_id>
</menuNode>
<menuNode id="501">
<name>Triggers - entering</name>
<label>Triggers - On entering state</label>
<hyperlink>UI.php</hyperlink>
<icon_path>../images/std_view.gif</icon_path>
<template>
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;search&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT TriggerOnStateEnter&lt;/itopblock&gt;
&lt;div id=&quot;BottomPane&quot;&gt;
&lt;p&gt;&lt;/p&gt;
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;list&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT TriggerOnStateEnter&lt;/itopblock&gt;
&lt;/div&gt;
</template>
<type>administrator</type>
<rank>2</rank>
<parent_id>500</parent_id>
<user_id>0</user_id>
</menuNode>
<menuNode id="502">
<name>Triggers - leaving</name>
<label>Triggers - On leaving state</label>
<hyperlink>UI.php</hyperlink>
<icon_path>../images/std_view.gif</icon_path>
<template>
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;search&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT TriggerOnStateLeave&lt;/itopblock&gt;
&lt;div id=&quot;BottomPane&quot;&gt;
&lt;p&gt;&lt;/p&gt;
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;list&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT TriggerOnStateLeave&lt;/itopblock&gt;
&lt;/div&gt;
</template>
<type>administrator</type>
<rank>2</rank>
<parent_id>500</parent_id>
<user_id>0</user_id>
</menuNode>
<menuNode id="505">
<name>Actions</name>
<label>Actions - Send an email</label>
<hyperlink>UI.php</hyperlink>
<icon_path>../images/std_view.gif</icon_path>
<template>
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;search&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT ActionEmail&lt;/itopblock&gt;
&lt;div id=&quot;BottomPane&quot;&gt;
&lt;p&gt;&lt;/p&gt;
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;list&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT ActionEmail&lt;/itopblock&gt;
&lt;/div&gt;
</template>
<type>administrator</type>
<rank>2</rank>
<parent_id>500</parent_id>
<user_id>0</user_id>
</menuNode>
<menuNode id="510">
<name>Application log</name>
<label>Application log</label>
<hyperlink>UI.php</hyperlink>
<icon_path>../images/std_view.gif</icon_path>
<template>
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;search&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT Event&lt;/itopblock&gt;
&lt;div id=&quot;BottomPane&quot;&gt;
&lt;p&gt;&lt;/p&gt;
&lt;itopblock BlockClass=&quot;DisplayBlock&quot; type=&quot;list&quot; asynchronous=&quot;false&quot; encoding=&quot;text/oql&quot;&gt;SELECT Event&lt;/itopblock&gt;
&lt;/div&gt;
</template>
<type>administrator</type>
<rank>2</rank>
<parent_id>1</parent_id>
<user_id>0</user_id>
</menuNode>
</Set>