/**
  * Constructs a DisplayBlock object from an XML template
  * @param $sTemplate string The XML template
  * @return DisplayBlock The DisplayBlock object, or null if the template is invalid
  */
 public static function FromTemplate($sTemplate)
 {
     $iStartPos = stripos($sTemplate, '<' . self::TAG_BLOCK . ' ', 0);
     $iEndPos = stripos($sTemplate, '</' . self::TAG_BLOCK . '>', $iStartPos);
     $iEndTag = stripos($sTemplate, '>', $iStartPos);
     $aParams = array();
     if ($iStartPos === false || $iEndPos === false) {
         return null;
     }
     // invalid template
     $sITopBlock = substr($sTemplate, $iStartPos, $iEndPos - $iStartPos + strlen('</' . self::TAG_BLOCK . '>'));
     $sITopData = substr($sTemplate, 1 + $iEndTag, $iEndPos - $iEndTag - 1);
     $sITopTag = substr($sTemplate, $iStartPos + strlen('<' . self::TAG_BLOCK), $iEndTag - $iStartPos - strlen('<' . self::TAG_BLOCK));
     $aMatches = array();
     $sBlockClass = "DisplayBlock";
     $bAsynchronous = false;
     $sBlockType = 'list';
     $sEncoding = 'text/serialize';
     if (preg_match('/ type="(.*)"/U', $sITopTag, $aMatches)) {
         $sBlockType = strtolower($aMatches[1]);
     }
     if (preg_match('/ asynchronous="(.*)"/U', $sITopTag, $aMatches)) {
         $bAsynchronous = strtolower($aMatches[1]) == 'true';
     }
     if (preg_match('/ blockclass="(.*)"/U', $sITopTag, $aMatches)) {
         $sBlockClass = $aMatches[1];
     }
     if (preg_match('/ objectclass="(.*)"/U', $sITopTag, $aMatches)) {
         $sObjectClass = $aMatches[1];
     }
     if (preg_match('/ encoding="(.*)"/U', $sITopTag, $aMatches)) {
         $sEncoding = strtolower($aMatches[1]);
     }
     if (preg_match('/ link_attr="(.*)"/U', $sITopTag, $aMatches)) {
         // The list to display is a list of links to the specified object
         $aParams['link_attr'] = $aMatches[1];
         // Name of the Ext. Key that makes this linkage
     }
     if (preg_match('/ target_attr="(.*)"/U', $sITopTag, $aMatches)) {
         // The list to display is a list of links to the specified object
         $aParams['target_attr'] = $aMatches[1];
         // Name of the Ext. Key that make this linkage
     }
     if (preg_match('/ object_id="(.*)"/U', $sITopTag, $aMatches)) {
         // The list to display is a list of links to the specified object
         $aParams['object_id'] = $aMatches[1];
         // Id of the object to be linked to
     }
     // Parameters contains a list of extra parameters for the block
     // the syntax is param_name1:value1;param_name2:value2;...
     if (preg_match('/ parameters="(.*)"/U', $sITopTag, $aMatches)) {
         $sParameters = $aMatches[1];
         $aPairs = explode(';', $sParameters);
         foreach ($aPairs as $sPair) {
             if (preg_match('/(.*)\\:(.*)/', $sPair, $aMatches)) {
                 $aParams[trim($aMatches[1])] = trim($aMatches[2]);
             }
         }
     }
     if (!empty($aParams['link_attr'])) {
         // Check that all mandatory parameters are present:
         if (empty($aParams['object_id'])) {
             // if 'links' mode is requested the d of the object to link to must be specified
             throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_object_id'));
         }
         if (empty($aParams['target_attr'])) {
             // if 'links' mode is requested the id of the object to link to must be specified
             throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_target_attr'));
         }
     }
     switch ($sEncoding) {
         case 'text/serialize':
             $oFilter = DBSearch::unserialize($sITopData);
             break;
         case 'text/oql':
             $oFilter = DBSearch::FromOQL($sITopData);
             break;
     }
     return new $sBlockClass($oFilter, $sBlockType, $bAsynchronous, $aParams);
 }
 protected function DoExecute()
 {
     CMDBSource::Query('START TRANSACTION');
     //CMDBSource::Query('ROLLBACK'); automatique !
     ////////////////////////////////////////////////////////////////////////////////
     // Set the stage
     //
     $oProvider = new Organization();
     $oProvider->Set('name', 'Test-Provider1');
     $oProvider->DBInsert();
     $iProvider = $oProvider->GetKey();
     $oDM1 = new DeliveryModel();
     $oDM1->Set('name', 'Test-DM-1');
     $oDM1->Set('org_id', $iProvider);
     $oDM1->DBInsert();
     $iDM1 = $oDM1->GetKey();
     $oDM2 = new DeliveryModel();
     $oDM2->Set('name', 'Test-DM-2');
     $oDM2->Set('org_id', $iProvider);
     $oDM2->DBInsert();
     $iDM2 = $oDM2->GetKey();
     ////////////////////////////////////////////////////////////////////////////////
     // Scenarii
     //
     $aScenarii = array(array('description' => 'Add the first customer', 'organizations' => array(array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Remove the customer by loading an empty set', 'organizations' => array(), 'expected-res' => array(), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Create two customers at once', 'organizations' => array(array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1'), array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1", "Test-Customer-2, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Move Customer-1 to the second Delivery Model', 'organizations' => array(array('id' => "SELECT Organization WHERE name='Test-Customer-1'", 'deliverymodel_id' => $iDM2, 'name' => 'Test-Customer-1'), array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-2, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Move Customer-1 back to the first Delivery Model and reset Customer-2 (no Delivery Model)', 'organizations' => array(array('id' => "SELECT Organization WHERE name='Test-Customer-1'", 'deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1'), array('id' => "SELECT Organization WHERE name='Test-Customer-2'", 'deliverymodel_id' => 0, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0));
     foreach ($aScenarii as $aScenario) {
         echo "<h4>" . $aScenario['description'] . "</h4>\n";
         $oChange = MetaModel::NewObject("CMDBChange");
         $oChange->Set("date", time());
         $oChange->Set("userinfo", CMDBChange::GetCurrentUserName());
         $oChange->Set("origin", 'custom-extension');
         $oChange->DBInsert();
         CMDBObject::SetCurrentChange($oChange);
         $iChange = $oChange->GetKey();
         // Prepare set
         $oLinkset = DBObjectSet::FromScratch('Organization');
         foreach ($aScenario['organizations'] as $aOrgData) {
             if (array_key_exists('id', $aOrgData)) {
                 $sOQL = $aOrgData['id'];
                 $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
                 $oOrg = $oSet->Fetch();
                 if (!is_object($oOrg)) {
                     throw new Exception('Failed to find the Organization: ' . $sOQL);
                 }
             } else {
                 $oOrg = MetaModel::NewObject('Organization');
             }
             foreach ($aOrgData as $sAttCode => $value) {
                 if ($sAttCode == 'id') {
                     continue;
                 }
                 $oOrg->Set($sAttCode, $value);
             }
             $oLinkset->AddObject($oOrg);
         }
         // Write
         $oDM = MetaModel::GetObject('DeliveryModel', $iDM1);
         $oDM->Set('customers_list', $oLinkset);
         $oDM->DBWrite();
         // Check Results
         $bFoundIssue = false;
         $oDM = MetaModel::GetObject('DeliveryModel', $iDM1);
         $oLinkset = $oDM->Get('customers_list');
         $aRes = $this->StandardizedDump($oLinkset, 'zzz');
         $sRes = var_export($aRes, true);
         echo "Found: <pre>" . $sRes . "</pre>\n";
         $sExpectedRes = var_export($aScenario['expected-res'], true);
         if ($sRes != $sExpectedRes) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: <pre>" . $sExpectedRes . "</pre>\n";
         }
         // Check History
         $aQueryParams = array('change' => $iChange, 'objclass' => get_class($oDM), 'objkey' => $oDM->GetKey());
         $oAdded = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksAddRemove WHERE objclass = :objclass AND objkey = :objkey AND change = :change AND type = 'added'"), array(), $aQueryParams);
         echo "added: " . $oAdded->Count() . "<br/>\n";
         if ($aScenario['history_added'] != $oAdded->Count()) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_added'] . "<br/>\n";
         }
         $oRemoved = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksAddRemove WHERE objclass = :objclass AND objkey = :objkey AND change = :change AND type = 'removed'"), array(), $aQueryParams);
         echo "removed: " . $oRemoved->Count() . "<br/>\n";
         if ($aScenario['history_removed'] != $oRemoved->Count()) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_removed'] . "<br/>\n";
         }
         $oModified = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksTune WHERE objclass = :objclass AND objkey = :objkey AND change = :change"), array(), $aQueryParams);
         echo "modified: " . $oModified->Count() . "<br/>\n";
         if ($aScenario['history_modified'] != $oModified->Count()) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_modified'] . "<br/>\n";
         }
         if ($bFoundIssue) {
             throw new Exception('Stopping on failed scenario');
         }
     }
 }
 function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
 {
     parent::DisplayBareRelations($oPage, $bEditMode);
     $sTicketListAttCode = 'tickets_list';
     if (MetaModel::IsValidAttCode(get_class($this), $sTicketListAttCode)) {
         // Display one list per leaf class (the only way to display the status as of now)
         $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sTicketListAttCode);
         $sLnkClass = $oAttDef->GetLinkedClass();
         $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
         $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
         $iTotal = 0;
         $aSearches = array();
         foreach (MetaModel::EnumChildClasses('Ticket') as $sSubClass) {
             if (!MetaModel::HasChildrenClasses($sSubClass)) {
                 $sStateAttCode = MetaModel::GetStateAttributeCode($sSubClass);
                 if ($sStateAttCode != '') {
                     $oSearch = DBSearch::FromOQL("SELECT {$sSubClass} AS t JOIN {$sLnkClass} AS lnk ON lnk.{$sExtKeyToRemote} = t.id WHERE {$sExtKeyToMe} = :myself AND {$sStateAttCode} NOT IN ('rejected', 'resolved', 'closed')", array('myself' => $this->GetKey()));
                     $aSearches[$sSubClass] = $oSearch;
                     $oSet = new DBObjectSet($oSearch);
                     $iTotal += $oSet->Count();
                 }
             }
         }
         $sCount = $iTotal > 0 ? ' (' . $iTotal . ')' : '';
         $oPage->SetCurrentTab(Dict::S('Class:FunctionalCI/Tab:OpenedTickets') . $sCount);
         foreach ($aSearches as $sSubClass => $oSearch) {
             $sBlockId = __CLASS__ . '_opened_' . $sSubClass;
             $oPage->add('<fieldset>');
             $oPage->add('<legend>' . MetaModel::GetName($sSubClass) . '</legend>');
             $oBlock = new DisplayBlock($oSearch, 'list', false);
             $oBlock->Display($oPage, $sBlockId, array('menu' => false));
             $oPage->add('</fieldset>');
         }
     }
 }
     //$sOrg = utils::ReadParam('org_id', '');
     $sName = utils::ReadParam('q', '');
     $iMaxCount = utils::ReadParam('max', 30);
     $iCount = 0;
     $oFilter = new DBObjectSearch($sClass);
     $oFilter->AddCondition($sAttCode, $sName, 'Begins with');
     //$oFilter->AddCondition('org_id', $sOrg, '=');
     $oSet = new CMDBObjectSet($oFilter, array($sAttCode => true));
     while ($iCount < $iMaxCount && ($oObj = $oSet->fetch())) {
         $oPage->add($oObj->GetAsHTML($sAttCode) . "|" . $oObj->GetKey() . "\n");
         $iCount++;
     }
     break;
 case 'combo_options':
     $oPage->SetContentType('text/html');
     $oFilter = DBSearch::FromOQL($sFilter);
     $oSet = new CMDBObjectSet($oFilter);
     while ($oObj = $oSet->fetch()) {
         $oPage->add('<option title="Here is more information..." value="' . $oObj->GetKey() . '">' . $oObj->GetName() . '</option>');
     }
     break;
 case 'display_document':
     $id = utils::ReadParam('id', '');
     $sField = utils::ReadParam('field', '');
     if (!empty($sClass) && !empty($id) && !empty($sField)) {
         DownloadDocument($oPage, $sClass, $id, $sField, 'inline');
     }
     break;
 case 'download_document':
     $id = utils::ReadParam('id', '');
     $sField = utils::ReadParam('field', '');