Moved under "trunk" to be able to track releases under "tags"

SVN:trunk[55]
This commit is contained in:
Denis Flaven
2009-04-28 09:03:12 +00:00
parent 3c438e20ed
commit b756db0992
422 changed files with 62557 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
<?php
require_once("../application/webpage.class.inc.php");
/**
* Simple web page with no includes, header or fancy formatting, useful to
* generate HTML fragments when called by an AJAX method
*
* @package iTopApplication
* @access public
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <dflaven@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
*/
class ajax_page extends web_page
{
/**
* Jquery style ready script
* @var Hash
*/
protected $m_sReadyScript;
/**
* constructor for the web page
* @param string $s_title Not used
*/
function __construct($s_title)
{
parent::__construct($s_title);
$this->m_sReadyScript = "";
}
/**
* Echoes the content of the whole page
* @return void
*/
public function output()
{
foreach($this->a_headers as $s_header)
{
header($s_header);
}
$s_captured_output = ob_get_contents();
ob_end_clean();
echo trim($this->s_content);
if (!empty($this->m_sReadyScript))
{
echo "<script>\n";
echo $this->m_sReadyScript; // Ready Scripts are output as simple scripts
echo "</script>\n";
}
if (trim($s_captured_output) != "")
{
echo $s_captured_output;
}
}
/**
* Adds a paragraph with a smaller font into the page
* NOT implemented (i.e does nothing)
* @param string $sText Content of the (small) paragraph
* @return void
*/
public function small_p($sText)
{
}
/**
* Adds a tabular content to the web page
* @param Hash $aConfig Configuration of the table: hash array of 'column_id' => 'Column Label'
* @param Hash $aData Hash array. Data to display in the table: each row is made of 'column_id' => Data. A column 'pkey' is expected for each row
* @param Hash $aParams Hash array. Extra parameters for the table. Entry 'class' holds the class of the objects listed in the table
* @return void
*/
public function table($aConfig, $aData, $aParams = array())
{
// WARNING WARNING WARNING
// This whole function is actually a copy paste from iTopWebPage::table
$oAppContext = new ApplicationContext();
static $iNbTables = 0;
$iNbTables++;
$sHtml = "";
$sHtml .= "<table class=\"listResults\">\n";
$sHtml .= "<thead>\n";
$sHtml .= "<tr>\n";
foreach($aConfig as $sName=>$aDef)
{
$sHtml .= "<th title=\"".$aDef['description']."\">".$aDef['label']."</th>\n";
}
$sHtml .= "</tr>\n";
$sHtml .= "</thead>\n";
$sHtml .= "<tbody>\n";
foreach($aData as $aRow)
{
if (false) //(isset($aParams['preview']) && $aParams['preview'])
{
$sHtml .= "<tr id=\"Row_".$iNbTables."_".$aRow['key']."\" onClick=\"DisplayPreview(".$iNbTables.",".$aRow['key'].",'".$aParams['class']."')\">\n";
}
else if (isset($aRow['key']))
{
$sHtml .= "<tr onDblClick=\"DisplayDetails(".$aRow['key'].",'".$aParams['class']."')\">\n";
}
else
{
$sHtml .= "<tr>\n";
}
foreach($aConfig as $sName=>$aVoid)
{
if ($sName != 'key')
{
$sValue = empty($aRow[$sName]) ? '&nbsp;' : $aRow[$sName];
$sHtml .= "<td>$sValue</td>\n";
}
else
{
$sUIPage = cmdbAbstractObject::ComputeUIPage($aParams['class']);
$sHtml .= "<td><a class=\"no-arrow\" href=\"$sUIPage?operation=details&id=".$aRow['key']."&class=".$aParams['class']."&".$oAppContext->GetForLink()."\"><img src=\"../images/zoom.gif\" title=\"Details\" border=\"0\"></a></td>\n";
}
}
$sHtml .= "</tr>\n";
}
$sHtml .= "</tbody>\n";
$sHtml .= "</table>\n";
if (isset($aParams['preview']) && $aParams['preview'])
{
$sHtml .= "<div class=\"PreviewPane\" id=\"PreviewPane_".$iNbTables."\" style=\"height:100px;border:1px solid black;margin-top:2px;padding:3px;text-align:left;display:none;\">Preview Pane</div>";
}
$this->add($sHtml);
}
/**
* Adds a script to be executed when the DOM is ready (typical JQuery use)
* NOT implemented in this version of the class.
* @return void
*/
public function add_ready_script($sScript)
{
// Does nothing in ajax rendered content.. for now...
// Maybe we should add this as a simple <script> tag at the end of the output
// considering that at this time everything in the page is "ready"...
$this->m_sReadyScript .= $sScript;
}
}
?>

View File

@@ -0,0 +1,12 @@
<?php
// Includes all the classes to have the application up and running
require_once('../application/applicationcontext.class.inc.php');
require_once('../application/usercontext.class.inc.php');
require_once('../application/cmdbabstract.class.inc.php');
require_once('../application/displayblock.class.inc.php');
require_once('../application/iotask.class.inc.php');
require_once('../application/audit.category.class.inc.php');
require_once('../application/audit.rule.class.inc.php');
//require_once('../application/menunode.class.inc.php');
require_once('../application/utils.inc.php');
?>

View File

@@ -0,0 +1,81 @@
<?php
require_once("../application/utils.inc.php");
/**
* Helper class to store and manipulate the parameters that make the application's context
*
* Usage:
* 1) Build the application's context by constructing the object
* (the object will read some of the page's parameters)
*
* 2) Add these parameters to hyperlinks or to forms using the helper, functions
* GetForLink(), GetForForm() or GetAsHash()
*/
class ApplicationContext
{
protected $aNames;
protected $aValues;
public function __construct()
{
$this->aNames = array(
'org_id', 'menu'
);
$this->ReadContext();
}
/**
* Read the context directly in the PHP parameters (either POST or GET)
* return nothing
*/
protected function ReadContext()
{
$this->aValues = array();
foreach($this->aNames as $sName)
{
$sValue = utils::ReadParam($sName, '');
// TO DO: check if some of the context parameters are mandatory (or have default values)
if (!empty($sValue))
{
$this->aValues[$sName] = $sValue;
}
}
}
/**
* Returns the context as string with the format name1=value1&name2=value2....
* return string The context as a string to be appended to an href property
*/
public function GetForLink()
{
$aParams = array();
foreach($this->aValues as $sName => $sValue)
{
$aParams[] = $sName.'='.urlencode($sValue);
}
return implode("&", $aParams);
}
/**
* Returns the context as sequence of input tags to be inserted inside a <form> tag
* return string The context as a sequence of <input type="hidden" /> tags
*/
public function GetForForm()
{
$sContext = "";
foreach($this->aValues as $sName => $sValue)
{
$sContext .= "<input type=\"hidden\" name=\"$sName\" value=\"$sValue\" />\n";
}
return $sContext;
}
/**
* Returns the context as a hash array 'parameter_name' => value
* return array The context information
*/
public function GetAsHash()
{
return $this->aValues;
}
}
?>

View File

@@ -0,0 +1,45 @@
<?php
require_once('../application/cmdbabstract.class.inc.php');
/**
* This class manages the audit "categories". Each category defines a set of objects
* to check and is linked to a set of rules that determine the valid or invalid objects
* inside the set
*/
class AuditCategory extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "application",
"name" => "AuditCategory",
"description" => "A section inside the overall audit",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array('name'),
"db_table" => "priv_auditcategory",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../application/templates/audit_category.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Category Name", "description"=>"Short name for this category", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("label"=>"Audit Category Description", "description"=>"Long description for this audit category", "allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("definition_set", array("label"=>"Definition Set", "description"=>"SibusQL expression defining the set of objects to audit", "allowed_values"=>null, "sql"=>"definition_set", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("description");
MetaModel::Init_AddFilterFromAttribute("definition_set");
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'definition_set')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'description', )); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'description')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'description', 'definition_set')); // Criteria of the advanced search form
}
}
?>

View File

