Communications displayed on Condition
Prerequisite: You must be familiar with the
Syntax used in Tutorials and
have already created an
extension.
- learning:
- Portal User Communication displayed if the user Organization matches some condition defined per Communication
- level:
- Intermediate
- domains:
- XML, PHP, Portal, Communication, Presentation
- min version:
- 2.7.0
If you are a Service Provider, you may want to inform your customers as a Communication on the User Portal, when their contract is about to expire and need to be renewed, or when their credit consumption has expired.
For this you could define “permanent” Communication(s) which would be displayed only if the user's Organization match a particular condition. This condition would be dynamically defined through an OQL for each Communication, for example it would retrieve the Customer whose contract is about to expire and need to be renewed, or whose consumption of credit has expired or whatever logic.
Communication
In order to do this we will modify the Communications to the Customers extension, so you need to have it…
Fields
Add an oql
value to the org_match_type
field and create a new OQL field to allow any condition on the
applicable Organizations
- itop-design | class@Communication | fields
-
<field id="org_match_type" xsi:type="AttributeEnum" _delta="must_exist"> <values> <value id="oql" _delta="define"> <!-- Cautious this part uses XML 3.0 format and <code> tag is not closed correctly due to wiki limitation --> <code>oql</ code> </value> </values> </field> <field id="org_oql" xsi:type="AttributeOQL" _delta="define"> <sql>org_oql</sql> <default_value/> <is_null_allowed>true</is_null_allowed> <width/> <height/> <tracking_level>all</tracking_level> </field>
Presentation
Modify the Communication presentation, to display the oql field
- itop-design | class@Communication | presentation | details
-
<details> <items> <item id="col:col0"> <items> <item id="org_oql" _delta="define"> <rank>65</rank> </item> </items> </item> </items> </details>
Methods
-
Modify
IsUserInScope
method to compute the case where organizations are specified through an OQL -
Modify the
DoCheckToWrite
method to guarantee that the OQL is set when needed, is a valid OQL and returns Organizations objects -
Create a
DisplayBareRelations
method to display the list of Organizations matching the OQL right now
- Communication
-
public function IsUserInScope(User $oUser) { // Is the user org within the target organizations $iContact = $oUser->Get('contactid'); $oContact = MetaModel::GetObject('Contact', $iContact, true, true); $iUserOrg = $oContact->Get('org_id'); $sMatchType = $this->Get('org_match_type'); $bRet = false; if ($sMatchType == 'oql') { // Target organizations defined as an OQL $oOrgSearch = DBSearch::FromOQL_AllData($this->Get('org_oql')); $oOrgSet = new DBObjectSet($oOrgSearch, array(), array()); $aTargetOrgs = $oOrgSet->GetColumnAsArray('id'); $bRet = in_array($iUserOrg, $aTargetOrgs); } else { // Target organizations are those linked to the Communication $oOrgSearch = DBSearch::FromOQL_AllData('SELECT lnkCommunicationToOrganization WHERE communication_id = :communication_id'); $oOrgSet = new DBObjectSet($oOrgSearch, array(), array('communication_id' => $this->GetKey())); $aTargetOrgs = $oOrgSet->GetColumnAsArray('org_id'); if (count($aTargetOrgs) == 0) { // Target organizations are "All organizations" when none are explicitly linked to the Communication $bRet = true; } elseif ($sMatchType == 'direct') { // Target organizations are those directly linked to the communication $bRet = in_array($iUserOrg, $aTargetOrgs); } else { // ($sMatchType == 'cascade') // Target organizations are those directly linked to the communication or one of their sub-organizations $oOrgHierarchical = DBSearch::FromOQL_AllData('SELECT Organization AS child JOIN Organization AS root ON child.parent_id BELOW root.id WHERE root.id IN (:target_org_list) AND child.id = :contact_org_id'); $oOrgHSet = new DBObjectSet($oOrgHierarchical, array(), array('contact_org_id' => $iUserOrg, 'target_org_list' => $aTargetOrgs)); $bRet = $oOrgHSet->Count() > 0; } } return $bRet; } public function DoCheckToWrite() { parent::DoCheckToWrite(); if ($this->Get('start_date') > $this->Get('end_date')) { $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:EndDateMustBeGreaterThanStartDate'); } if ($this->Get('org_match_type') == 'oql') { $sOql = $this->Get('org_oql'); if (empty($sOql)) { $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:OQLMustBeProvided'); } else { try { $oSearch = DBObjectSearch::FromOQL($sOql); $sOqlClass = $oSearch->GetClass(); if ($sOqlClass != 'Organization') { $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:OQLMustReturnOrganization'); } } catch(Exception $e) { $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:OQLNotValid', $e->getMessage()); } } } } public function DisplayBareRelations(WebPage $oPage, $bEditMode = false) { parent::DisplayBareRelations($oPage, $bEditMode); if(!$bEditMode && ($this->Get('org_match_type') == 'oql')) { $oPage->SetCurrentTab(Dict::S('Class:Communication/Tab:Preview')); $aParams = array( 'menu' => true, 'table_id' => 'communication_preview_orgs_'.$this->GetKey(), ); $oSearch = DBSearch::FromOQL_AllData($this->Get('org_oql')); $oBlock = new DisplayBlock($oSearch, 'list', true, $aParams); $oBlock->Display($oPage, 'communication_preview_'.$this->GetKey(), $aParams); } }
Dictionaries
Define corresponding dictionary entries
<entry id="Class:Communication/Attribute:org_match_type/Value:oql" _delta="define"><![CDATA[Organizations from OQL]]></entry> <entry id="Class:Communication/Attribute:org_oql" _delta="define"><![CDATA[Organizations OQL]]></entry> <entry id="Class:Communication/Attribute:org_oql+" _delta="define"><![CDATA[This OQL must return Organizations. It is used only if 'target organizations...' is based on OQL=oql]]></entry> <entry id="Class:Communication/Error:OQLMustBeProvided" _delta="force"><![CDATA[Organizations OQL must be provided]]></entry> <entry id="Class:Communication/Error:OQLMustReturnOrganization" _delta="force"><![CDATA[OQL must return Organization objects]]></entry> <entry id="Class:Communication/Error:OQLNotValid" _delta="force"><![CDATA[OQL is not valid: %1$s]]></entry>