public function GetHeader()
 {
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'running';
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     $aData = array();
     foreach ($this->aStatusInfo['fields'] as $sExtendedAttCode) {
         if (preg_match('/^([^\\.]+)\\.(.+)$/', $sExtendedAttCode, $aMatches)) {
             $sAlias = $aMatches[1];
             $sAttCode = $aMatches[2];
         } else {
             $sAlias = reset($aSelectedClasses);
             $sAttCode = $sExtendedAttCode;
         }
         if (!array_key_exists($sAlias, $aSelectedClasses)) {
             throw new Exception("Invalid alias '{$sAlias}' for the column '{$sExtendedAttCode}'. Availables aliases: '" . implode("', '", array_keys($aSelectedClasses)) . "'");
         }
         $sClass = $aSelectedClasses[$sAlias];
         switch ($sAttCode) {
             case 'id':
                 if (count($aSelectedClasses) > 1) {
                     $aData[] = $sAlias . '.id';
                     //@@@
                 } else {
                     $aData[] = 'id';
                     //@@@
                 }
                 break;
             default:
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 $sColLabel = $this->aStatusInfo['localize'] ? MetaModel::GetLabel($sClass, $sAttCode) : $sAttCode;
                 $oFinalAttDef = $oAttDef->GetFinalAttDef();
                 if (get_class($oFinalAttDef) == 'AttributeDateTime') {
                     if (count($aSelectedClasses) > 1) {
                         $aData[] = $sAlias . '.' . $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Date') . ')';
                         $aData[] = $sAlias . '.' . $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Time') . ')';
                     } else {
                         $aData[] = $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Date') . ')';
                         $aData[] = $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Time') . ')';
                     }
                 } else {
                     if (count($aSelectedClasses) > 1) {
                         $aData[] = $sAlias . '.' . $sColLabel;
                     } else {
                         $aData[] = $sColLabel;
                     }
                 }
         }
     }
     $sData = "<table border=\"1\">\n";
     $sData .= "<tr>\n";
     foreach ($aData as $sLabel) {
         $sData .= "<td>" . $sLabel . "</td>\n";
     }
     $sData .= "</tr>\n";
     return $sData;
 }
 public function GetHeader()
 {
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $sData = "<" . "?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Set>\n";
     return $sData;
 }
 public function GetHeader()
 {
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'retrieving';
     $this->aStatusInfo['tmp_file'] = $this->MakeTmpFile('data');
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     foreach ($aSelectedClasses as $sAlias => $sClassName) {
         if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) {
             $aAuthorizedClasses[$sAlias] = $sClassName;
         }
     }
     $aAliases = array_keys($aAuthorizedClasses);
     $aTableHeaders = array();
     foreach ($this->aStatusInfo['fields'] as $sExtendedAttCode) {
         if (preg_match('/^([^\\.]+)\\.(.+)$/', $sExtendedAttCode, $aMatches)) {
             $sAlias = $aMatches[1];
             $sAttCode = $aMatches[2];
         } else {
             $sAlias = reset($aAliases);
             $sAttCode = $sExtendedAttCode;
         }
         if (!in_array($sAlias, $aAliases)) {
             throw new Exception("Invalid alias '{$sAlias}' for the column '{$sExtendedAttCode}'. Availables aliases: '" . implode("', '", $aAliases) . "'");
         }
         $sClass = $aSelectedClasses[$sAlias];
         $sFullAlias = '';
         if (count($aSelectedClasses) > 1) {
             $sFullAlias = $sAlias . '.';
         }
         switch ($sAttCode) {
             case 'id':
                 $aTableHeaders[] = array('label' => $sFullAlias . 'id', 'type' => '0');
                 break;
             default:
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 $sType = 'string';
                 if ($oAttDef instanceof AttributeDateTime) {
                     $sType = 'datetime';
                 }
                 $sLabel = $sAttCode;
                 if ($this->aStatusInfo['localize']) {
                     $sLabel = $oAttDef->GetLabel();
                 }
                 $aTableHeaders[] = array('label' => $sFullAlias . $sLabel, 'type' => $sType);
         }
     }
     $sRow = json_encode($aTableHeaders);
     $hFile = @fopen($this->aStatusInfo['tmp_file'], 'ab');
     if ($hFile === false) {
         throw new Exception('ExcelBulkExport: Failed to open temporary data file: "' . $this->aStatusInfo['tmp_file'] . '" for writing.');
     }
     fwrite($hFile, $sRow . "\n");
     fclose($hFile);
     return '';
 }
 public function GetHeader()
 {
     $sData = '';
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'running';
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     foreach ($aSelectedClasses as $sAlias => $sClassName) {
         if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) {
             $aAuthorizedClasses[$sAlias] = $sClassName;
         }
     }
     $aAliases = array_keys($aAuthorizedClasses);
     $aData = array();
     foreach ($this->aStatusInfo['fields'] as $sExtendedAttCode) {
         if (preg_match('/^([^\\.]+)\\.(.+)$/', $sExtendedAttCode, $aMatches)) {
             $sAlias = $aMatches[1];
             $sAttCode = $aMatches[2];
         } else {
             $sAlias = reset($aAliases);
             $sAttCode = $sExtendedAttCode;
         }
         if (!in_array($sAlias, $aAliases)) {
             throw new Exception("Invalid alias '{$sAlias}' for the column '{$sExtendedAttCode}'. Availables aliases: '" . implode("', '", $aAliases) . "'");
         }
         $sClass = $aSelectedClasses[$sAlias];
         switch ($sAttCode) {
             case 'id':
                 if (count($aSelectedClasses) > 1) {
                     $aData[] = $sAlias . '.id';
                     //@@@
                 } else {
                     $aData[] = 'id';
                     //@@@
                 }
                 break;
             default:
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 if (count($aSelectedClasses) > 1) {
                     $aData[] = $sAlias . '.' . $oAttDef->GetLabel();
                 } else {
                     $aData[] = $oAttDef->GetLabel();
                 }
         }
     }
     $sData .= "<table class=\"listResults\">\n";
     $sData .= "<thead>\n";
     $sData .= "<tr>\n";
     foreach ($aData as $sLabel) {
         $sData .= "<th>" . $sLabel . "</th>\n";
     }
     $sData .= "</tr>\n";
     $sData .= "</thead>\n";
     $sData .= "<tbody>\n";
     return $sData;
 }
 public function GetHeader()
 {
     // Check permissions
     foreach ($this->oSearch->GetSelectedClasses() as $sAlias => $sClass) {
         if (UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_READ) != UR_ALLOWED_YES) {
             throw new Exception("You do not have enough permissions to bulk read data of class '{$sClass}' (alias: {$sAlias})");
         }
     }
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $sData = "<" . "?xml version=\"1.0\" encoding=\"UTF-8\"?" . ">\n<Set>\n";
     return $sData;
 }
 public function GetHeader()
 {
     $sData = '';
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'running';
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $sData .= "<table class=\"listResults\">\n";
     $sData .= "<thead>\n";
     $sData .= "<tr>\n";
     foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
         $sData .= "<th>" . $aFieldSpec['sColLabel'] . "</th>\n";
     }
     $sData .= "</tr>\n";
     $sData .= "</thead>\n";
     $sData .= "<tbody>\n";
     return $sData;
 }
Example #7
0
/**
 * Create a User Request ticket from the basic information retrieved from an email
 * @param string $sSenderEmail eMail address of the sender (From), used to lookup a contact in iTop
 * @param string $sSubject eMail's subject, will be turned into the title of the ticket
 * @param string $sBody Body of the email, will be fitted into the ticket's description
 * @return UserRequest The created ticket, or  null if the creation failed for some reason...
 */
function CreateTicket($sSenderEmail, $sSubject, $sBody)
{
    $oTicket = null;
    try {
        $oContactSearch = new DBObjectSearch('Contact');
        // Can be either a Person or a Team, but must be a valid Contact
        $oContactSearch->AddCondition('email', $sSenderEmail, '=');
        $oSet = new DBObjectSet($oContactSearch);
        if ($oSet->Count() == 1) {
            $oContact = $oSet->Fetch();
            $oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id'));
            $oTicket = new UserRequest();
            $oTicket->Set('title', $sSubject);
            $oTicket->Set('description', $sBody);
            $oTicket->Set('org_id', $oOrganization->GetKey());
            $oTicket->Set('caller_id', $oContact->GetKey());
            $oTicket->Set('impact', DEFAULT_IMPACT);
            $oTicket->Set('urgency', DEFAULT_URGENCY);
            $oTicket->Set('product', DEFAULT_PRODUCT);
            $oTicket->Set('service_id', DEFAULT_SERVICE_ID);
            //  Can be replaced by a search for a valid service for this 'org_id'
            $oTicket->Set('servicesubcategory_id', DEFAULT_SUBSERVICE_ID);
            // Same as above...
            $oTicket->Set('workgroup_id', DEFAULT_WORKGROUP_ID);
            // Same as above...
            // Record the change information about the object
            $oMyChange = MetaModel::NewObject("CMDBChange");
            $oMyChange->Set("date", time());
            $sUserString = $oContact->GetName() . ', submitted by email';
            $oMyChange->Set("userinfo", $sUserString);
            $iChangeId = $oMyChange->DBInsert();
            $oTicket->DBInsertTracked($oMyChange);
        } else {
            echo "No contact found in iTop having the email: {$sSenderEmail}, email message ignored.\n";
        }
    } catch (Exception $e) {
        echo "Error: exception " . $e->getMessage();
        $oTicket = null;
    }
    return $oTicket;
}
Example #8
0
/**
 * Helper to protect the portal against malicious usages
 * Throws an exception if the current user is not allowed to view the object details  
 */