@@ -0,0 +1,52 @@
<?php
require_once('../application/audit.category.class.inc.php');
/**
* This class manages the audit "rule" linked to a given audit category.
* Each rule is based ona SibusQL expression that returns either the "good" objects
* or the "bad" ones. The core audit engines computes the complement to the definition
* set when needed to obtain either the valid objects, or the ones with an error
*/
class AuditRule extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "application",
"name" => "AuditRule",
"description" => "A rule to check for a given Audit category",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array('name'),
"db_table" => "priv_auditrule",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Rule Name", "description"=>"Short name for this rule", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("label"=>"Audit Rule Description", "description"=>"Long description for this audit rule", "allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("query", array("label"=>"Query to Run", "description"=>"The SibusQL expression to run", "allowed_values"=>null, "sql"=>"query", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("valid_flag", array("label"=>"Valid objects?", "description"=>"True if the rule returns the valid objects, false otherwise", "allowed_values"=>new ValueSetEnum('true,false'), "sql"=>"valid_flag", "default_value"=>"true", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("category_id", array("label"=>"Category", "description"=>"The category for this rule", "allowed_values"=>null, "sql"=>"category_id", "targetclass"=>"AuditCategory", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("category_name", array("label"=>"Category", "description"=>"Name of the category for this rule", "allowed_values"=>null, "extkey_attcode"=> 'category_id', "target_attcode"=>"name")));
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("description");
MetaModel::Init_AddFilterFromAttribute("query");
MetaModel::Init_AddFilterFromAttribute("valid_flag");
MetaModel::Init_AddFilterFromAttribute("category_id");
MetaModel::Init_AddFilterFromAttribute("category_name");
// Display lists
MetaModel::Init_SetZListItems('details', array('category_id', 'name', 'description', 'query', 'valid_flag')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('category_id', 'name', 'description', 'valid_flag')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('category_id', 'name', 'description', 'valid_flag')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('category_id', 'name', 'description', 'valid_flag', 'query')); // Criteria of the advanced search form
}
}
?>

View File

@@ -0,0 +1,647 @@
<?php
require_once('../core/cmdbobject.class.inc.php');
require_once('../application/utils.inc.php');
require_once('../application/applicationcontext.class.inc.php');
require_once('../application/ui.linkswidget.class.inc.php');
////////////////////////////////////////////////////////////////////////////////////
/**
* Abstract class that implements some common and useful methods for displaying
* the objects
*/
////////////////////////////////////////////////////////////////////////////////////
abstract class cmdbAbstractObject extends CMDBObject
{
public static function GetUIPage()
{
return './UI.php';
}
public static function ComputeUIPage($sClass)
{
static $aUIPagesCache = array(); // Cache to store the php page used to display each class of object
if (!isset($aUIPagesCache[$sClass]))
{
$UIPage = false;
if (is_callable("$sClass::GetUIPage"))
{
$UIPage = eval("return $sClass::GetUIPage();"); // May return false in case of error
}
$aUIPagesCache[$sClass] = $UIPage === false ? './UI.php' : $UIPage;
}
$sPage = $aUIPagesCache[$sClass];
return $sPage;
}
protected static function MakeHyperLink($sObjClass, $sObjKey, $aAvailableFields)
{
$oAppContext = new ApplicationContext();
$sExtClassNameAtt = MetaModel::GetNameAttributeCode($sObjClass);
$sPage = self::ComputeUIPage($sObjClass);
// Use the "name" of the target class as the label of the hyperlink
// unless it's not available in the external attributes...
if (isset($aAvailableFields[$sExtClassNameAtt]))
{
$sLabel = $aAvailableFields[$sExtClassNameAtt];
}
else
{
$sLabel = implode(' / ', $aAvailableFields);
}
$sHint = htmlentities("$sObjClass::$sObjKey");
return "<a href=\"$sPage?operation=details&class=$sObjClass&id=$sObjKey&".$oAppContext->GetForLink()."\" title=\"$sHint\">$sLabel</a>";
}
public function GetDisplayValue($sAttCode)
{
$sDisplayValue = "";
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
if ($sStateAttCode == $sAttCode)
{
$aStates = MetaModel::EnumStates(get_class($this));
$sDisplayValue = $aStates[$this->Get($sAttCode)]['label'];
}
else
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($oAtt->IsExternalKey())
{
// retrieve the "external fields" linked to this external key
$sTargetClass = $oAtt->GetTargetClass();
$aAvailableFields = array();
foreach (MetaModel::GetExternalFields(get_class($this), $sAttCode) as $oExtField)
{
$aAvailableFields[$oExtField->GetExtAttCode()] = $oExtField->GetAsHTML($this->Get($oExtField->GetCode()));
}
$sExtClassNameAtt = MetaModel::GetNameAttributeCode($sTargetClass);
// Use the "name" of the target class as the label of the hyperlink
// unless it's not available in the external fields...
if (isset($aAvailableFields[$sExtClassNameAtt]))
{
$sDisplayValue = $aAvailableFields[$sExtClassNameAtt];
}
else
{
$sDisplayValue = implode(' / ', $aAvailableFields);
}
}
else
{
$sDisplayValue = $this->GetAsHTML($sAttCode);
}
}
return $sDisplayValue;
}
function DisplayBareDetails(web_page $oPage)
{
$oPage->add($this->GetBareDetails($oPage));
}
function GetDisplayName()
{
return $this->GetAsHTML(MetaModel::GetNameAttributeCode(get_class($this)));
}
function GetBareDetails(web_page $oPage)
{
$sHtml = '';
$oAppContext = new ApplicationContext();
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
$aDetails = array();
$sClass = get_class($this);
$aList = MetaModel::GetZListItems($sClass, 'details');
foreach($aList as $sAttCode)
{
$iFlags = $this->GetAttributeFlags($sAttCode);
if ( ($iFlags & OPT_ATT_HIDDEN) == 0)
{
// The field is visible in the current state of the object
if ($sStateAttCode == $sAttCode)
{
// Special display for the 'state' attribute itself
$sDisplayValue = $this->GetState();
}
else
{
$sDisplayValue = $this->GetAsHTML($sAttCode);
}
$aDetails[] = array('label' => MetaModel::GetLabel($sClass, $sAttCode), 'value' => $sDisplayValue);
}
}
$sHtml .= $oPage->GetDetails($aDetails);
return $sHtml;
}
function DisplayDetails(web_page $oPage)
{
$sTemplate = Utils::ReadFromFile(MetaModel::GetDisplayTemplate(get_class($this)));
if (!empty($sTemplate))
{
$oTemplate = new DisplayTemplate($sTemplate);
$oTemplate->Render($oPage, array('class'=> get_class($this),'pkey'=> $this->GetKey(), 'name' => $this->GetName()));
}
else
{
// Standard Header with name, actions menu and history block
$oPage->add("<div class=\"page_header\">\n");
$oSingletonFilter = new DBObjectSearch(get_class($this));
$oSingletonFilter->AddCondition('pkey', array($this->GetKey()));
$oBlock = new MenuBlock($oSingletonFilter, 'popup', false);
$oBlock->Display($oPage, -1);
$oPage->add("<h1>".Metamodel::GetName(get_class($this)).": <span class=\"hilite\">".$this->GetDisplayName()."</span></h1>\n");
$oHistoryFilter = new DBObjectSearch('CMDBChangeOpSetAttribute');
$oHistoryFilter->AddCondition('objkey', $this->GetKey());
$oBlock = new HistoryBlock($oHistoryFilter, 'toggle', false);
$oBlock->Display($oPage, -1);
$oPage->add("</div>\n");
// Object's details
// template not found display the object using the *old style*
self::DisplayBareDetails($oPage);
// Related objects
$oPage->AddTabContainer('Related Objects');
$oPage->SetCurrentTabContainer('Related Objects');
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if ((get_class($oAttDef) == 'AttributeLinkedSetIndirect') || (get_class($oAttDef) == 'AttributeLinkedSet'))
{
$oPage->SetCurrentTab($oAttDef->GetLabel());
$oPage->p($oAttDef->GetDescription());
if (get_class($oAttDef) == 'AttributeLinkedSet')
{
$sTargetClass = $oAttDef->GetLinkedClass();
$oFilter = new DBObjectSearch($sTargetClass);
$oFilter->AddCondition($oAttDef->GetExtKeyToMe(), $this->GetKey()); // @@@ condition has same name as field ??
$oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oPage, 0);
}
else // get_class($oAttDef) == 'AttributeLinkedSetIndirect'
{
$sLinkClass = $oAttDef->GetLinkedClass();
// Transform the DBObjectSet into a CMBDObjectSet !!!
$aLinkedObjects = $this->Get($sAttCode)->ToArray(false);
if (count($aLinkedObjects) > 0)
{
$oSet = CMDBObjectSet::FromArray($sLinkClass, $aLinkedObjects);
$this->DisplaySet($oPage, $oSet, $oAttDef->GetExtKeyToMe());
}
}
}
}
$oPage->SetCurrentTab('');
}
}
function DisplayPreview(web_page $oPage)
{
$aDetails = array();
$sClass = get_class($this);
$aList = MetaModel::GetZListItems($sClass, 'preview');
foreach($aList as $sAttCode)
{
$aDetails[] = array('label' => MetaModel::GetLabel($sClass, $sAttCode), 'value' =>$this->GetAsHTML($sAttCode));
}
$oPage->details($aDetails);
}
// Comment by Rom: this helper may be used to display objects of class DBObject
// -> I am using this to display the changes history
public static function DisplaySet(web_page $oPage, CMDBObjectSet $oSet, $sLinkageAttribute = '')
{
$oPage->add(self::GetDisplaySet($oPage, $oSet, $sLinkageAttribute));
}
public static function GetDisplaySet(web_page $oPage, CMDBObjectSet $oSet, $sLinkageAttribute = '', $bDisplayMenu = true)
{
$sHtml = '';
$oAppContext = new ApplicationContext();
$sClassName = $oSet->GetFilter()->GetClass();
$aAttribs = array();
$aList = MetaModel::GetZListItems($sClassName, 'list');
if (!empty($sLinkageAttribute))
{
// The set to display is in fact a set of links between the object specified in the $sLinkageAttribute
// and other objects...
// The display will then group all the attributes related to the link itself:
// | Link_attr1 | link_attr2 | ... || Object_attr1 | Object_attr2 | Object_attr3 | .. | Object_attr_n |
$aAttDefs = MetaModel::ListAttributeDefs($sClassName);
assert(isset($aAttDefs[$sLinkageAttribute]));
$oAttDef = $aAttDefs[$sLinkageAttribute];
assert($oAttDef->IsExternalKey());
// First display all the attributes specific to the link record
foreach($aList as $sLinkAttCode)
{
$oLinkAttDef = $aAttDefs[$sLinkAttCode];
if ( (!$oLinkAttDef->IsExternalKey()) && (!$oLinkAttDef->IsExternalField()) )
{
$aDisplayList[] = $sLinkAttCode;
}
}
// Then display all the attributes neither specific to the link record nor to the 'linkage' object (because the latter are constant)
foreach($aList as $sLinkAttCode)
{
$oLinkAttDef = $aAttDefs[$sLinkAttCode];
if (($oLinkAttDef->IsExternalKey() && ($sLinkAttCode != $sLinkageAttribute))
|| ($oLinkAttDef->IsExternalField() && ($oLinkAttDef->GetKeyAttCode()!=$sLinkageAttribute)) )
{
$aDisplayList[] = $sLinkAttCode;
}
}
// First display all the attributes specific to the link
// Then display all the attributes linked to the other end of the relationship
$aList = $aDisplayList;
}
foreach($aList as $sAttCode)
{
$aAttribs['key'] = array('label' => '', 'description' => 'Click to display');
$aAttribs[$sAttCode] = array('label' => MetaModel::GetLabel($sClassName, $sAttCode), 'description' => MetaModel::GetDescription($sClassName, $sAttCode));
}
$aValues = array();
$oSet->Seek(0);
while ($oObj = $oSet->Fetch())
{
$aRow['key'] = $oObj->GetKey();
foreach($aList as $sAttCode)
{
$aRow[$sAttCode] = $oObj->GetAsHTML($sAttCode);
}
$aValues[] = $aRow;
}
$oMenuBlock = new MenuBlock($oSet->GetFilter());
$sHtml .= '<table class="listContainer">';
if ($bDisplayMenu)
{
$sHtml .= '<tr class="containerHeader"><td>';
$sHtml .= $oMenuBlock->GetRenderContent($oPage, $sLinkageAttribute);
$sHtml .= '</td></tr>';
}
$sHtml .= '<tr><td>';
$sHtml .= $oPage->GetTable($aAttribs, $aValues, array('class'=>$sClassName, 'filter'=>$oSet->GetFilter()->serialize(), 'preview' => true));
$sHtml .= '</td></tr>';
$sHtml .= '</table>';
return $sHtml;
}
static function DisplaySetAsCSV(web_page $oPage, CMDBObjectSet $oSet, $aParams = array())
{
$oPage->add(self::GetSetAsCSV($oSet, $aParams));
}
static function GetSetAsCSV(DBObjectSet $oSet, $aParams = array())
{
$sSeparator = isset($aParams['separator']) ? $aParams['separator'] : ','; // default separator is comma
$sTextQualifier = isset($aParams['text_qualifier']) ? $aParams['text_qualifier'] : '"'; // default text qualifier is double quote
$oAppContext = new ApplicationContext();
$sClassName = $oSet->GetFilter()->GetClass();
$aAttribs = array();
$aList = MetaModel::GetZListItems($sClassName, 'details');
$aHeader = array();
$aHeader[] = MetaModel::GetKeyLabel($sClassName);
foreach($aList as $sAttCode)
{
$aHeader[] = MetaModel::GetLabel($sClassName, $sAttCode);
}
$sHtml = '#'.$oSet->GetFilter()->ToOQL()."\n";
$sHtml .= implode($sSeparator, $aHeader)."\n";
$oSet->Seek(0);
while ($oObj = $oSet->Fetch())
{
$aRow = array();
$aRow[] = $oObj->GetKey();
foreach($aList as $sAttCode)
{
if (strstr($oObj->Get($sAttCode), $sSeparator)) // Escape the text only when it contains the separator
{
$aRow[] = $sTextQualifier.$oObj->Get($sAttCode).$sTextQualifier;
}
else
{
$aRow[] = $oObj->Get($sAttCode);
}
}
$sHtml .= implode($sSeparator, $aRow)."\n";
}
return $sHtml;
}
static function DisplaySetAsXML(web_page $oPage, CMDBObjectSet $oSet, $aParams = array())
{
$oAppContext = new ApplicationContext();
$sClassName = $oSet->GetFilter()->GetClass();
$aAttribs = array();
$aList = MetaModel::GetZListItems($sClassName, 'details');
$oPage->add("<Set>\n");
$oSet->Seek(0);
while ($oObj = $oSet->Fetch())
{
$oPage->add("<$sClassName id=\"".$oObj->GetKey()."\">\n");
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode=>$oAttDef)
{
if (($oAttDef->IsWritable()) && ($oAttDef->IsScalar()) && ($sAttCode != 'finalclass') )
{
$sValue = $oObj->GetAsXML($sAttCode);
$oPage->add("<$sAttCode>$sValue</$sAttCode>\n");
}
}
$oPage->add("</$sClassName>\n");
}
$oPage->add("</Set>\n");
}
// By rom
function DisplayChangesLog(web_page $oPage)
{
$oFltChangeOps = new CMDBSearchFilter('CMDBChangeOpSetAttribute');
$oFltChangeOps->AddCondition('objkey', $this->GetKey(), '=');
$oFltChangeOps->AddCondition('objclass', get_class($this), '=');
$oSet = new CMDBObjectSet($oFltChangeOps, array('date' => false)); // order by date descending (i.e. false)
$count = $oSet->Count();
if ($count > 0)
{
$oPage->p("Changes log ($count):");
self::DisplaySet($oPage, $oSet);
}
else
{
$oPage->p("Changes log is empty");
}
}
public static function DisplaySearchForm(web_page $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
{
$oPage->add(self::GetSearchForm($oPage, $oSet, $aExtraParams));
}
public static function GetSearchForm(web_page $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
{
$sHtml = '';
$numCols=4;
$sClassName = $oSet->GetFilter()->GetClass();
$oUnlimitedFilter = new DBObjectSearch($sClassName);
$sHtml .= "<form>\n";
$index = 0;
$sHtml .= "<table>\n";
$aFilterCriteria = $oSet->GetFilter()->GetCriteria();
$aMapCriteria = array();
foreach($aFilterCriteria as $aCriteria)
{
$aMapCriteria[$aCriteria['filtercode']][] = array('value' => $aCriteria['value'], 'opcode' => $aCriteria['opcode']);
}
$aList = MetaModel::GetZListItems($sClassName, 'standard_search');
foreach($aList as $sFilterCode)
{
if (($index % $numCols) == 0)
{
if ($index != 0)
{
$sHtml .= "</tr>\n";
}
$sHtml .= "<tr>\n";
}
$sFilterValue = '';
$sFilterValue = utils::ReadParam($sFilterCode, '');
$sFilterOpCode = null; // Use the default 'loose' OpCode
if (empty($sFilterValue))
{
if (isset($aMapCriteria[$sFilterCode]))
{
if (count($aMapCriteria[$sFilterCode]) > 1)
{
$sFilterValue = '* mixed *';
}
else
{
$sFilterValue = $aMapCriteria[$sFilterCode][0]['value'];
$sFilterOpCode = $aMapCriteria[$sFilterCode][0]['opcode'];
}
if ($sFilterCode != 'company')
{
$oUnlimitedFilter->AddCondition($sFilterCode, $sFilterValue, $sFilterOpCode);
}
}
}
$aAllowedValues = MetaModel::GetAllowedValues_flt($sClassName, $sFilterCode, array(), '');
if ($aAllowedValues != null)
{
//Enum field or external key, display a combo
$sValue = "<select name=\"$sFilterCode\">\n";
$sValue .= "<option value=\"\">* Any *</option>\n";
foreach($aAllowedValues as $key => $value)
{
if ($sFilterValue == $key)
{
$sSelected = ' selected';
}
else
{
$sSelected = '';
}
$sValue .= "<option value=\"$key\"$sSelected>$value</option>\n";
}
$sValue .= "</select>\n";
$sHtml .= "<td><label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label></td><td>$sValue</td>\n";
}
else
{
// Any value is possible, display an input box
$sHtml .= "<td><label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label></td><td><input class=\"textSearch\" name=\"$sFilterCode\" value=\"$sFilterValue\"/></td>\n";
}
$index++;
}
if (($index % $numCols) != 0)
{
$sHtml .= "<td colspan=\"".(2*($numCols - ($index % $numCols)))."\"></td>\n";
}
$sHtml .= "</tr>\n";
$sHtml .= "<tr><td colspan=\"".(2*$numCols)."\" align=\"right\"><input type=\"submit\" value=\" Search \"></td></tr>\n";
$sHtml .= "</table>\n";
foreach($aExtraParams as $sName => $sValue)
{
$sHtml .= "<input type=\"hidden\" name=\"$sName\" value=\"$sValue\">\n";
}
$sHtml .= "<input type=\"hidden\" name=\"dosearch\" value=\"1\">\n";
$sHtml .= "</form>\n";
// Soem Debug dumps...
//$sHtml .= "<tt>".$oSet->GetFilter()->__DescribeHTML()."</tt><br/>\n";
//$sHtml .= "<tt>encoding=\"text/serialize\" : ".$oSet->GetFilter()->serialize()."</tt><br/>\n";
//$sHtml .= "<tt>encoding=\"text/sibusql\" : ".$oSet->GetFilter()->ToSibusQL()."</tt><br/>\n";
//$sHtml .= "<tt>(Unlimited) ".$oUnlimitedFilter->__DescribeHTML()."</tt><br/>\n";
//$sHtml .= "<tt>encoding=\"text/serialize\" : ".$oUnlimitedFilter->serialize()."</tt><br/>\n";
//$sHtml .= "<tt>encoding=\"text/sibusql\" : ".$oUnlimitedFilter->ToSibusQL()."</tt>\n";
return $sHtml;
}
public static function GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value = '', $sDisplayValue = '', $iId = '')
{
static $iInputId = 0;
if (!empty($iId))
{
$iInputId = $iId;
}
else
{
$iInputId++;
}
if (!$oAttDef->IsExternalField())
{
switch($oAttDef->GetEditClass())
{
case 'Date':
$sHTMLValue = "<input type=\"text\" size=\"20\" name=\"attr_$sAttCode\" value=\"$value\" id=\"$iInputId\" class=\"date-pick\"/>";
break;
case 'Text':
$sHTMLValue = "<textarea name=\"attr_$sAttCode\" rows=\"8\" cols=\"40\" id=\"$iInputId\">$value</textarea>";
break;
case 'List':
$oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId);
$sHTMLValue = $oWidget->Display($oPage, $value);
break;
case 'String':
default:
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array(), '');
if ($aAllowedValues !== null)
{
//Enum field or external key, display a combo
if (count($aAllowedValues) == 0)
{
$sHTMLValue = "<input type=\"text\" size=\"70\" value=\"\" name=\"attr_$sAttCode\" id=\"$iInputId\"/>";
}
else if (count($aAllowedValues) > 20)
{
// too many choices, use an autocomplete
// The input for the auto complete
$sHTMLValue = "<input type=\"text\" id=\"$iInputId\" size=\"50\" name=\"\" value=\"$sDisplayValue\" />";
// another hidden input to store & pass the object's Id
$sHTMLValue .= "<input type=\"hidden\" id=\"id_ac_$iInputId\" name=\"attr_$sAttCode\" value=\"$value\" />\n";
$oPage->add_ready_script("\$('#$iInputId').autocomplete('./ajax.render.php', { minChars:3, onItemSelect:selectItem, onFindValue:findValue, formatItem:formatItem, autoFill:true, keyHolder:'#id_ac_$iInputId', extraParams:{operation:'autocomplete', sclass:'$sClass',attCode:'".$sAttCode."'}});");
}
else
{
// Few choices, use a normal 'select'
$sHTMLValue = "<select name=\"attr_$sAttCode\" id=\"$iInputId\">\n";
foreach($aAllowedValues as $key => $display_value)
{
$sSelected = ($value == $key) ? ' selected' : '';
$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
}
$sHTMLValue .= "</select>\n";
}
}
else
{
$sHTMLValue = "<input type=\"text\" size=\"50\" name=\"attr_$sAttCode\" value=\"$value\" id=\"$iInputId\">";
}
}
}
return $sHTMLValue;
}
public function DisplayModifyForm(web_page $oPage)
{
$oAppContext = new ApplicationContext();
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
$iKey = $this->GetKey();
$aDetails = array();
$oPage->add("<form method=\"post\">\n");
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if ('finalclass' == $sAttCode) // finalclass is a reserved word, hardcoded !
{
// Do nothing, the class field is always hidden, it cannot be edited
}
else if ($sStateAttCode == $sAttCode)
{
// State attribute is always read-only from the UI
$sHTMLValue = $this->GetState();
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
else if (!$oAttDef->IsExternalField())
{
$iFlags = $this->GetAttributeFlags($sAttCode);
if ($iFlags & OPT_ATT_HIDDEN)
{
// Attribute is hidden, do nothing
}
else
{
if ($iFlags & OPT_ATT_READONLY)
{
// Attribute is read-only
$sHTMLValue = $this->GetAsHTML($sAttCode);
}
else
{
$sValue = $this->Get($sAttCode);
$sDisplayValue = $this->GetDisplayValue($sAttCode);
$sHTMLValue = self::GetFormElementForField($oPage, get_class($this), $sAttCode, $oAttDef, $sValue, $sDisplayValue);
}
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
}
}
$oPage->details($aDetails);
$oPage->add("<input type=\"hidden\" name=\"id\" value=\"$iKey\">\n");
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"".get_class($this)."\">\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_modify\">\n");
$oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
$oPage->add($oAppContext->GetForForm());
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span>Cancel</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>Apply</span></button>\n");
$oPage->add("</form>\n");
}
public static function DisplayCreationForm(web_page $oPage, $sClass, $oObjectToClone = null)
{
$oAppContext = new ApplicationContext();
$aDetails = array();
$sOperation = ($oObjectToClone == null) ? 'apply_new' : 'apply_clone';
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($oObjectToClone));
$oPage->add("<form method=\"post\">\n");
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
{
if ('finalclass' == $sAttCode) // finalclass is a reserved word, hardcoded !
{
// Do nothing, the class field is always hidden, it cannot be edited
}
else if ($sStateAttCode == $sAttCode)
{
// State attribute is always read-only from the UI
$sHTMLValue = $oObjectToClone->GetState();
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
else if (!$oAttDef->IsExternalField())
{
$sValue = ($oObjectToClone == null) ? '' : $oObjectToClone->Get($sAttCode);
$sDisplayValue = ($oObjectToClone == null) ? '' : $oObjectToClone->GetDisplayValue($sAttCode);
$sHTMLValue = self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue);
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
}
$oPage->details($aDetails);
if ($oObjectToClone != null)
{
$oPage->add("<input type=\"hidden\" name=\"clone_id\" value=\"".$oObjectToClone->GetKey()."\">\n");
}
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"$sOperation\">\n");
$oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
$oPage->add($oAppContext->GetForForm());
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span>Cancel</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>Apply</span></button>\n");
$oPage->add("</form>\n");
}
}
?>

View File

@@ -0,0 +1,35 @@
<?php
require_once("../application/webpage.class.inc.php");
/**
* Simple web page with no includes or fancy formatting, useful to generateXML documents
* The page adds the content-type text/XML and the encoding into the headers
*/
class CSVPage extends web_page
{
function __construct($s_title)
{
parent::__construct($s_title);
$this->add_header("Content-type: text/html; charset=iso-8859-1");
$this->add_header("Cache-control: no-cache");
}
public function output()
{
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
foreach($this->a_headers as $s_header)
{
header($s_header);
}
echo trim($this->s_content);
}
public function small_p($sText)
{
}
public function table($aConfig, $aData, $aParams = array())
{
}
}
?>

View File

