foreach ($aClassLabels as $sCurrentClass => $sLabel) {
    $sDescription = MetaModel::GetClassDescription($sCurrentClass);
    $sSelected = $sCurrentClass == $sBaseClass ? " SELECTED" : "";
    $oP->add("<option value=\"{$sCurrentClass}\" title=\"{$sDescription}\"{$sSelected}>{$sLabel}</option>");
}
$oP->add("</select>\n");
$oP->add($oAppContext->GetForForm());
$oP->add("</form>\n");
try {
    if ($sOperation == 'search_form') {
        $sOQL = "SELECT {$sClass} {$sOQLClause}";
        $oFilter = DBObjectSearch::FromOQL($sOQL);
    } else {
        // Second part: advanced search form:
        if (!empty($sFilter)) {
            $oFilter = DBSearch::unserialize($sFilter);
        } else {
            if (!empty($sClass)) {
                $oFilter = new DBObjectSearch($sClass);
            }
        }
    }
} catch (CoreException $e) {
    $oFilter = new DBObjectSearch($sClass);
    $oP->P("<b>" . Dict::Format('UI:UniversalSearch:Error', $e->getHtmlDesc()) . "</b>");
}
if ($oFilter != null) {
    $oSet = new CMDBObjectSet($oFilter);
    $oBlock = new DisplayBlock($oFilter, 'search', false);
    $aExtraParams = $oAppContext->GetAsHash();
    $aExtraParams['open'] = true;
 /**
  * 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);
 }
     $oPage->add('</textarea>');
     $oPage->add("</div>");
     $oPage->add("</div>");
     break;
 case 'history':
     $oPage->SetContentType('text/html');
     $id = (int) utils::ReadParam('id', 0);
     $iStart = (int) utils::ReadParam('start', 0);
     $iCount = (int) utils::ReadParam('count', MetaModel::GetConfig()->Get('max_history_length', '50'));
     $oObj = MetaModel::GetObject($sClass, $id);
     $oObj->DisplayBareHistory($oPage, false, $iCount, $iStart);
     $oPage->add_ready_script("\$('#history table.listResults').tableHover(); \$('#history table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );");
     break;
 case 'history_from_filter':
     $oPage->SetContentType('text/html');
     $oHistoryFilter = DBSearch::unserialize($sFilter);
     $iStart = (int) utils::ReadParam('start', 0);
     $iCount = (int) utils::ReadParam('count', MetaModel::GetConfig()->Get('max_history_length', '50'));
     $oBlock = new HistoryBlock($oHistoryFilter, 'table', false);
     $oBlock->SetLimit($iCount, $iStart);
     $oBlock->Display($oPage, 'history');
     $oPage->add_ready_script("\$('#history table.listResults').tableHover(); \$('#history table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );");
     break;
 case 'full_text_search':
     $aFullTextNeedles = utils::ReadParam('needles', array(), false, 'raw_data');
     $sFullText = trim(implode(' ', $aFullTextNeedles));
     $sClassName = utils::ReadParam('class', '');
     $iCount = utils::ReadParam('count', 0);
     $iCurrentPos = utils::ReadParam('position', 0);
     $iTune = utils::ReadParam('tune', 0);
     if (empty($sFullText)) {