function ValidateObject($oObject)
{
    if (IsPowerUser()) {
        $sValidationDefine = 'PORTAL_' . strtoupper(get_class($oObject)) . '_DISPLAY_POWERUSER_QUERY';
    } else {
        $sValidationDefine = 'PORTAL_' . strtoupper(get_class($oObject)) . '_DISPLAY_QUERY';
    }
    if (defined($sValidationDefine)) {
        $sValidationOql = constant($sValidationDefine);
        $oSearch = DBObjectSearch::FromOQL($sValidationOql);
        $oSearch->AddCondition('id', $oObject->GetKey());
        if ($iUser = UserRights::GetContactId()) {
            $oContact = MetaModel::GetObject('Contact', $iUser);
            $aArgs = $oContact->ToArgs('contact');
        } else {
            $aArgs = array();
        }
        $oSet = new DBObjectSet($oSearch, array(), $aArgs);
        if ($oSet->Count() == 0) {
            throw new SecurityException('You are not allowed to access the object ' . get_class($oObject) . '::' . $oObject->GetKey());
        }
    }
}
 public function GetDashboard()
 {
     $sDashboardDefinition = @file_get_contents($this->sDashboardFile);
     if ($sDashboardDefinition !== false) {
         $bCustomized = false;
         // Search for an eventual user defined dashboard, overloading the existing one
         $oUDSearch = new DBObjectSearch('UserDashboard');
         $oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
         $oUDSearch->AddCondition('menu_code', $this->sMenuId, '=');
         $oUDSet = new DBObjectSet($oUDSearch);
         if ($oUDSet->Count() > 0) {
             // Assuming there is at most one couple {user, menu}!
             $oUserDashboard = $oUDSet->Fetch();
             $sDashboardDefinition = $oUserDashboard->Get('contents');
             $bCustomized = true;
         }
         $oDashboard = new RuntimeDashboard($this->sMenuId);
         $oDashboard->FromXml($sDashboardDefinition);
         $oDashboard->SetCustomFlag($bCustomized);
     } else {
         $oDashboard = null;
     }
     return $oDashboard;
 }
    public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
    {
        $sHtml = '';
        // Add the extra params into the filter if they make sense for such a filter
        $bDoSearch = utils::ReadParam('dosearch', false);
        if ($this->m_oSet == null) {
            $aQueryParams = array();
            if (isset($aExtraParams['query_params'])) {
                $aQueryParams = $aExtraParams['query_params'];
            }
            if ($this->m_sStyle != 'links') {
                $oAppContext = new ApplicationContext();
                $sClass = $this->m_oFilter->GetClass();
                $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($sClass));
                $aCallSpec = array($sClass, 'MapContextParam');
                if (is_callable($aCallSpec)) {
                    foreach ($oAppContext->GetNames() as $sContextParam) {
                        $sParamCode = call_user_func($aCallSpec, $sContextParam);
                        //Map context parameter to the value/filter code depending on the class
                        if (!is_null($sParamCode)) {
                            $sParamValue = $oAppContext->GetCurrentValue($sContextParam, null);
                            if (!is_null($sParamValue)) {
                                $aExtraParams[$sParamCode] = $sParamValue;
                            }
                        }
                    }
                }
                foreach ($aFilterCodes as $sFilterCode) {
                    $externalFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
                    $condition = null;
                    if (isset($aExtraParams[$sFilterCode])) {
                        $condition = $aExtraParams[$sFilterCode];
                    }
                    if ($bDoSearch && $externalFilterValue != "") {
                        // Search takes precedence over context params...
                        unset($aExtraParams[$sFilterCode]);
                        if (!is_array($externalFilterValue)) {
                            $condition = trim($externalFilterValue);
                        } else {
                            if (count($externalFilterValue) == 1) {
                                $condition = trim($externalFilterValue[0]);
                            } else {
                                $condition = $externalFilterValue;
                            }
                        }
                    }
                    if (!is_null($condition)) {
                        $sOpCode = null;
                        // default operator
                        if (is_array($condition)) {
                            // Multiple values, add them as AND X IN (v1, v2, v3...)
                            $sOpCode = 'IN';
                        }
                        $this->AddCondition($sFilterCode, $condition, $sOpCode);
                    }
                }
                if ($bDoSearch) {
                    // Keep the table_id identifying this table if we're performing a search
                    $sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
                    if ($sTableId != null) {
                        $aExtraParams['table_id'] = $sTableId;
                    }
                }
            }
            $aOrderBy = array();
            if (isset($aExtraParams['order_by'])) {
                // Convert the string describing the order_by parameter into an array
                // The syntax is +attCode1,-attCode2
                // attCode1 => ascending, attCode2 => descending
                $aTemp = explode(',', $aExtraParams['order_by']);
                foreach ($aTemp as $sTemp) {
                    $aMatches = array();
                    if (preg_match('/^([+-])?(.+)$/', $sTemp, $aMatches)) {
                        $bAscending = true;
                        if ($aMatches[1] == '-') {
                            $bAscending = false;
                        }
                        $aOrderBy[$aMatches[2]] = $bAscending;
                    }
                }
            }
            $this->m_oSet = new CMDBObjectSet($this->m_oFilter, $aOrderBy, $aQueryParams);
        }
        switch ($this->m_sStyle) {
            case 'count':
                if (isset($aExtraParams['group_by'])) {
                    if (isset($aExtraParams['group_by_label'])) {
                        $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                        $sGroupByLabel = $aExtraParams['group_by_label'];
                    } else {
                        // Backward compatibility: group_by is simply a field id
                        $sAlias = $this->m_oFilter->GetClassAlias();
                        $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                        $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                    }
                    $aGroupBy = array();
                    $aGroupBy['grouped_by_1'] = $oGroupByExp;
                    $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                    $aRes = CMDBSource::QueryToArray($sSql);
                    $aGroupBy = array();
                    $aLabels = array();
                    $aValues = array();
                    $iTotalCount = 0;
                    foreach ($aRes as $iRow => $aRow) {
                        $sValue = $aRow['grouped_by_1'];
                        $aValues[$iRow] = $sValue;
                        $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                        $aLabels[$iRow] = $sHtmlValue;
                        $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                        $iTotalCount += $aRow['_itop_count_'];
                    }
                    $aData = array();
                    $oAppContext = new ApplicationContext();
                    $sParams = $oAppContext->GetForLink();
                    foreach ($aGroupBy as $iRow => $iCount) {
                        // Build the search for this subset
                        $oSubsetSearch = $this->m_oFilter->DeepClone();
                        $oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
                        $oSubsetSearch->AddConditionExpression($oCondition);
                        $sFilter = urlencode($oSubsetSearch->serialize());
                        $aData[] = array('group' => $aLabels[$iRow], 'value' => "<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=search&dosearch=1&{$sParams}&filter={$sFilter}\">{$iCount}</a>");
                        // TO DO: add the context information
                    }
                    $aAttribs = array('group' => array('label' => $sGroupByLabel, 'description' => ''), 'value' => array('label' => Dict::S('UI:GroupBy:Count'), 'description' => Dict::S('UI:GroupBy:Count+')));
                    $sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
                    $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount));
                    $sHtml .= $oPage->GetTable($aAttribs, $aData);
                } else {
                    // Simply count the number of elements in the set
                    $iCount = $this->m_oSet->Count();
                    $sFormat = 'UI:CountOfObjects';
                    if (isset($aExtraParams['format'])) {
                        $sFormat = $aExtraParams['format'];
                    }
                    $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iCount));
                }
                break;
            case 'join':
                $aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']) : array();
                if (!isset($aExtraParams['group_by'])) {
                    $sHtml .= $oPage->GetP(Dict::S('UI:Error:MandatoryTemplateParameter_group_by'));
                } else {
                    $aGroupByFields = array();
                    $aGroupBy = explode(',', $aExtraParams['group_by']);
                    foreach ($aGroupBy as $sGroupBy) {
                        $aMatches = array();
                        if (preg_match('/^(.+)\\.(.+)$/', $sGroupBy, $aMatches) > 0) {
                            $aGroupByFields[] = array('alias' => $aMatches[1], 'att_code' => $aMatches[2]);
                        }
                    }
                    if (count($aGroupByFields) == 0) {
                        $sHtml .= $oPage->GetP(Dict::Format('UI:Error:InvalidGroupByFields', $aExtraParams['group_by']));
                    } else {
                        $aResults = array();
                        $aCriteria = array();
                        while ($aObjects = $this->m_oSet->FetchAssoc()) {
                            $aKeys = array();
                            foreach ($aGroupByFields as $aField) {
                                $sAlias = $aField['alias'];
                                if (is_null($aObjects[$sAlias])) {
                                    $aKeys[$sAlias . '.' . $aField['att_code']] = '';
                                } else {
                                    $aKeys[$sAlias . '.' . $aField['att_code']] = $aObjects[$sAlias]->Get($aField['att_code']);
                                }
                            }
                            $sCategory = implode($aKeys, ' ');
                            $aResults[$sCategory][] = $aObjects;
                            $aCriteria[$sCategory] = $aKeys;
                        }
                        $sHtml .= "<table>\n";
                        // Construct a new (parametric) query that will return the content of this block
                        $oBlockFilter = $this->m_oFilter->DeepClone();
                        $aExpressions = array();
                        $index = 0;
                        foreach ($aGroupByFields as $aField) {
                            $aExpressions[] = '`' . $aField['alias'] . '`.`' . $aField['att_code'] . '` = :param' . $index++;
                        }
                        $sExpression = implode(' AND ', $aExpressions);
                        $oExpression = Expression::FromOQL($sExpression);
                        $oBlockFilter->AddConditionExpression($oExpression);
                        $aExtraParams['menu'] = false;
                        foreach ($aResults as $sCategory => $aObjects) {
                            $sHtml .= "<tr><td><h1>{$sCategory}</h1></td></tr>\n";
                            if (count($aDisplayAliases) == 1) {
                                $aSimpleArray = array();
                                foreach ($aObjects as $aRow) {
                                    $oObj = $aRow[$aDisplayAliases[0]];
                                    if (!is_null($oObj)) {
                                        $aSimpleArray[] = $oObj;
                                    }
                                }
                                $oSet = CMDBObjectSet::FromArray($this->m_oFilter->GetClass(), $aSimpleArray);
                                $sHtml .= "<tr><td>" . cmdbAbstractObject::GetDisplaySet($oPage, $oSet, $aExtraParams) . "</td></tr>\n";
                            } else {
                                $index = 0;
                                $aArgs = array();
                                foreach ($aGroupByFields as $aField) {
                                    $aArgs['param' . $index] = $aCriteria[$sCategory][$aField['alias'] . '.' . $aField['att_code']];
                                    $index++;
                                }
                                $oSet = new CMDBObjectSet($oBlockFilter, array(), $aArgs);
                                $sHtml .= "<tr><td>" . cmdbAbstractObject::GetDisplayExtendedSet($oPage, $oSet, $aExtraParams) . "</td></tr>\n";
                            }
                        }
                        $sHtml .= "</table>\n";
                    }
                }
                break;
            case 'list':
                $aClasses = $this->m_oSet->GetSelectedClasses();
                $aAuthorizedClasses = array();
                if (count($aClasses) > 1) {
                    // Check the classes that can be read (i.e authorized) by this user...
                    foreach ($aClasses as $sAlias => $sClassName) {
                        if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) {
                            $aAuthorizedClasses[$sAlias] = $sClassName;
                        }
                    }
                    if (count($aAuthorizedClasses) > 0) {
                        if ($this->m_oSet->Count() > 0) {
                            $sHtml .= cmdbAbstractObject::GetDisplayExtendedSet($oPage, $this->m_oSet, $aExtraParams);
                        } else {
                            // Empty set
                            $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay'));
                        }
                    } else {
                        // Not authorized
                        $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay'));
                    }
                } else {
                    // The list is made of only 1 class of objects, actions on the list are possible
                    if ($this->m_oSet->Count() > 0 && UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) {
                        $sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
                    } else {
                        $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay'));
                        $sClass = $this->m_oFilter->GetClass();
                        $bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true;
                        if ($bDisplayMenu) {
                            if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES) {
                                $sLinkTarget = '';
                                $oAppContext = new ApplicationContext();
                                $sParams = $oAppContext->GetForLink();
                                // 1:n links, populate the target object as a default value when creating a new linked object
                                if (isset($aExtraParams['target_attr'])) {
                                    $sLinkTarget = ' target="_blank" ';
                                    $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id'];
                                }
                                $sDefault = '';
                                if (!empty($aExtraParams['default'])) {
                                    foreach ($aExtraParams['default'] as $sKey => $sValue) {
                                        $sDefault .= "&default[{$sKey}]={$sValue}";
                                    }
                                }
                                $sHtml .= $oPage->GetP("<a{$sLinkTarget} href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=new&class={$sClass}&{$sParams}{$sDefault}\">" . Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass)) . "</a>\n");
                            }
                        }
                    }
                }
                break;
            case 'links':
                //$bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false;
                //$bSelectMode = isset($aExtraParams['select']) ? ($aExtraParams['select'] == 'true') : false;
                if ($this->m_oSet->Count() > 0 && UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) {
                    //$sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : '';
                    $sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
                } else {
                    $sClass = $this->m_oFilter->GetClass();
                    $oAttDef = MetaModel::GetAttributeDef($sClass, $this->m_aParams['target_attr']);
                    $sTargetClass = $oAttDef->GetTargetClass();
                    $sHtml .= $oPage->GetP(Dict::Format('UI:NoObject_Class_ToDisplay', MetaModel::GetName($sTargetClass)));
                    $bDisplayMenu = isset($this->m_aParams['menu']) ? $this->m_aParams['menu'] == true : true;
                    if ($bDisplayMenu) {
                        if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES) {
                            $oAppContext = new ApplicationContext();
                            $sParams = $oAppContext->GetForLink();
                            $sDefaults = '';
                            if (isset($this->m_aParams['default'])) {
                                foreach ($this->m_aParams['default'] as $sName => $sValue) {
                                    $sDefaults .= '&' . urlencode($sName) . '=' . urlencode($sValue);
                                }
                            }
                            $sHtml .= $oPage->GetP("<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=modify_links&class={$sClass}&sParams&link_attr=" . $aExtraParams['link_attr'] . "&id=" . $aExtraParams['object_id'] . "&target_class={$sTargetClass}&addObjects=true{$sDefaults}\">" . Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass)) . "</a>\n");
                        }
                    }
                }
                break;
            case 'details':
                while ($oObj = $this->m_oSet->Fetch()) {
                    $sHtml .= $oObj->GetDetails($oPage);
                    // Still used ???
                }
                break;
            case 'actions':
                $sClass = $this->m_oFilter->GetClass();
                $oAppContext = new ApplicationContext();
                $bContextFilter = isset($aExtraParams['context_filter']) ? isset($aExtraParams['context_filter']) != 0 : false;
                if ($bContextFilter) {
                    $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
                    foreach ($oAppContext->GetNames() as $sFilterCode) {
                        $sContextParamValue = $oAppContext->GetCurrentValue($sFilterCode, null);
                        if (!is_null($sContextParamValue) && !empty($sContextParamValue) && MetaModel::IsValidFilterCode($sClass, $sFilterCode)) {
                            $this->AddCondition($sFilterCode, $sContextParamValue);
                        }
                    }
                    $aQueryParams = array();
                    if (isset($aExtraParams['query_params'])) {
                        $aQueryParams = $aExtraParams['query_params'];
                    }
                    $this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
                }
                $iCount = $this->m_oSet->Count();
                $sHyperlink = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($this->m_oFilter->serialize());
                $sHtml .= '<p><a class="actions" href="' . $sHyperlink . '">';
                // Note: border set to 0 due to various browser interpretations (IE9 adding a 2px border)
                $sHtml .= MetaModel::GetClassIcon($sClass, true, 'float;left;margin-right:10px;border:0;');
                $sHtml .= MetaModel::GetName($sClass) . ': ' . $iCount . '</a></p>';
                $sParams = $oAppContext->GetForLink();
                $sHtml .= '<p>';
                if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) {
                    $sHtml .= "<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=new&class={$sClass}&{$sParams}\">" . Dict::Format('UI:ClickToCreateNew', MetaModel::GetName($sClass)) . "</a><br/>\n";
                }
                $sHtml .= "<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=search_form&do_search=0&class={$sClass}&{$sParams}\">" . Dict::Format('UI:SearchFor_Class', MetaModel::GetName($sClass)) . "</a>\n";
                $sHtml .= '</p>';
                break;
            case 'summary':
                $sClass = $this->m_oFilter->GetClass();
                $oAppContext = new ApplicationContext();
                $sTitle = isset($aExtraParams['title[block]']) ? $aExtraParams['title[block]'] : '';
                $sLabel = isset($aExtraParams['label[block]']) ? $aExtraParams['label[block]'] : '';
                $sStateAttrCode = isset($aExtraParams['status[block]']) ? $aExtraParams['status[block]'] : 'status';
                $sStatesList = isset($aExtraParams['status_codes[block]']) ? $aExtraParams['status_codes[block]'] : '';
                $bContextFilter = isset($aExtraParams['context_filter']) ? isset($aExtraParams['context_filter']) != 0 : false;
                if ($bContextFilter) {
                    $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
                    foreach ($oAppContext->GetNames() as $sFilterCode) {
                        $sContextParamValue = $oAppContext->GetCurrentValue($sFilterCode, null);
                        if (!is_null($sContextParamValue) && !empty($sContextParamValue) && MetaModel::IsValidFilterCode($sClass, $sFilterCode)) {
                            $this->AddCondition($sFilterCode, $sContextParamValue);
                        }
                    }
                    $aQueryParams = array();
                    if (isset($aExtraParams['query_params'])) {
                        $aQueryParams = $aExtraParams['query_params'];
                    }
                    $this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
                }
                // Summary details
                $aCounts = array();
                $aStateLabels = array();
                if (!empty($sStateAttrCode) && !empty($sStatesList)) {
                    $aStates = explode(',', $sStatesList);
                    $oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
                    foreach ($aStates as $sStateValue) {
                        $oFilter = $this->m_oFilter->DeepClone();
                        $oFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
                        $oSet = new DBObjectSet($oFilter);
                        $aCounts[$sStateValue] = $oSet->Count();
                        $aStateLabels[$sStateValue] = htmlentities($oAttDef->GetValueLabel($sStateValue), ENT_QUOTES, 'UTF-8');
                        if ($aCounts[$sStateValue] == 0) {
                            $aCounts[$sStateValue] = '-';
                        } else {
                            $sHyperlink = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($oFilter->serialize());
                            $aCounts[$sStateValue] = "<a href=\"{$sHyperlink}\">{$aCounts[$sStateValue]}</a>";
                        }
                    }
                }
                $sHtml .= '<div class="summary-details"><table><tr><th>' . implode('</th><th>', $aStateLabels) . '</th></tr>';
                $sHtml .= '<tr><td>' . implode('</td><td>', $aCounts) . '</td></tr></table></div>';
                // Title & summary
                $iCount = $this->m_oSet->Count();
                $sHyperlink = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($this->m_oFilter->serialize());
                $sHtml .= '<h1>' . Dict::S(str_replace('_', ':', $sTitle)) . '</h1>';
                $sHtml .= '<a class="summary" href="' . $sHyperlink . '">' . Dict::Format(str_replace('_', ':', $sLabel), $iCount) . '</a>';
                $sHtml .= '<div style="clear:both;"></div>';
                break;
            case 'csv':
                $bAdvancedMode = utils::ReadParam('advanced', false);
                $sCsvFile = strtolower($this->m_oFilter->GetClass()) . '.csv';
                $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'webservices/export.php?expression=' . urlencode($this->m_oFilter->ToOQL(true)) . '&format=csv&filename=' . urlencode($sCsvFile);
                $sLinkToToggle = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($this->m_oFilter->serialize()) . '&format=csv';
                if ($bAdvancedMode) {
                    $sDownloadLink .= '&fields_advanced=1';
                    $sChecked = 'CHECKED';
                } else {
                    $sLinkToToggle = $sLinkToToggle . '&advanced=1';
                    $sChecked = '';
                }
                $sAjaxLink = $sDownloadLink . '&charset=UTF-8';
                // Includes &fields_advanced=1 if in advanced mode
                /*
                			$sCSVData = cmdbAbstractObject::GetSetAsCSV($this->m_oSet, array('fields_advanced' => $bAdvancedMode));
                			$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
                			if ($sCharset == 'UTF-8')
                			{
                				$bLostChars = false;
                			}
                			else
                			{
                				$sConverted = @iconv('UTF-8', $sCharset, $sCSVData);
                				$sRestored = @iconv($sCharset, 'UTF-8', $sConverted);
                				$bLostChars = ($sRestored != $sCSVData);
                			}
                			if ($bLostChars)
                			{
                				$sCharsetNotice = "&nbsp;&nbsp;<span id=\"csv_charset_issue\">";
                				$sCharsetNotice .= '<img src="../images/error.png"  style="vertical-align:middle"/>';
                				$sCharsetNotice .= "</span>";
                				$sTip = "<p>".htmlentities(Dict::S('UI:CSVExport:LostChars'), ENT_QUOTES, 'UTF-8')."</p>";
                				$sTip .= "<p>".htmlentities(Dict::Format('UI:CSVExport:LostChars+', $sCharset), ENT_QUOTES, 'UTF-8')."</p>";
                				$oPage->add_ready_script("$('#csv_charset_issue').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
                			}
                			else
                			{
                				$sCharsetNotice = '';
                			}
                */
                $sCharsetNotice = false;
                $sHtml .= "<div>";
                $sHtml .= '<table style="width:100%" class="transparent">';
                $sHtml .= '<tr>';
                $sHtml .= '<td><a href="' . $sDownloadLink . '">' . Dict::Format('UI:Download-CSV', $sCsvFile) . '</a>' . $sCharsetNotice . '</td>';
                $sHtml .= '<td style="text-align:right"><input type="checkbox" ' . $sChecked . ' onClick="window.location.href=\'' . $sLinkToToggle . '\'">&nbsp;' . Dict::S('UI:CSVExport:AdvancedMode') . '</td>';
                $sHtml .= '</tr>';
                $sHtml .= '</table>';
                if ($bAdvancedMode) {
                    $sHtml .= "<p>";
                    $sHtml .= htmlentities(Dict::S('UI:CSVExport:AdvancedMode+'), ENT_QUOTES, 'UTF-8');
                    $sHtml .= "</p>";
                }
                $sHtml .= "</div>";
                $sHtml .= "<div id=\"csv_content_loading\"><div style=\"width: 250px; height: 20px; background: url(../setup/orange-progress.gif); border: 1px #999 solid; margin-left:auto; margin-right: auto; text-align: center;\">" . Dict::S('UI:Loading') . "</div></div><textarea id=\"csv_content\" style=\"display:none;\">\n";
                //$sHtml .= htmlentities($sCSVData, ENT_QUOTES, 'UTF-8');
                $sHtml .= "</textarea>\n";
                $oPage->add_ready_script("\$.post('{$sAjaxLink}', {}, function(data) { \$('#csv_content').html(data); \$('#csv_content_loading').hide(); \$('#csv_content').show();} );");
                break;
            case 'modify':
                if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES) {
                    while ($oObj = $this->m_oSet->Fetch()) {
                        $sHtml .= $oObj->GetModifyForm($oPage);
                    }
                }
                break;
            case 'search':
                $sStyle = isset($aExtraParams['open']) && $aExtraParams['open'] == 'true' ? 'SearchDrawer' : 'SearchDrawer DrawerClosed';
                $sHtml .= "<div id=\"ds_{$sId}\" class=\"{$sStyle}\">\n";
                $oPage->add_ready_script(<<<EOF
\t\$("#dh_{$sId}").click( function() {
\t\t\$("#ds_{$sId}").slideToggle('normal', function() { \$("#ds_{$sId}").parent().resize(); FixSearchFormsDisposition(); } );
\t\t\$("#dh_{$sId}").toggleClass('open');
\t});
EOF
);
                $aExtraParams['currentId'] = $sId;
                $sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams);
                $sHtml .= "</div>\n";
                $sHtml .= "<div class=\"HRDrawer\"></div>\n";
                $sHtml .= "<div id=\"dh_{$sId}\" class=\"DrawerHandle\">" . Dict::S('UI:SearchToggle') . "</div>\n";
                break;
            case 'open_flash_chart':
                static $iChartCounter = 0;
                $oAppContext = new ApplicationContext();
                $sContext = $oAppContext->GetForLink();
                if (!empty($sContext)) {
                    $sContext = '&' . $sContext;
                }
                $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
                $sTitle = isset($aExtraParams['chart_title']) ? $aExtraParams['chart_title'] : '';
                $sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
                $sGroupByExpr = isset($aExtraParams['group_by_expr']) ? '&params[group_by_expr]=' . $aExtraParams['group_by_expr'] : '';
                $sFilter = $this->m_oFilter->serialize();
                $sHtml .= "<div id=\"my_chart_{$sId}{$iChartCounter}\">If the chart does not display, <a href=\"http://get.adobe.com/flash/\" target=\"_blank\">install Flash</a></div>\n";
                $oPage->add_script("function ofc_resize(left, width, top, height) { /* do nothing special */ }");
                if (isset($aExtraParams['group_by_label'])) {
                    $sUrl = urlencode(utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=open_flash_chart&params[group_by]={$sGroupBy}{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]={$sChartType}&params[chart_title]={$sTitle}&params[currentId]={$sId}&id={$sId}&filter=" . urlencode($sFilter));
                } else {
                    $sUrl = urlencode(utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=open_flash_chart&params[group_by]={$sGroupBy}{$sGroupByExpr}&params[chart_type]={$sChartType}&params[chart_title]={$sTitle}&params[currentId]={$sId}&id={$sId}&filter=" . urlencode($sFilter));
                }
                $oPage->add_ready_script("swfobject.embedSWF(\"../images/open-flash-chart.swf\", \"my_chart_{$sId}{$iChartCounter}\", \"100%\", \"300\",\"9.0.0\", \"expressInstall.swf\",\n\t\t\t\t{\"data-file\":\"" . $sUrl . "\"}, {wmode: 'transparent'} );\n");
                $iChartCounter++;
                if (isset($aExtraParams['group_by'])) {
                    if (isset($aExtraParams['group_by_label'])) {
                        $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                        $sGroupByLabel = $aExtraParams['group_by_label'];
                    } else {
                        // Backward compatibility: group_by is simply a field id
                        $sAlias = $this->m_oFilter->GetClassAlias();
                        $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                        $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                    }
                    $aGroupBy = array();
                    $aGroupBy['grouped_by_1'] = $oGroupByExp;
                    $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                    $aRes = CMDBSource::QueryToArray($sSql);
                    $aGroupBy = array();
                    $aLabels = array();
                    $aValues = array();
                    $iTotalCount = 0;
                    foreach ($aRes as $iRow => $aRow) {
                        $sValue = $aRow['grouped_by_1'];
                        $aValues[$iRow] = $sValue;
                        $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                        $aLabels[$iRow] = $sHtmlValue;
                        $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                        $iTotalCount += $aRow['_itop_count_'];
                    }
                    $aData = array();
                    $idx = 0;
                    $aURLs = array();
                    foreach ($aGroupBy as $iRow => $iCount) {
                        // Build the search for this subset
                        $oSubsetSearch = $this->m_oFilter->DeepClone();
                        $oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
                        $oSubsetSearch->AddConditionExpression($oCondition);
                        $aURLs[$idx] = $oSubsetSearch->serialize();
                        $idx++;
                    }
                    $sURLList = '';
                    foreach ($aURLs as $index => $sURL) {
                        $sURLList .= "\taURLs[{$index}] = '" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=search&format=html{$sContext}&filter=" . urlencode($sURL) . "';\n";
                    }
                    $oPage->add_script(<<<EOF
function ofc_drill_down_{$sId}(index)
{
\tvar aURLs = new Array();
{$sURLList}
\twindow.location.href=aURLs[index];
}
EOF
);
                }
                break;
            case 'open_flash_chart_ajax':
                require_once APPROOT . '/pages/php-ofc-library/open-flash-chart.php';
                $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
                $sId = utils::ReadParam('id', '');
                $oChart = new open_flash_chart();
                switch ($sChartType) {
                    case 'bars':
                        $oChartElement = new bar_glass();
                        if (isset($aExtraParams['group_by'])) {
                            if (isset($aExtraParams['group_by_label'])) {
                                $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                                $sGroupByLabel = $aExtraParams['group_by_label'];
                            } else {
                                // Backward compatibility: group_by is simply a field id
                                $sAlias = $this->m_oFilter->GetClassAlias();
                                $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                                $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                            }
                            $aGroupBy = array();
                            $aGroupBy['grouped_by_1'] = $oGroupByExp;
                            $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                            $aRes = CMDBSource::QueryToArray($sSql);
                            $aGroupBy = array();
                            $aLabels = array();
                            $iTotalCount = 0;
                            foreach ($aRes as $iRow => $aRow) {
                                $sValue = $aRow['grouped_by_1'];
                                $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                                $aLabels[$iRow] = strip_tags($sHtmlValue);
                                $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                                $iTotalCount += $aRow['_itop_count_'];
                            }
                            $aData = array();
                            $aChartLabels = array();
                            $maxValue = 0;
                            foreach ($aGroupBy as $iRow => $iCount) {
                                $oBarValue = new bar_value($iCount);
                                $oBarValue->on_click("ofc_drill_down_{$sId}");
                                $aData[] = $oBarValue;
                                if ($iCount > $maxValue) {
                                    $maxValue = $iCount;
                                }
                                $aChartLabels[] = html_entity_decode($aLabels[$iRow], ENT_QUOTES, 'UTF-8');
                            }
                            $oYAxis = new y_axis();
                            $aMagicValues = array(1, 2, 5, 10);
                            $iMultiplier = 1;
                            $index = 0;
                            $iTop = $aMagicValues[$index % count($aMagicValues)] * $iMultiplier;
                            while ($maxValue > $iTop) {
                                $index++;
                                $iTop = $aMagicValues[$index % count($aMagicValues)] * $iMultiplier;
                                if ($index % count($aMagicValues) == 0) {
                                    $iMultiplier = $iMultiplier * 10;
                                }
                            }
                            //echo "oYAxis->set_range(0, $iTop, $iMultiplier);\n";
                            $oYAxis->set_range(0, $iTop, $iMultiplier);
                            $oChart->set_y_axis($oYAxis);
                            $oChartElement->set_values($aData);
                            $oXAxis = new x_axis();
                            $oXLabels = new x_axis_labels();
                            // set them vertical
                            $oXLabels->set_vertical();
                            // set the label text
                            $oXLabels->set_labels($aChartLabels);
                            // Add the X Axis Labels to the X Axis
                            $oXAxis->set_labels($oXLabels);
                            $oChart->set_x_axis($oXAxis);
                        }
                        break;
                    case 'pie':
                    default:
                        $oChartElement = new pie();
                        $oChartElement->set_start_angle(35);
                        $oChartElement->set_animate(true);
                        $oChartElement->set_tooltip('#label# - #val# (#percent#)');
                        $oChartElement->set_colours(array('#FF8A00', '#909980', '#2C2B33', '#CCC08D', '#596664'));
                        if (isset($aExtraParams['group_by'])) {
                            if (isset($aExtraParams['group_by_label'])) {
                                $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                                $sGroupByLabel = $aExtraParams['group_by_label'];
                            } else {
                                // Backward compatibility: group_by is simply a field id
                                $sAlias = $this->m_oFilter->GetClassAlias();
                                $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                                $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                            }
                            $aGroupBy = array();
                            $aGroupBy['grouped_by_1'] = $oGroupByExp;
                            $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                            $aRes = CMDBSource::QueryToArray($sSql);
                            $aGroupBy = array();
                            $aLabels = array();
                            $iTotalCount = 0;
                            foreach ($aRes as $iRow => $aRow) {
                                $sValue = $aRow['grouped_by_1'];
                                $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                                $aLabels[$iRow] = strip_tags($sHtmlValue);
                                $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                                $iTotalCount += $aRow['_itop_count_'];
                            }
                            $aData = array();
                            foreach ($aGroupBy as $iRow => $iCount) {
                                $sFlashLabel = html_entity_decode($aLabels[$iRow], ENT_QUOTES, 'UTF-8');
                                $PieValue = new pie_value($iCount, $sFlashLabel);
                                //@@ BUG: not passed via ajax !!!
                                $PieValue->on_click("ofc_drill_down_{$sId}");
                                $aData[] = $PieValue;
                            }
                            $oChartElement->set_values($aData);
                            $oChart->x_axis = null;
                        }
                }
                if (isset($aExtraParams['chart_title'])) {
                    // The title has been given in an url, and urlencoded...
                    // and urlencode transforms utf-8 into something similar to ISO-8859-1
                    // Example: é (C3A9 becomes %E9)
                    // As a consequence, json_encode (called within open-flash-chart.php)
                    // was returning 'null' and the graph was not displayed at all
                    // To make sure that the graph is displayed AND to get a correct title
                    // (at least for european characters) let's transform back into utf-8 !
                    $sTitle = iconv("ISO-8859-1", "UTF-8//IGNORE", $aExtraParams['chart_title']);
                    // If the title is a dictionnary entry, fetch it
                    $sTitle = Dict::S($sTitle);
                    $oTitle = new title($sTitle);
                    $oChart->set_title($oTitle);
                    $oTitle->set_style("{font-size: 16px; font-family: Tahoma; font-weight: bold; text-align: center;}");
                }
                $oChart->set_bg_colour('#FFFFFF');
                $oChart->add_element($oChartElement);
                $sHtml = $oChart->toPrettyString();
                break;
            default:
                // Unsupported style, do nothing.
                $sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle);
        }
        return $sHtml;
    }