@@ -0,0 +1,252 @@
<?php
/**
* Helper class to allow modal-style dialog box in an html form
*
* Possible improvement: do not use _SESSION for the caller's data,
* instead set a member variable with caller information
* and take the opportunity of the first edit button to place the information
* into a hidden field
*
* Usage:
*/
define('DLGSTACK_OK', 1);
define('DLGSTACK_CANCEL', 2);
//session_name("dialogstack");
session_start();
class dialogstack
{
private static $m_bCurrPageDeclared = false;
/**
* Declare the current page as being a dialog issuer, potentially pop...
*/
static public function DeclareCaller($sTitle)
{
self::$m_bCurrPageDeclared = false;
$_SESSION['dialogstack_calleruri'] = $_SERVER["REQUEST_URI"];
$_SESSION['dialogstack_callertitle'] = $sTitle;
if (isset($_POST["dialogstackpop"]) && ($_POST["dialogstackpop"] == count($_SESSION['dialogstack_currdlg'])))
{
// Pop !
array_pop($_SESSION['dialogstack_currdlg']);
}
}
/**
* True if the current page has been loaded from an "dialog startup button"
*/
static private function GetRetArgName()
{
foreach($_REQUEST as $sArgName=>$sArgValue)
{
if (strstr($sArgName, "dlgstack_go,"))
{
$aTokens = explode(",", $sArgName);
return self::ArgNameDecode($aTokens[1]);
}
}
return "";
}
/**
* Protect against weird effects of PHP interpreting brackets...
*/
static private function ArgNameEncode($sArgName)
{
return str_replace(array('[', ']'), array('_bracket_open_', '_bracket_close_'), $sArgName);
}
static private function ArgNameDecode($sCodedArgName)
{
return str_replace(array('_bracket_open_', '_bracket_close_'), array('[', ']'), $sCodedArgName);
}
/**
* True if the current page has been loaded from an "dialog startup button"
*/
static public function IsDialogStartup()
{
return (strlen(self::GetRetArgName()) > 0);
}
/**
* Helper to
*/
static private function RemoveArg(&$aValues, $sKey, &$retval = null)
{
if (isset($aValues[$sKey]))
{
if (empty($retval))
{
$retval = $aValues[$sKey];
}
unset($aValues[$sKey]);
}
}
/**
* Record current page args, and returns the initial value for the dialog
*/
static public function StartDialog()
{
if (!isset($_SESSION['dialogstack_currdlg']))
{
// Init stack
$_SESSION['dialogstack_currdlg'] = array();
}
$sRetArgName = self::GetRetArgName();
$sCodedArgName = self::ArgNameEncode($sRetArgName);
$sArgForRetArgName = "dlgstack_init_".$sCodedArgName;
$sButtonName = "dlgstack_go,".$sCodedArgName;
// Do not record utility arguments, neither the current value (stored separately)
//
$initValue = null;
$aPost = $_POST;
self::RemoveArg($aPost, $sArgForRetArgName, $initValue);
self::RemoveArg($aPost, $sButtonName);
self::RemoveArg($aPost, 'dlgstack_onok_page', $sOnOKPage);
self::RemoveArg($aPost, 'dlgstack_onok_args', $aOnOKArgs);
$aGet = $_GET;
self::RemoveArg($aGet, $sArgForRetArgName, $initValue);
self::RemoveArg($aGet, $sButtonName);
self::RemoveArg($aGet, 'dlgstack_onok_page', $sOnOKPage);
self::RemoveArg($aGet, 'dlgstack_onok_args', $aOnOKArgs);
if (self::$m_bCurrPageDeclared)
{
throw new Exception("DeclareCaller() must not be called before StartDialog()");
}
$aCall = array(
"title"=>$_SESSION['dialogstack_callertitle'],
"uri"=>$_SESSION['dialogstack_calleruri'],
"post"=>$aPost,
"get"=>$aGet,
"retarg"=>$sRetArgName,
"initval"=>$initValue,
);
if (isset($sOnOKPage)) $aCall["onok_page"] = $sOnOKPage;
if (isset($aOnOKArgs)) $aCall["onok_args"] = $aOnOKArgs;
array_push($_SESSION['dialogstack_currdlg'], $aCall);
return $initValue;
}
/**
* Render a button to launch a new dialog
*/
static public function RenderEditableField($sTitle, $sArgName, $sCurrValue, $bAddFieldValue, $sOnOKPage = "", $aOnOKArgs = array())
{
$sRet = "";
$sCodedArgName = self::ArgNameEncode($sArgName);
if ($bAddFieldValue)
{
$sRet .= "<input type=\"hidden\" name=\"$sArgName\" value=\"$sCurrValue\">\n";
}
$sRet .= "<input type=\"hidden\" name=\"dlgstack_init_$sCodedArgName\" value=\"$sCurrValue\">\n";
$sRet .= "<input type=\"submit\" name=\"dlgstack_go,$sCodedArgName\" value=\"$sTitle\">\n";
if (!empty($sOnOKPage))
{
$sRet .= "<input type=\"hidden\" name=\"dlgstack_onok_page\" value=\"$sCurrValue\">\n";
}
foreach($aOnOKArgs as $sArgName=>$value)
{
$sRet .= "<input type=\"hidden\" name=\"dlgstack_onok_args[$sArgName]\" value=\"$value\">\n";
}
return $sRet;
}
/**
* Render a [set of] hidden field, from a value that may be an array
*/
static private function RenderHiddenField($sName, $value)
{
$sRet = "";
if (is_array($value))
{
foreach($value as $sKey=>$subvalue)
{
$sRet .= self::RenderHiddenField($sName.'['.$sKey.']', $subvalue);
}
}
else
{
$sRet .= "<input type=\"hidden\" name=\"$sName\" value=\"$value\">\n";
}
return $sRet;
}
/**
* Render a form to end the current dialog and return to the caller
*/
static public function RenderEndDialogForm($iButtonStyle, $sTitle, $sRetValue = null)
{
$aCall = end($_SESSION['dialogstack_currdlg']);
if (!$aCall) return;
return self::privRenderEndDialogForm($aCall, $iButtonStyle, $sTitle, $sRetValue);
}
/**
* Returns an array of buttons to get back to upper dialog levels
*/
static public function GetCurrentStack()
{
$aRet = array();
if (isset($_SESSION['dialogstack_currdlg']))
{
foreach ($_SESSION['dialogstack_currdlg'] as $aCall)
{
$aRet[] = self::privRenderEndDialogForm($aCall, DLGSTACK_CANCEL, $aCall["title"]);
}
}
return $aRet;
}
/**
* Render a form to end the current dialog and return to the caller
*/
static private function privRenderEndDialogForm($aCall, $iButtonStyle, $sTitle, $sRetValue = null)
{
if (($iButtonStyle == DLGSTACK_OK) && isset($aCall["onok_page"])) $sFormAction = $aCall["onok_page"];
else $sFormAction = $aCall["uri"];
$sRet = "<form method=\"post\" action=\"$sFormAction\">\n";
foreach ($aCall["post"] as $sName=>$value)
{
$sRet .= self::RenderHiddenField($sName, $value);
}
if ($iButtonStyle == DLGSTACK_OK)
{
if (isset($aCall["onok_args"]))
{
foreach($aCall["onok_args"] as $sArgName=>$value)
{
$sRet .= "<input type=\"hidden\" name=\"$sArgName\" value=\"$value\">\n";
}
}
$sRet .= "<input type=\"hidden\" name=\"".$aCall["retarg"]."\" value=\"$sRetValue\">\n";
$sRet .= "<input type=\"submit\" name=\"dlgstackOK\" value=\"$sTitle, (OK) Back to ".$aCall["title"]."\">\n";
}
elseif ($iButtonStyle == DLGSTACK_CANCEL)
{
if (!is_null($aCall["initval"]))
{
$sRet .= "<input type=\"hidden\" name=\"".$aCall["retarg"]."\" value=\"".$aCall["initval"]."\">\n";
}
$sRet .= "<input type=\"submit\" name=\"dlgstackCANCEL\" value=\"$sTitle\">\n";
}
else
{
throw new Exception("Wrong value for button style ($iButtonStyle)");
}
$sRet .= "<input type=\"hidden\" name=\"dialogstackpop\" value=\"".count($_SESSION['dialogstack_currdlg'])."\">\n";
$sRet .= "</form>\n";
return $sRet;
}
}
?>

View File

@@ -0,0 +1,686 @@
<?php
require_once('../application/webpage.class.inc.php');
require_once('../application/utils.inc.php');
require_once('../core/userrights.class.inc.php');
/**
* Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects
*
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
* The list of cmdbObjects to be displayed into the block is defined by a filter
* Right now the type of display is either: list, count, bare_details, details, csv, modify or search
* - list produces a table listing the objects
* - count produces a paragraphs with a sentence saying 'cont' objects found
* - bare_details displays just the details of the attributes of the object (best if only one)
* - details display the full details of each object found using its template (best if only one)
* - csv displays a textarea with the CSV export of the list of objects
* - modify displays the form to modify an object (best if only one)
* - search displays a search form with the criteria of the filter set
*/
class DisplayBlock
{
const TAG_BLOCK = 'itopblock';
protected $m_oFilter;
protected $m_sStyle;
protected $m_bAsynchronous;
protected $m_aParams;
protected $m_oSet;
public function __construct(DBObjectSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null)
{
$this->m_oFilter = $oFilter;
$this->m_sStyle = $sStyle;
$this->m_bAsynchronous = $bAsynchronous;
$this->m_aParams = $aParams;
$this->m_oSet = $oSet;
}
/**
* Constructs a DisplayBlock object from a DBObjectSet already in memory
* @param $oSet DBObjectSet
* @return DisplayBlock The DisplayBlock object, or null if the creation failed
*/
public static function FromObjectSet(DBObjectSet $oSet, $sStyle, $aParams = array())
{
$oDummyFilter = new DBObjectSearch($oSet->GetClass());
$oBlock = new DisplayBlock($oDummyFilter, $sStyle, false, $aParams, $oSet); // DisplayBlocks built this way are synchronous
return $oBlock;
}
/**
* Constructs a DisplayBlock object from an XML template
* @param $sTemplate string The XML template
* @return DisplayBlock The DisplayBlock object, or null if the template is invalid
*/
public static function FromTemplate($sTemplate)
{
$iStartPos = stripos($sTemplate, '<'.self::TAG_BLOCK.' ',0);
$iEndPos = stripos($sTemplate, '</'.self::TAG_BLOCK.'>', $iStartPos);
if (($iStartPos === false) || ($iEndPos === false)) return null; // invalid template
$sITopBlock = substr($sTemplate,$iStartPos, $iEndPos-$iStartPos);
$sITopData = substr($sITopBlock, 1+stripos($sITopBlock, ">"));
$sITopTag = substr($sITopBlock, 0, stripos($sITopBlock, ">"));
$aMatches = array();
$sBlockClass = "DisplayBlock";
$bAsynchronous = false;
$sBlockType = 'list';
$sEncoding = 'text/serialize';
if (preg_match('/ type="(.*)"/U',$sITopTag, $aMatches))
{
$sBlockType = strtolower($aMatches[1]);
}
if (preg_match('/ asynchronous="(.*)"/U',$sITopTag, $aMatches))
{
$bAsynchronous = (strtolower($aMatches[1]) == 'true');
}
if (preg_match('/ blockclass="(.*)"/U',$sITopTag, $aMatches))
{
$sBlockClass = $aMatches[1];
}
if (preg_match('/ objectclass="(.*)"/U',$sITopTag, $aMatches))
{
$sObjectClass = $aMatches[1];
}
if (preg_match('/ encoding="(.*)"/U',$sITopTag, $aMatches))
{
$sEncoding = strtolower($aMatches[1]);
}
if (preg_match('/ linkage="(.*)"/U',$sITopTag, $aMatches))
{
// The list to display is a list of links to the specified object
$sExtKey = strtolower($aMatches[1]);
$aParams['linkage'] = $sExtKey; // Name of the Ext. Key that make this linkage
}
// Parameters contains a list of extra parameters for the block
// the syntax is param_name1:value1;param_name2:value2;...
$aParams = array();
if (preg_match('/ parameters="(.*)"/U',$sITopTag, $aMatches))
{
$sParameters = $aMatches[1];
$aPairs = explode(';', $sParameters);
foreach($aPairs as $sPair)
{
if (preg_match('/(.*)\:(.*)/',$sPair, $aMatches))
{
$aParams[trim($aMatches[1])] = trim($aMatches[2]);
}
}
}
switch($sEncoding)
{
case 'text/serialize':
$oFilter = CMDBSearchFilter::unserialize($sITopData);
break;
case 'text/sibusql':
$oFilter = CMDBSearchFilter::FromSibusQL($sITopData);
break;
case 'text/oql':
$oFilter = CMDBSearchFilter::FromOQL($sITopData);
break;
}
return new $sBlockClass($oFilter, $sBlockType, $bAsynchronous, $aParams);
}
public function Display(web_page $oPage, $sId, $aExtraParams = array())
{
$aExtraParams = array_merge($aExtraParams, $this->m_aParams);
if (!$this->m_bAsynchronous)
{
// render now
$oPage->add("<div id=\"$sId\" class=\"display_block\">\n");
$this->RenderContent($oPage, $aExtraParams);
$oPage->add("</div>\n");
}
else
{
// render it as an Ajax (asynchronous) call
$sFilter = $this->m_oFilter->serialize();
$oPage->add("<div id=\"$sId\" class=\"display_block loading\">\n");
$oPage->p("<img src=\"../images/indicator_arrows.gif\"> Loading...");
$oPage->add("</div>\n");
$oPage->add('
<script language="javascript">
$.get("ajax.render.php?filter='.$sFilter.'&style='.$this->m_sStyle.'",
{ operation: "ajax" },
function(data){
$("#'.$sId.'").empty();
$("#'.$sId.'").append(data);
$("#'.$sId.'").removeClass("loading");
}
);
</script>'); // TO DO: add support for $aExtraParams in asynchronous/Ajax mode
}
}
public function GetDisplay(web_page $oPage, $sId, $aExtraParams = array())
{
$sHtml = '';
$aExtraParams = array_merge($aExtraParams, $this->m_aParams);
if (!$this->m_bAsynchronous)
{
// render now
$sHtml .= "<div id=\"$sId\" class=\"display_block\">\n";
$sHtml .= $this->GetRenderContent($oPage, $aExtraParams);
$sHtml .= "</div>\n";
}
else
{
// render it as an Ajax (asynchronous) call
$sFilter = $this->m_oFilter->serialize();
$sHtml .= "<div id=\"$sId\" class=\"display_block loading\">\n";
$sHtml .= $oPage->GetP("<img src=\"../images/indicator_arrows.gif\"> Loading...");
$sHtml .= "</div>\n";
$sHtml .= '
<script language="javascript">
$.get("ajax.render.php?filter='.$sFilter.'&style='.$this->m_sStyle.'",
{ operation: "ajax" },
function(data){
$("#'.$sId.'").empty();
$("#'.$sId.'").append(data);
$("#'.$sId.'").removeClass("loading");
}
);
</script>'; // TO DO: add support for $aExtraParams in asynchronous/Ajax mode
}
return $sHtml;
}
public function RenderContent(web_page $oPage, $aExtraParams = array())
{
$oPage->add($this->GetRenderContent($oPage, $aExtraParams));
}
public function GetRenderContent(web_page $oPage, $aExtraParams = array())
{
$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)
{
$aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
foreach($aFilterCodes as $sFilterCode)
{
$sExternalFilterValue = utils::ReadParam($sFilterCode, '');
if (isset($aExtraParams[$sFilterCode]))
{
$this->m_oFilter->AddCondition($sFilterCode, $aExtraParams[$sFilterCode]); // Use the default 'loose' operator
}
else if ($bDoSearch && $sExternalFilterValue != "")
{
$this->m_oFilter->AddCondition($sFilterCode, $sExternalFilterValue); // Use the default 'loose' operator
}
}
$this->m_oSet = new CMDBObjectSet($this->m_oFilter);
}
switch($this->m_sStyle)
{
case 'count':
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
foreach($aGroupBy as $sValue => $iCount)
{
$aData[] = array ( 'group' => $sValue,
'value' => "<a href=\"./UI.php?operation=search&dosearch=1&filter=$sFilter&$sGroupByField=".urlencode($sValue)."\">$iCount</a>"); // TO DO: add the context information
}
$sHtml .= $oPage->GetTable(array('group' => array('label' => MetaModel::GetLabel($this->m_oFilter->GetClass(), $sGroupByField), 'description' => ''), 'value' => array('label'=>'Count', 'description' => 'Number of elements')), $aData);
}
else
{
// Simply count the number of elements in the set
$iCount = $oSet->Count();
$sHtml .= $oPage->GetP("$iCount objects matching the criteria.");
}
break;
case 'list':
$bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false;
if ( ($this->m_oSet->Count()> 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) )
{
if (!$bDashboardMode)
{
$sHtml .= $oPage->GetP($this->m_oSet->Count()." object(s).");
}
$sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : '';
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $sLinkage, !$bDashboardMode /* bDisplayMenu */);
}
else
{
$sHtml .= $oPage->GetP("No object to display.");
$sClass = $this->m_oFilter->GetClass();
if (!$bDashboardMode)
{
if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES)
{
$sHtml .= $oPage->GetP("<a href=\"./UI.php?operation=new&class=$sClass\">Click here to create a new ".Metamodel::GetName($sClass)."</a>\n");
}
}
}
break;
case 'details':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)
{
while($oObj = $this->m_oSet->Fetch())
{
$sHtml .= $oObj->GetDetails($oPage);
}
}
break;
case 'bare_details':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)
{
while($oObj = $this->m_oSet->Fetch())
{
$sHtml .= $oObj->GetBareDetails($oPage);
}
}
break;
case 'csv':
if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES)
{
$sHtml .= "<textarea style=\"width:100%;height:98%\">\n";
$sHtml .= cmdbAbstractObject::GetSetAsCSV($this->m_oSet);
$sHtml .= "</textarea>\n";
}
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':
$iSearchSectionId = 1;
$sStyle = (isset($aExtraParams['open']) && ($aExtraParams['open'] == 'true')) ? 'SearchDrawer' : 'SearchDrawer DrawerClosed';
$sHtml .= "<div id=\"Search_$iSearchSectionId\" class=\"$sStyle\">\n";
$sHtml .= "<h1>Search form for ".Metamodel::GetName($this->m_oSet->GetClass())."</h1>\n";
$oPage->add_ready_script("\$(\"#LnkSearch_$iSearchSectionId\").click(function() {\$(\"#Search_$iSearchSectionId\").slideToggle('normal'); $(\"#LnkSearch_$iSearchSectionId\").toggleClass('open');});");
$sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams);
$sHtml .= "</div>\n";
$sHtml .= "<div class=\"HRDrawer\"/></div>\n";
$sHtml .= "<div id=\"LnkSearch_$iSearchSectionId\" class=\"DrawerHandle\">Search</div>\n";
break;
case 'pie_chart':
$sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
$sFilter = $this->m_oFilter->ToOQL();
$sHtml .= "
<OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"
codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\"
WIDTH=\"400\"
HEIGHT=\"250\"
id=\"charts\"
ALIGN=\"\">
<PARAM NAME=movie VALUE=\"../images/charts.swf?library_path=../images/charts_library&xml_source=".urlencode("../pages/ajax.render.php?operation=pie_chart&group_by=$sGroupBy&encoding=oql&filter=".urlencode($sFilter))."\">
<PARAM NAME=\"quality\" VALUE=\"high\">
<PARAM NAME=\"bgcolor\" VALUE=\"#ffffff\">
<EMBED src=\"../images/charts.swf?library_path=../images/charts_library&xml_source=".urlencode("../pages/ajax.render.php?operation=pie_chart&group_by=$sGroupBy&encoding=oql&filter=".urlencode($sFilter))."\"
quality=\"high\"
bgcolor=\"#ffffff\"
WIDTH=\"400\"
HEIGHT=\"250\"
NAME=\"charts\"
ALIGN=\"\"
swLiveConnect=\"true\"
TYPE=\"application/x-shockwave-flash\"
PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\">
</EMBED>
</OBJECT>
";
break;
case 'pie_chart_ajax':
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
$sHtml .= "<chart>\n";
$sHtml .= "<chart_type>3d pie</chart_type>\n";
$sHtml .= "<chart_data>\n";
$sHtml .= "<row>\n";
$sHtml .= "<null/>\n";
foreach($aGroupBy as $sValue => $void)
{
$sHtml .= "<string>$sValue</string>\n";
}
$sHtml .= "</row>\n";
$sHtml .= "<row>\n";
$sHtml .= "<string></string>\n";
foreach($aGroupBy as $void => $iCount)
{
$sHtml .= "<number>$iCount</number>\n";
}
$sHtml .= "</row>\n";
$sHtml .= "</chart_data>\n";
$sHtml .= "
<chart_value color='ffffff' alpha='90' font='arial' bold='true' size='10' position='inside' prefix='' suffix='' decimals='0' separator='' as_percentage='true' />
<draw>
<text color='000000' alpha='10' font='arial' rotation='0' bold='true' size='30' x='0' y='140' width='400' height='150' h_align='center' v_align='bottom'>|||||||||||||||||||||||||||||||||||||||||||||||</text>
</draw>
<legend_label layout='horizontal' bullet='circle' font='arial' bold='true' size='13' color='000000' alpha='85' />
<legend_rect fill_color='ffffff' fill_alpha='10' line_color='ffffff' line_alpha='50' line_thickness='0' />
<series_color>
<color>ddaa41</color>
<color>88dd11</color>
<color>4e62dd</color>
<color>ff8811</color>
<color>4d4d4d</color>
<color>5a4b6e</color>
<color>1188ff</color>
</series_color>
";
$sHtml .= "</chart>\n";
}
else
{
// Simply count the number of elements in the set
$iCount = $oSet->Count();
$sHtml .= "<chart>\n</chart>\n";
}
break;
case 'open_flash_chart':
static $iChartCounter = 0;
$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'] : '';
$sFilter = $this->m_oFilter->ToOQL();
$sHtml .= "<script>
swfobject.embedSWF(\"../images/open-flash-chart.swf\", \"my_chart_{$iChartCounter}\", \"400\", \"400\",\"9.0.0\", \"expressInstall.swf\",
{\"data-file\":\"".urlencode("../pages/ajax.render.php?operation=open_flash_chart&params[group_by]=$sGroupBy&params[chart_type]=$sChartType&params[chart_title]=$sTitle&encoding=oql&filter=".urlencode($sFilter))."\"});
</script>\n";
$sHtml .= "<div id=\"my_chart_{$iChartCounter}\">Here goes the chart</div>\n";
$iChartCounter++;
break;
case 'open_flash_chart_ajax':
include './php-ofc-library/open-flash-chart.php';
$sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
$oChart = new open_flash_chart();
switch($sChartType)
{
case 'bars':
$oChartElement = new bar_glass();
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
$aLabels = array();
foreach($aGroupBy as $sValue => $iValue)
{
$aData[] = $iValue;
$aLabels[] = $sValue;
}
$maxValue = max($aData);
$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($aLabels);
// 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#)' );
if (isset($aExtraParams['group_by']))
{
$sGroupByField = $aExtraParams['group_by'];
$aGroupBy = array();
while($oObj = $this->m_oSet->Fetch())
{
$sValue = $oObj->Get($sGroupByField);
$aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1;
}
$sFilter = urlencode($this->m_oFilter->serialize());
$aData = array();
foreach($aGroupBy as $sValue => $iValue)
{
$aData[] = new pie_value($iValue, $sValue);
}
$oChartElement->set_values( $aData );
$oChart->x_axis = null;
}
}
if (isset($aExtraParams['chart_title'])) //@@ BUG: not passed via ajax !!!
{
$oTitle = new title( $aExtraParams['chart_title'] );
$oChart->set_title( $oTitle );
}
$oChart->set_bg_colour('#FFFFFF');
$oChart->add_element( $oChartElement );
$sHtml = $oChart->toPrettyString();
break;
default:
// Unsupported style, do nothing.
$sHtml .= "Error: unsupported style of block: ".$this->m_sStyle;
}
return $sHtml;
}
}
/**
* Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects
*
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
* The list of cmdbObjects to be displayed into the block is defined by a filter
* Right now the type of display is either: list, count or details
* - list produces a table listing the objects
* - count produces a paragraphs with a sentence saying 'cont' objects found
* - details display (as table) the details of each object found (best if only one)
*/
class HistoryBlock extends DisplayBlock
{
public function GetRenderContent(web_page $oPage, $aExtraParams = array())
{
$sHtml = '';
// Add the extra params into the filter if they make sense for such a filter
$aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
foreach($aFilterCodes as $sFilterCode)
{
if (isset($aExtraParams[$sFilterCode]))
{
$this->m_oFilter->AddCondition($sFilterCode, $aExtraParams[$sFilterCode]); // Use the default 'loose' operator
}
}
$oSet = new CMDBObjectSet($this->m_oFilter, array('date'=>false));
$sHtml .= "<!-- filter: ".($this->m_oFilter->ToOQL())."-->\n";
switch($this->m_sStyle)
{
case 'toggle':
$oLatestChangeOp = $oSet->Fetch();
if (is_object($oLatestChangeOp))
{
global $oContext; // User Context.. should be statis instead of global...
// There is one change in the list... only when the object has been created !
$sDate = $oLatestChangeOp->GetAsHTML('date');
$oChange = $oContext->GetObject('CMDBChange', $oLatestChangeOp->Get('change'));
$sUserInfo = $oChange->GetAsHTML('userinfo');
$oSet->Load(); // Reset the pointer to the beginning of the set: there should be a better way to do this...
$sHtml .= $oPage->GetStartCollapsibleSection("Last modified on $sDate by $sUserInfo.");
$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $oSet);
$sHtml .= $oPage->GetEndCollapsibleSection();
}
break;
default:
$sHtml .= parent::GetRenderContent($oPage, $aExtraParams);
}
return $sHtml;
}
}
class MenuBlock extends DisplayBlock
{
public function GetRenderContent(web_page $oPage, $aExtraParams = array())
{
$sHtml = '';
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$sClass = $this->m_oFilter->GetClass();
$oSet = new CMDBObjectSet($this->m_oFilter);
$sFilter = $this->m_oFilter->serialize();
$aActions = array();
$sUIPage = cmdbAbstractObject::ComputeUIPage($sClass);
switch($oSet->Count())
{
case 0:
// No object in the set, the only possible action is "new"
$bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet);
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New', 'url' => "../page/$sUIPage?operation=new&class=$sClass&$sContext"); }
break;
case 1:
$oObj = $oSet->Fetch();
$id = $oObj->GetKey();
$bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet);
$bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet);
$bIsBulkModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet);
$bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet);
// Just one object in the set, possible actions are "new / clone / modify and delete"
if (isset($aExtraParams['linkage']))
{
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "#"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "#"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All', 'url' => "#"); }
if ($bIsModifyAllowed | $bIsDeleteAllowed) { $aActions[] = array ('label' => 'Manage Links...', 'url' => "#"); }
}
else
{
$aActions[] = array ('label' => 'eMail', 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("http://localhost:81/pages/UI.php?operation=search&filter=$sFilter&$sContext"));
$aActions[] = array ('label' => 'CSV Export', 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext");
$aActions[] = array ('label' => 'Bookmark...', 'url' => "../pages/ajax.render.php?operation=create&class=$sClass&filter=$sFilter", 'class' => 'jqmTrigger');
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext"); }
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'Clone...', 'url' => "../pages/$sUIPage?operation=clone&class=$sClass&id=$id&$sContext"); }
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'Modify...', 'url' => "../pages/$sUIPage?operation=modify&class=$sClass&id=$id&$sContext"); }
if ($bIsDeleteAllowed) { $aActions[] = array ('label' => 'Delete', 'url' => "../pages/$sUIPage?operation=delete&class=$sClass&id=$id&$sContext"); }
}
$aTransitions = $oObj->EnumTransitions();
$aStimuli = Metamodel::EnumStimuli($sClass);
foreach($aTransitions as $sStimulusCode => $aTransitionDef)
{
$iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet);
switch($iActionAllowed)
{
case UR_ALLOWED_YES:
$aActions[] = array('label' => $aStimuli[$sStimulusCode]->Get('label'), 'url' => "../pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id&$sContext");
break;
case UR_ALLOWED_DEPENDS:
$aActions[] = array('label' => $aStimuli[$sStimulusCode]->Get('label').' (*)', 'url' => "../pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id&$sContext");
break;
default:
// Do nothing
}
}
//print_r($aTransitions);
break;
default:
// Check rights
// New / Modify
$bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet);
$bIsBulkModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet);
$bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet);
if (isset($aExtraParams['linkage']))
{
$bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet);
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "#"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "#"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All', 'url' => "#"); }
if ($bIsModifyAllowed | $bIsDeleteAllowed) { $aActions[] = array ('label' => 'Manage Links...', 'url' => "#"); }
}
else
{
// many objects in the set, possible actions are: new / modify all / delete all
$aActions[] = array ('label' => 'eMail', 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("http://localhost:81/pages/UI.php?operation=search&filter=$sFilter&$sContext"));
$aActions[] = array ('label' => 'CSV Export', 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext");
$aActions[] = array ('label' => 'Bookmark...', 'url' => "../pages/ajax.render.php?operation=create&class=$sClass&filter=$sFilter", 'class' => 'jqmTrigger');
if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "../pages/$sUIPage?operation=modify_all&filter=$sFilter&$sContext"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Delete All', 'url' => "../pages/$sUIPage?operation=delete_all&filter=$sFilter&$sContext"); }
}
}
$sHtml .= "<div class=\"jd_menu_itop\"><ul class=\"jd_menu jd_menu_itop\">\n<li>Actions\n<ul>\n";
foreach ($aActions as $aAction)
{
$sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : "";
$sHtml .= "<li><a href=\"{$aAction['url']}\"$sClass>{$aAction['label']}</a></li>\n<li>\n";
}
$sHtml .= "</ul>\n</li>\n</ul></div>\n";
$oPage->add_ready_script("$(\"ul.jd_menu\").jdMenu();\n");
return $sHtml;
}
}
?>

View File

@@ -0,0 +1,54 @@
<?php
require_once('../application/cmdbabstract.class.inc.php');
/**
* This class manages the input/output tasks
* for synchronizing information with external data sources
*/
class InputOutputTask extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "application",
"name" => "IOTask",
"description" => "Input / Output Task for synchronizing information with external data sources",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_iotask",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Task Name", "description"=>"Short name for this task", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("label"=>"Task Description", "description"=>"Long description for this task", "allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("category", array("label"=>"Category", "description"=>"Type of task", "allowed_values"=>new ValueSetEnum('Input, Ouput'), "sql"=>"category", "default_value"=>"Input", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_type", array("label"=>"Source Type", "description"=>"Type of data source", "allowed_values"=>new ValueSetEnum('File, Database, Web Service'), "sql"=>"source_type", "default_value"=>"File", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_subtype", array("label"=>"Source Subtype", "description"=>"Subtype of Data Source", "allowed_values"=>new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql"=>"source_subtype", "default_value"=>"CSV", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("source_path", array("label"=>"Source Path", "description"=>"Path to the icon o the menu", "allowed_values"=>null, "sql"=>"source_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("objects_class", array("label"=>"Objects Class", "description"=>"Class of the objects processed by this task", "allowed_values"=>new ValueSetEnum('bizOrganization, bizContact, bizTeam, bizPerson, bizLocation, bizServer, bizPC, bizNetworkDevice, bizInterface, bizService, bizContract, bizInfraGroup, bizIncidentTicket, bizSoftware, bizApplication, bizPatch, bizWorkgroup, lnkContactRealObject, lnkInterfaces, bizInfraGrouping' ), "sql"=>"objects_class", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", array("label"=>"Test Mode", "description"=>"If set to 'Yes' the modifications are not applied", "allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"test_mode", "default_value"=>'No', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", array("label"=>"Verbose Mode", "description"=>"If set to 'Yes' extra debug information is added to the log", "allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"verbose_mode", "default_value" => 'No', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("options", array("label"=>"Options", "description"=>"Reconciliation options", "allowed_values"=>new ValueSetEnum('Full, Update Only, Creation Only'), "sql"=>"options", "default_value"=> 'Full', "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("description");
MetaModel::Init_AddFilterFromAttribute("category");
MetaModel::Init_AddFilterFromAttribute("source_type");
MetaModel::Init_AddFilterFromAttribute("source_subtype");
MetaModel::Init_AddFilterFromAttribute("objects_class");
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'source_path' , 'options', 'test_mode', 'verbose_mode')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the advanced search form
}
}
?>

View File

@@ -0,0 +1,414 @@
<?php
require_once("../application/nicewebpage.class.inc.php");
require_once("../application/usercontext.class.inc.php");
require_once("../application/applicationcontext.class.inc.php");
/**
* Web page with some associated CSS and scripts (jquery) for a fancier display
*/
class iTopWebPage extends nice_web_page
{
private $m_sMenu;
private $m_currentOrganization;
private $m_aTabs;
private $m_sCurrentTabContainer;
private $m_sCurrentTab;
public function __construct($sTitle, $currentOrganization)
{
parent::__construct($sTitle);
$this->m_sCurrentTabContainer = '';
$this->m_sCurrentTab = '';
$this->m_aTabs = array();
$this->m_sMenu = "";
$oAppContext = new ApplicationContext();
$sExtraParams = $oAppContext->GetForLink();
$this->add_header("Content-type: text/html; charset=utf-8");
$this->add_header("Cache-control: no-cache");
$this->m_currentOrganization = $currentOrganization;
$this->add_linked_script("../js/jquery.dimensions.js");
$this->add_linked_script("../js/splitter.js");
$this->add_linked_script("../js/jquery.tablehover.js");
$this->add_linked_script("../js/jquery.treeview.js");
$this->add_linked_script("../js/jquery.autocomplete.js");
$this->add_linked_script("../js/jquery.bgiframe.js");
$this->add_linked_script("../js/jquery.jdMenu.js");
$this->add_linked_script("../js/date.js");
$this->add_linked_script("../js/jquery.date.picker.js");
$this->add_linked_script("../js/jquery.tablesorter.min.js");
//$this->add_linked_script("../js/jquery-ui-personalized-1.5.3.js");
$this->add_linked_script("../js/swfobject.js");
$this->add_linked_stylesheet("../css/jquery.treeview.css");
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
$this->add_linked_stylesheet("../css/date.picker.css");
$this->add_ready_script(
<<<EOF
// Vertical splitter. The min/max/starting sizes for the left (A) pane
// are set here. All values are in pixels.
$("#MySplitter").splitter({
type: "v",
minA: 100, initA: 250, maxA: 500,
accessKey: "|"
});
// Horizontal splitter, nested in the right pane of the vertical splitter.
if ( $("#TopPane").length > 0)
{
$("#RightPane").splitter({
type: "h" //,
//minA: 100, initA: 150, maxA: 500,
//accessKey: "_"
});
}
// Manually set the outer splitter's height to fill the browser window.
// This must be re-done any time the browser window is resized.
$(window).bind("resize", function(){
var ms = $("#MySplitter");
var top = ms.offset().top; // from dimensions.js
var wh = $(window).height();
// Account for margin or border on the splitter container
var mrg = parseInt(ms.css("marginBottom")) || 0;
var brd = parseInt(ms.css("borderBottomWidth")) || 0;
ms.css("height", (wh-top-mrg-brd)+"px");
// IE fires resize for splitter; others don't so do it here
if ( !jQuery.browser.msie )
ms.trigger("resize");
}).trigger("resize");
var ms = $("#MySplitter");
ms.trigger("resize");
if ( $("#TopPane").length > 0)
{
$("#RightPane").trigger("resize");
}
$("#tabbedContent > ul").tabs( 1, { fxFade: true, fxSpeed: 'fast' } ); // tabs
$("table.listResults").tableHover(); // hover tables
$(".listResults").tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables
$(".date-pick").datePicker( {clickInput: false, createButton: true, startDate: '2000-01-01'} ); // Date picker
$('#ModalDlg').jqm({ajax: '@href', trigger: 'a.jqmTrigger', overlay:70, modal:true, toTop:true}); // jqModal Window
//$('.display_block').draggable(); // make the blocks draggable
EOF
);
$this->add_script("
// For automplete
function findValue(li) {
if( li == null ) return alert(\"No match!\");
// if coming from an AJAX call, let's use the CityId as the value
if( !!li.extra ) var sValue = li.extra[0];
// otherwise, let's just display the value in the text box
else var sValue = li.selectValue;
//alert(\"The value you selected was: \" + sValue);
}
function selectItem(li) {
findValue(li);
}
function formatItem(row) {
return row[0];
}
function goBack()
{
window.history.back();
}
");
$this->DisplayMenu();
}
public function AddToMenu($sHtml)
{
$this->m_sMenu .= $sHtml;
}
public function DisplayMenu()
{
// Combo box to select the organization
$this->AddToMenu("<div id=\"OrganizationSelection\">
<form style=\"display:inline\"><select style=\"width:150px;font-size:x-small\" name=\"org_id\" \"title=\"Pick an organization\" onChange=\"this.form.submit();\">\n");
// List of visible Organizations
$oContext = new UserContext();
$oSearchFilter = $oContext->NewFilter("bizOrganization");
$oSet = new CMDBObjectSet($oSearchFilter);
$sSelected = ($this->m_currentOrganization == '') ? ' selected' : '';
$this->AddToMenu("<option value=\"\"$sSelected> All Organizations </option>");
if ($oSet->Count() > 0)
while($oOrg = $oSet->Fetch())
{
if ($this->m_currentOrganization == $oOrg->GetKey())
{
$oCurrentOrganization = $oOrg;
$sSelected = " selected";
}
else
{
$sSelected = "";
}
$this->AddToMenu("<option value=\"".$oOrg->GetKey()."\"$sSelected>".$oOrg->Get('name')."</option>\n");
}
$this->AddToMenu("</select></form>\n");
$this->AddToMenu("</div>\n");
$this->AddToMenu("<ul id=\"browser\" class=\"dir\">\n");
$oAppContext = new ApplicationContext();
// Display the menu
// 1) Application defined menus
$oSearchFilter = $oContext->NewFilter("menuNode");
$oSearchFilter->AddCondition('parent_id', 0, '=');
$oSearchFilter->AddCondition('type', 'application', '=');
// There may be more criteria added later to have a specific menu based on the user's profile
$oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true));
while ($oRootMenuNode = $oSet->Fetch())
{
$oRootMenuNode->DisplayMenu($this, 'application', $oAppContext->GetAsHash());
}
// 2) User defined menus (Bookmarks)
$oSearchFilter = $oContext->NewFilter("menuNode");
$oSearchFilter->AddCondition('parent_id', 0, '=');
$oSearchFilter->AddCondition('type', 'user', '=');
$oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '=');
// There may be more criteria added later to have a specific menu based on the user's profile
$oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true));
while ($oRootMenuNode = $oSet->Fetch())
{
$oRootMenuNode->DisplayMenu($this, 'user', $oAppContext->GetAsHash());
}
$this->AddToMenu("</ul>\n");
}
/**
* Outputs (via some echo) the complete HTML page by assembling all its elements
*/
public function output()
{
foreach($this->a_headers as $s_header)
{
header($s_header);
}
$s_captured_output = ob_get_contents();
ob_end_clean();
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
echo "<html>\n";
echo "<head>\n";
echo "<title>{$this->s_title}</title>\n";
foreach($this->a_linked_scripts as $s_script)
{
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
}
if (count($this->m_aReadyScripts)>0)
{
$this->add_script("\$(document).ready(function() {\n".implode("\n", $this->m_aReadyScripts)."\n});");
}
if (count($this->a_scripts)>0)
{
echo "<script type=\"text/javascript\">\n";
foreach($this->a_scripts as $s_script)
{
echo "$s_script\n";
}
echo "</script>\n";
}
foreach($this->a_linked_stylesheets as $a_stylesheet)
{
if ($a_stylesheet['condition'] != "")
{
echo "<!--[if {$a_stylesheet['condition']}]>\n";
}
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$a_stylesheet['link']}\" />\n";
if ($a_stylesheet['condition'] != "")
{
echo "<![endif]-->\n";
}
}
if (count($this->a_styles)>0)
{
echo "<style>\n";
foreach($this->a_styles as $s_style)
{
echo "$s_style\n";
}
echo "</style>\n";
}
echo "<link rel=\"search\" type=\"application/opensearchdescription+xml\" title=\"iTop\" href=\"./opensearch.xml.php\">\n";
echo "</head>\n";
echo "<body>\n";
// Display the header
echo "<div id=\"Header\">\n";
echo "<div class=\"iTopLogo\"><span>iTop</span></div>\n";
//echo "<div id=\"GlobalSearch\"><div style=\"border: 1px solid #999; padding:1px; background-color:#fff;\"><img src=\"/images/magnifier.gif\"/><input style=\"border:0\" type=\"text\" size=\"15\" title=\"Global Search\"></input></div></div>\n";
$sText = Utils::ReadParam('text', '');
$sOnClick = "";
if (empty($sText))
{
// if no search text is supplied then
// 1) the search text is filled with "your search"
// 2) clicking on it will erase it
$sText = "Your search";
$sOnClick = " onclick=\"this.value='';this.onclick=null;\"";
}
echo "<div id=\"OrganizationSelection\" style=\"position:absolute; top:18px; right:16px; width:400px;\">";
echo "<form action=\"../pages/UI.php\" style=\"display:inline\"><div style=\"padding:1px; background-color:#fff;display:inline;\"><img src=\"../images/magnifier.gif\"/><input style=\"border:0\" type=\"text\" size=\"15\" title=\"Global Search\" name=\"text\" value=\"$sText\"$sOnClick></input></div><input type=\"Submit\" value=\"Search\">
<input type=\"hidden\" name=\"operation\" value=\"full_text\"></form>\n";
echo "</div>\n";
echo "</div>\n";
// Display the menu
echo "<div id=\"MySplitter\">\n";
echo " <div id=\"LeftPane\">\n";
echo $this->m_sMenu;
echo " </div> <!-- LeftPane -->\n";
echo "<div id=\"RightPane\">\n";
// Render the tabs in the page (if any)
foreach($this->m_aTabs as $sTabContainerName => $m_aTabs)
{
$sTabs = '';
if (count($m_aTabs) > 0)
{
$sTabs = "<!-- tabs -->\n<div id=\"tabbedContent\" class=\"light\">\n";
$sTabs .= "<ul>\n";
// Display the unordered list that will be rendered as the tabs
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<li><a href=\"#fragment_$i\" class=\"tab\"><span>".htmlentities($sTabName)."</span></a></li>\n";
$i++;
}
$sTabs .= "</ul>\n";
// Now add the content of the tabs themselves
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<div id=\"fragment_$i\">".$sTabContent."</div>\n";
$i++;
}
$sTabs .= "</div>\n<!-- end of tabs-->\n";
}
$this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content);
}
// Display the page's content
echo $this->s_content;
// Add the captured output
if (trim($s_captured_output) != "")
{
echo "<div class=\"raw_output\">$s_captured_output</div>\n";
}
echo "<div class=\"jqmWindow\" id=\"ex2\">Please wait...</div>\n"; // jqModal Window
echo "</div> <!-- RightPane -->\n";
echo "</div> <!-- Splitter -->\n";
echo "<div class=\"jqmWindow\" id=\"ModalDlg\"></div>";
echo "</body>\n";
echo "</html>\n";
}
public function AddTabContainer($sTabContainer)
{
$this->m_aTabs[$sTabContainer] = array();
$this->add("\$Tabs:$sTabContainer\$");
}
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
{
if (!isset($this->m_aTabs[$sTabContainer][$sTabLabel]))
{
// Set the content of the tab
$this->m_aTabs[$sTabContainer][$sTabLabel] = $sHtml;
}
else
{
// Append to the content of the tab
$this->m_aTabs[$sTabContainer][$sTabLabel] .= $sHtml;
}
}
public function SetCurrentTabContainer($sTabContainer = '')
{
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
$this->m_sCurrentTabContainer = $sTabContainer;
return $sPreviousTabContainer;
}
public function SetCurrentTab($sTabLabel = '')
{
$sPreviousTab = $this->m_sCurrentTab;
$this->m_sCurrentTab = $sTabLabel;
return $sPreviousTab;
}
public function StartCollapsibleSection($sSectionLabel, $bOpen = false)
{
$this->add($this->GetStartCollapsibleSection($sSectionLabel, $bOpen));
}
public function GetStartCollapsibleSection($sSectionLabel, $bOpen = false)
{
$sHtml = '';
static $iSectionId = 0;
$sHtml .= "<a id=\"LnkCollapse_$iSectionId\" class=\"CollapsibleLabel\" href=\"#\">$sSectionLabel</a></br>\n";
$sStyle = $bOpen ? '' : 'style="display:none" ';
$sHtml .= "<div id=\"Collapse_$iSectionId\" $sStyle>";
$this->add_ready_script("\$(\"#LnkCollapse_$iSectionId\").click(function() {\$(\"#Collapse_$iSectionId\").slideToggle('normal'); $(\"#LnkCollapse_$iSectionId\").toggleClass('open');});");
//$this->add_ready_script("$('#LnkCollapse_$iSectionId').hide();");
$iSectionId++;
return $sHtml;
}
public function EndCollapsibleSection()
{
$this->add($this->GetEndCollapsibleSection());
}
public function GetEndCollapsibleSection()
{
return "</div>";
}
public function add($sHtml)
{
if (!empty($this->m_sCurrentTabContainer) && !empty($this->m_sCurrentTab))
{
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
}
else
{
parent::add($sHtml);
}
}
/*
public function AddSearchForm($sClassName, $bOpen = false)
{
$iSearchSectionId = 0;
$sStyle = $bOpen ? 'SearchDrawer' : 'SearchDrawer DrawerClosed';
$this->add("<div id=\"Search_$iSearchSectionId\" class=\"$sStyle\">\n");
$this->add("<h1>Search form for ".Metamodel::GetName($sClassName)."</h1>\n");
$this->add_ready_script("\$(\"#LnkSearch_$iSearchSectionId\").click(function() {\$(\"#Search_$iSearchSectionId\").slideToggle('normal'); $(\"#LnkSearch_$iSearchSectionId\").toggleClass('open');});");
$oFilter = new DBObjectSearch($sClassName);
$sFilter = $oFilter->serialize();
$oSet = new CMDBObjectSet($oFilter);
cmdbAbstractObject::DisplaySearchForm($this, $oSet, array('operation' => 'search', 'filter' => $sFilter, 'search_form' => true));
$this->add("</div>\n");
$this->add("<div class=\"HRDrawer\"/></div>\n");
$this->add("<div id=\"LnkSearch_$iSearchSectionId\" class=\"DrawerHandle\">Search</div>\n");
$iSearchSectionId++;
}
*/
}
?>