Example #11
0
 $sClass = trim(utils::ReadParam('class', ''));
 $iTune = utils::ReadParam('tune', 0);
 if (preg_match('/^"(.*)"$/', $sFullText, $aMatches)) {
     // The text is surrounded by double-quotes, remove the quotes and treat it as one single expression
     $aFullTextNeedles = array($aMatches[1]);
 } else {
     // Split the text on the blanks and treat this as a search for <word1> AND <word2> AND <word3>
     $aFullTextNeedles = explode(' ', $sFullText);
 }
 $oFilter = new DBObjectSearch($sClass);
 foreach ($aFullTextNeedles as $sSearchText) {
     $oFilter->AddCondition_FullText($sSearchText);
 }
 $oSet = new DBObjectSet($oFilter);
 $oPage->add("<div class=\"page_header\">\n");
 $oPage->add("<h2>" . MetaModel::GetClassIcon($sClass) . "&nbsp;<span class=\"hilite\">" . Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), Metamodel::GetName($sClass)) . "</h2>\n");
 $oPage->add("</div>\n");
 if ($oSet->Count() > 0) {
     $aLeafs = array();
     while ($oObj = $oSet->Fetch()) {
         if (get_class($oObj) == $sClass) {
             $aLeafs[] = $oObj->GetKey();
         }
     }
     $oLeafsFilter = new DBObjectSearch($sClass);
     if (count($aLeafs) > 0) {
         $oLeafsFilter->AddCondition('id', $aLeafs, 'IN');
         $oBlock = new DisplayBlock($oLeafsFilter, 'list', false);
         $sBlockId = 'global_search_' . $sClass;
         $oPage->add('<div id="' . $sBlockId . '">');
         $oBlock->RenderContent($oPage, array('table_id' => $sBlockId, 'currentId' => $sBlockId));
 /**
  * Determine if there is a redundancy (or use the existing one) and add the corresponding nodes/edges	
  */
 protected function ComputeRedundancy($sRelCode, $aQueryInfo, $oFromNode, $oToNode)
 {
     $oRedundancyNode = null;
     $oObject = $oToNode->GetProperty('object');
     if ($this->IsRedundancyEnabled($sRelCode, $aQueryInfo, $oToNode)) {
         $sId = RelationRedundancyNode::MakeId($sRelCode, $aQueryInfo['sNeighbour'], $oToNode->GetProperty('object'));
         $oRedundancyNode = $this->GetNode($sId);
         if (is_null($oRedundancyNode)) {
             // Get the upper neighbours
             $sQuery = $aQueryInfo['sQueryUp'];
             try {
                 $oFlt = DBObjectSearch::FromOQL($sQuery);
                 $oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery());
                 $iCount = $oObjSet->Count();
             } catch (Exception $e) {
                 throw new Exception("Wrong query (upstream) for the relation {$sRelCode}/{$aQueryInfo['sDefinedInClass']}/{$aQueryInfo['sNeighbour']}: " . $e->getMessage());
             }
             $iMinUp = $this->GetRedundancyMinUp($sRelCode, $aQueryInfo, $oToNode, $iCount);
             $fThreshold = max(0, $iCount - $iMinUp);
             $oRedundancyNode = new RelationRedundancyNode($this, $sId, $iMinUp, $fThreshold);
             new RelationEdge($this, $oRedundancyNode, $oToNode);
             while ($oUpperObj = $oObjSet->Fetch()) {
                 $sObjectRef = RelationObjectNode::MakeId($oUpperObj);
                 $oUpperNode = $this->GetNode($sObjectRef);
                 if (is_null($oUpperNode)) {
                     $oUpperNode = new RelationObjectNode($this, $oUpperObj);
                 }
                 new RelationEdge($this, $oUpperNode, $oRedundancyNode);
             }
         }
     }
     return $oRedundancyNode;
 }
    /**
     * Get the HTML fragment corresponding to the ext key editing widget
     * @param WebPage $oP The web page used for all the output
     * @param Hash $aArgs Extra context arguments
     * @return string The HTML fragment to be inserted into the page
     */
    public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true)
    {
        if (!is_null($bSearchMode)) {
            $this->bSearchMode = $bSearchMode;
        }
        $sTitle = addslashes($sTitle);
        $oPage->add_linked_script('../js/extkeywidget.js');
        $oPage->add_linked_script('../js/forms-json-utils.js');
        $bCreate = !$this->bSearchMode && !MetaModel::IsAbstract($this->sTargetClass) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
        $bExtensions = true;
        $sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
        $sAttrFieldPrefix = $this->bSearchMode ? '' : 'attr_';
        $sHTMLValue = "<span style=\"white-space:nowrap\">";
        // no wrap
        $sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
        if ($this->bSearchMode) {
            $sWizHelper = 'null';
            $sWizHelperJSON = "''";
            $sJSSearchMode = 'true';
        } else {
            if (isset($aArgs['wizHelper'])) {
                $sWizHelper = $aArgs['wizHelper'];
            } else {
                $sWizHelper = 'oWizardHelper' . $sFormPrefix;
            }
            $sWizHelperJSON = $sWizHelper . '.UpdateWizardToJSON()';
            $sJSSearchMode = 'false';
        }
        if (is_null($oAllowedValues)) {
            throw new Exception('Implementation: null value for allowed values definition');
        } elseif ($oAllowedValues->Count() < $iMaxComboLength) {
            // Discrete list of values, use a SELECT or RADIO buttons depending on the config
            switch ($sDisplayStyle) {
                case 'radio':
                case 'radio_horizontal':
                case 'radio_vertical':
                    $sValidationField = "<span id=\"v_{$this->iId}\"></span>";
                    $sHTMLValue = '';
                    $bVertical = $sDisplayStyle != 'radio_horizontal';
                    $bExtensions = false;
                    $oAllowedValues->Rewind();
                    $aAllowedValues = array();
                    while ($oObj = $oAllowedValues->Fetch()) {
                        $aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
                    }
                    $sHTMLValue = $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", $bMandatory, $bVertical, $sValidationField);
                    $aEventsList[] = 'change';
                    break;
                case 'select':
                case 'list':
                default:
                    $sSelectMode = 'true';
                    $sHelpText = '';
                    //$this->oAttDef->GetHelpOnEdition();
                    if ($this->bSearchMode) {
                        if ($bSearchMultiple) {
                            $sHTMLValue = "<select class=\"multiselect\" multiple title=\"{$sHelpText}\" name=\"{$sAttrFieldPrefix}{$sFieldName}[]\" id=\"{$this->iId}\">\n";
                        } else {
                            $sHTMLValue = "<select title=\"{$sHelpText}\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"{$this->iId}\">\n";
                            $sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : Dict::S('UI:SearchValue:Any');
                            $sHTMLValue .= "<option value=\"\">{$sDisplayValue}</option>\n";
                        }
                    } else {
                        $sHTMLValue = "<select title=\"{$sHelpText}\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"{$this->iId}\">\n";
                        $sHTMLValue .= "<option value=\"\">" . Dict::S('UI:SelectOne') . "</option>\n";
                    }
                    $oAllowedValues->Rewind();
                    while ($oObj = $oAllowedValues->Fetch()) {
                        $key = $oObj->GetKey();
                        $display_value = $oObj->GetName();
                        if ($oAllowedValues->Count() == 1 && $bMandatory == 'true') {
                            // When there is only once choice, select it by default
                            $sSelected = ' selected';
                        } else {
                            $sSelected = is_array($value) && in_array($key, $value) || $value == $key ? ' selected' : '';
                        }
                        $sHTMLValue .= "<option value=\"{$key}\"{$sSelected}>{$display_value}</option>\n";
                    }
                    $sHTMLValue .= "</select>\n";
                    if ($this->bSearchMode && $bSearchMultiple) {
                        $aOptions = array('header' => true, 'checkAllText' => Dict::S('UI:SearchValue:CheckAll'), 'uncheckAllText' => Dict::S('UI:SearchValue:UncheckAll'), 'noneSelectedText' => Dict::S('UI:SearchValue:Any'), 'selectedText' => Dict::S('UI:SearchValue:NbSelected'), 'selectedList' => 1);
                        $sJSOptions = json_encode($aOptions);
                        $oPage->add_ready_script("\$('.multiselect').multiselect({$sJSOptions});");
                    }
                    $oPage->add_ready_script(<<<EOF
\t\toACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '{$sFilter}', '{$sTitle}', true, {$sWizHelper}, '{$this->sAttCode}', {$sJSSearchMode});
\t\toACWidget_{$this->iId}.emptyHtml = "<div style=\\"background: #fff; border:0; text-align:center; vertical-align:middle;\\"><p>{$sMessage}</p></div>";
\t\t\$('#{$this->iId}').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
\t\t\$('#{$this->iId}').bind('change', function() { \$(this).trigger('extkeychange') } );

EOF
);
            }
            // Switch
        } else {
            // Too many choices, use an autocomplete
            $sSelectMode = 'false';
            // Check that the given value is allowed
            $oSearch = $oAllowedValues->GetFilter();
            $oSearch->AddCondition('id', $value);
            $oSet = new DBObjectSet($oSearch);
            if ($oSet->Count() == 0) {
                $value = null;
            }
            if (is_null($value) || $value == 0) {
                $sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
            } else {
                $sDisplayValue = $this->GetObjectName($value);
            }
            $iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 3;
            //@@@ $this->oAttDef->GetMinAutoCompleteChars();
            $iFieldSize = isset($aArgs['iFieldSize']) ? $aArgs['iFieldSize'] : 30;
            //@@@ $this->oAttDef->GetMaxSize();
            // the input for the auto-complete
            $sHTMLValue = "<input count=\"" . $oAllowedValues->Count() . "\" type=\"text\" id=\"label_{$this->iId}\" size=\"{$iFieldSize}\" value=\"{$sDisplayValue}\"/>&nbsp;";
            $sHTMLValue .= "<img id=\"mini_search_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_search.gif\" onClick=\"oACWidget_{$this->iId}.Search();\"/>&nbsp;";
            // another hidden input to store & pass the object's Id
            $sHTMLValue .= "<input type=\"hidden\" id=\"{$this->iId}\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"" . htmlentities($value, ENT_QUOTES, 'UTF-8') . "\" />\n";
            $JSSearchMode = $this->bSearchMode ? 'true' : 'false';
            // Scripts to start the autocomplete and bind some events to it
            $oPage->add_ready_script(<<<EOF
\t\toACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '{$sFilter}', '{$sTitle}', false, {$sWizHelper}, '{$this->sAttCode}', {$sJSSearchMode});
\t\toACWidget_{$this->iId}.emptyHtml = "<div style=\\"background: #fff; border:0; text-align:center; vertical-align:middle;\\"><p>{$sMessage}</p></div>";
\t\t\$('#label_{$this->iId}').autocomplete(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { scroll:true, minChars:{$iMinChars}, autoFill:false, matchContains:true, mustMatch: true, keyHolder:'#{$this->iId}', extraParams:{operation:'ac_extkey', sTargetClass:'{$this->sTargetClass}',sFilter:'{$sFilter}',bSearchMode:{$JSSearchMode}, json: function() { return {$sWizHelperJSON}; } }});
\t\t\$('#label_{$this->iId}').keyup(function() { if (\$(this).val() == '') { \$('#{$this->iId}').val(''); } } ); // Useful for search forms: empty value in the "label", means no value, immediatly !
\t\t\$('#label_{$this->iId}').result( function(event, data, formatted) { OnAutoComplete('{$this->iId}', event, data, formatted); } );
\t\t\$('#{$this->iId}').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
\t\tif (\$('#ac_dlg_{$this->iId}').length == 0)
\t\t{
\t\t\t\$('body').append('<div id="ac_dlg_{$this->iId}"></div>');
\t\t}
EOF
);
        }
        if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false) {
            $sHTMLValue .= "<img id=\"mini_tree_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_tree.gif\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"/>&nbsp;";
            $oPage->add_ready_script(<<<EOF
\t\t\tif (\$('#ac_tree_{$this->iId}').length == 0)
\t\t\t{
\t\t\t\t\$('body').append('<div id="ac_tree_{$this->iId}"></div>');
\t\t\t}\t\t
EOF
);
        }
        if ($bCreate && $bExtensions) {
            $sHTMLValue .= "<img id=\"mini_add_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_add.gif\" onClick=\"oACWidget_{$this->iId}.CreateObject();\"/>&nbsp;";
            $oPage->add_ready_script(<<<EOF
\t\tif (\$('#ajax_{$this->iId}').length == 0)
\t\t{
\t\t\t\$('body').append('<div id="ajax_{$this->iId}"></div>');
\t\t}
EOF
);
        }
        if ($sDisplayStyle == 'select' || $sDisplayStyle == 'list') {
            $sHTMLValue .= "<span id=\"v_{$this->iId}\"></span>";
        }
        $sHTMLValue .= "</span>";
        // end of no wrap
        return $sHTMLValue;
    }
    public function DisplayAttachments($oObject, WebPage $oPage, $bEditMode = false)
    {
        // Exit here if the class is not allowed
        if (!$this->IsTargetObject($oObject)) {
            return;
        }
        $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
        $oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
        if ($this->GetAttachmentsPosition() == 'relations') {
            $sTitle = $oSet->Count() > 0 ? Dict::Format('Attachments:TabTitle_Count', $oSet->Count()) : Dict::S('Attachments:EmptyTabTitle');
            $oPage->SetCurrentTab($sTitle);
        }
        $oPage->add_style(<<<EOF
.attachment {
\tdisplay: inline-block;
\ttext-align:center;
\tfloat:left;
\tpadding:5px;\t
}
.attachment:hover {
\tbackground-color: #e0e0e0;
}
.attachment img {
\tborder: 0;
}
.attachment a {
\ttext-decoration: none;
\tcolor: #1C94C4;
}
.btn_hidden {
\tdisplay: none;
}
EOF
);
        $oPage->add('<fieldset>');
        $oPage->add('<legend>' . Dict::S('Attachments:FieldsetTitle') . '</legend>');
        if ($bEditMode) {
            $sIsDeleteEnabled = $this->m_bDeleteEnabled ? 'true' : 'false';
            $iTransactionId = $oPage->GetTransactionId();
            $sClass = get_class($oObject);
            $sTempId = session_id() . '_' . $iTransactionId;
            $sDeleteBtn = Dict::S('Attachments:DeleteBtn');
            $oPage->add_script(<<<EOF
\tfunction RemoveNewAttachment(att_id)
\t{
\t\t\$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
\t\t\$('#display_attachment_'+att_id).hide();
\t\t\$('#attachment_plugin').trigger('remove_attachment', [att_id]);
\t\treturn false; // Do not submit the form !
\t}
\tfunction ajaxFileUpload()
\t{
\t\t//starting setting some animation when the ajax starts and completes
\t\t\$("#attachment_loading").ajaxStart(function(){
\t\t\t\$(this).show();
\t\t}).ajaxComplete(function(){
\t\t\t\$(this).hide();
\t\t});
\t\t
\t\t/*
\t\t\tprepareing ajax file upload
\t\t\turl: the url of script file handling the uploaded files
                        fileElementId: the file type of input element id and it will be the index of  \$_FILES Array()
\t\t\tdataType: it support json, xml
\t\t\tsecureuri:use secure protocol
\t\t\tsuccess: call back function when the ajax complete
\t\t\terror: callback function when the ajax failed
\t\t\t
                */
\t\t\$.ajaxFileUpload
\t\t(
\t\t\t{
\t\t\t\turl: GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.attachment.php?obj_class={$sClass}&temp_id={$sTempId}&operation=add', 
\t\t\t\tsecureuri:false,
\t\t\t\tfileElementId:'file',
\t\t\t\tdataType: 'json',
\t\t\t\tsuccess: function (data, status)
\t\t\t\t{
\t\t\t\t\tif(typeof(data.error) != 'undefined')
\t\t\t\t\t{
\t\t\t\t\t\tif(data.error != '')
\t\t\t\t\t\t{
\t\t\t\t\t\t\talert(data.error);
\t\t\t\t\t\t}
\t\t\t\t\t\telse
\t\t\t\t\t\t{
\t\t\t\t\t\t\tvar sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.att_id+'&field=contents';
\t\t\t\t\t\t\t\$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a href="'+sDownloadLink+'"><img src="'+data.icon+'"><br/>'+data.msg+'<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveNewAttachment('+data.att_id+');"/></div>');
\t\t\t\t\t\t\tif({$sIsDeleteEnabled})
\t\t\t\t\t\t\t{
\t\t\t\t\t\t\t\t\$('#display_attachment_'+data.att_id).hover( function() { \$(this).children(':button').toggleClass('btn_hidden'); } );
\t\t\t\t\t\t\t}
\t\t\t\t\t\t\t\$('#attachment_plugin').trigger('add_attachment', [data.att_id, data.msg]);
\t\t\t\t\t\t\t
\t\t\t\t\t\t\t//alert(data.msg);
\t\t\t\t\t\t}
\t\t\t\t\t}
\t\t\t\t},
\t\t\t\terror: function (data, status, e)
\t\t\t\t{
\t\t\t\t\talert(e);
\t\t\t\t}
\t\t\t}
\t\t)
\t\t
\t\treturn false;

\t}
EOF
);
            $oPage->add('<span id="attachments">');
            while ($oAttachment = $oSet->Fetch()) {
                $iAttId = $oAttachment->GetKey();
                $oDoc = $oAttachment->Get('contents');
                $sFileName = $oDoc->GetFileName();
                $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                $oPage->add('<div class="attachment" id="attachment_' . $iAttId . '"><a href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="$(\'#attachment_' . $iAttId . '\').remove();"/>&nbsp;</div>');
            }
            // Suggested attachments are listed here but treated as temporary
            $aDefault = utils::ReadParam('default', array(), false, 'raw_data');
            if (array_key_exists('suggested_attachments', $aDefault)) {
                $sSuggestedAttachements = $aDefault['suggested_attachments'];
                if (is_array($sSuggestedAttachements)) {
                    $sSuggestedAttachements = implode(',', $sSuggestedAttachements);
                }
                $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id IN({$sSuggestedAttachements})");
                $oSet = new DBObjectSet($oSearch, array());
                if ($oSet->Count() > 0) {
                    while ($oAttachment = $oSet->Fetch()) {
                        // Mark the attachments as temporary attachments for the current object/form
                        $oAttachment->Set('temp_id', $sTempId);
                        $oAttachment->DBUpdate();
                        // Display them
                        $iAttId = $oAttachment->GetKey();
                        $oDoc = $oAttachment->Get('contents');
                        $sFileName = $oDoc->GetFileName();
                        $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                        $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                        $oPage->add('<div class="attachment" id="display_attachment_' . $iAttId . '"><a href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveNewAttachment(' . $iAttId . ');"/>&nbsp;</div>');
                        $oPage->add_ready_script("\$('#attachment_plugin').trigger('add_attachment', [{$iAttId}, '" . addslashes($sFileName) . "']);");
                    }
                }
            }
            $oPage->add('</span>');
            $oPage->add('<div style="clear:both"></div>');
            $sMaxUpload = $this->GetMaxUpload();
            $oPage->p(Dict::S('Attachments:AddAttachment') . '<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> ' . $sMaxUpload);
            $oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
            $oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
            $oPage->add('</fieldset>');
            if ($this->m_bDeleteEnabled) {
                $oPage->add_ready_script('$(".attachment").hover( function() {$(this).children(":button").toggleClass("btn_hidden"); } );');
            }
        } else {
            $oPage->add('<span id="attachments">');
            if ($oSet->Count() == 0) {
                $oPage->add(Dict::S('Attachments:NoAttachment'));
            } else {
                while ($oAttachment = $oSet->Fetch()) {
                    $iAttId = $oAttachment->GetKey();
                    $oDoc = $oAttachment->Get('contents');
                    $sFileName = $oDoc->GetFileName();
                    $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                    $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                    $oPage->add('<div class="attachment" id="attachment_' . $iAttId . '"><a href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '</a><input type="hidden" name="attachments[]" value="' . $iAttId . '"/><br/>&nbsp;&nbsp;</div>');
                }
            }
        }
    }
 public function GetHeader()
 {
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'retrieving';
     $this->aStatusInfo['tmp_file'] = $this->MakeTmpFile('data');
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
         $sExtendedAttCode = $aFieldSpec['sFieldSpec'];
         $sAttCode = $aFieldSpec['sAttCode'];
         $sColLabel = $aFieldSpec['sColLabel'];
         switch ($sAttCode) {
             case 'id':
                 $sType = '0';
                 break;
             default:
                 $oAttDef = MetaModel::GetAttributeDef($aFieldSpec['sClass'], $aFieldSpec['sAttCode']);
                 $sType = 'string';
                 if ($oAttDef instanceof AttributeDateTime) {
                     $sType = 'datetime';
                 }
         }
         $aTableHeaders[] = array('label' => $sColLabel, 'type' => $sType);
     }
     $sRow = json_encode($aTableHeaders);
     $hFile = @fopen($this->aStatusInfo['tmp_file'], 'ab');
     if ($hFile === false) {
         throw new Exception('ExcelBulkExport: Failed to open temporary data file: "' . $this->aStatusInfo['tmp_file'] . '" for writing.');
     }
     fwrite($hFile, $sRow . "\n");
     fclose($hFile);
     return '';
 }