View File

@@ -0,0 +1,32 @@
<?php
require_once('itopwebpage.class.inc.php');
/**
* Web page to display a wizard in the iTop framework
*/
class iTopWizardWebPage extends iTopWebPage
{
var $m_iCurrentStep;
var $m_aSteps;
public function __construct($sTitle, $currentOrganization, $iCurrentStep, $aSteps)
{
parent::__construct($sTitle." - step $iCurrentStep of ".count($aSteps)." - ".$aSteps[$iCurrentStep - 1], $currentOrganization);
$this->m_iCurrentStep = $iCurrentStep;
$this->m_aSteps = $aSteps;
}
public function output()
{
$aSteps = array();
$iIndex = 0;
foreach($this->m_aSteps as $sStepTitle)
{
$iIndex++;
$sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep';
$aSteps[] = "<div class=\"$sStyle\"><span>$sStepTitle</span></div>";
}
$sWizardHeader = "<div class=\"wizHeader\"><h1>{$this->s_title}</h1>\n".implode("<div class=\"wizSeparator\"><img align=\"bottom\" src=\"/images/wizArrow.gif\"></div>", $aSteps)."<br style=\"clear:both;\"/></div>\n";
$this->s_content = "$sWizardHeader<div class=\"wizContainer\">".$this->s_content."</div>";
parent::output();
}
}
?>

View File

@@ -0,0 +1,117 @@
<?php
require_once("../application/nicewebpage.class.inc.php");
/**
* Web page used for displaying the login form
*/
class login_web_page extends nice_web_page
{
public function __construct()
{
parent::__construct("iTop Login");
$this->add_style("
body {
background-color: #eee;
margin: 0;
padding: 0;
}
#login {
width: 230px;
margin-left: auto;
margin-right: auto;
margin-top: 150px;
padding: 20px;
background-color: #fff;
border: 1px solid #000;
}
.center {
text-align: center;
}
h1 {
color: #83b217;
font-size: 16pt;
}
.v-spacer {
padding-top: 1em;
}
");
}
public function DisplayLoginForm($bFailedLogin = false)
{
$sAuthUser = utils::ReadParam('auth_user', '');
$sAuthPwd = utils::ReadParam('suggest_pwd', '');
$this->add("<div id=\"login\">\n");
$this->add("<h1>Welcome to iTop!</h1>\n");
if ($bFailedLogin)
{
$this->add("<p class=\"hilite\">Incorrect login/password, please try again.</p>\n");
}
else
{
$this->add("<p>Please identify yourself before continuing.</p>\n");
}
$this->add("<form method=\"post\">\n");
$this->add("<table>\n");
$this->add("<tr><td><label for=\"user\">User Name:</label></td><td><input id=\"user\" type=\"text\" name=\"auth_user\" value=\"$sAuthUser\" /></td></tr>\n");
$this->add("<tr><td><label for=\"pwd\">Password:</label></td><td><input id=\"pwd\" type=\"password\" name=\"auth_pwd\" value=\"$sAuthPwd\" /></td></tr>\n");
$this->add("<tr><td colspan=\"2\" class=\"center v-spacer\"> <input type=\"submit\" value=\"Enter iTop\" /></td></tr>\n");
$this->add("</table>\n");
$this->add("<input type=\"hidden\" name=\"operation\" value=\"login\" />\n");
$this->add("</form>\n");
$this->add("</div>\n");
}
static function DoLogin()
{
$operation = utils::ReadParam('operation', '');
session_start();
if (!session_is_registered('auth_user') || !session_is_registered('auth_pwd'))
{
if ($operation == 'login')
{
$sAuthUser = utils::ReadParam('auth_user', '', 'post');
$sAuthPwd = utils::ReadParam('auth_pwd', '', 'post');
}
else
{
$oPage = new login_web_page();
$oPage->DisplayLoginForm();
$oPage->output();
exit;
}
}
else
{
$sAuthUser = $_SESSION['auth_user'];
$sAuthPwd = $_SESSION['auth_pwd'];
}
if (!UserRights::Login($sAuthUser, $sAuthPwd))
{
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (isset($_COOKIE[session_name()]))
{
setcookie(session_name(), '', time()-3600, '/');
}
// Finally, destroy the session.
session_destroy();
$oPage = new login_web_page();
$oPage->DisplayLoginForm( true /* failed attempt */);
$oPage->output();
exit;
}
else
{
$_SESSION['auth_user'] = $sAuthUser ;
$_SESSION['auth_pwd'] = $sAuthPwd;
}
}
} // End of class
?>

View File

@@ -0,0 +1,219 @@
<?php
require_once('../core/attributedef.class.inc.php');
require_once('../core/filterdef.class.inc.php');
require_once('../core/stimulus.class.inc.php');
require_once('../core/MyHelpers.class.inc.php');
require_once('../core/cmdbsource.class.inc.php');
require_once('../core/sqlquery.class.inc.php');
require_once('../core/dbobject.class.php');
require_once('../core/dbobjectsearch.class.php');
require_once('../core/dbobjectset.class.php');
require_once('../application/displayblock.class.inc.php');
/**
* This class manages en entries in the menu tree on the left of the iTop pages
*/
class menuNode extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "gui",
"name" => "menuNode",
"description" => "Main menu configuration elements",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_menunode",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
// MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("label"=>"change", "description"=>"change", "allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "jointype"=>"closed")));
// MetaModel::Init_AddAttribute(new AttributeExternalField("date", array("label"=>"date", "description"=>"date and time of the change", "allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"date")));
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Menu Name", "description"=>"Short name for this menu", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("label", array("label"=>"Menu Description", "description"=>"Long description for this menu", "allowed_values"=>null, "sql"=>"label", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("hyperlink", array("label"=>"Hyperlink", "description"=>"Hyperlink to the page", "allowed_values"=>null, "sql"=>"hyperlink", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("icon_path", array("label"=>"Menu Icon", "description"=>"Path to the icon o the menu", "allowed_values"=>null, "sql"=>"icon_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("template", array("label"=>"Template", "description"=>"HTML template for the view", "allowed_values"=>null, "sql"=>"template", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("type", array("label"=>"Type", "description"=>"Type of menu", "allowed_values"=>new ValueSetEnum('application,user'), "sql"=>"type", "default_value"=>"application", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("rank", array("label"=>"Display rank", "description"=>"Sort order for displaying the menu", "allowed_values"=>null, "sql"=>"rank", "default_value" => 999, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("parent_id", array("label"=>"Parent Menu Item", "description"=>"Parent Menu Item", "allowed_values"=>null, "sql"=>"parent_id", "targetclass"=>"menuNode", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("parent_name", array("label"=>"Parent Menu Item", "description"=>"Parent Menu Item", "allowed_values"=>null, "extkey_attcode"=>"parent_id", "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("label"=>"Owner of the menu", "description"=>"User who owns this menu (for user defined menus)", "allowed_values"=>null, "sql"=>"user_id", "targetclass"=>"UserRightsMatrixUsers", "is_null_allowed"=>true, "depends_on"=>array('type'))));
MetaModel::Init_AddFilterFromAttribute("label");
MetaModel::Init_AddFilterFromAttribute("parent_id");
MetaModel::Init_AddFilterFromAttribute("rank");
MetaModel::Init_AddFilterFromAttribute("type");
MetaModel::Init_AddFilterFromAttribute("user_id");
MetaModel::Init_SetZListItems('details', array('parent_id', 'name', 'label', 'hyperlink', 'template', 'rank', 'type')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('parent_id', 'name', 'label', 'rank', 'type')); // Attributes to be displayed for a list
}
public function IsVisible()
{
return true;
}
public function GetMenuName()
{
return $this->Get('name');
}
public function GetMenuIcon()
{
return $this->Get('icon_path');
}
public function GetMenuLabel()
{
return $this->Get('label');
}
public function GetMenuLink($aExtraParams)
{
$aExtraParams['menu'] = $this->GetKey(); // Make sure we overwrite the current menu id (if any)
$aParams = array();
foreach($aExtraParams as $sName => $sValue)
{
$aParams[] = urlencode($sName)."=".urlencode($sValue);
}
return $this->Get('hyperlink')."?".implode("&", $aParams);
}
public function GetChildNodesSet($sType)
{
$oSearchFilter = new DBObjectSearch("menuNode");
$oSearchFilter->AddCondition('parent_id', $this->GetKey(), '=');
$oSearchFilter->AddCondition('type', $sType, '=');
if ($sType == 'user')
{
$oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '=');
}
$oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true));
return $oSet;
}
public function RenderContent(web_page $oPage, $aExtraParams = array())
{
$sTemplate = $this->Get('template');
$this->ProcessTemplate($sTemplate, $oPage, $aExtraParams);
}
protected function ProcessTemplate($sTemplate, web_page $oPage, $aExtraParams = array())
{
$iStartPos = stripos($sTemplate, '<'.DisplayBlock::TAG_BLOCK.' ',0);
$index = 0;
while(($iStartPos = stripos($sTemplate, '<'.DisplayBlock::TAG_BLOCK.' ',0)) !== false)
{
$iEndPos = stripos($sTemplate, '</'.DisplayBlock::TAG_BLOCK.'>', $iStartPos);
$sBlockDefinition = substr($sTemplate, $iStartPos, $iEndPos - $iStartPos + strlen('</'.DisplayBlock::TAG_BLOCK.'>'));
$oBlock = DisplayBlock::FromTemplate($sBlockDefinition);
$oPage->add(substr($sTemplate, 0, $iStartPos));
if ($oBlock) // Protects agains invalid XML templates
{
$oBlock->Display($oPage, "block{$index}", $aExtraParams); // Values from $aExtraParams have precedence over $aParams
}
$index++;
$sTemplate = substr($sTemplate, $iEndPos + strlen('</'.DisplayBlock::TAG_BLOCK.'>'));
}
// What remains is purely static (without any block inside), just output as it is
$oPage->add($sTemplate);
}
public function DisplayMenu(iTopWebPage $oP, $sType, $aExtraParams)
{
$oP->AddToMenu("<li><a href=\"".$this->GetMenuLink($aExtraParams)."\" title=\"".$this->GetMenuLabel()."\">".$this->GetMenuName()."</a>");
$oSet = $this->GetChildNodesSet($sType);
if ($oSet->Count() > 0)
{
$oP->AddToMenu("\n<ul>\n");
while($oChildNode = $oSet->Fetch())
{
$oChildNode->DisplayMenu($oP, $sType, $aExtraParams);
}
$oP->AddToMenu("</ul>\n");
}
$oP->AddToMenu("</li>\n");
}
static public function DisplayCreationForm(web_page $oP, $sClass, $sFilter, $aExtraParams = array())
{
$oFilter = DBObjectSearch::unserialize($sFilter);
$oP->p('Create a new menu item for: '.$oFilter->__DescribeHTML());
$oP->add('<form action="UniversalSearch.php" method="post">');
$oP->add('<input type="hidden" name="operation" value="add_menu">');
$oP->add('<input type="hidden" name="filter" value="'.$sFilter.'">');
$oP->add('<input type="hidden" name="class" value="'.$sClass.'">');
$oP->p('Menu Label: <input type="text" name="label" size="30">');
$oP->p('Description: <input type="text" name="description" size="30">');
$oP->add('<p>Insert after: <select name="previous_node_id">');
$aNodes = self::GetMenuAsArray(null, 'user');
foreach($aNodes as $aNodeDesc)
{
$oP->add('<option value="'.$aNodeDesc['id'].'">'.str_repeat('&nbsp;&nbsp;&nbsp;', $aNodeDesc['depth']).$aNodeDesc['label'].'</option>');
}
$oP->add('</select></p>');
$oP->p('<input type="checkbox" name="child_item" value="1"> Create as a child menu item');
$oP->p('<input type="submit" value=" Ok "> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="button" class="jqmClose" value="Cancel">');
$oP->add('</form>');
}
static public function GetMenuAsArray($oRootNode = null, $sType = 'application', $iDepth = 0)
{
$aNodes = array();
if (is_object($oRootNode))
{
$oChildSet = $oRootNode->GetChildNodesSet($sType);
while($oNode = $oChildSet->Fetch())
{
$aNodes[] = array('depth' => $iDepth, 'id' => $oNode->GetKey(), 'label' => $oNode->GetName());
$aNodes = array_merge($aNodes, self::GetMenuAsArray($oNode, $sType, $iDepth+1));
}
}
else
{
$oSearchFilter = new DbObjectSearch("menuNode");
$oSearchFilter->AddCondition('parent_id', 0, '=');
$oSearchFilter->AddCondition('type', $sType, '=');
if ($sType == 'user')
{
$oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '=');
}
$oRootSet = new CMDBObjectSet($oSearchFilter, array('rank' => true));
while($oNode = $oRootSet->Fetch())
{
$aNodes[] = array('depth' => $iDepth, 'id' => $oNode->GetKey(), 'label' => $oNode->GetName());
$aNodes = array_merge($aNodes, self::GetMenuAsArray($oNode, $sType, $iDepth+1));
}
}
return $aNodes;
}
/**
* Returns a set of all the nodes following the current node in the tree
* (i.e. nodes with the same parent but with a greater rank)
*/
public function GetNextNodesSet($sType = 'application')
{
$oSearchFilter = new DBObjectSearch("menuNode");
$oSearchFilter->AddCondition('parent_id', $this->Get('parent_id'));
$oSearchFilter->AddCondition('rank', $this->Get('rank'), '>');
$oSearchFilter->AddCondition('type', $sType, '=');
if ($sType == 'user')
{
$oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '=');
}
$oSet = new DBObjectSet($oSearchFilter, array('rank'=> true)); // Order by rank (true means ascending)
return $oSet;
}
}
?>

View File

@@ -0,0 +1,76 @@
<?php
require_once("../application/webpage.class.inc.php");
/**
* Web page with some associated CSS and scripts (jquery) for a fancier display
*/
class nice_web_page extends web_page
{
var $m_aReadyScripts;
public function __construct($s_title)
{
parent::__construct($s_title);
$this->m_aReadyScripts = array();
$this->add_linked_script("../js/jquery.latest.js");
$this->add_linked_script("../js/jquery.history_remote.pack.js");
//$this->add_linked_script("../js/ui.resizable.js");
$this->add_linked_script("../js/ui.tabs.js");
$this->add_linked_script("../js/hovertip.js");
$this->add_linked_script("../js/jqModal.js");
$this->add_linked_stylesheet("../css/light-grey.css");
$this->add_linked_stylesheet("../js/themes/light/light.tabs.css");
//$this->add_linked_stylesheet("../css/jquery.tabs-ie.css", "lte IE 7");
$this->add_linked_stylesheet("../css/jqModal.css");
$this->add_ready_script(' window.setTimeout(hovertipInit, 1);');
}
public function small_p($sText)
{
$this->add("<p style=\"font-size:smaller\">$sText</p>\n");
}
// By Rom, used by CSVImport and Advanced search
public function MakeClassesSelect($sName, $sDefaultValue, $iWidthPx)
{
// $aTopLevelClasses = array('bizService', 'bizContact', 'logInfra', 'bizDocument');
// These are classes wich root class is cmdbAbstractObject !
$this->add("<select id=\"select_$sName\" name=\"$sName\">");
foreach(MetaModel::GetClasses('bizmodel') as $sClassName)
{
$sSelected = ($sClassName == $sDefaultValue) ? " SELECTED" : "";
$this->add("<option style=\"width: ".$iWidthPx." px;\" value=\"$sClassName\"$sSelected>$sClassName - ".MetaModel::GetClassDescription($sClassName)."</option>");
}
$this->add("</select>");
}
// By Rom, used by Advanced search
public function add_select($aChoices, $sName, $sDefaultValue, $iWidthPx)
{
$this->add("<select id=\"select_$sName\" name=\"$sName\">");
foreach($aChoices as $sKey => $sValue)
{
$sSelected = ($sKey == $sDefaultValue) ? " SELECTED" : "";
$this->add("<option style=\"width: ".$iWidthPx." px;\" value=\"$sKey\"$sSelected>$sValue</option>");
}
$this->add("</select>");
}
public function add_ready_script($sScript)
{
$this->m_aReadyScripts[] = $sScript;
}
/**
* Outputs (via some echo) the complete HTML page by assembling all its elements
*/
public function output()
{
if (count($this->m_aReadyScripts)>0)
{
$this->add_script("\$(document).ready(function() {\n".implode("\n", $this->m_aReadyScripts)."\n});");
}
parent::output();
}
}
?>

View File

@@ -0,0 +1,7 @@
<?
require_once('../application/utils.inc.php');
MetaModel::Startup('../config-itop.php');
?>

View File

@@ -0,0 +1,224 @@
<?php
require_once('../application/displayblock.class.inc.php');
/**
* This class manages the special template format used internally to build the iTop web pages
*/
class DisplayTemplate
{
protected $m_sTemplate;
protected $m_aTags;
public function __construct($sTemplate)
{
$this->m_aTags = array('itopblock', 'itoptabs', 'itoptab', 'itoptoggle');
$this->m_sTemplate = $sTemplate;
}
public function Render(web_page $oPage, $aParams = array())
{
$this->ApplyParams($aParams);
$iStart = 0;
$iEnd = strlen($this->m_sTemplate);
$iCount = 0;
$iBeforeTagPos = $iStart;
$iAfterTagPos = $iStart;
while($sTag = $this->GetNextTag($iStart, $iEnd))
{
$sContent = $this->GetTagContent($sTag, $iStart, $iEnd);
$aAttributes = $this->GetTagAttributes($sTag, $iStart, $iEnd);
//$oPage->p("Tag: $sTag - ($iStart, $iEnd)");
$oPage->add(substr($this->m_sTemplate, $iBeforeTagPos, $iStart - $iBeforeTagPos));
$this->RenderTag($oPage, $sTag, $aAttributes, $sContent);
$iAfterTagPos = $iEnd + strlen('</'.$sTag.'>');
$iBeforeTagPos = $iAfterTagPos;
$iStart = $iEnd;
$iEnd = strlen($this->m_sTemplate);
$iCount++;
if ($iCount > 10) break;
}
$oPage->add(substr($this->m_sTemplate, $iAfterTagPos));
}
/**
* Replaces all the parameters by the values passed in the hash array
*/
public function ApplyParams($aParams)
{
$aSearches = array();
$aReplacements = array();
foreach($aParams as $sSearch => $sReplace)
{
$aSearches[] = '$'.$sSearch.'$';
$aReplacements[] = $sReplace;
}
$this->m_sTemplate = str_replace($aSearches, $aReplacements, $this->m_sTemplate);
}
public function GetNextTag(&$iStartPos, &$iEndPos)
{
$iChunkStartPos = $iStartPos;
$sNextTag = null;
$iStartPos = $iEndPos;
foreach($this->m_aTags as $sTag)
{
// Search for the opening tag
$iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.' ', $iChunkStartPos);
if ($iOpeningPos === false)
{
$iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.'>', $iChunkStartPos);
}
if ($iOpeningPos !== false)
{
$iClosingPos = stripos($this->m_sTemplate, '</'.$sTag.'>', $iOpeningPos);
}
if ( ($iOpeningPos !== false) && ($iClosingPos !== false))
{
if ($iOpeningPos < $iStartPos)
{
// This is the next tag
$iStartPos = $iOpeningPos;
$iEndPos = $iClosingPos;
$sNextTag = $sTag;
}
}
}
return $sNextTag;
}
public function GetTagContent($sTag, $iStartPos, $iEndPos)
{
$sContent = "";
$iContentStart = strpos($this->m_sTemplate, '>', $iStartPos); // Content of tag start immediatly after the first closing bracket
if ($iContentStart !== false)
{
$sContent = substr($this->m_sTemplate, 1+$iContentStart, $iEndPos - $iContentStart - 1);
}
return $sContent;
}
public function GetTagAttributes($sTag, $iStartPos, $iEndPos)
{
$aAttr = array();
$iAttrStart = strpos($this->m_sTemplate, ' ', $iStartPos); // Attributes start just after the first space
$iAttrEnd = strpos($this->m_sTemplate, '>', $iStartPos); // Attributes end just before the first closing bracket
if ( ($iAttrStart !== false) && ($iAttrEnd !== false) && ($iAttrEnd > $iAttrStart))
{
$sAttributes = substr($this->m_sTemplate, 1+$iAttrStart, $iAttrEnd - $iAttrStart - 1);
$aAttributes = explode(' ', $sAttributes);
foreach($aAttributes as $sAttr)
{
if ( preg_match('/(.+) *= *"(.+)"$/', $sAttr, $aMatches) )
{
$aAttr[strtolower($aMatches[1])] = $aMatches[2];
}
}
}
return $aAttr;
}
protected function RenderTag($oPage, $sTag, $aAttributes, $sContent)
{
static $iTabContainerCount = 0;
static $iBlockCount = 0;
switch($sTag)
{
case 'itoptabs':
$oPage->AddTabContainer('Tabs_'.$iTabContainerCount);
$oPage->SetCurrentTabContainer('Tabs_'.$iTabContainerCount);
$iTabContainerCount++;
//$oPage->p('Content:<pre>'.htmlentities($sContent).'</pre>');
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
$oPage->SetCurrentTabContainer('');
break;
case 'itoptab':
$oPage->SetCurrentTab($aAttributes['name']);
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
//$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent).'</pre>');
$oPage->SetCurrentTab('');
break;
case 'itoptoggle':
$oPage->StartCollapsibleSection($aAttributes['name']);
$oTemplate = new DisplayTemplate($sContent);
$oTemplate->Render($oPage, array()); // no params to apply, they have already been applied
//$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent).'</pre>');
$oPage->EndCollapsibleSection();
break;
case 'itopblock': // TO DO: Use DisplayBlock::FromTemplate here
$sBlockClass = $aAttributes['blockclass'];
$sBlockType = $aAttributes['type'];
$aExtraParams = array();
if (isset($aAttributes['linkage']))
{
$aExtraParams['linkage'] = $aAttributes['linkage'];
}
switch($aAttributes['encoding'])
{
case 'text/sibusql':
$oFilter = CMDBSearchFilter::FromSibusQL($sContent);
break;
case 'text/oql':
$oFilter = CMDBSearchFilter::FromOQL($sContent);
break;
case 'text/serialize':
default:
$oFilter = CMDBSearchFilter::unserialize($sContent);
break;
}
$oBlock = new $sBlockClass($oFilter, $sBlockType, false, $aExtraParams);
$oBlock->Display($oPage, 'block_'.$iBlockCount);
$iBlockCount++;
break;
default:
// Unknown tag, just ignore it or now -- output an HTML comment
$oPage->add("<!-- unsupported tag: $sTag -->");
}
}
/**
* Unit test
*/
static public function UnitTest()
{
require_once('../application/startup.inc.php');
require_once("../application/itopwebpage.class.inc.php");
$sTemplate = '<div class="page_header">
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizNetworkDevice: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizInterface: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizContact: PKEY IS contact_id IN (ContactsLinks: object_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizDocument: PKEY IS doc_id IN (lnkDocumentRealObject: object_id = $pkey$)</itopblock>
</itoptab>
</itoptabs>';
$oPage = new iTopWebPage('Unit Test', 3);
//$oPage->add("Template content: <pre>".htmlentities($sTemplate)."</pre>\n");
$oTemplate = new DisplayTemplate($sTemplate);
$oTemplate->Render($oPage, array('class'=>'Network device','pkey'=> 271, 'name' => 'deliversw01.mecanorama.fr', 'org_id' => 3));
$oPage->output();
}
}
//DisplayTemplate::UnitTest();
?>

View File

@@ -0,0 +1,12 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/oql">SELECT CMDBChangeOpSetAttribute WHERE objkey = $pkey$ AND objclass = '$class$'</itopblock>
</div>
<img src="../../images/clean.png" style="margin-top:-20px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Rules">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">AuditRule: category_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,301 @@
<?php
require_once('../application/webpage.class.inc.php');
require_once('../application/displayblock.class.inc.php');
class UILinksWidget
{
protected $m_sClass;
protected $m_sAttCode;
protected $m_iInputId;
public function __construct($sClass, $sAttCode, $iInputId)
{
$this->m_sClass = $sClass;
$this->m_sAttCode = $sAttCode;
$this->m_iInputId = $iInputId;
}
public function Display(web_page $oPage, $oCurrentValuesSet = null)
{
$sHTMLValue = '';
$sTargetClass = self::GetTargetClass($this->m_sClass, $this->m_sAttCode);
$aAllowedValues = MetaModel::GetAllowedValues_att($this->m_sClass, $this->m_sAttCode, array(), '');
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode);
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
$sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
$sDefaultState = MetaModel::GetDefaultState($this->m_sClass);
$sLinkedClass = $oAttDef->GetLinkedClass();
foreach(MetaModel::ListAttributeDefs($sLinkedClass) as $sAttCode=>$oAttDef)
{
if ($sStateAttCode == $sAttCode)
{
// State attribute is always hidden from the UI
}
else if (!$oAttDef->IsExternalField() && ($sAttCode != $sExtKeyToMe) && ($sAttCode != $sExtKeyToRemote))
{
$iFlags = MetaModel::GetAttributeFlags($this->m_sClass, $sDefaultState, $sAttCode);
if ( !($iFlags & OPT_ATT_HIDDEN) && !($iFlags & OPT_ATT_READONLY) )
{
$aAttributes[] = $sAttCode;
}
}
}
$sAttributes = "['".implode("','", $aAttributes)."']";
if ($oCurrentValuesSet != null)
{
// Serialize the link set into a JSon object
$aCurrentValues = array();
$sRow = '{';
while($oLinkObj = $oCurrentValuesSet->Fetch())
{
foreach($aAttributes as $sLinkAttCode)
{
$sRow.= "\"$sLinkAttCode\": \"".addslashes($oLinkObj->Get($sLinkAttCode))."\", ";
}
$sRow .= "\"$sExtKeyToRemote\": ".$oLinkObj->Get($sExtKeyToRemote).'}';
$aCurrentValues[] = $sRow;
}
$sJSON = '['.implode(',', $aCurrentValues).']';
}
// Many values (or even a unknown list) display an autocomplete
if ( (count($aAllowedValues) == 0) || (count($aAllowedValues) > 20) )
{
// too many choices, use an autocomplete
// The input for the auto complete
$sTitle = $oAttDef->GetDescription();
$sHTMLValue .= "<script>\n";
$sHTMLValue .= "oLinkWidget{$this->m_iInputId} = new LinksWidget('{$this->m_iInputId}', '$sLinkedClass', '$sExtKeyToMe', '$sExtKeyToRemote', $sAttributes);\n";
$sHTMLValue .= "</script>\n";
$sHTMLValue .= $this->GetObjectPickerDialog($oPage, $sTargetClass, 'oLinkWidget'.$this->m_iInputId.'.OnOk');
$sHTMLValue .= $this->GetLinkObjectDialog($oPage, $this->m_iInputId);
$sHTMLValue .= "<input type=\"text\" id=\"ac_{$this->m_iInputId}\" size=\"35\" name=\"\" value=\"\" style=\"border: 1px solid red;\" />";
$sHTMLValue .= "<input type=\"button\" value=\" Add... \" class=\"action\" onClick=\"oLinkWidget{$this->m_iInputId}.AddObject();\"/>";
$sHTMLValue .= "&nbsp;<input type=\"button\" value=\"Browse...\" class=\"action\" onClick=\"return ManageObjects('$sTitle', '$sTargetClass', '$this->m_iInputId', '$sExtKeyToRemote');\"/>";
// another hidden input to store & pass the object's Id
$sHTMLValue .= "<input type=\"hidden\" id=\"id_ac_{$this->m_iInputId}\"/>\n";
$sHTMLValue .= "<input type=\"hidden\" id=\"{$this->m_iInputId}\" name=\"attr_{$this->m_sAttCode}\" value=\"\"/>\n";
$oPage->add_ready_script("\$('#{$this->m_iInputId}').val('$sJSON');\n\$('#ac_{$this->m_iInputId}').autocomplete('./ajax.render.php', { minChars:3, onItemSelect:selectItem, onFindValue:findValue, formatItem:formatItem, autoFill:true, keyHolder:'#id_ac_{$this->m_iInputId}', extraParams:{operation:'ui.linkswidget', sclass:'{$this->m_sClass}', attCode:'{$this->m_sAttCode}', max:30}});");
}
else
{
// Few choices, use a normal 'select'
$sHTMLValue = "<select name=\"attr_{$this->m_sAttCode}\" id=\"{$this->m_iInputId}\">\n";
foreach($aAllowedValues as $key => $value)
{
$sHTMLValue .= "<option value=\"$key\"$sSelected>$value</option>\n";
}
$sHTMLValue .= "</select>\n";
}
$sHTMLValue .= "<div id=\"{$this->m_iInputId}_values\">\n";
if ($oCurrentValuesSet != null)
{
// transform the DBObjectSet into a CMDBObjectSet !!!
$aLinkedObjects = $oCurrentValuesSet->ToArray(false);
if (count($aLinkedObjects) > 0)
{
$oSet = CMDBObjectSet::FromArray($sLinkedClass, $aLinkedObjects);
$oDisplayBlock = DisplayBlock::FromObjectSet($oSet, 'list');
$sHTMLValue .= $oDisplayBlock->GetDisplay($oPage, $this->m_iInputId.'_current', array('linkage' => $sExtKeyToMe));
}
}
$sHTMLValue .= "</div>\n";
return $sHTMLValue;
}
/**
* This static function is called by the Ajax Page when there is a need to fill an autocomplete combo
* @param $oPage web_page The ajax page used for the put^put (sent back to the browser
* @param $oContext UserContext The context of the user (for limiting the search)
* @param $sClass string The name of the class of the current object being edited
* @param $sAttCode string The name of the attribute being edited
* @param $sName string The partial name that was typed by the user
* @param $iMaxCount integer The maximum number of items to return
* @return void
*/
static public function Autocomplete(web_page $oPage, UserContext $oContext, $sClass, $sAttCode, $sName, $iMaxCount)
{
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array() /* $aArgs */, $sName);
if ($aAllowedValues != null)
{
$iCount = $iMaxCount;
foreach($aAllowedValues as $key => $value)
{
$oPage->add($value."|".$key."\n");
$iCount--;
if ($iCount == 0) break;
}
}
else // No limitation to the allowed values
{
// Search for all the object of the linked class
$oAttDef = $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sLinkedClass = $oAttDef->GetLinkedClass();
$sSearchClass = self::GetTargetClass($sClass, $sAttCode);
$oFilter = $oContext->NewFilter($sSearchClass);
$sSearchAttCode = MetaModel::GetNameAttributeCode($sSearchClass);
$oFilter->AddCondition($sSearchAttCode, $sName, 'Begins with');
$oSet = new CMDBObjectSet($oFilter, array($sSearchAttCode => true));
$iCount = 0;
while( ($iCount < $iMaxCount) && ($oObj = $oSet->fetch()) )
{
$oPage->add($oObj->GetName()."|".$oObj->GetKey()."\n");
$iCount++;
}
}
}
/**
* This static function is called by the Ajax Page display a set of objects being linked
* to the object being created
* @param $oPage web_page The ajax page used for the put^put (sent back to the browser
* @param $sClass string The name of the class 'linking class' which is the class of the objects to display
* @param $sAttCode string The name of the attribute is the main object being created
* @param $sSet JSON serialized set of objects
* @return void
*/
static public function RenderSet($oPage, $sClass, $sJSONSet, $sExtKeyToMe)
{
$aSet = json_decode($sJSONSet, true); // true means hash array instead of object
$oSet = CMDBObjectSet::FromScratch($sClass);
foreach($aSet as $aObject)
{
$oObj = MetaModel::NewObject($sClass);
foreach($aObject as $sAttCode => $value)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->IsExternalKey())
{
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value); // @@ optimization, don't do & query per object in the set !
$oObj->Set($sAttCode, $oTargetObj);
}
else
{
$oObj->Set($sAttCode, $value);
}
}
$oSet->AddObject($oObj);
}
cmdbAbstractObject::DisplaySet($oPage, $oSet, $sExtKeyToMe);
}
protected static function GetTargetClass($sClass, $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sLinkedClass = $oAttDef->GetLinkedClass();
switch(get_class($oAttDef))
{
case 'AttributeLinkedSetIndirect':
$oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote());
$sTargetClass = $oLinkingAttDef->GetTargetClass();
break;
case 'AttributeLinkedSet':
$sTargetClass = $sLinkedClass;
break;
}
return $sTargetClass;
}
protected function GetObjectPickerDialog($oPage, $sTargetClass, $sOkFunction)
{
$sHTML = <<< EOF
<div class="jqmWindow" id="ManageObjectsDlg_{$this->m_iInputId}">
<div class="page_header"><h1 id="Manage_DlgTitle_{$this->m_iInputId}">Selected Objects</h1></div>
<table width="100%">
<tr>
<td>
<p>Selected objects:</p>
<button type="button" class="action" onClick="FilterLeft('$sTargetClass');"><span> Filter... </span></button>
<p><select id="selected_objects_{$this->m_iInputId}" size="10" multiple onChange="Manage_UpdateButtons('$this->m_iInputId')" style="width:300px;">
</select></p>
</td>
<td style="text-align:center; valign:middle;">
<p><button type="button" id="btn_add_objects_{$this->m_iInputId}" onClick="Manage_AddObjects('$this->m_iInputId');"> &lt;&lt; Add </button></p>
<p><button type="button" id="btn_remove_objects_{$this->m_iInputId}" onClick="Manage_RemoveObjects('$this->m_iInputId');"> Remove &gt;&gt; </button></p>
</td>
<td>
<p>Available objects:</p>
<button type="button" class="action" onClick="FilterRight('$sTargetClass');"><span> Filter... </span></button>
<p><select id="available_objects_{$this->m_iInputId}" size="10" multiple onChange="Manage_UpdateButtons('$this->m_iInputId')" style="width:300px;">
</select></p>
</td>
</tr>
<tr>
<td colspan="3">
<button type="button" class="jqmClose" onClick="$('#ManageObjectsDlg_{$this->m_iInputId}').jqmHide(); $sOkFunction('$sTargetClass', 'selected_objects')"> Ok </button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button type="button" class="jqmClose"> Cancel</button>
</td>
</tr>
</table>
</div>
EOF;
$oPage->add_ready_script("$('#ManageObjectsDlg_$this->m_iInputId').jqm({overlay:70, modal:true, toTop:true});"); // jqModal Window
//$oPage->add_ready_script("UpdateObjectList('$sClass');");
return $sHTML;
}
protected function GetLinkObjectDialog($oPage, $sId)
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode);
$sLinkedClass = $oAttDef->GetLinkedClass();
$sStateAttCode = MetaModel::GetStateAttributeCode($sLinkedClass);
$sDefaultState = MetaModel::GetDefaultState($sLinkedClass);
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode);
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$sHTML = "<div class=\"jqmWindow\" id=\"LinkDlg_$sId\">\n";
$sHTML .= "<div class=\"page_header\"><h1 id=\"LinkObject_DlgTitle\">$sLinkedClass attributes</h1></div>\n";
$sHTML .= "<form>\n";
$index = 0;
$aAttrsMap = array();
foreach(MetaModel::ListAttributeDefs($sLinkedClass) as $sAttCode=>$oAttDef)
{
if ($sStateAttCode == $sAttCode)
{
// State attribute is always hidden from the UI
//$sHTMLValue = $this->GetState();
//$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
else if (!$oAttDef->IsExternalField() && ($sAttCode != $sExtKeyToMe) && ($sAttCode != $sExtKeyToRemote))
{
$iFlags = MetaModel::GetAttributeFlags($sLinkedClass, $sDefaultState, $sAttCode);
if ($iFlags & OPT_ATT_HIDDEN)
{
// Attribute is hidden, do nothing
}
else
{
if ($iFlags & OPT_ATT_READONLY)
{
// Attribute is read-only
$sHTMLValue = $this->GetAsHTML($sAttCode);
}
else
{
$sValue = ""; //$this->Get($sAttCode);
$sDisplayValue = ""; //$this->GetDisplayValue($sAttCode);
$sSubId = $sId.'_'.$index;
$aAttrsMap[$sAttCode] = $sSubId;
$index++;
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sLinkedClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sSubId);
}
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
}
}
$sHTML .= $oPage->GetDetails($aDetails);
$sHTML .= "<button type=\"button\" class=\"jqmClose\" onClick=\"oLinkWidget$sId.OnLinkOk()\"> Ok </button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button type=\"button\" class=\"jqmClose\" onClick=\"LinkWidget$sId.OnLinkCancel()\"> Cancel</button>\n";
$sHTML .= "</form>\n";
$sHTML .= "</div>\n";
$oPage->add_ready_script("$('#LinkDlg_$sId').jqm({overlay:70, modal:true, toTop:true});"); // jqModal Window
//$oPage->add_ready_script("UpdateObjectList('$sClass');");
return $sHTML;
}
}
?>