Example #16
0
    /**
     *  Prompt for the data to be loaded (either via a file or a copy/paste)
     * @param WebPage $oPage The current web page
     * @return void
     */
    function Welcome(iTopWebPage $oPage)
    {
        $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
        if (!empty($sSynchroScope)) {
            $oSearch = DBObjectSearch::FromOQL($sSynchroScope);
            $sClassName = $oSearch->GetClass();
            $oSet = new DBObjectSet($oSearch);
            $iCount = $oSet->Count();
            DisplaySynchroBanner($oPage, $sClassName, $iCount);
            $aSynchroUpdate = utils::ReadParam('synchro_update', array());
        } else {
            $aSynchroUpdate = null;
        }
        $oPage->add("<div><p><h1>" . Dict::S('UI:Title:BulkImport+') . "</h1></p></div>\n");
        $oPage->AddTabContainer('tabs1');
        $sSeparator = utils::ReadParam('separator', '', false, 'raw_data');
        $sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data');
        $bHeaderLine = utils::ReadParam('header_line', true);
        $sClassName = utils::ReadParam('class_name', '');
        $bAdvanced = utils::ReadParam('advanced', 0);
        $sEncoding = utils::ReadParam('encoding', '');
        if ($sEncoding == '') {
            $sEncoding = MetaModel::GetConfig()->Get('csv_file_default_charset');
        }
        $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
        $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
        $sFileLoadHtml = '<div><form enctype="multipart/form-data" method="post"><p>' . Dict::S('UI:CSVImport:SelectFile') . '</p>' . '<p><input type="file" name="csvdata"/></p>';
        $sFileLoadHtml .= '<p>' . Dict::S('UI:CSVImport:Encoding') . ': ';
        $sFileLoadHtml .= '<select name="encoding" style="font-family:Arial,Helvetica,Sans-serif">';
        // IE 8 has some troubles if the font is different
        $aPossibleEncodings = utils::GetPossibleEncodings(MetaModel::GetConfig()->GetCSVImportCharsets());
        foreach ($aPossibleEncodings as $sIconvCode => $sDisplayName) {
            $sSelected = '';
            if ($sEncoding == $sIconvCode) {
                $sSelected = ' selected';
            }
            $sFileLoadHtml .= '<option value="' . $sIconvCode . '"' . $sSelected . '>' . $sDisplayName . '</option>';
        }
        $sFileLoadHtml .= '</select></p>';
        $sFileLoadHtml .= '<p><input type="submit" value="' . Dict::S('UI:Button:Next') . '"/></p>' . '<input type="hidden" name="step" value="2"/>' . '<input type="hidden" name="operation" value="file_upload"/>' . '<input type="hidden" name="header_line" value="' . $bHeaderLine . '"/>' . '<input type="hidden" name="nb_skipped_lines" value="' . utils::ReadParam('nb_skipped_lines', '0') . '"/>' . '<input type="hidden" name="box_skiplines" value="' . utils::ReadParam('box_skiplines', '0') . '"/>' . '<input type="hidden" name="class_name" value="' . $sClassName . '"/>' . '<input type="hidden" name="advanced" value="' . $bAdvanced . '"/>' . '<input type="hidden" name="synchro_scope" value="' . $sSynchroScope . '"/>';
        if (!empty($sSynchroScope)) {
            foreach ($aSynchroUpdate as $sKey => $value) {
                $sFileLoadHtml .= '<input type="hidden" name="synchro_update[' . $sKey . ']" value="' . $value . '"/>';
            }
        }
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            $oPage->add('<input type="hidden" name="field[' . $iNumber . ']" value="' . $sAttCode . '"/>');
        }
        foreach ($aSearchFields as $index => $sDummy) {
            $oPage->add('<input type="hidden" name="search_field[' . $index . ']" value="1"/>');
        }
        $sFileLoadHtml .= '</form></div>';
        $oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:LoadFromFile'), $sFileLoadHtml);
        $sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
        $sPasteDataHtml = '<div><form enctype="multipart/form-data" method="post"><p>' . Dict::S('UI:CSVImport:PasteData') . '</p>' . '<p><textarea cols="100" rows="30" name="csvdata">' . htmlentities($sCSVData, ENT_QUOTES, 'UTF-8') . '</textarea></p>';
        $sPasteDataHtml .= '<hidden name="encoding" value="UTF-8">';
        $sPasteDataHtml .= '<p><input type="submit" value="' . Dict::S('UI:Button:Next') . '"/></p>' . '<input type="hidden" name="step" value="2"/>' . '<input type="hidden" name="operation" value="csv_data"/>' . '<input type="hidden" name="separator" value="' . htmlentities($sSeparator, ENT_QUOTES, 'UTF-8') . '"/>' . '<input type="hidden" name="text_qualifier" value="' . htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8') . '"/>' . '<input type="hidden" name="header_line" value="' . $bHeaderLine . '"/>' . '<input type="hidden" name="nb_skipped_lines" value="' . utils::ReadParam('nb_skipped_lines', '0') . '"/>' . '<input type="hidden" name="box_skiplines" value="' . utils::ReadParam('box_skiplines', '0') . '"/>' . '<input type="hidden" name="class_name" value="' . $sClassName . '"/>' . '<input type="hidden" name="advanced" value="' . $bAdvanced . '"/>' . '<input type="hidden" name="synchro_scope" value="' . $sSynchroScope . '"/>';
        if (!empty($sSynchroScope)) {
            foreach ($aSynchroUpdate as $sKey => $value) {
                $sPasteDataHtml .= '<input type="hidden" name="synchro_update[' . $sKey . ']" value="' . $value . '"/>';
            }
        }
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            $sPasteDataHtml .= '<input type="hidden" name="field[' . $iNumber . ']" value="' . $sAttCode . '"/>';
        }
        foreach ($aSearchFields as $index => $sDummy) {
            $sPasteDataHtml .= '<input type="hidden" name="search_field[' . $index . ']" value="1"/>';
        }
        $sPasteDataHtml .= '</form></div>';
        $oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:CopyPaste'), $sPasteDataHtml);
        if (!empty($sCSVData)) {
            // When there are some data, activate the 'copy & paste' tab by default
            $oPage->SelectTab('tabs1', Dict::S('UI:CSVImport:Tab:CopyPaste'));
        }
        $sTemplateHtml = '<div><p>' . Dict::S('UI:CSVImport:PickClassForTemplate') . ' ';
        $sTemplateHtml .= GetClassesSelect('template_class', '', 300, UR_ACTION_BULK_MODIFY);
        $sTemplateHtml .= '</div>';
        $sTemplateHtml .= '<div id="template" style="text-align:center">';
        $sTemplateHtml .= '</div>';
        $oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:Templates'), $sTemplateHtml);
        $oPage->add_script(<<<EOF
var ajax_request = null;

function DisplayTemplate(sClassName) {

\$('#template').block();

// Make sure that we cancel any pending request before issuing another
// since responses may arrive in arbitrary order
if (ajax_request != null)
{
\tajax_request.abort();
\tajax_request = null;
}

ajax_request = \$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.csvimport.php',
\t   { operation: 'get_csv_template', class_name: sClassName },
\t   function(data) {
\t\t \$('#template').empty();
\t\t \$('#template').append(data);
\t\t \$('#template').unblock();
\t\t}
\t );
}
EOF
);
        $oPage->add_ready_script(<<<EOF
\$('#select_template_class').change( function() {
\tDisplayTemplate(this.value);
});
EOF
);
        if (Utils::GetConfig()->Get('csv_import_history_display')) {
            $oPage->SetCurrentTabContainer('tabs1');
            $oPage->AddAjaxTab(Dict::S('UI:History:BulkImports'), utils::GetAbsoluteUrlAppRoot() . 'pages/csvimport.php?step=11', true);
        }
    }
 public function IsTargetObject($iObjectId)
 {
     $sFilter = trim($this->Get('filter'));
     if (strlen($sFilter) > 0) {
         $oSearch = DBObjectSearch::FromOQL($sFilter);
         $oSearch->AddCondition('id', $iObjectId, '=');
         $oSet = new DBObjectSet($oSearch);
         $bRet = $oSet->Count() > 0;
     } else {
         $bRet = true;
     }
     return $bRet;
 }
 /**
  * Find an object from a polymorph search specification (Rest/Json)
  * 	 
  * @param string $sClass Name of the class
  * @param mixed $key Either search criteria (substructure), or an object or an OQL string.
  * @param bool $bAllowNullValue Allow the cases such as key = 0 or key = {null} and return null then
  * @return DBObject The object found
  * @throws Exception If the input structure is not valid or it could not find exactly one object
  * @api
  */
 public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
 {
     if (is_object($key)) {
         $res = static::FindObjectFromCriteria($sClass, $key);
     } elseif (is_numeric($key)) {
         if ($bAllowNullValue && $key == 0) {
             $res = null;
         } else {
             $res = MetaModel::GetObject($sClass, $key, false);
             if (is_null($res)) {
                 throw new Exception("Invalid object {$sClass}::{$key}");
             }
         }
     } elseif (is_string($key)) {
         // OQL
         $oSearch = DBObjectSearch::FromOQL($key);
         $oSet = new DBObjectSet($oSearch);
         $iCount = $oSet->Count();
         if ($iCount == 0) {
             throw new Exception("No item found for query: {$key}");
         } elseif ($iCount > 1) {
             throw new Exception("Several items found ({$iCount}) for query: {$key}");
         }
         $res = $oSet->Fetch();
     } else {
         throw new Exception("Wrong format for key");
     }
     return $res;
 }
 /**
  * Displays a list of objects, without any hyperlink (except for the object's details)
  * @param DBObjectSet $oSet The set of objects to display
  * @param Array $aZList The ZList (list of field codes) to use for the tabular display
  * @param String $sEmptyListMessage Message displayed whenever the list is empty
  * @return string The HTML text representing the list
  */
 public function DisplaySet($oSet, $aZList, $sEmptyListMessage = '')
 {
     if ($oSet->Count() > 0) {
         $sClass = $oSet->GetClass();
         if (is_subclass_of($sClass, 'cmdbAbstractObject')) {
             // Home-made and very limited display of an object set
             $sUniqueId = $sClass . $this->GetUniqueId();
             $this->add("<div id=\"{$sUniqueId}\">\n");
             // The id here MUST be the same as currentId, otherwise the pagination will be broken
             cmdbAbstractObject::DisplaySet($this, $oSet, array('currentId' => $sUniqueId, 'menu' => false, 'toolkit_menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList)));
             $this->add("</div>\n");
         } else {
             // Home-made and very limited display of an object set
             $aAttribs = array();
             $aValues = array();
             $aAttribs['key'] = array('label' => MetaModel::GetName($sClass), 'description' => '');
             foreach ($aZList as $sAttCode) {
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 $aAttribs[$sAttCode] = array('label' => $oAttDef->GetLabel(), 'description' => $oAttDef->GetDescription());
             }
             while ($oObj = $oSet->Fetch()) {
                 $aRow = array();
                 $aRow['key'] = '<a href="./index.php?operation=details&class=' . get_class($oObj) . '&id=' . $oObj->GetKey() . '">' . $oObj->GetName() . '</a>';
                 $sHilightClass = $oObj->GetHilightClass();
                 if ($sHilightClass != '') {
                     $aRow['@class'] = $sHilightClass;
                 }
                 foreach ($aZList as $sAttCode) {
                     $aRow[$sAttCode] = $oObj->GetAsHTML($sAttCode);
                 }
                 $aValues[$oObj->GetKey()] = $aRow;
             }
             $this->table($aAttribs, $aValues);
         }
     } elseif (strlen($sEmptyListMessage) > 0) {
         $this->add($sEmptyListMessage);
     }
 }
 public function IsStimulusAllowed($oUser, $sClass, $sStimulusCode, $oInstanceSet = null)
 {
     $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '{$sClass}' AND stimulus = '{$sStimulusCode}' AND userid = '{$oUser->GetKey()}'"));
     if ($oSet->Count() < 1) {
         return UR_ALLOWED_NO;
     }
     $oGrantRecord = $oSet->Fetch();
     switch ($oGrantRecord->Get('permission')) {
         case 'yes':
             $iRetCode = UR_ALLOWED_YES;
             break;
         case 'no':
         default:
             $iRetCode = UR_ALLOWED_NO;
             break;
     }
     return $iRetCode;
 }
 public function ReadParameters()
 {
     parent::ReadParameters();
     $sQueryId = utils::ReadParam('query', null, true);
     $sFields = utils::ReadParam('fields', null, true, 'raw_data');
     if (($sFields === null || $sFields === '') && $sQueryId === null) {
         throw new BulkExportMissingParameterException('fields');
     } else {
         if ($sQueryId !== null && $sQueryId !== null) {
             $oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
             $oQueries = new DBObjectSet($oSearch);
             if ($oQueries->Count() > 0) {
                 $oQuery = $oQueries->Fetch();
                 if ($sFields === null || $sFields === '') {
                     // No 'fields' parameter supplied, take the fields from the query phrasebook definition
                     $sFields = trim($oQuery->Get('fields'));
                     if ($sFields === '') {
                         throw new BulkExportMissingParameterException('fields');
                     }
                 }
             } else {
                 throw BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = ' . $sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
             }
         }
     }
     $aFields = explode(',', $sFields);
     $this->aStatusInfo['fields'] = array();
     foreach ($aFields as $sField) {
         // Trim the values since it's too temping to write: fields=name, first_name, org_name instead of fields=name,first_name,org_name
         $this->aStatusInfo['fields'][] = trim($sField);
     }
 }
 public function ReadParameters()
 {
     parent::ReadParameters();
     $sQueryId = utils::ReadParam('query', null, true);
     $sFields = utils::ReadParam('fields', null, true, 'raw_data');
     if (($sFields === null || $sFields === '') && $sQueryId === null) {
         throw new BulkExportMissingParameterException('fields');
     } else {
         if ($sQueryId !== null && $sQueryId !== null) {
             $oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
             $oQueries = new DBObjectSet($oSearch);
             if ($oQueries->Count() > 0) {
                 $oQuery = $oQueries->Fetch();
                 if ($sFields === null || $sFields === '') {
                     // No 'fields' parameter supplied, take the fields from the query phrasebook definition
                     $sFields = trim($oQuery->Get('fields'));
                     if ($sFields === '') {
                         throw new BulkExportMissingParameterException('fields');
                     }
                 }
             } else {
                 throw BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = ' . $sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
             }
         }
     }
     // Interpret (and check) the list of fields
     //
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     $aAliases = array_keys($aSelectedClasses);
     $aAuthorizedClasses = array();
     foreach ($aSelectedClasses as $sAlias => $sClassName) {
         if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ) == UR_ALLOWED_YES) {
             $aAuthorizedClasses[$sAlias] = $sClassName;
         }
     }
     $aFields = explode(',', $sFields);
     $this->aStatusInfo['fields'] = array();
     foreach ($aFields as $sFieldSpec) {
         // Trim the values since it's natural to write: fields=name, first_name, org_name instead of fields=name,first_name,org_name
         $sExtendedAttCode = trim($sFieldSpec);
         if (preg_match('/^([^\\.]+)\\.(.+)$/', $sExtendedAttCode, $aMatches)) {
             $sAlias = $aMatches[1];
             $sAttCode = $aMatches[2];
         } else {
             $sAlias = reset($aAliases);
             $sAttCode = $sExtendedAttCode;
         }
         if (!array_key_exists($sAlias, $aSelectedClasses)) {
             throw new Exception("Invalid alias '{$sAlias}' for the column '{$sExtendedAttCode}'. Availables aliases: '" . implode("', '", $aAliases) . "'");
         }
         $sClass = $aSelectedClasses[$sAlias];
         if (!array_key_exists($sAlias, $aAuthorizedClasses)) {
             throw new Exception("You do not have enough permissions to bulk read data of class '{$sClass}' (alias: {$sAlias})");
         }
         if ($this->bLocalizeOutput) {
             try {
                 $sLabel = MetaModel::GetLabel($sClass, $sAttCode);
             } catch (Exception $e) {
                 throw new Exception("Wrong field specification '{$sFieldSpec}': " . $e->getMessage());
             }
         } else {
             $sLabel = $sAttCode;
         }
         if (count($aAuthorizedClasses) > 1) {
             $sColLabel = $sAlias . '.' . $sLabel;
         } else {
             $sColLabel = $sLabel;
         }
         $this->aStatusInfo['fields'][] = array('sFieldSpec' => $sExtendedAttCode, 'sAlias' => $sAlias, 'sClass' => $sClass, 'sAttCode' => $sAttCode, 'sLabel' => $sLabel, 'sColLabel' => $sColLabel);
     }
 }
 /**
  * Describe (as a text string) the modifications corresponding to this change
  */
 public function GetDescription()
 {
     // Temporary, until we change the options of GetDescription() -needs a more global revision
     $bIsHtml = true;
     $sResult = '';
     $sTargetObjectClass = 'Attachment';
     $iTargetObjectKey = $this->Get('attachment_id');
     $sFilename = htmlentities($this->Get('filename'), ENT_QUOTES, 'UTF-8');
     $oTargetSearch = new DBObjectSearch($sTargetObjectClass);
     $oTargetSearch->AddCondition('id', $iTargetObjectKey, '=');
     $oMonoObjectSet = new DBObjectSet($oTargetSearch);
     if ($oMonoObjectSet->Count() > 0) {
         $oAttachment = $oMonoObjectSet->Fetch();
         $oDoc = $oAttachment->Get('contents');
         $sPreview = $oDoc->IsPreviewAvailable() ? 'data-preview="true"' : '';
         $sResult = Dict::Format('Attachments:History_File_Added', '<span class="attachment-history-added attachment"><a ' . $sPreview . ' target="_blank" href="' . $oDoc->GetDownloadURL($sTargetObjectClass, $iTargetObjectKey, 'contents') . '">' . $sFilename . '</a></span>');
     } else {
         $sResult = Dict::Format('Attachments:History_File_Added', '<span class="attachment-history-deleted">' . $sFilename . '</span>');
     }
     return $sResult;
 }
 protected function AddConnectedNetworkDevice()
 {
     $oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
     if (is_object($oDevice) && get_class($oDevice) == 'NetworkDevice') {
         $sOQL = "SELECT  lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
         $oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('network' => $this->Get('connectableci_id'), 'device' => $this->Get('networkdevice_id'), 'devport' => $this->Get('network_port'), 'nwport' => $this->Get('device_port')));
         if ($oConnectionSet->Count() == 0) {
             $sLink = $this->Get('connection_type');
             $sConnLink = $sLink == 'uplink' ? 'downlink' : 'uplink';
             $oNewLink = new lnkConnectableCIToNetworkDevice();
             $oNewLink->Set('networkdevice_id', $this->Get('connectableci_id'));
             $oNewLink->Set('connectableci_id', $this->Get('networkdevice_id'));
             $oNewLink->Set('network_port', $this->Get('device_port'));
             $oNewLink->Set('device_port', $this->Get('network_port'));
             $oNewLink->Set('connection_type', $sConnLink);
             $oNewLink->DBInsert();
         }
     }
 }