View File

@@ -0,0 +1,257 @@
<?php
class UIWizard
{
protected $m_oPage;
protected $m_sClass;
protected $m_sTargetState;
protected $m_aWizardSteps;
public function __construct($oPage, $sClass, $sTargetState = '')
{
$this->m_oPage = $oPage;
$this->m_sClass = $sClass;
if (empty($sTargetState))
{
$sTargetState = MetaModel::GetDefaultState($sClass);
}
$this->m_sTargetState = $sTargetState;
$this->m_aWizardSteps = $this->ComputeWizardStructure();
}
public function GetObjectClass() { return $this->m_sClass; }
public function GetTargetState() { return $this->m_sTargetState; }
public function GetWizardStructure() { return $this->m_aWizardSteps; }
/**
* Displays one step of the wizard
*/
public function DisplayWizardStep($aStep, $iStepIndex, &$iMaxInputId, &$aFieldsMap, $bFinishEnabled = false)
{
$this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep$iStepIndex\" style=\"display:none;\">\n");
$this->m_oPage->add("<a name=\"step$iStepIndex\" />\n");
$aStates = MetaModel::EnumStates($this->m_sClass);
$aDetails = array();
$sJSHandlerCode = ''; // Javascript code to be executed each time this step of the wizard is entered
foreach($aStep as $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$sAttLabel = $oAttDef->GetLabel();
$iOptions = isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode]) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
if ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT))
{
$aFields[$sAttCode] = array();
foreach($aPrerequisites as $sCode)
{
$aFields[$sAttCode][$sCode] = '';
}
}
if (count($aPrerequisites) > 0)
{
$aOptions[] = 'Prerequisites: '.implode(', ', $aPrerequisites);
}
$sFieldFlag = ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE)) ? ' <span class="hilite">*</span>' : '';
$oDefaultValuesSet = $oAttDef->GetDefaultValue(); // @@@ TO DO: get the object's current value if the object exists
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($this->m_oPage, $this->m_sClass, $sAttCode, $oAttDef, $oDefaultValuesSet, '', "att_$iMaxInputId");
$aFieldsMap[$iMaxInputId] = $sAttCode;
$aDetails[] = array('label' => $oAttDef->GetLabel().$sFieldFlag, 'value' => "<div id=\"field_$iMaxInputId\">$sHTMLValue</div>");
if ($oAttDef->GetValuesDef() != null)
{
$sJSHandlerCode .= "\toWizardHelper.RequestAllowedValues('$sAttCode');\n";
}
if ($oAttDef->GetDefaultValue() != null)
{
$sJSHandlerCode .= "\toWizardHelper.RequestDefaultValue('$sAttCode');\n";
}
if ($oAttDef->IsLinkSet())
{
$sJSHandlerCode .= "\toLinkWidgetatt_$iMaxInputId.Init();";
}
$iMaxInputId++;
}
//$aDetails[] = array('label' => '', 'value' => '<input type="button" value="Next &gt;&gt;">');
$this->m_oPage->details($aDetails);
$sBackButtonDisabled = ($iStepIndex <= 1) ? 'disabled' : '';
$sDisabled = $bFinishEnabled ? '' : 'disabled';
$nbSteps = count($this->m_aWizardSteps['mandatory']) + count($this->m_aWizardSteps['optional']);
$this->m_oPage->add("<div style=\"text-align:center\">
<input type=\"button\" value=\"&lt;&lt; Back \" $sBackButtonDisabled onClick=\"GoToStep($iStepIndex, $iStepIndex - 1)\">
<input type=\"button\" value=\" Next &gt;&gt;\" onClick=\"GoToStep($iStepIndex, 1+$iStepIndex)\">
<input type=\"button\" value=\" Finish \" $sDisabled onClick=\"GoToStep($iStepIndex, 1+$nbSteps)\">
</div>\n");
$this->m_oPage->add("
<script>
function OnEnterStep{$iStepIndex}()
{
oWizardHelper.ResetQuery();
$sJSHandlerCode
oWizardHelper.AjaxQueryServer();
}
</script>\n");
$this->m_oPage->add("</div>\n\n");
}
/**
* Display the final step of the wizard: a confirmation screen
*/
public function DisplayFinalStep($iStepIndex, $aFieldsMap)
{
$this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep$iStepIndex\" style=\"display:none;\">\n");
$this->m_oPage->add("<a name=\"step$iStepIndex\" />\n");
$this->m_oPage->P("Final step: confirmation");
$this->m_oPage->add("<form method=\"post\" action=\"../pages/UI.php\">\n");
$this->m_oPage->add("<input type=\"hidden\" name=\"operation\" value=\"wizard_apply_new\">\n");
$this->m_oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
$this->m_oPage->add("<input type=\"hidden\" id=\"wizard_json_obj\" name=\"json_obj\" value=\"\">\n");
$this->m_oPage->add("<script>\n");
$this->m_oPage->add("function OnEnterStep$iStepIndex() {\n");
foreach($aFieldsMap as $iInputId => $sAttCode)
{
$this->m_oPage->add("\toWizardHelper.UpdateCurrentValue('$sAttCode');\n");
}
$this->m_oPage->add("\toWizardHelper.Preview('object_preview');\n");
$this->m_oPage->add("\t$('#wizard_json_obj').val(oWizardHelper.ToJSON());\n");
$this->m_oPage->add("}\n");
$this->m_oPage->add("</script>\n");
$this->m_oPage->add("<div id=\"object_preview\">\n");
$this->m_oPage->add("</div>\n");
$this->m_oPage->add("<input type=\"submit\" value=\"Create {$this->m_sClass}\">\n");
$this->m_oPage->add("</form>\n");
$this->m_oPage->add("</div>\n");
}
/**
* Compute the order of the fields & pages in the wizard
* @param $oPage iTopWebPage The current page (used to display error messages)
* @param $sClass string Name of the class
* @param $sStateCode string Code of the target state of the object
* @return hash Two dimensional array: each element represents the list of fields for a given page
*/
protected function ComputeWizardStructure()
{
$aWizardSteps = array( 'mandatory' => array(), 'optional' => array());
$aFieldsDone = array(); // Store all the fields that are already covered by a previous step of the wizard
$aStates = MetaModel::EnumStates($this->m_sClass);
if ( (!empty($this->m_sTargetState)) && (count($aStates[$this->m_sTargetState]['attribute_list']) > 0) )
{
// Check all the fields that *must* be included in the wizard for this
// particular target state
$aFields = array();
foreach($aStates[$this->m_sTargetState]['attribute_list'] as $sAttCode => $iOptions)
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$sAttLabel = $oAttDef->GetLabel();
if ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT))
{
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
$aFields[$sAttCode] = array();
foreach($aPrerequisites as $sCode)
{
$aFields[$sAttCode][$sCode] = '';
}
}
}
// Now use the dependencies between the fields to order them
while(count($aFields) > 0)
{
$aCurrentStep = array();
foreach($aFields as $sAttCode => $aDependencies)
{
// All fields with no remaining dependencies can be entered at this
// step of the wizard
if (count($aDependencies) == 0)
{
$aCurrentStep[] = $sAttCode;
$aFieldsDone[$sAttCode] = '';
unset($aFields[$sAttCode]);
// Remove this field from the dependencies of the other fields
foreach($aFields as $sUpdatedCode => $aDummy)
{
// remove the dependency
unset($aFields[$sUpdatedCode][$sAttCode]);
}
}
}
if (count($aCurrentStep) == 0)
{
// This step of the wizard would contain NO field !
echo "<strong>Error:</strong> Circular reference in the dependencies between the fields.";
print_r($aFields);
break;
}
$aWizardSteps['mandatory'][] = $aCurrentStep;
}
}
// Now computes the steps to fill the optional fields
$sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
$aFields = array(); // reset
foreach(MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode=>$oAttDef)
{
$iOptions = (isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode])) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
if ( ($sStateAttCode != $sAttCode) &&
(!$oAttDef->IsExternalField()) &&
(($iOptions & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)) == 0) &&
(!isset($aFieldsDone[$sAttCode])) )
{
// 'State', external fields, read-only and hidden fields
// and fields that are already listed in the wizard
// are removed from the 'optional' part of the wizard
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
$aFields[$sAttCode] = array();
foreach($aPrerequisites as $sCode)
{
if (!isset($aFieldsDone[$sCode]))
{
// retain only the dependencies that were not covered
// in the 'mandatory' part of the wizard
$aFields[$sAttCode][$sCode] = '';
}
}
}
}
// Now use the dependencies between the fields to order them
while(count($aFields) > 0)
{
$aCurrentStep = array();
foreach($aFields as $sAttCode => $aDependencies)
{
// All fields with no remaining dependencies can be entered at this
// step of the wizard
if (count($aDependencies) == 0)
{
$aCurrentStep[] = $sAttCode;
$aFieldsDone[$sAttCode] = '';
unset($aFields[$sAttCode]);
// Remove this field from the dependencies of the other fields
foreach($aFields as $sUpdatedCode => $aDummy)
{
// remove the dependency
unset($aFields[$sUpdatedCode][$sAttCode]);
}
}
}
if (count($aCurrentStep) == 0)
{
// This step of the wizard would contain NO field !
$oPage->add("<strong>Error:</strong> Circular reference in the dependencies between the fields.");
print_r($aFields);
break;
}
$aWizardSteps['optional'][] = $aCurrentStep;
}
return $aWizardSteps;
}
}
?>

View File