Example #25
0
/**
 * Checks the parameters and returns the appropriate exporter (if any)
 * @param string $sExpression The OQL query to export or null
 * @param string $sQueryId The entry in the query phrasebook if $sExpression is null
 * @param string $sFormat The code of export format: csv, pdf, html, xlsx
 * @throws MissingQueryArgument
 * @return Ambigous <iBulkExport, NULL>
 */
function CheckParameters($sExpression, $sQueryId, $sFormat)
{
    $oExporter = null;
    if ($sExpression === null && $sQueryId === null) {
        ReportErrorAndUsage("Missing parameter. The parameter 'expression' or 'query' must be specified.");
    }
    // Either $sExpression or $sQueryId must be specified
    if ($sExpression === null) {
        $oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
        $oQueries = new DBObjectSet($oSearch);
        if ($oQueries->Count() > 0) {
            $oQuery = $oQueries->Fetch();
            $sExpression = $oQuery->Get('oql');
            $sFields = $oQuery->Get('fields');
            if (strlen($sFields) == 0) {
                $sFields = trim($oQuery->Get('fields'));
            }
        } else {
            ReportErrorAndExit("Invalid query phrasebook identifier: '{$sQueryId}'");
        }
    }
    if ($sFormat === null) {
        ReportErrorAndUsage("Missing parameter 'format'.");
    }
    // Check if the supplied query is valid (and all the parameters are supplied
    try {
        $oSearch = DBObjectSearch::FromOQL($sExpression);
        $aArgs = array();
        foreach ($oSearch->GetQueryParams() as $sParam => $foo) {
            $value = utils::ReadParam('arg_' . $sParam, null, true, 'raw_data');
            if (!is_null($value)) {
                $aArgs[$sParam] = $value;
            } else {
                throw new MissingQueryArgument("Missing parameter '--arg_{$sParam}'");
            }
        }
        $oSearch->SetInternalParams($aArgs);
        $sFormat = utils::ReadParam('format', 'html', true, 'raw_data');
        $oExporter = BulkExport::FindExporter($sFormat, $oSearch);
        if ($oExporter == null) {
            $aSupportedFormats = BulkExport::FindSupportedFormats();
            ReportErrorAndExit("Invalid output format: '{$sFormat}'. The supported formats are: " . implode(', ', array_keys($aSupportedFormats)));
        }
    } catch (MissingQueryArgument $e) {
        ReportErrorAndUsage("Invalid OQL query: '{$sExpression}'.\n" . $e->getMessage());
    } catch (OQLException $e) {
        ReportErrorAndExit("Invalid OQL query: '{$sExpression}'.\n" . $e->getMessage());
    } catch (Exception $e) {
        ReportErrorAndExit($e->getMessage());
    }
    $oExporter->SetFormat($sFormat);
    $oExporter->SetChunkSize(EXPORTER_DEFAULT_CHUNK_SIZE);
    $oExporter->SetObjectList($oSearch);
    $oExporter->ReadParameters();
    return $oExporter;
}
 /**
  * Do the synchronization job #3: Delete replica depending on the obsolescence scheme
  * @param integer $iMaxReplica Limit the number of replicas to process 
  * @param integer $iCurrPos Current position where to resume the processing 
  * @return true if the process must be continued
  */
 protected function DoJob3($iMaxReplica = null, $iCurrPos = -1)
 {
     $sDeletePolicy = $this->m_oDataSource->Get('delete_policy');
     if ($sDeletePolicy != 'update_then_delete') {
         // Job complete!
         $this->m_oStatLog->Set('status_curr_job', 0);
         $this->m_oStatLog->Set('status_curr_pos', -1);
         return false;
     }
     $bFirstPass = $iCurrPos == -1;
     // Get all the replicas that are to be deleted
     //
     $oDeletionDate = $this->m_oLastFullLoadStartDate;
     $iDeleteRetention = $this->m_oDataSource->Get('delete_policy_retention');
     // Duration in seconds
     if ($iDeleteRetention > 0) {
         $sInterval = "-{$iDeleteRetention} seconds";
         $oDeletionDate->Modify($sInterval);
     }
     $sDeletionDate = $oDeletionDate->Format('Y-m-d H:i:s');
     if ($bFirstPass) {
         $this->m_oStatLog->AddTrace("Deletion date: {$sDeletionDate}");
     }
     $sSelectToDelete = "SELECT SynchroReplica WHERE id > :curr_pos AND sync_source_id = :source_id AND status IN ('obsolete') AND status_last_seen < :last_import";
     $oSetScope = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToDelete), array(), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sDeletionDate, 'curr_pos' => $iCurrPos));
     $iCountScope = $oSetScope->Count();
     if ($iMaxReplica) {
         // Consider a given subset, starting from replica iCurrPos, limited to the count of iMaxReplica
         // The replica have to be ordered by id
         $oSetToProcess = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToDelete), array('id' => true), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sDeletionDate, 'curr_pos' => $iCurrPos));
         $oSetToProcess->SetLimit($iMaxReplica);
     } else {
         $oSetToProcess = $oSetScope;
     }
     $iLastReplicaProcessed = -1;
     while ($oReplica = $oSetToProcess->Fetch()) {
         $iLastReplicaProcessed = $oReplica->GetKey();
         $this->m_oStatLog->AddTrace("Destination object to be DELETED", $oReplica);
         $oReplica->DeleteDestObject($this->m_oChange, $this->m_oStatLog);
     }
     if ($iMaxReplica) {
         if ($iMaxReplica < $iCountScope) {
             // Continue with this job!
             $this->m_oStatLog->Set('status_curr_pos', $iLastReplicaProcessed);
             return true;
         }
     }
     // Job complete!
     $this->m_oStatLog->Set('status_curr_job', 0);
     $this->m_oStatLog->Set('status_curr_pos', -1);
     return false;
 }
 function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
 {
     $aRedundancySettings = $this->FindVisibleRedundancySettings();
     // Related objects: display all the linkset attributes, each as a separate tab
     // In the order described by the 'display' ZList
     $aList = $this->FlattenZList(MetaModel::GetZListItems(get_class($this), 'details'));
     if (count($aList) == 0) {
         // Empty ZList defined, display all the linkedset attributes defined
         $aList = array_keys(MetaModel::ListAttributeDefs(get_class($this)));
     }
     $sClass = get_class($this);
     foreach ($aList as $sAttCode) {
         $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
         // Display mode
         if (!$oAttDef->IsLinkset()) {
             continue;
         }
         // Process only linkset attributes...
         // $oSet = new DBObjectSet($this->Get($sAttCode)->GetFilter()); // Why do something so useless ?
         $oSet = $this->Get($sAttCode);
         $iCount = $oSet->Count();
         $sCount = '';
         if ($iCount != 0) {
             $sCount = " ({$iCount})";
         }
         $oPage->SetCurrentTab($oAttDef->GetLabel() . $sCount);
         if ($this->IsNew()) {
             $iFlags = $this->GetInitialStateAttributeFlags($sAttCode);
         } else {
             $iFlags = $this->GetAttributeFlags($sAttCode);
         }
         // Adjust the flags according to user rights
         if ($oAttDef->IsIndirect()) {
             $sLinkedClass = $oAttDef->GetLinkedClass();
             $oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote());
             $sTargetClass = $oLinkingAttDef->GetTargetClass();
             // n:n links => must be allowed to modify the linking class AND  read the target class in order to edit the linkedset
             if (!UserRights::IsActionAllowed($sLinkedClass, UR_ACTION_MODIFY) || !UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ)) {
                 $iFlags |= OPT_ATT_READONLY;
             }
             // n:n links => must be allowed to read the linking class AND  the target class in order to display the linkedset
             if (!UserRights::IsActionAllowed($sLinkedClass, UR_ACTION_READ) || !UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ)) {
                 $iFlags |= OPT_ATT_HIDDEN;
             }
         } else {
             // 1:n links => must be allowed to modify the linked class in order to edit the linkedset
             if (!UserRights::IsActionAllowed($oAttDef->GetLinkedClass(), UR_ACTION_MODIFY)) {
                 $iFlags |= OPT_ATT_READONLY;
             }
             // 1:n links => must be allowed to read the linked class in order to display the linkedset
             if (!UserRights::IsActionAllowed($oAttDef->GetLinkedClass(), UR_ACTION_READ)) {
                 $iFlags |= OPT_ATT_HIDDEN;
             }
         }
         // Non-readable/hidden linkedset... don't display anything
         if ($iFlags & OPT_ATT_HIDDEN) {
             continue;
         }
         $aArgs = array('this' => $this);
         $bReadOnly = $iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE);
         if ($bEditMode && !$bReadOnly) {
             $sInputId = $this->m_iFormId . '_' . $sAttCode;
             $sLinkedClass = $oAttDef->GetLinkedClass();
             if ($oAttDef->IsIndirect()) {
                 $oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote());
                 $sTargetClass = $oLinkingAttDef->GetTargetClass();
             } else {
                 $sTargetClass = $sLinkedClass;
             }
             $oPage->p(MetaModel::GetClassIcon($sTargetClass) . "&nbsp;" . $oAttDef->GetDescription() . '<span id="busy_' . $sInputId . '"></span>');
             $oValue = $this->Get($sAttCode);
             $sDisplayValue = '';
             // not used
             $sHTMLValue = "<span id=\"field_{$sInputId}\">" . self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $oValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs) . '</span>';
             $this->AddToFieldsMap($sAttCode, $sInputId);
             $oPage->add($sHTMLValue);
         } else {
             // Display mode
             if (!$oAttDef->IsIndirect()) {
                 // 1:n links
                 $sTargetClass = $oAttDef->GetLinkedClass();
                 $aDefaults = array($oAttDef->GetExtKeyToMe() => $this->GetKey());
                 $oAppContext = new ApplicationContext();
                 foreach ($oAppContext->GetNames() as $sKey) {
                     // The linked object inherits the parent's value for the context
                     if (MetaModel::IsValidAttCode($sClass, $sKey)) {
                         $aDefaults[$sKey] = $this->Get($sKey);
                     }
                 }
                 $aParams = array('target_attr' => $oAttDef->GetExtKeyToMe(), 'object_id' => $this->GetKey(), 'menu' => false, 'default' => $aDefaults, 'table_id' => $sClass . '_' . $sAttCode);
             } else {
                 // n:n links
                 $sLinkedClass = $oAttDef->GetLinkedClass();
                 $oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote());
                 $sTargetClass = $oLinkingAttDef->GetTargetClass();
                 $bMenu = $this->Get($sAttCode)->Count() > 0;
                 // The menu is enabled only if there are already some elements...
                 $aParams = array('link_attr' => $oAttDef->GetExtKeyToMe(), 'object_id' => $this->GetKey(), 'target_attr' => $oAttDef->GetExtKeyToRemote(), 'view_link' => false, 'menu' => false, 'display_limit' => true, 'table_id' => $sClass . '_' . $sAttCode);
             }
             $oPage->p(MetaModel::GetClassIcon($sTargetClass) . "&nbsp;" . $oAttDef->GetDescription());
             $oBlock = new DisplayBlock($this->Get($sAttCode)->GetFilter(), 'list', false);
             $oBlock->Display($oPage, 'rel_' . $sAttCode, $aParams);
         }
         if (array_key_exists($sAttCode, $aRedundancySettings)) {
             foreach ($aRedundancySettings[$sAttCode] as $oRedundancyAttDef) {
                 $sRedundancyAttCode = $oRedundancyAttDef->GetCode();
                 $sValue = $this->Get($sRedundancyAttCode);
                 $iRedundancyFlags = $this->GetFormAttributeFlags($sRedundancyAttCode);
                 $bRedundancyReadOnly = $iRedundancyFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE);
                 $oPage->add('<fieldset>');
                 $oPage->add('<legend>' . $oRedundancyAttDef->GetLabel() . '</legend>');
                 if ($bEditMode && !$bRedundancyReadOnly) {
                     $sInputId = $this->m_iFormId . '_' . $sRedundancyAttCode;
                     $oPage->add("<span id=\"field_{$sInputId}\">" . self::GetFormElementForField($oPage, $sClass, $sRedundancyAttCode, $oRedundancyAttDef, $sValue, '', $sInputId, '', $iFlags, $aArgs) . '</span>');
                 } else {
                     $oPage->add($oRedundancyAttDef->GetDisplayForm($sValue, $oPage, false, $this->m_iFormId));
                 }
                 $oPage->add('</fieldset>');
             }
         }
     }
     $oPage->SetCurrentTab('');
     foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) {
         $oExtensionInstance->OnDisplayRelations($this, $oPage, $bEditMode);
     }
     // Display Notifications after the other tabs since this tab disappears in edition
     if (!$bEditMode) {
         // Look for any trigger that considers this object as "In Scope"
         // If any trigger has been found then display a tab with notifications
         //
         $oTriggerSet = new CMDBObjectSet(new DBObjectSearch('Trigger'));
         $aTriggers = array();
         while ($oTrigger = $oTriggerSet->Fetch()) {
             if ($oTrigger->IsInScope($this)) {
                 $aTriggers[] = $oTrigger->GetKey();
             }
         }
         if (count($aTriggers) > 0) {
             $iId = $this->GetKey();
             $sTriggersList = implode(',', $aTriggers);
             $aNotifSearches = array();
             $iNotifsCount = 0;
             $aNotificationClasses = MetaModel::EnumChildClasses('EventNotification', ENUM_CHILD_CLASSES_EXCLUDETOP);
             foreach ($aNotificationClasses as $sNotifClass) {
                 $aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT {$sNotifClass} AS Ev JOIN Trigger AS T ON Ev.trigger_id = T.id WHERE T.id IN ({$sTriggersList}) AND Ev.object_id = {$iId}");
                 $oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass]);
                 $iNotifsCount += $oNotifSet->Count();
             }
             // Display notifications regarding the object: on block per subclass to have the intersting columns
             $sCount = $iNotifsCount > 0 ? ' (' . $iNotifsCount . ')' : '';
             $oPage->SetCurrentTab(Dict::S('UI:NotificationsTab') . $sCount);
             foreach ($aNotificationClasses as $sNotifClass) {
                 $oPage->p(MetaModel::GetClassIcon($sNotifClass, true) . '&nbsp;' . MetaModel::GetName($sNotifClass));
                 $oBlock = new DisplayBlock($aNotifSearches[$sNotifClass], 'list', false);
                 $oBlock->Display($oPage, 'notifications_' . $sNotifClass, array('menu' => false));
             }
         }
     }
 }
    public function DisplayAttachments($oObject, WebPage $oPage, $bEditMode = false)
    {
        // Exit here if the class is not allowed
        if (!$this->IsTargetObject($oObject)) {
            return;
        }
        $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
        $oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
        if ($this->GetAttachmentsPosition() == 'relations') {
            $sTitle = $oSet->Count() > 0 ? Dict::Format('Attachments:TabTitle_Count', $oSet->Count()) : Dict::S('Attachments:EmptyTabTitle');
            $oPage->SetCurrentTab($sTitle);
        }
        $oPage->add_style(<<<EOF
.attachment {
\tdisplay: inline-block;
\ttext-align:center;
\tfloat:left;
\tpadding:5px;\t
}
.attachment:hover {
\tbackground-color: #e0e0e0;
}
.attachment img {
\tborder: 0;
}
.attachment a {
\ttext-decoration: none;
\tcolor: #1C94C4;
}
.btn_hidden {
\tdisplay: none;
}
.drag_in {
\t-webkit-box-shadow:inset 0 0 10px 2px #1C94C4;
\tbox-shadow:inset 0 0 10px 2px #1C94C4;
}
EOF
);
        $oPage->add('<fieldset>');
        $oPage->add('<legend>' . Dict::S('Attachments:FieldsetTitle') . '</legend>');
        if ($bEditMode) {
            $sIsDeleteEnabled = $this->m_bDeleteEnabled ? 'true' : 'false';
            $iTransactionId = $oPage->GetTransactionId();
            $sClass = get_class($oObject);
            $sTempId = session_id() . '_' . $iTransactionId;
            $sDeleteBtn = Dict::S('Attachments:DeleteBtn');
            $oPage->add_script(<<<EOF
\tfunction RemoveAttachment(att_id)
\t{
\t\t\$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
\t\t\$('#display_attachment_'+att_id).hide();
\t\t\$('#attachment_plugin').trigger('remove_attachment', [att_id]);
\t\treturn false; // Do not submit the form !
\t}
\tfunction ajaxFileUpload()
\t{
\t\t//starting setting some animation when the ajax starts and completes
\t\t\$("#attachment_loading").ajaxStart(function(){
\t\t\t\$(this).show();
\t\t}).ajaxComplete(function(){
\t\t\t\$(this).hide();
\t\t});
\t\t
\t\t/*
\t\t\tprepareing ajax file upload
\t\t\turl: the url of script file handling the uploaded files
                        fileElementId: the file type of input element id and it will be the index of  \$_FILES Array()
\t\t\tdataType: it support json, xml
\t\t\tsecureuri:use secure protocol
\t\t\tsuccess: call back function when the ajax complete
\t\t\terror: callback function when the ajax failed
\t\t\t
                */
\t\t\$.ajaxFileUpload
\t\t(
\t\t\t{
\t\t\t\turl: GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.attachment.php?obj_class={$sClass}&temp_id={$sTempId}&operation=add', 
\t\t\t\tsecureuri:false,
\t\t\t\tfileElementId:'file',
\t\t\t\tdataType: 'json',
\t\t\t\tsuccess: function (data, status)
\t\t\t\t{
\t\t\t\t\tif(typeof(data.error) != 'undefined')
\t\t\t\t\t{
\t\t\t\t\t\tif(data.error != '')
\t\t\t\t\t\t{
\t\t\t\t\t\t\talert(data.error);
\t\t\t\t\t\t}
\t\t\t\t\t\telse
\t\t\t\t\t\t{
\t\t\t\t\t\t\tvar sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.att_id+'&field=contents';
\t\t\t\t\t\t\t\$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a data-preview="'+data.preview+'" href="'+sDownloadLink+'"><img src="'+data.icon+'"><br/>'+data.msg+'<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.att_id+');"/></div>');
\t\t\t\t\t\t\tif({$sIsDeleteEnabled})
\t\t\t\t\t\t\t{
\t\t\t\t\t\t\t\t\$('#display_attachment_'+data.att_id).hover( function() { \$(this).children(':button').toggleClass('btn_hidden'); } );
\t\t\t\t\t\t\t}
\t\t\t\t\t\t\t\$('#attachment_plugin').trigger('add_attachment', [data.att_id, data.msg]);
\t\t\t\t\t\t\t
\t\t\t\t\t\t\t//alert(data.msg);
\t\t\t\t\t\t}
\t\t\t\t\t}
\t\t\t\t},
\t\t\t\terror: function (data, status, e)
\t\t\t\t{
\t\t\t\t\talert(e);
\t\t\t\t}
\t\t\t}
\t\t)
\t\t
\t\treturn false;

\t}
EOF
);
            $oPage->add('<span id="attachments">');
            while ($oAttachment = $oSet->Fetch()) {
                $iAttId = $oAttachment->GetKey();
                $oDoc = $oAttachment->Get('contents');
                $sFileName = $oDoc->GetFileName();
                $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                $sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
                $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                $oPage->add('<div class="attachment" id="display_attachment_' . $iAttId . '"><a data-preview="' . $sPreview . '" href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input id="attachment_' . $iAttId . '" type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveAttachment(' . $iAttId . ');"/>&nbsp;</div>');
            }
            // Suggested attachments are listed here but treated as temporary
            $aDefault = utils::ReadParam('default', array(), false, 'raw_data');
            if (array_key_exists('suggested_attachments', $aDefault)) {
                $sSuggestedAttachements = $aDefault['suggested_attachments'];
                if (is_array($sSuggestedAttachements)) {
                    $sSuggestedAttachements = implode(',', $sSuggestedAttachements);
                }
                $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id IN({$sSuggestedAttachements})");
                $oSet = new DBObjectSet($oSearch, array());
                if ($oSet->Count() > 0) {
                    while ($oAttachment = $oSet->Fetch()) {
                        // Mark the attachments as temporary attachments for the current object/form
                        $oAttachment->Set('temp_id', $sTempId);
                        $oAttachment->DBUpdate();
                        // Display them
                        $iAttId = $oAttachment->GetKey();
                        $oDoc = $oAttachment->Get('contents');
                        $sFileName = $oDoc->GetFileName();
                        $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                        $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                        $sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
                        $oPage->add('<div class="attachment" id="display_attachment_' . $iAttId . '"><a data-preview="' . $sPreview . '" href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input id="attachment_' + data . result . att_id + '" type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveAttachment(' . $iAttId . ');"/>&nbsp;</div>');
                        $oPage->add_ready_script("\$('#attachment_plugin').trigger('add_attachment', [{$iAttId}, '" . addslashes($sFileName) . "']);");
                    }
                }
            }
            $oPage->add('</span>');
            $oPage->add('<div style="clear:both"></div>');
            $sMaxUpload = $this->GetMaxUpload();
            //			$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> '.$sMaxUpload);
            $oPage->p(Dict::S('Attachments:AddAttachment') . '<input type="file" name="file" id="file"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> ' . $sMaxUpload);
            $oPage->add_linked_script('../js/jquery.iframe-transport.js');
            $oPage->add_linked_script('../js/jquery.fileupload.js');
            $oPage->add_ready_script(<<<EOF
    \$('#file').fileupload({
\t\turl: GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.attachment.php',
\t\tformData: { operation: 'add', temp_id: '{$sTempId}', obj_class: '{$sClass}' },
        dataType: 'json',
        done: function (e, data) {
\t\t\tif(typeof(data.result.error) != 'undefined')
\t\t\t{
\t\t\t\tif(data.result.error != '')
\t\t\t\t{
\t\t\t\t\talert(data.result.error);
\t\t\t\t}
\t\t\t\telse
\t\t\t\t{
\t\t\t\t\tvar sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.result.att_id+'&field=contents';
\t\t\t\t\t\$('#attachments').append('<div class="attachment" id="display_attachment_'+data.result.att_id+'"><a data-preview="'+data.result.preview+'" href="'+sDownloadLink+'"><img src="'+data.result.icon+'"><br/>'+data.result.msg+'<input id="attachment_'+data.result.att_id+'" type="hidden" name="attachments[]" value="'+data.result.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.result.att_id+');"/></div>');
\t\t\t\t\tif({$sIsDeleteEnabled})
\t\t\t\t\t{
\t\t\t\t\t\t\$('#display_attachment_'+data.result.att_id).hover( function() { \$(this).children(':button').toggleClass('btn_hidden'); } );
\t\t\t\t\t}
\t\t\t\t\t\$('#attachment_plugin').trigger('add_attachment', [data.result.att_id, data.msg]);
\t\t\t\t}
\t\t\t}
        },
        start: function() {
        \t\$('#attachment_loading').show();
\t\t},
        stop: function() {
        \t\$('#attachment_loading').hide();
\t\t}
    });

\t\$(document).bind('dragover', function (e) {
\t\tvar bFiles = false;
\t\t
\t\tif (e.dataTransfer.types)
\t\t{
\t\t\tfor (var i = 0; i < e.dataTransfer.types.length; i++)
\t\t\t{
\t\t\t\tif (e.dataTransfer.types[i] == "text/plain")
\t\t\t\t{
\t\t\t\t\tbFiles = false; // mozilla contains "Files" in the types list when dragging images inside the page, but it also contains "text/plain" before
\t\t\t\t\tbreak;
\t\t\t\t}
\t\t\t\t
\t\t\t\tif (e.dataTransfer.types[i] == "Files")
\t\t\t\t{
\t\t\t\t\tbFiles = true;
\t\t\t\t\tbreak;
\t\t\t\t}
\t\t\t}
\t\t}
\t
\t\tif (!bFiles) return; // Not dragging files
\t\t
\t\tvar dropZone = \$('#file').closest('fieldset');
\t\tif (!dropZone.is(':visible'))
\t\t{
\t\t\t// Hidden, but inside an inactive tab? Higlight the tab
\t\t\tvar sTabId = dropZone.closest('.ui-tabs-panel').attr('aria-labelledby');
\t\t\tdropZone = \$('#'+sTabId).closest('li');
\t\t}
\t    timeout = window.dropZoneTimeout;
\t    if (!timeout) {
\t        dropZone.addClass('drag_in');
\t    } else {
\t        clearTimeout(timeout);
\t    }
\t    window.dropZoneTimeout = setTimeout(function () {
\t        window.dropZoneTimeout = null;
\t        dropZone.removeClass('drag_in');
\t    }, 300);
\t});   
EOF
);
            $oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
            $oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
            $oPage->add('</fieldset>');
            if ($this->m_bDeleteEnabled) {
                $oPage->add_ready_script('$(".attachment").hover( function() {$(this).children(":button").toggleClass("btn_hidden"); } );');
            }
        } else {
            $oPage->add('<span id="attachments">');
            if ($oSet->Count() == 0) {
                $oPage->add(Dict::S('Attachments:NoAttachment'));
            } else {
                while ($oAttachment = $oSet->Fetch()) {
                    $iAttId = $oAttachment->GetKey();
                    $oDoc = $oAttachment->Get('contents');
                    $sFileName = $oDoc->GetFileName();
                    $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                    $sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
                    $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                    $oPage->add('<div class="attachment" id="attachment_' . $iAttId . '"><a data-preview="' . $sPreview . '" href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '</a><input type="hidden" name="attachments[]" value="' . $iAttId . '"/><br/>&nbsp;&nbsp;</div>');
                }
            }
        }
        $sPreviewNotAvailable = addslashes(Dict::S('Attachments:PreviewNotAvailable'));
        $oPage->add_ready_script("\$(document).tooltip({ items: '.attachment a',  position: { my: 'left top', at: 'right top', using: function( position, feedback ) { \$( this ).css( position ); }}, content: function() { if (\$(this).attr('data-preview') == 'true') { return('<img style=\"max-width:290px\" src=\"'+\$(this).attr('href')+'\"></img>');} else { return '{$sPreviewNotAvailable}'; }}});");
    }
 public function GetHeader()
 {
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'running';
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $aData = array();
     foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
         $aData[] = $aFieldSpec['sColLabel'];
     }
     $sFrom = array("\r\n", $this->aStatusInfo['text_qualifier']);
     $sTo = array("\n", $this->aStatusInfo['text_qualifier'] . $this->aStatusInfo['text_qualifier']);
     foreach ($aData as $idx => $sData) {
         // Escape and encode (if needed) the headers
         $sEscaped = str_replace($sFrom, $sTo, (string) $sData);
         $aData[$idx] = $this->aStatusInfo['text_qualifier'] . $sEscaped . $this->aStatusInfo['text_qualifier'];
         if ($this->aStatusInfo['charset'] != 'UTF-8') {
             // Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string
             // and thus to convert field by field and not the whole row or file at once (see ticket #991)
             $aData[$idx] = iconv('UTF-8', $this->aStatusInfo['charset'] . '//IGNORE//TRANSLIT', $aData[$idx]);
         }
     }
     $sData = implode($this->aStatusInfo['separator'], $aData) . "\n";
     return $sData;
 }
 public function GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode)
 {
     if (isset($this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode])) {
         return $this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode];
     }
     // Get the permission for this profile/class/stimulus
     $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_StimulusGrant WHERE class = :class AND stimulus = :stimulus AND profileid = :profile AND permission = 'yes'");
     $oSet = new DBObjectSet($oSearch, array(), array('class' => $sClass, 'stimulus' => $sStimulusCode, 'profile' => $iProfile));
     if ($oSet->Count() >= 1) {
         $oGrantRecord = $oSet->Fetch();
     } else {
         $oGrantRecord = null;
     }
     $this->m_aClassStimulusGrants[$iProfile][$sClass][$sStimulusCode] = $oGrantRecord;
     return $oGrantRecord;
 }