@@ -0,0 +1,106 @@
<?php
require_once('../core/cmdbobject.class.inc.php');
require_once('../core/userrights.class.inc.php');
/**
* Helper class to capture a user's restrictions (access rights, profiles...) as a set of limiting conditions
*
* **** NOW OBSOLETE *** SHOULD BE REPLACED EVERYWHERE BY UserRights *****
*
*
*
*
* Usage:
* 1) Build the user's context (from her rights, a lookup in the database, a cookie, whatever)
* $oContext = new UserContext();
* $oContext->AddCondition('SomeClass', 'someFilter', 'SomeValue', '=');
* ...
*
* 2) Use the restrictions contained in the context when retrieving objects either when:
* getting directly an instance of an object
* $oObj = $oContext->GetObject('myClass', 'someKey'); // Instead of $oObj = MetaModel::GetObject('Klass', 'someKey');
* or when building a new search filter
* $oFilter = $oContext->NewFilter('myClass'); // Instead of $oFilter = new CMDBSearchFilter('Klass');
*/
class UserContext
{
/**
* Hash array to store the restricting conditions by myClass
*/
protected $m_aConditions;
/**
* Constructor
*/
public function __construct()
{
$this->m_aConditions = array();
}
/**
* Create a new search filter for the given class of objects that already contains the context's restrictions
*/
public function NewFilter($sClass)
{
return UserRights::GetFilter($sClass);
/*
$oFilter = new CMDBSearchFilter($sClass);
foreach($this->m_aConditions as $sConditionClass => $aConditionList)
{
// Add to the filter all the conditions of the parent classes of this class
if ($this->IsSubclass($sConditionClass,$sClass))
{
foreach($aConditionList as $sFilterCode => $aCondition)
{
$oFilter->AddCondition($sFilterCode, $aCondition['value'], $aCondition['operator']);
}
}
}
return $oFilter;
*/
}
/**
* Retrieve an instance of an object (if allowed by the context)
*/
public function GetObject($sClass, $sKey)
{
$oObject = null;
$oFilter = $this->NewFilter($sClass);
$oFilter->AddCondition('pkey', $sKey, '=');
$oSet = new CMDBObjectSet($oFilter);
if ($oSet->Count() > 0)
{
$oObject = $oSet->Fetch();
}
return $oObject;
}
/**
* Add a restriction to the context for a given class of objects (and all its persistent subclasses)
*/
public function AddCondition($sClass, $sFilterCode, $value, $sOperator)
{
if(!isset($this->m_aConditions[$sClass]))
{
$this->m_aConditions[$sClass] = array();
}
$this->m_aConditions[$sClass][$sFilterCode] = array('value'=>$value, 'operator'=>$sOperator);
}
/**
* Check if a given class is a subclass of (or same as) another one
*/
protected function IsSubclass($sParentClass, $sSubclass)
{
$bResult = false;
if ($sParentClass == $sSubclass)
{
$bResult = true;
}
else
{
$aParentList = MetaModel::EnumParentClasses($sSubclass);
$bResult = in_array($sParentClass, $aParentList);
}
return $bResult;
}
}
?>

80
application/utils.inc.php Normal file
View File

@@ -0,0 +1,80 @@
<?php
define('CONFIGFILE', '../config.txt');
class utils
{
private static $m_aConfig = null;
public static function ReadParam($sName, $defaultValue = "")
{
return isset($_REQUEST[$sName]) ? $_REQUEST[$sName] : $defaultValue;
}
public static function ReadPostedParam($sName, $defaultValue = "")
{
return isset($_POST[$sName]) ? $_POST[$sName] : $defaultValue;
}
public static function GetNewTransactionId()
{
// TO DO implement the real mechanism here
return sprintf("%08x", rand(0,2000000000));
}
public static function IsTransactionValid($sId)
{
// TO DO implement the real mechanism here
return true;
}
public static function ReadFromFile($sFileName)
{
if (!file_exists($sFileName)) return false;
return file_get_contents($sFileName);
}
public static function ReadConfig()
{
self::$m_aConfig = array();
$sConfigContents = self::ReadFromFile(CONFIGFILE);
if (!$sConfigContents) throw new Exception("Could not load file ".CONFIGFILE);
foreach (explode("\n", $sConfigContents) as $sLine)
{
$sLine = trim($sLine);
if (($iPos = strpos($sLine, '#')) !== false)
{
// strip out the end of the line right after the #
$sLine = substr($sLine, 0, $iPos);
}
$aMatches = array();
if (preg_match("@(\\S+.*)=\s*(\S+.*)@", $sLine, $aMatches))
{
$sParamName = trim($aMatches[1]);
$sParamValue = trim($aMatches[2]);
self::$m_aConfig[$sParamName] = $sParamValue;
}
}
}
public static function GetConfig($sParamName, $defaultValue = "")
{
if (is_null(self::$m_aConfig))
{
self::ReadConfig();
}
if (array_key_exists($sParamName, self::$m_aConfig))
{
return self::$m_aConfig[$sParamName];
}
else
{
return $defaultValue;
}
}
}
?>

View File

@@ -0,0 +1,289 @@
<?php
/**
* Simple helper class to ease the production of HTML pages
*
* This class provide methods to add content, scripts, includes... to a web page
* and renders the full web page by putting the elements in the proper place & order
* when the output() method is called.
* Usage:
* $oPage = new web_page("Title of my page");
* $oPage->p("Hello World !");
* $oPage->output();
*/
class web_page
{
protected $s_title;
protected $s_content;
protected $a_scripts;
protected $a_styles;
protected $a_include_scripts;
protected $a_include_stylesheets;
protected $a_headers;
public function __construct($s_title)
{
$this->s_title = $s_title;
$this->s_content = "";
$this->a_scripts = array();
$this->a_styles = array();
$this->a_linked_scripts = array();
$this->a_linked_stylesheets = array();
$this->a_headers = array();
ob_start(); // Start capturing the output
}
/**
* Change the title of the page after its creation
*/
public function set_title($s_title)
{
$this->s_title = $s_title;
}
/**
* Add any text or HTML fragment to the body of the page
*/
public function add($s_html)
{
$this->s_content .= $s_html;
}
/**
* Add a paragraph to the body of the page
*/
public function p($s_html)
{
$this->add($this->GetP($s_html));
}
/**
* Add a paragraph to the body of the page
*/
public function GetP($s_html)
{
return "<p>$s_html</p>\n";
}
public function table($aConfig, $aData, $aParams = array())
{
$this->add($this->GetTable($aConfig, $aData, $aParams));
}
public function GetTable($aConfig, $aData, $aParams = array())
{
$oAppContext = new ApplicationContext();
static $iNbTables = 0;
$iNbTables++;
$sHtml = "";
$sHtml .= "<table class=\"listResults\">\n";
$sHtml .= "<thead>\n";
$sHtml .= "<tr>\n";
foreach($aConfig as $sName=>$aDef)
{
$sHtml .= "<th title=\"".$aDef['description']."\">".$aDef['label']."</th>\n";
}
$sHtml .= "</tr>\n";
$sHtml .= "</thead>\n";
$sHtml .= "<tbody>\n";
foreach($aData as $aRow)
{
if (false) //(isset($aParams['preview']) && $aParams['preview'])
{
$sHtml .= "<tr id=\"Row_".$iNbTables."_".$aRow['key']."\" onClick=\"DisplayPreview(".$iNbTables.",".$aRow['key'].",'".$aParams['class']."')\">\n";
}
else if (isset($aRow['key']))
{
$sHtml .= "<tr onDblClick=\"DisplayDetails(".$aRow['key'].",'".$aParams['class']."')\">\n";
}
else
{
$sHtml .= "<tr>\n";
}
foreach($aConfig as $sName=>$aAttribs)
{
$sClass = isset($aAttribs['class']) ? 'class="'.$aAttribs['class'].'"' : '';
if ($sName != 'key')
{
$sValue = ($aRow[$sName] === '') ? '&nbsp;' : $aRow[$sName];
$sHtml .= "<td $sClass>$sValue</td>\n";
}
else
{
$sUIPage = cmdbAbstractObject::ComputeUIPage($aParams['class']);
$sHtml .= "<td><a class=\"no-arrow\" href=\"$sUIPage?operation=details&id=".$aRow['key']."&class=".$aParams['class']."&".$oAppContext->GetForLink()."\"><img src=\"../images/zoom.gif\" title=\"Details\" border=\"0\"></a></td>\n";
}
}
$sHtml .= "</tr>\n";
}
$sHtml .= "</tbody>\n";
$sHtml .= "</table>\n";
return $sHtml;
}
/**
* Add some Javascript to the header of the page
*/
public function add_script($s_script)
{
$this->a_scripts[] = $s_script;
}
/**
* Add some Javascript to the header of the page
*/
public function add_ready_script($s_script)
{
// Do nothing silently... this is not supported by this type of page...
}
/**
* Add some CSS definitions to the header of the page
*/
public function add_style($s_style)
{
$this->a_styles[] = $s_style;
}
/**
* Add a script (as an include, i.e. link) to the header of the page
*/
public function add_linked_script($s_linked_script)
{
$this->a_linked_scripts[] = $s_linked_script;
}
/**
* Add a CSS stylesheet (as an include, i.e. link) to the header of the page
*/
public function add_linked_stylesheet($s_linked_stylesheet, $s_condition = "")
{
$this->a_linked_stylesheets[] = array( 'link' => $s_linked_stylesheet, 'condition' => $s_condition);
}
/**
* Add some custom header to the page
*/
public function add_header($s_header)
{
$this->a_headers[] = $s_header;
}
/**
* Add needed headers to the page so that it will no be cached
*/
public function no_cache()
{
$this->add_header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
$this->add_header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
}
/**
* Build a special kind of TABLE useful for displaying the details of an object from a hash array of data
*/
public function details($aFields)
{
$this->add($this->GetDetails($aFields));
}
/**
* Build a special kind of TABLE useful for displaying the details of an object from a hash array of data
*/
public function GetDetails($aFields)
{
$sHtml = "<table>\n";
$sHtml .= "<tbody>\n";
foreach($aFields as $aAttrib)
{
$sHtml .= "<tr>\n";
// By Rom, for csv import, proposed to show several values for column selection
if (is_array($aAttrib['value']))
{
$sHtml .= "<td class=\"label\">".$aAttrib['label']."</td><td>".implode("</td><td>", $aAttrib['value'])."</td>\n";
}
else
{
$sHtml .= "<td class=\"label\">".$aAttrib['label']."</td><td>".$aAttrib['value']."</td>\n";
}
$sHtml .= "</tr>\n";
}
$sHtml .= "</tbody>\n";
$sHtml .= "</table>\n";
return $sHtml;
}
/**
* Outputs (via some echo) the complete HTML page by assembling all its elements
*/
public function output()
{
foreach($this->a_headers as $s_header)
{
header($s_header);
}
$s_captured_output = ob_get_contents();
ob_end_clean();
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
echo "<html>\n";
echo "<head>\n";
echo "<title>{$this->s_title}</title>\n";
foreach($this->a_linked_scripts as $s_script)
{
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
}
if (count($this->a_scripts)>0)
{
echo "<script type=\"text/javascript\">\n";
foreach($this->a_scripts as $s_script)
{
echo "$s_script\n";
}
echo "</script>\n";
}
foreach($this->a_linked_stylesheets as $a_stylesheet)
{
if ($a_stylesheet['condition'] != "")
{
echo "<!--[if {$a_stylesheet['condition']}]>\n";
}
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$a_stylesheet['link']}\" />\n";
if ($a_stylesheet['condition'] != "")
{
echo "<![endif]-->\n";
}
}
if (count($this->a_styles)>0)
{
echo "<style>\n";
foreach($this->a_styles as $s_style)
{
echo "$s_style\n";
}
echo "</style>\n";
}
echo "</head>\n";
echo "<body>\n";
echo $this->s_content;
if (trim($s_captured_output) != "")
{
echo "<div class=\"raw_output\">$s_captured_output</div>\n";
}
echo "</body>\n";
echo "</html>\n";
}
/**
* Build a series of hidden field[s] from an array
*/
// By Rom - je verrais bien une serie d'outils pour gerer des parametres que l'on retransmet entre pages d'un wizard...
// ptet deriver webpage en webwizard
public function add_input_hidden($sLabel, $aData)
{
foreach($aData as $sKey=>$sValue)
{
$this->add("<input type=\"hidden\" name=\"".$sLabel."[$sKey]\" value=\"$sValue\">");
}
}
}
?>

View File

@@ -0,0 +1,204 @@
<?php
require_once('../application/uiwizard.class.inc.php');
class WizardHelper
{
protected $m_aData;
public function __construct()
{
}
public function GetTargetObject()
{
$oObj = MetaModel::NewObject($this->m_aData['m_sClass']);
foreach($this->m_aData['m_aCurrentValues'] as $iIndex => $value)
{
$sAttCode = array_search($iIndex, $this->m_aData['m_oFieldsMap']);
// Because this is stored in a Javascript array, unused indexes
// are filled with null values
if ( ($sAttCode !== false) && ($value !== null))
{
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
if (($oAttDef->IsLinkSet()) && ($value != '') )
{
// special handling for lists
// assumes this is handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
$aData = json_decode($value, true); // true means decode as a hash array (not an object)
// Check what are the meaningful attributes
$aFields = $this->GetLinkedWizardStructure($oAttDef);
$sLinkedClass = $oAttDef->GetLinkedClass();
$aLinkedObjectsArray = array();
if (!is_array($aData))
{
echo ("aData: '$aData' (value: '$value')\n");
}
foreach($aData as $aLinkedObject)
{
$oLinkedObj = MetaModel::NewObject($sLinkedClass);
foreach($aFields as $sLinkedAttCode)
{
if ( isset($aLinkedObject[$sLinkedAttCode]) && ($aLinkedObject[$sLinkedAttCode] !== null) )
{
$sLinkedAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLinkedAttCode);
if (($sLinkedAttDef->IsExternalKey()) && ($aLinkedObject[$sLinkedAttCode] != '') )
{
// For external keys: load the target object so that external fields
// get filled too
$oTargetObj = MetaModel::GetObject($sLinkedAttDef->GetTargetClass(), $aLinkedObject[$sLinkedAttCode]);
$oLinkedObj->Set($sLinkedAttCode, $oTargetObj);
}
else
{
$oLinkedObj->Set($sLinkedAttCode, $aLinkedObject[$sLinkedAttCode]);
}
}
}
$aLinkedObjectsArray[] = $oLinkedObj;
}
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
$oObj->Set($sAttCode, $oSet);
}
else if (($oAttDef->IsExternalKey()) && ($value != '') )
{
// For external keys: load the target object so that external fields
// get filled too
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value);
$oObj->Set($sAttCode, $oTargetObj);
}
else
{
$oObj->Set($sAttCode, $value);
}
}
}
return $oObj;
}
public function GetFieldsForDefaultValue()
{
return $this->m_aData['m_aDefaultValueRequested'];
}
public function SetDefaultValue($sAttCode, $value)
{
// Protect against a request for a non existing field
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode]))
{
$iIndex = $this->m_aData['m_oFieldsMap'][$sAttCode];
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
if ($oAttDef->GetEditClass() == 'List')
{
// special handling for lists
// this as to be handled as an array of objects
// thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...]
// NOT YET IMPLEMENTED !!
$sLinkedClass = $oAttDef->GetLinkedClass();
$oSet = $value;
$aData = array();
$aFields = $this->GetLinkedWizardStructure($oAttDef);
while($oSet->fetch())
{
foreach($aFields as $sLinkedAttCode)
{
$aRow[$sAttCode] = $oLinkedObj->Get($sLinkedAttCode);
}
$aData[] = $aRow;
}
$this->m_aData['m_aDefaultValue'][$iIndex] = json_encode($aData);
}
else
{
// Normal handling for all other scalar attributes
$this->m_aData['m_aDefaultValue'][$iIndex] = $value;
}
}
}
public function GetFieldsForAllowedValues()
{
return $this->m_aData['m_aAllowedValuesRequested'];
}
public function SetAllowedValuesHtml($sAttCode, $sHtml)
{
// Protect against a request for a non existing field
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode]))
{
$iIndex = $this->m_aData['m_oFieldsMap'][$sAttCode];
$this->m_aData['m_aAllowedValues'][$iIndex] = $sHtml;
}
}
public function ToJSON()
{
return json_encode($this->m_aData);
}
static public function FromJSON($sJSON)
{
$oWizHelper = new WizardHelper();
if (get_magic_quotes_gpc())
{
$sJSON = stripslashes($sJSON);
}
$aData = json_decode($sJSON, true); // true means hash array instead of object
$oWizHelper->m_aData = $aData;
return $oWizHelper;
}
protected function GetLinkedWizardStructure($oAttDef)
{
$oWizard = new UIWizard(null, $oAttDef->GetLinkedClass());
$aWizardSteps = $oWizard->GetWizardStructure();
$aFields = array();
$sExtKeyToMeCode = $oAttDef->GetExtKeyToMe();
// Retrieve as a flat list, all the attributes that are needed to create
// an object of the linked class and put them into a flat array, except
// the attribute 'ext_key_to_me' which is a constant in our case
foreach($aWizardSteps as $sDummy => $aMainSteps)
{
// 2 entries: 'mandatory' and 'optional'
foreach($aMainSteps as $aSteps)
{
// One entry for each step of the wizard
foreach($aSteps as $sAttCode)
{
if ($sAttCode != $sExtKeyToMeCode)
{
$aFields[] = $sAttCode;
}
}
}
}
return $aFields;
}
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
{
$aSet = json_decode($sJsonSet, true); // true means hash array instead of object
$oSet = CMDBObjectSet::FromScratch($sLinkClass);
foreach($aSet as $aLinkObj)
{
$oLink = MetaModel::NewObject($sLinkClass);
foreach($aLinkObj as $sAttCode => $value)
{
$oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
if (($oAttDef->IsExternalKey()) && ($value != '') )
{
// For external keys: load the target object so that external fields
// get filled too
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value);
$oLink->Set($sAttCode, $oTargetObj);
}
$oLink->Set($sAttCode, $value);
}
$oLink->Set($sExtKeyToMe, $oMe->GetKey());
$oSet->AddObject($oLink);
}
return $oSet;
}
}
?>

View File

@@ -0,0 +1,36 @@
<?php
require_once("../application/webpage.class.inc.php");
/**
* Simple web page with no includes or fancy formatting, useful to generateXML documents
* The page adds the content-type text/XML and the encoding into the headers
*/
class XMLPage extends web_page
{
function __construct($s_title)
{
parent::__construct($s_title);
$this->add_header("Content-type: text/xml; charset=utf-8");
$this->add_header("Cache-control: no-cache");
$this->add_header("Content-location: export.xml");
$this->add("<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n");
}
public function output()
{
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
foreach($this->a_headers as $s_header)
{
header($s_header);
}
echo trim($this->s_content);
}
public function small_p($sText)
{
}
public function table($aConfig, $aData, $aParams = array())
{
}
}
?>