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

SVN:code[55]
This commit is contained in:
Denis Flaven
2009-04-28 09:03:12 +00:00
parent 27c05b460b
commit 6545595f19
422 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,467 @@
<?php
//
// ITop consultant home page
// tool box
// object model analysis
// DB integrity check and repair
//
function sexyclass($sClass, $sBaseArgs)
{
return "Class <a href=\"?$sBaseArgs&todo=showclass&class=$sClass\">$sClass</a>";
}
function sexyclasslist($aClasses, $sBaseArgs)
{
if (count($aClasses) == 0) return "";
$aRes = array();
foreach($aClasses as $sClass)
{
$aRes[] = sexyclass($sClass, $sBaseArgs);
}
return ("'".implode("', '", $aRes)."'");
}
function ShowClass($sClass, $sBaseArgs)
{
if (!MetaModel::IsValidClass($sClass))
{
echo "Invalid class, expecting a value in {".sexyclasslist(MetaModel::GetClasses(), $sBaseArgs)."}<br/>\n";
return;
}
// en recursif jusque "": MetaModel::GetParentPersistentClass($sClass)
$aProps["Root class"] = MetaModel::GetRootClass($sClass);
$aProps["Parent classes"] = sexyclasslist(MetaModel::EnumParentClasses($sClass), $sBaseArgs);
$aProps["Child classes"] = sexyclasslist(MetaModel::EnumChildClasses($sClass), $sBaseArgs);
$aProps["Subclasses (children + pure PHP)"] = sexyclasslist(MetaModel::GetSubclasses($sClass), $sBaseArgs);
$aProps["Description"] = MetaModel::GetClassDescription($sClass);
$aProps["Autoincrement id?"] = MetaModel::IsAutoIncrementKey($sClass);
$aProps["Key label"] = MetaModel::GetKeyLabel($sClass);
$aProps["Name attribute"] = MetaModel::GetNameAttributeCode($sClass);
$aProps["Reconciliation keys"] = implode(", ", MetaModel::GetReconcKeys($sClass));
$aProps["DB key column"] = MetaModel::DBGetKey($sClass);
$aProps["DB class column"] = MetaModel::DBGetClassField($sClass);
$aProps["Is standalone?"] = MetaModel::IsStandaloneClass($sClass);
foreach (MetaModel::ListAttributeDefs($sClass) as $oAttDef)
{
$aAttProps = array();
$aAttProps["Direct field"] = $oAttDef->IsDirectField();
$aAttProps["External key"] = $oAttDef->IsExternalKey();
$aAttProps["External field"] = $oAttDef->IsExternalField();
$aAttProps["Link set"] = $oAttDef->IsLinkSet();
$aAttProps["Code"] = $oAttDef->GetCode();
$aAttProps["Label"] = $oAttDef->GetLabel();
$aAttProps["Description"] = $oAttDef->GetDescription();
$oValDef = $oAttDef->GetValuesDef();
if (is_object($oValDef))
{
//$aAttProps["Allowed values"] = $oValDef->Describe();
$aAttProps["Allowed values"] = "... object of class ".get_class($oValDef);
}
else
{
$aAttProps["Allowed values"] = "";
}
// MetaModel::IsAttributeInZList($sClass, $sListCode, $sAttCodeOrFltCode)
}
// $aProps["Description"] = MetaModel::DBGetTable($sClass, $sAttCode = null)
$aAttributes = array();
foreach (MetaModel::GetClassFilterDefs($sClass) as $oFilterDef)
{
$aAttProps = array();
$aAttProps["Label"] = $oFilterDef->GetLabel();
$aOpDescs = array();
foreach ($oFilterDef->GetOperators() as $sOpCode => $sOpDescription)
{
$sIsTheLooser = ($sOpCode == $oFilterDef->GetLooseOperator()) ? " (loose search)" : "";
$aOpDescs[] = "$sOpCode ($sOpDescription)$sIsTheLooser";
}
$aAttProps["Operators"] = implode(" / ", $aOpDescs);
$aAttributes[] = $aAttProps;
}
$aProps["Filters"] = MyHelpers::make_table_from_assoc_array($aAttributes);
foreach ($aProps as $sKey => $sDesc)
{
echo "<h4>$sKey</h4>\n";
echo "<p>$sDesc</p>\n";
}
}
function ShowBizModel($sBaseArgs)
{
echo "<ul>\n";
foreach(MetaModel::GetClasses() as $sClass)
{
echo "<li>".sexyclass($sClass, $sBaseArgs)."</li>\n";
}
echo "</ul>\n";
}
function ShowZLists($sBaseArgs)
{
$aData = array();
// 1 row per class, header made after the first row keys
//
foreach(MetaModel::GetClasses() as $sClass)
{
$aRow = array();
$aRow["_"] = $sClass;
foreach (MetaModel::EnumZLists() as $sListCode)
{
$aRow[$sListCode] = implode(", ", MetaModel::GetZListItems($sClass, $sListCode));
}
$aData[] = $aRow;
}
echo MyHelpers::make_table_from_assoc_array($aData);
}
function ShowDatabaseInfo()
{
$aTables = array();
foreach (CMDBSource::EnumTables() as $sTable)
{
$aTableData = array();
$aTableData["Name"] = $sTable;
$aTableDesc = CMDBSource::GetTableInfo($sTable);
$aTableData["Fields"] = MyHelpers::make_table_from_assoc_array($aTableDesc["Fields"]);
$aTables[$sTable] = $aTableData;
}
echo MyHelpers::make_table_from_assoc_array($aTables);
}
function CreateDB()
{
$sRes = "<p>Creating the DB...</p>\n";
if (MetaModel::DBExists())
{
$sRes .= "<p>It appears that the DB already exists.</p>\n";
}
else
{
MetaModel::DBCreate();
$sRes .= "<p>Done!</p>\n";
}
return $sRes;
}
function DebugQuery($sConfigFile)
{
$sQuery = ReadParam("oql");
if (empty($sQuery))
{
$sQueryTemplate = "SELECT Foo AS f JOIN Dummy AS D ON d.spirit = f.id WHERE f.age * d.height > TO_DAYS(NOW()) OR d.alive";
}
else
{
$sQueryTemplate = $sQuery;
}
echo "<form>\n";
echo "<input type=\"hidden\" name=\"todo\" value=\"debugquery\">\n";
echo "<input type=\"hidden\" name=\"config\" value=\"$sConfigFile\">\n";
echo "<textarea name=\"oql\" rows=\"10\" cols=\"120\" name=\"csvdata\" wrap=\"soft\">$sQueryTemplate</textarea>\n";
echo "<input type=\"submit\" name=\"foo\">\n";
echo "</form>\n";
if (empty($sQuery)) return;
echo "<h1>Testing query</h1>\n";
echo "<p>$sQuery</p>\n";
echo "<h1>Follow up the query build</h1>\n";
MetaModel::StartDebugQuery();
$oFlt = DBObjectSearch::FromOQL($sQuery);
echo "<p>To OQL: ".$oFlt->ToOQL()."</p>";
$sSQL = MetaModel::MakeSelectQuery($oFlt);
MetaModel::StopDebugQuery();
echo "<h1>Explain</h1>\n";
echo "<table border=\"1\">\n";
foreach (CMDBSource::ExplainQuery($sSQL) as $aRow)
{
echo " <tr>\n";
echo " <td>".implode('</td><td>', $aRow)."</td>\n";
echo " </tr>\n";
}
echo "</table>\n";
echo "<h1>Results</h1>\n";
$oSet = new CMDBObjectSet($oFlt);
echo $oSet; // __toString()
}
/////////////////////////////////////////////////////////////////////////////////////
// Helper functions
/////////////////////////////////////////////////////////////////////////////////////
function printMenu($sConfigFile)
{
$sClassCount = count(MetaModel::GetClasses());
$bHasDB = MetaModel::DBExists();
$sUrl = "?config=".urlencode($sConfigFile);
echo "<div style=\"background-color:eeeeee; padding:10px;\">\n";
echo "<h2>phpMyORM integration sandbox</h2>\n";
echo "<h4>Target database: $sConfigFile</h4>\n";
echo "<p>$sClassCount classes referenced in the model</p>\n";
echo "<ul>";
echo " <li><a href=\"$sUrl&todo=checkmodel\">Biz model consistency</a></li>";
echo " <li><a href=\"$sUrl&todo=showzlists\">Show ZLists</a></li>";
echo " <li><a href=\"$sUrl&todo=showbizmodel\">Browse business model</a></li>";
if ($bHasDB)
{
echo " <li><a href=\"$sUrl&todo=checkmodeltodb\">Concordance between Biz model and DB format</a></li>";
echo " <li><a href=\"$sUrl&todo=checkdb\">DB integrity check</a></li>";
echo " <li><a href=\"$sUrl&todo=userrightssetup\">Setup userrights (init DB)</a></li>";
echo " <li><a href=\"$sUrl&todo=checkall\">Check business model, DB format and data integrity</a></li>";
echo " <li><a href=\"$sUrl&todo=showtables\">Show Tables</a></li>";
echo " <li><a href=\"$sUrl&todo=debugquery\">Test an OQL query (debug)</a></li>";
// echo " <li>".htmlentities($sUrl)."&amp;<b>todo=execsql</b>&amp;<b>sql=xxx</b>, to execute a specific sql request</li>";
}
else
{
echo " <li><a href=\"$sUrl&todo=createdb\">Create the DB</a></li>";
}
echo "</ul>";
echo "</div>\n";
}
function printConfigList()
{
echo "<h2>phpMyORM integration sandbox</h2>\n";
echo "<h4>Configuration sumary</h4>\n";
$sBasePath = '..';
$aConfigs = array();
foreach(scandir($sBasePath) as $sFile)
{
if (preg_match('/^config-.+\\.php$/', $sFile)) $aConfigs[] = $sFile;
}
$aConfigDetails = array();
foreach ($aConfigs as $sConfigFile)
{
$sRealPath = $sBasePath.'/'.$sConfigFile;
$oConfig = new Config($sRealPath);
$sAppModules = implode(', ', $oConfig->GetAppModules());
$sDataModels = implode(', ', $oConfig->GetDataModels());
$sAddons = implode(', ', $oConfig->GetAddons());
$sDBSubname = (strlen($oConfig->GetDBSubname()) > 0) ? '('.$oConfig->GetDBSubname().')' : '';
$sUrl = "?config=".urlencode($sRealPath);
$sHLink = "<a href=\"$sUrl\">Manage <b>$sConfigFile</b></a></br>\n";
$aConfigDetails[] = array('Config'=>$sHLink, 'Application'=>$sAppModules, 'Data models'=>$sDataModels, 'Addons'=>$sAddons, 'Database'=>$oConfig->GetDBHost().'/'.$oConfig->GetDBName().$sDBSubname.' as '.$oConfig->GetDBUser());
}
echo MyHelpers::make_table_from_assoc_array($aConfigDetails);
}
function ReadParam($sName, $defaultValue = "")
{
return isset($_REQUEST[$sName]) ? $_REQUEST[$sName] : $defaultValue;
}
function ReadMandatoryParam($sName)
{
$value = ReadParam($sName, null);
if (is_null($value))
{
echo "<p>Missing mandatory argument <b>$sName</b></p>";
exit;
}
return $value;
}
function DisplayDBFormatIssues($aErrors, $aSugFix, $sRepairUrl = "", $sSQLStatementArgName = "")
{
$aSQLFixes = array(); // each and every SQL repair statement
if (count($aErrors) > 0)
{
echo "<div style=\"width:100%;padding:10px;background:#FFAAAA;display:;\">";
echo "<h1>Wrong Database format</h1>\n";
echo "<p>The current database is not consistent with the given business model. Please investigate.</p>\n";
foreach ($aErrors as $sClass => $aMessages)
{
echo "<p>Wrong declaration (or DB format ?) for class <b>$sClass</b></p>\n";
echo "<ul class=\"treeview\">\n";
$i = 0;
foreach ($aMessages as $sMsg)
{
if (!empty($sRepairUrl))
{
$aSQLFixes[] = $aSugFix[$sClass][$i];
$sUrl = "$sRepairUrl&$sSQLStatementArgName=".urlencode($aSugFix[$sClass][$i]);
echo "<li>$sMsg (<a href=\"$sUrl\" title=\"".$aSugFix[$sClass][$i]."\" target=\"_blank\">fix it now!</a>)</li>\n";
}
else
{
echo "<li>$sMsg ({$aSugFix[$sClass][$i]})</li>\n";
}
$i++;
}
echo "</ul>\n";
}
if (count($aSQLFixes) > 1)
{
MetaModel::DBShowApplyForm($sRepairUrl, $sSQLStatementArgName, $aSQLFixes);
}
echo "<p>Aborting...</p>\n";
echo "</div>\n";
exit;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// M a i n P r o g r a m
//
/////////////////////////////////////////////////////////////////////////////////////////////////
require_once('../core/cmdbobject.class.inc.php');
$sConfigFile = ReadParam("config", '');
if (empty($sConfigFile))
{
printConfigList();
exit;
}
MetaModel::Startup($sConfigFile, true); // allow missing DB
$sBaseArgs = "config=".urlencode($sConfigFile);
$sTodo = ReadParam("todo", "");
if ($sTodo == 'execsql')
{
$sSql = ReadMandatoryParam("sql");
$aSql = explode("##SEP##", $sSql);
$sConfirm = ReadParam("confirm");
if (empty($sConfirm) || ($sConfirm != "Yes"))
{
echo "<form method=\"post\" action=\"?$sBaseArgs\">\n";
echo "<input type=\"hidden\" name=\"todo\" value=\"execsql\">\n";
echo "<input type=\"hidden\" name=\"sql\" value=\"".htmlentities($sSql)."\">\n";
if (count($aSql) == 1)
{
echo "Do you confirm that you want to execute this command: <b>".htmlentities($aSql[0])."</b> ?</br>\n";
}
else
{
$sAllQueries = "<li>".implode("</li>\n<li>", $aSql)."</li>\n";
echo "Please confirm that you want to execute these commands: <ul style=\"font-size: smaller;\">".$sAllQueries."</ul>\n";
}
echo "<input type=\"submit\" name=\"confirm\" value=\"Yes\">\n";
echo "</form>\n";
}
else
{
foreach ($aSql as $sOneSingleSql)
{
echo "Executing command: <b>$sOneSingleSql</b></br>\n";
CMDBSource::Query($sOneSingleSql);
echo "... done!</br>\n";
}
}
}
else
{
$sBaseUrl = "?$sBaseArgs&todo=execsql";
switch ($sTodo)
{
case "createdb":
// do NOT print the menu, because it will change...
break;
default:
printMenu($sConfigFile);
}
switch ($sTodo)
{
case "showtables":
ShowDatabaseInfo();
break;
case "showbizmodel":
ShowBizModel($sBaseArgs);
break;
case "showclass":
$sClass = ReadMandatoryParam("class");
ShowClass($sClass, $sBaseArgs);
break;
case "showzlists":
ShowZLists($sBaseArgs);
break;
case "debugquery":
DebugQuery($sConfigFile);
break;
case "createdb":
$sRes = CreateDB();
// As the menu depends on the existence of the DB, we have to do display it right after the job is done
printMenu($sConfigFile);
echo $sRes;
break;
case "checkmodel":
echo "Check definitions...</br>\n";
MetaModel::CheckDefinitions();
echo "done...</br>\n";
break;
case "checkmodeltodb":
echo "Check DB format...</br>\n";
list($aErrors, $aSugFix) = MetaModel::DBCheckFormat();
DisplayDBFormatIssues($aErrors, $aSugFix, $sBaseUrl, $sSQLStatementArgName = "sql");
echo "done...</br>\n";
break;
case "checkdb":
echo "Check DB integrity...</br>\n";
MetaModel::DBCheckIntegrity($sBaseUrl, "sql");
echo "done...</br>\n";
break;
case "userrightssetup":
echo "Setup user rights module (init DB)...</br>\n";
UserRights::Setup();
echo "done...</br>\n";
break;
case "checkall":
echo "Check definitions...</br>\n";
MetaModel::CheckDefinitions();
echo "done...</br>\n";
echo "Check DB format...</br>\n";
list($aErrors, $aSugFix) = MetaModel::DBCheckFormat();
DisplayDBFormatIssues($aErrors, $aSugFix, $sBaseUrl, $sSQLStatementArgName = "sql");
echo "done...</br>\n";
echo "Check DB integrity...</br>\n";
MetaModel::DBCheckIntegrity($sBaseUrl, "sql");
echo "done...</br>\n";
break;
}
}
?>

660
trunk/pages/UI.php Normal file
View File

@@ -0,0 +1,660 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/wizardhelper.class.inc.php');
require_once('../application/startup.inc.php');
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', '');
if (empty($iActiveNodeId))
{
// No menu specified, let's get the default one:
// 1) It's a root menu item (parent_id == 0)
// 2) with the lowest rank
$oFilter = DBObjectSearch::FromOQL('SELECT menuNode AS M WHERE M.parent_id = 0');
if ($oFilter)
{
$oMenuSet = new CMDBObjectSet($oFilter);
while($oMenu = $oMenuSet->Fetch())
{
$aRanks[$oMenu->GetKey()] = $oMenu->Get('rank');
}
asort($aRanks); // sort by ascending rank: menuId => rank
$aKeys = array_keys($aRanks);
$iActiveNodeId = array_shift($aKeys); // Takes the first key, i.e. the menuId with the lowest rank
}
}
$currentOrganization = utils::ReadParam('org_id', '');
$operation = utils::ReadParam('operation', '');
require_once('../application/loginwebpage.class.inc.php');
login_web_page::DoLogin(); // Check user rights and prompt if needed
$oP = new iTopWebPage("Welcome to ITop", $currentOrganization);
// From now on the context is limited to the the selected organization ??
if ($iActiveNodeId != -1)
{
$oActiveNode = $oContext->GetObject('menuNode', $iActiveNodeId);
}
else
{
$oActiveNode = null;
}
switch($operation)
{
case 'details':
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
$oSearch = new DBObjectSearch($sClass);
$oBlock = new DisplayBlock($oSearch, 'search', false);
$oBlock->Display($oP, 0);
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$oP->set_title("iTop - ".$oObj->GetDisplayName()." - $sClass details");
$oObj->DisplayDetails($oP);
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to view it).</p>\n");
}
}
break;
case 'search':
$sFilter = utils::ReadParam('filter', '');
$sFormat = utils::ReadParam('format', '');
$bSearchForm = utils::ReadParam('search_form', true);
if (empty($sFilter))
{
$oP->set_title("iTop - Error");
$oP->add("<p>'filter' must be specifed for this operation.</p>\n");
}
else
{
$oP->set_title("iTop - Search results");
// TO DO: limit the search filter by the user context
$oFilter = CMDBSearchFilter::unserialize($sFilter); // TO DO : check that the filter is valid
$oSet = new DBObjectSet($oFilter);
if ($bSearchForm)
{
$oBlock = new DisplayBlock($oFilter, 'search', false);
$oBlock->Display($oP, 0);
}
if (strtolower($sFormat) == 'csv')
{
$oBlock = new DisplayBlock($oFilter, 'csv', false);
$oBlock->Display($oP, 0);
}
else
{
$oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oP, 0);
}
}
break;
case 'full_text':
$sFullText = trim(utils::ReadParam('text', ''));
if (empty($sFullText))
{
$oP->p('Nothing to search.');
}
else
{
$oP->p("<h2>Results for '$sFullText':</h2>\n");
$iCount = 0;
// Search in full text mode in all the classes
foreach(MetaModel::GetClasses('bizmodel') as $sClassName)
{
$oFilter = new DBObjectSearch($sClassName);
$oFilter->AddCondition_FullText($sFullText);
$oSet = new DBObjectSet($oFilter);
if ($oSet->Count() > 0)
{
$aLeafs = array();
while($oObj = $oSet->Fetch())
{
if (get_class($oObj) == $sClassName)
{
$aLeafs[] = $oObj->GetKey();
}
}
$oLeafsFilter = new DBObjectSearch($sClassName);
if (count($aLeafs) > 0)
{
$iCount += count($aLeafs);
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1><span class=\"hilite\">".Metamodel::GetName($sClassName).":</span> ".count($aLeafs)." object(s) found.</h1>\n");
$oP->add("</div>\n");
$oLeafsFilter->AddCondition('pkey', $aLeafs, 'IN');
$oBlock = new DisplayBlock($oLeafsFilter, 'list', false);
$oBlock->Display($oP, 0);
}
}
}
if ($iCount == 0)
{
$oP->p('No object found.');
}
}
break;
case 'modify':
$oP->add_linked_script("../js/json.js");
$oP->add_linked_script("../js/forms-json-utils.js");
$oP->add_linked_script("../js/wizardhelper.js");
$oP->add_linked_script("../js/wizard.utils.js");
$oP->add_linked_script("../js/linkswidget.js");
$oP->add_linked_script("../js/jquery.blockUI.js");
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else
{
// Check if the user can modify this object
$oSearch = new DBObjectSearch($sClass);
$oSearch->AddCondition('pkey', $id, '=');
$oSet = new CMDBObjectSet($oSearch);
if ($oSet->Count() > 0)
{
$oObj = $oSet->Fetch();
}
$bIsModifiedAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) == UR_ALLOWED_YES);
$bIsReadAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_READ, $oSet) == UR_ALLOWED_YES);
if( ($oObj != null) && ($bIsModifiedAllowed) && ($bIsReadAllowed))
{
$oP->set_title("iTop - ".$oObj->GetName()." - $sClass modification");
$oP->add("<h1>".$oObj->GetName()." - $sClass modification</h1>\n");
$oObj->DisplayModifyForm($oP);
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to view it).</p>\n");
}
}
break;
case 'clone':
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else
{
// Check if the user can modify this object
$oSearch = new DBObjectSearch($sClass);
$oSearch->AddCondition('pkey', $id, '=');
$oSet = new CMDBObjectSet($oSearch);
if ($oSet->Count() > 0)
{
$oObjToClone = $oSet->Fetch();
}
$bIsModifiedAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) == UR_ALLOWED_YES);
$bIsReadAllowed = (UserRights::IsActionAllowed($sClass, UR_ACTION_READ, $oSet) == UR_ALLOWED_YES);
if( ($oObjToClone != null) && ($bIsModifiedAllowed) && ($bIsReadAllowed))
{
$oP->set_title("iTop - ".$oObjToClone->GetName()." - $sClass clone");
$oP->add("<h1>".$oObjToClone->GetName()." - $sClass clone</h1>\n");
cmdbAbstractObject::DisplayCreationForm($oP, $sClass, $oObjToClone);
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to view it).</p>\n");
}
}
break;
case 'new':
$sClass = utils::ReadParam('class', '');
$sStateCode = utils::ReadParam('state', '');
if ( empty($sClass) )
{
$oP->p("The class must be specified for this operation!");
}
else
{
$oP->add_linked_script("../js/json.js");
$oP->add_linked_script("../js/forms-json-utils.js");
$oP->add_linked_script("../js/wizardhelper.js");
$oP->add_linked_script("../js/wizard.utils.js");
$oP->add_linked_script("../js/linkswidget.js");
$oP->add_linked_script("../js/jquery.blockUI.js");
$oWizard = new UIWizard($oP, $sClass, $sStateCode);
$sStateCode = $oWizard->GetTargetState(); // Will computes the default state if none was supplied
if (!empty($sStateCode))
{
$aStates = MetaModel::EnumStates($sClass);
$sStateLabel = $aStates[$sStateCode]['label'];
$oP->p("Wizard for creating an object of class '$sClass' in state '$sStateCode'.");
}
else
{
// Stateless object
$oP->p("Wizard for creating an object of class '$sClass'.");
}
$aWizardSteps = $oWizard->GetWizardStructure();
// Display the structure of the wizard
$iStepIndex = 1;
$oP->p("<h2>Wizard Steps for creating an object of class '$sClass' in state '$sStateCode'</h2>\n");
$iMaxInputId = 0;
$aFieldsMap = array();
foreach($aWizardSteps['mandatory'] as $aSteps)
{
$oP->SetCurrentTab("Step $iStepIndex *");
$oWizard->DisplayWizardStep($aSteps, $iStepIndex, $iMaxInputId, $aFieldsMap);
//$oP->add("</div>\n");
$iStepIndex++;
}
foreach($aWizardSteps['optional'] as $aSteps)
{
$oP->SetCurrentTab("Step $iStepIndex *");
$oWizard->DisplayWizardStep($aSteps, $iStepIndex, $iMaxInputId, $aFieldsMap, true); // true means enable the finish button
//$oP->add("</div>\n");
$iStepIndex++;
}
$oWizard->DisplayFinalStep($iStepIndex, $aFieldsMap);
$oAppContext = new ApplicationContext();
$oContext = new UserContext();
$oObj = null;
if (!empty($id))
{
$oObj = $oContext->GetObject($sClass, $id);
}
if (!is_object($oObj))
{
// new object or or that can't be retrieved (corrupted id or object not allowed to this user)
$id = '';
$oObj = MetaModel::NewObject($sClass);
}
$oP->add("<script>
// Fill the map between the fields of the form and the attributes of the object\n");
$aNewFieldsMap = array();
foreach($aFieldsMap as $id => $sFieldCode)
{
$aNewFieldsMap[$sFieldCode] = $id;
}
$sJsonFieldsMap = json_encode($aNewFieldsMap);
$oP->add("
// Initializes the object once at the beginning of the page...
var oWizardHelper = new WizardHelper('$sClass');
oWizardHelper.SetFieldsMap($sJsonFieldsMap);
ActivateStep(1);
</script>\n");
}
break;
case 'apply_modify':
$sClass = utils::ReadPostedParam('class', '');
$id = utils::ReadPostedParam('id', '');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else if (!utils::IsTransactionValid($sTransactionId))
{
$oP->p("<strong>Error: object has already be updated!</strong>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$oP->set_title("iTop - ".$oObj->GetName()." - $sClass modification");
$oP->add("<h1>".$oObj->GetName()." - $sClass modification</h1>\n");
$bObjectModified = false;
foreach(MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode=>$oAttDef)
{
$iFlags = $oObj->GetAttributeFlags($sAttCode);
if ($iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))
{
// Non-visible, or read-only attribute, do nothing
}
else if ($oAttDef->IsLinkSet())
{
// Link set, the data is a set of link objects, encoded in JSON
$aAttributes[$sAttCode] = trim(utils::ReadPostedParam("attr_$sAttCode", ''));
if (!empty($aAttributes[$sAttCode]))
{
$oLinkSet = WizardHelper::ParseJsonSet($oObj, $oAttDef->GetLinkedClass(), $oAttDef->GetExtKeyToMe(), $aAttributes[$sAttCode]);
$oObj->Set($sAttCode, $oLinkSet);
// TO DO: detect a real modification, for now always update !!
$bObjectModified = true;
}
}
else if (!$oAttDef->IsExternalField())
{
$aAttributes[$sAttCode] = trim(utils::ReadPostedParam("attr_$sAttCode", ''));
$previousValue = $oObj->Get($sAttCode);
if (!empty($aAttributes[$sAttCode]) && ($previousValue != $aAttributes[$sAttCode]))
{
$oObj->Set($sAttCode, $aAttributes[$sAttCode]);
$bObjectModified = true;
}
}
}
if (!$bObjectModified)
{
$oP->p("No modification detected. ".get_class($oObj)." has <strong>not</strong> been updated.\n");
}
else if ($oObj->CheckToUpdate())
{
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
if (UserRights::GetUser() != UserRights::GetRealUser())
{
$sUserString = UserRights::GetRealUser()." on behalf of ".UserRights::GetUser();
}
else
{
$sUserString = UserRights::GetUser();
}
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBUpdateTracked($oMyChange);
$oP->p(get_class($oObj)." updated.\n");
}
else
{
$oP->p("<strong>Error: object can not be updated!</strong>\n");
//$oObj->Reload(); // restore default values!
}
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to edit it).</p>\n");
}
}
$oObj->DisplayDetails($oP);
break;
case 'delete':
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
$oObj = $oContext->GetObject($sClass, $id);
$sName = $oObj->GetName();
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
if (UserRights::GetUser() != UserRights::GetRealUser())
{
$sUserString = UserRights::GetRealUser()." on behalf of ".UserRights::GetUser();
}
else
{
$sUserString = UserRights::GetUser();
}
$oMyChange->Set("userinfo", $sUserString);
$oMyChange->DBInsert();
$oObj->DBDeleteTracked($oMyChange);
$oP->add("<h1>".$sName." - $sClass deleted</h1>\n");
break;
case 'apply_new':
$oP->p('Creation of the object');
$oP->p('Obsolete, should now go through the wizard...');
break;
case 'apply_clone':
$sClass = utils::ReadPostedParam('class', '');
$iCloneId = utils::ReadPostedParam('clone_id', '');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if (!utils::IsTransactionValid($sTransactionId))
{
$oP->p("<strong>Error: object has already be cloned!</strong>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $iCloneId);
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
if (UserRights::GetUser() != UserRights::GetRealUser())
{
$sUserString = UserRights::GetRealUser()." on behalf of ".UserRights::GetUser();
}
else
{
$sUserString = UserRights::GetUser();
}
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($oObj));
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
{
if ( ('finalclass' != $sAttCode) && // finalclass is a reserved word, hardcoded !
($sStateAttCode != $sAttCode) &&
(!$oAttDef->IsExternalField()) )
{
$value = utils::ReadPostedParam('attr_'.$sAttCode, '');
$oObj->Set($sAttCode, $value);
}
}
$oObj->DBCloneTracked($oMyChange);
$oP->add("<h1>".$oObj->GetName()." - $sClass created</h1>\n");
$oObj->DisplayDetails($oP);
}
break;
case 'wizard_apply_new':
$sJson = utils::ReadPostedParam('json_obj', '');
$oWizardHelper = WizardHelper::FromJSON($sJson);
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if (!utils::IsTransactionValid($sTransactionId))
{
$oP->p("<strong>Error: object has already be created!</strong>\n");
}
else
{
$oObj = $oWizardHelper->GetTargetObject();
if (is_object($oObj))
{
$sClass = get_class($oObj);
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
if (UserRights::GetUser() != UserRights::GetRealUser())
{
$sUserString = UserRights::GetRealUser()." on behalf of ".UserRights::GetUser();
}
else
{
$sUserString = UserRights::GetUser();
}
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBInsertTracked($oMyChange);
$oP->set_title("iTop - ".$oObj->GetName()." - $sClass created");
$oP->add("<h1>".$oObj->GetName()." - $sClass created</h1>\n");
$oObj->DisplayDetails($oP);
}
}
break;
case 'stimulus':
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
$sStimulus = utils::ReadParam('stimulus', '');
if ( empty($sClass) || empty($id) || empty($sStimulus) ) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class', 'id' and 'stimulus' parameters must be specifed for this operation.</p>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$aTransitions = $oObj->EnumTransitions();
$aStimuli = MetaModel::EnumStimuli($sClass);
if (!isset($aTransitions[$sStimulus]))
{
$oP->add("<p><strong>Error:</strong> Invalid stimulus: '$sStimulus' on object: {$oObj->GetName()} in state {$oObj->GetState()}.</p>\n");
}
else
{
$sActionLabel = $aStimuli[$sStimulus]->Get('label');
$sActionDetails = $aStimuli[$sStimulus]->Get('description');
$aTransition = $aTransitions[$sStimulus];
$sTargetState = $aTransition['target_state'];
$aTargetStates = MetaModel::EnumStates($sClass);
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1>$sActionLabel - <span class=\"hilite\">{$oObj->GetName()}</span></h1>\n");
//$oP->add("<p>Applying '$sActionLabel' on object: {$oObj->GetName()} in state {$oObj->GetState()} to target state: $sTargetState.</p>\n");
$oP->add("</div>\n");
$oObj->DisplayBareDetails($oP);
$aTargetState = $aTargetStates[$sTargetState];
//print_r($aTransitions[$sStimulus]);
//print_r($aTargetState);
$aExpectedAttributes = $aTargetState['attribute_list'];
$oP->add("<div class=\"wizHeader\">\n");
$oP->add("<h1>$sActionDetails</h1>\n");
$oP->add("<div class=\"wizContainer\">\n");
$oP->add("<form method=\"post\">\n");
$aDetails = array();
foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
{
// Prompt for an attribute if
// - the attribute must be changed or must be displayed to the user for confirmation
// - or the field is mandatory and currently empty
if ( ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
(($iExpectCode & OPT_ATT_MANDATORY) && ($oObj->Get($sAttCode) == '')) )
{
$aAttributesDef = MetaModel::ListAttributeDefs($sClass);
$oAttDef = $aAttributesDef[$sAttCode];
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $oObj->Get($sAttCode), $oObj->GetDisplayValue($sAttCode));
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
}
$oP->details($aDetails);
$oP->add("<input type=\"hidden\" name=\"id\" value=\"$id\">\n");
$oP->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"apply_stimulus\">\n");
$oP->add("<input type=\"hidden\" name=\"stimulus\" value=\"$sStimulus\">\n");
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
$oP->add($oAppContext->GetForForm());
$oP->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span>Cancel</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oP->add("<button type=\"submit\" class=\"action\"><span>$sActionLabel</span></button>\n");
$oP->add("</form>\n");
$oP->add("</div>\n");
$oP->add("</div>\n");
}
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to edit it).</p>\n");
}
}
break;
case 'apply_stimulus':
$sClass = utils::ReadPostedParam('class', '');
$id = utils::ReadPostedParam('id', '');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
$sStimulus = utils::ReadPostedParam('stimulus', '');
if ( empty($sClass) || empty($id) || empty($sStimulus) ) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class', 'id' and 'stimulus' parameters must be specifed for this operation.</p>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$aTransitions = $oObj->EnumTransitions();
$aStimuli = MetaModel::EnumStimuli($sClass);
if (!isset($aTransitions[$sStimulus]))
{
$oP->add("<p><strong>Error:</strong> Invalid stimulus: '$sStimulus' on object: {$oObj->GetName()} in state {$oObj->GetState()}.</p>\n");
}
else if (!utils::IsTransactionValid($sTransactionId))
{
$oP->p("<strong>Error: object has already be updated!</strong>\n");
}
else
{
$sActionLabel = $aStimuli[$sStimulus]->Get('label');
$sActionDetails = $aStimuli[$sStimulus]->Get('description');
$aTransition = $aTransitions[$sStimulus];
$sTargetState = $aTransition['target_state'];
$aTargetStates = MetaModel::EnumStates($sClass);
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1>$sActionLabel - <span class=\"hilite\">{$oObj->GetName()}</span></h1>\n");
$oP->add("<p>$sActionDetails</p>\n");
$oP->add("<p>Applying '$sActionLabel' on object: {$oObj->GetName()} in state {$oObj->GetState()} to target state: $sTargetState.</p>\n");
$oP->add("</div>\n");
$aTargetState = $aTargetStates[$sTargetState];
//print_r($aTransitions[$sStimulus]);
//print_r($aTargetState);
$aExpectedAttributes = $aTargetState['attribute_list'];
$aDetails = array();
foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
{
if (($iExpectCode & OPT_ATT_MUSTCHANGE) || ($oObj->Get($sAttCode) == '') )
{
$paramValue = utils::ReadPostedParam("attr_$sAttCode", '');
$oObj->Set($sAttCode, $paramValue);
}
}
if ($oObj->ApplyStimulus($sStimulus) && $oObj->CheckToUpdate())
{
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
if (UserRights::GetUser() != UserRights::GetRealUser())
{
$sUserString = UserRights::GetRealUser()." on behalf of ".UserRights::GetUser();
}
else
{
$sUserString = UserRights::GetUser();
}
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBUpdateTracked($oMyChange);
$oP->p(get_class($oObj)." updated.\n");
}
$oObj->DisplayDetails($oP);
}
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to edit it).</p>\n");
}
}
break;
default:
$oActiveNode->RenderContent($oP, $oAppContext->GetAsHash());
}
$oP->output();
?>

View File

@@ -0,0 +1,142 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/applicationcontext.class.inc.php');
require_once('../application/startup.inc.php');
require_once('../application/loginwebpage.class.inc.php');
login_web_page::DoLogin(); // Check user rights and prompt if needed
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', -1);
$currentOrganization = utils::ReadParam('org_id', 1);
$oP = new iTopWebPage("iTop - Universal search", $currentOrganization);
// From now on the context is limited to the the selected organization ??
// Now render the content of the page
$sClassName = utils::ReadParam('class', 'bizOrganization');
$sFilter = utils::ReadParam('filter', '');
$sOperation = utils::ReadParam('operation', '');
// First part: select the class to search for
$oP->add("<div id=\"TopPane\">");
$oP->add("<form>");
$oP->add("<input type=\"hidden\" name=\"org_id\" value=\"$currentOrganization\" />");
$oP->add("Select the class to search: <select style=\"width: 150px;\" id=\"select_class\" name=\"class\" onChange=\"this.form.submit();\">");
foreach(MetaModel::GetClasses('bizmodel') as $sClass)
{
$sDescription = MetaModel::GetClassDescription($sClass);
$sSelected = ($sClass == $sClassName) ? " SELECTED" : "";
$oP->add("<option value=\"$sClass\" title=\"$sDescription\"$sSelected>$sClass</option>");
}
$oP->add("</select></form>");
// Second part: advanced search form:
$oFilter = null;
if (!empty($sFilter))
{
$oFilter = CMDBSearchFilter::unserialize($sFilter);
}
else if (!empty($sClassName))
{
$oFilter = new CMDBSearchFilter($sClassName);
}
if ($oFilter != null)
{
$oSet =new CMDBObjectSet($oFilter);
cmdbAbstractObject::DisplaySearchForm($oP, $oSet, array('org_id' => $currentOrganization, 'class' => $sClassName));
$oP->add("</div>\n");
// Search results
$oP->add("<div id=\"BottomPane\">");
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
$oResultBlock->RenderContent($oP);
// Menu node
$sFilter = $oFilter->ToSibusQL();
$sMenuNodeContent = <<<EOF
<div id="TopPane">
<itopblock BlockClass="DisplayBlock" objectclass="bizContact" type="search" asynchronous="false" encoding="text/sibusql">$sFilter</itopblock>
</div>
<div id="BottomPane">
<p></p>
<itopblock BlockClass="DisplayBlock" objectclass="bizContact" type="list" asynchronous="false" encoding="text/sibusql">$sFilter</itopblock>
</div>
EOF;
if ($sOperation == "add_menu")
{
$oMenuNode = MetaModel::NewObject('menuNode');
$sClass = utils::ReadPostedParam('class', '');
$sLabel = utils::ReadPostedParam('label', '');
$sDescription = utils::ReadPostedParam('description', '');
$iPreviousNodeId = utils::ReadPostedParam('previous_node_id', 1);
$bChildItem = utils::ReadPostedParam('child_item', false);
$oMenuNode->Set('label', $sDescription);
$oMenuNode->Set('name', $sLabel);
$oMenuNode->Set('icon_path', '/images/std_view.gif');
$oMenuNode->Set('template', $sMenuNodeContent);
$oMenuNode->Set('hyperlink', 'UI.php');
$oMenuNode->Set('type', 'user');
$oMenuNode->Set('user_id', UserRights::GetUserId());
$oPreviousNode = MetaModel::GetObject('menuNode', $iPreviousNodeId);
if ($bChildItem)
{
// Insert the new item as a child of the previous one
$oMenuNode->Set('parent_id', $iPreviousNodeId);
$oMenuNode->Set('rank', 1); // A new child item is the first one, so let's start the numbering at 1
// If there are already child nodes, shift their rank by one
// to make room for the newly inserted child node
$oNextNodeSet = $oPreviousNode->GetChildNodesSet(null); // null => don't limit ourselves to the user context
// since we need to update all children in order to keep
// the database consistent
while($oNextNode = $oNextNodeSet->Fetch())
{
$oNextNode->Set('rank', 1 + $oNextNode->Get('rank'));
$oNextNode->DBUpdate();
}
}
else
{
// Insert the new item as the next sibling of the previous one
$oMenuNode->Set('parent_id', $oPreviousNode->Get('parent_id'));
$oMenuNode->Set('rank', 1 + $oPreviousNode->Get('rank')); // the new item comes immediatly after the selected one
// Add 1 to the rank of all the nodes currently following the 'selected' one
// to make room for the newly inserted node
$oNextNodeSet = $oPreviousNode->GetNextNodesSet(null); // null => don't limit ourselves to the user context
// since we need to update all children in order to keep
// the database consistent
while($oNextNode = $oNextNodeSet->Fetch())
{
$oNextNode->Set('rank', 1 + $oNextNode->Get('rank'));
$oNextNode->DBUpdate();
}
}
if ($oMenuNode->CheckToInsert())
{
$oMenuNode->DBInsert();
$oP->add("<form method=\"get\">");
$oP->add("<p>Menu item created !</p>");
$oP->add("<input type=\"hidden\" name=\"filter\" value=\"$sFilter\">");
$oP->add("<input type=\"hidden\" name=\"class\" value=\"$sClassName\">");
$oP->add("<input type=\"submit\" name=\"\" value=\"Reload Page\">");
$oP->add("<form>");
}
}
$oP->add("</div>\n");
}
else
{
$oP->add("</div>\n");
}
$oP->output();
?>

View File

@@ -0,0 +1,310 @@
<?php
// By Rom
require_once('../application/nicewebpage.class.inc.php');
require_once('../application/dialogstack.class.inc.php');
require_once('../application/startup.inc.php');
// #@# not used, but... require_once('../classes/usercontext.class.inc.php');
$oPage = new nice_web_page("ITop finder");
$oPage->no_cache();
MetaModel::CheckDefinitions();
// new API - MetaModel::DBCheckFormat();
// not necessary, and time consuming!
// MetaModel::DBCheckIntegrity();
function ReadParam($sName, $defaultValue = "")
{
return isset($_REQUEST[$sName]) ? $_REQUEST[$sName] : $defaultValue;
}
function Page1_AskClass($oPage)
{
$oPage->add("<form method=\"post\" action=\"\">\n");
//$oPage->add("<input type=\"hidden\" name=\"tnut\" value=\"blah\">");
$oPage->p("Please select the type of object that you want to look for:");
$oPage->MakeClassesSelect("class", "", 50);
$oPage->add("<input type=\"submit\" name=\"userconfig\" value=\"Configure filters\">\n");
$oPage->add("</form>\n");
}
function Page2_ConfigFilters($oPage, $oFilter)
{
$sClass = $oFilter->GetClass();
$oPage->p("Objects of class <em>$sClass</em>");
$oPage->add("<form method=\"post\" action=\"\">\n");
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
// Full text input
//
$oPage->add("<div>\n");
$oPage->add("Full text: ");
$sFullText = "";
foreach($oFilter->GetCriteria_FullText() as $sFullText)
{
// #@# Known limitation: do not consider other full text conditions...
continue;
}
$oPage->add("<input type=\"text\" name=\"flt_fulltext\" value=\"$sFullText\">\n");
$oPage->add("</div>\n");
// Attribute-related criteria
//
foreach (MetaModel::GetClassFilterDefs($sClass) as $sFltCode => $oFltDef)
{
// Set its current values
$sOpCode = "__none__";
$sValue = "";
foreach($oFilter->GetCriteria() as $aCritInfo)
{
if ($aCritInfo["filtercode"] == "pkey")
{
// ???
}
elseif ($aCritInfo["filtercode"] == $sFltCode)
{
$sOpCode = $aCritInfo["opcode"];
$sValue = $aCritInfo["value"];
break;
}
}
$oPage->add("<div>\n");
//$oPage->add($oFltDef->GetType()." (".$oFltDef->GetTypeDesc().")");
$oPage->add(" ".$oFltDef->GetLabel()." ");
$aOperators = array_merge(array("__none__" => ""), $oFltDef->GetOperators());
$oPage->add_select($aOperators, "flt_ops[$sFltCode]", $sOpCode, 100);
$oPage->add("\n");
$oPage->add("<input type=\"text\" name=\"flt_values[$sFltCode]\" value=\"$sValue\">\n");
$oPage->add("</div>\n");
}
// Ext key criteria
//
foreach (MetaModel::EnumReferencedClasses($sClass) as $sExtKeyAttCode => $sRemoteClass)
{
// Set its current values
$oSubFilter = $oFilter->GetCriteria_PointingTo($sExtKeyAttCode);
if (!$oSubFilter)
{
$oSubFilter = new CMDBSearchFilter($sRemoteClass);
}
$oPage->add("<div>\n");
$oAtt = MetaModel::GetAttributeDef($oFilter->GetClass(), $sExtKeyAttCode);
$oPage->add($oAtt->GetLabel()." having ({$oSubFilter->DescribeConditions()})");
//$oPage->add("having $oFilter->DescribeConditionPointTo($sExtKeyAttCode));
$oPage->add("\n");
$oPage->add(dialogstack::RenderEditableField("Edit...", "flt_pointto[$sExtKeyAttCode]", $oSubFilter->serialize(), true));
$oPage->add("</div>\n");
}
// Ext key criteria, the other way
//
foreach (MetaModel::EnumReferencingClasses($sClass, true) as $sRemoteClass => $aRemoteKeys)
{
foreach ($aRemoteKeys as $sExtKeyAttCode)
{
// Set its current values
$oSubFilter = $oFilter->GetCriteria_ReferencedBy($sRemoteClass, $sExtKeyAttCode);
if (!$oSubFilter)
{
$oSubFilter = new CMDBSearchFilter($sRemoteClass);
}
$oPage->add("<div>\n");
//$oPage->add($oFilter->DescribeConditionRefBy($sRemoteClass, $sExtKeyAttCode));
$oAtt = MetaModel::GetAttributeDef($sRemoteClass, $sExtKeyAttCode);
$oPage->add("being ".$oAtt->GetLabel()." for ".$sRemoteClass."(e)s in ({$oSubFilter->DescribeConditions()})");
$oPage->add("\n");
$oPage->add(dialogstack::RenderEditableField("Edit...", "flt_refedby[$sRemoteClass][$sExtKeyAttCode]", $oSubFilter->serialize(), true));
$oPage->add("</div>\n");
}
}
// Ext key criteria -> link objects
//
foreach (MetaModel::EnumLinkingClasses($sClass) as $sLinkClass => $aRemoteClasses)
{
foreach($aRemoteClasses as $sExtKeyAttCode => $sRemoteClass)
{
// Set its current values
//$oSubFilter = $oFilter->GetCriteria_PointingTo($sExtKeyAttCode);
$oSubFilter = null;
if (!$oSubFilter)
{
$oSubFilter = new CMDBSearchFilter($sRemoteClass);
}
$oPage->add("<div>\n");
//$oPage->add(" ".MetaModel::GetClassLabel($sRemoteClass)." ");
$oPage->add(" Linked to '".MetaModel::GetLinkLabel($sLinkClass, $sExtKeyAttCode)."' by ");
$oSubFilter = new CMDBSearchFilter($sRemoteClass);
$oPage->add($oSubFilter->__DescribeHTML());
$oPage->add("\n");
$oPage->add(dialogstack::RenderEditableField("Edit...", "flt_linkedwith[$sRemoteClass][$sExtKeyAttCode]", $oSubFilter->serialize(), true));
$oPage->add("</div>\n");
}
}
$oPage->add("<input type=\"submit\" name=\"makeit\" value=\"Search\">\n");
$oPage->add("</form>\n");
}
function MakeFilterFromArgs()
{
$sClass = ReadParam("class");
$sFilterFullText = ReadParam("flt_fulltext", "");
$aFilterOps = ReadParam("flt_ops", array());
$aFilterValues = ReadParam("flt_values", array());
$aPointTo = ReadParam("flt_pointto", array());
$aRefedBy = ReadParam("flt_refedby", array());
$aLinkedWith = ReadParam("flt_linkedwith", array());
$oFilter = new CMDBSearchFilter($sClass);
if (!empty($sFilterFullText))
{
$oFilter->AddCondition_FullText($sFilterFullText);
}
foreach($aFilterOps as $sFltCode=>$sOpCode)
{
if ($sOpCode == "__none__") continue;
$oFilter->AddCondition($sFltCode, $aFilterValues[$sFltCode], $sOpCode);
}
foreach($aPointTo as $sExtKeyAttCode=>$sFilterShortcut)
{
$oSubFilter = CMDBSearchFilter::unserialize($sFilterShortcut);
$oFilter->AddCondition_PointingTo($oSubFilter, $sExtKeyAttCode);
}
foreach($aRefedBy as $sForeignClass=>$aExtKeys)
{
foreach($aExtKeys as $sForeignExtKey=>$sFilterShortcut)
{
//MyHelpers::var_dump_html("$sForeignClass / $sForeignExtKey / $sFilterShortcut");
$oSubFilter = CMDBSearchFilter::unserialize($sFilterShortcut);
//MyHelpers::var_dump_html($oSubFilter);
$oFilter->AddCondition_ReferencedBy($oSubFilter, $sForeignExtKey);
}
}
// $oFilter->AddCondition_LinkedTo(DBObjectSearch $oLinkFilter, $sExtKeyAttCodeToMe, $sExtKeyAttCodeTarget, DBObjectSearch $oFilterTarget);
return $oFilter;
}
function Page3_ViewResults($oPage, $oFilter)
{
// Output results in various forms...
//
if ($oFilter->IsAny())
{
$oPage->p("You are considering the ENTIRE set of objects...");
}
else
{
$oPage->p($oFilter->__DescribeHTML());
$oSet = new CMDBObjectSet($oFilter);
$oPage->p("Found ".$oSet->Count()." items");
$sFilterPhrase = $oFilter->serialize();
$oPage->p("<a href=\"/pages/index.php?operation=direct&filter=$sFilterPhrase\">See detailed results</a>");
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// M a i n P r o g r a m
//
///////////////////////////////////////////////////////////////////////////////////////////////////
$oPage->p("<h1>Advanced search</h1>");
// Page 1 - Ask class
//
// Page 2 - Class is given, enum existing filters/possible links
//
// Page 3 - Interpret user choices, create a filter and render its string representation
//
//MyHelpers::arg_dump_html();
//MyHelpers::var_dump_html($_SESSION);
if (ReadParam('userconfig', false))
{
$sTodo = 'userconfig';
}
if (ReadParam('makeit', false))
{
$sTodo = 'makeit';
}
else
{
if (dialogstack::IsDialogStartup())
{
$sInit = dialogstack::StartDialog();
$oFilter = CMDBSearchFilter::unserialize($sInit);
$sTodo = 'userconfig';
}
else
{
$sClass = ReadParam('class', '');
if (empty($sClass))
{
$sTodo = 'selectclass';
}
else
{
$oFilter = MakeFilterFromArgs();
$sTodo = 'userconfig';
}
}
}
switch ($sTodo)
{
case "selectclass":
Page1_AskClass($oPage);
break;
case "userconfig":
dialogstack::DeclareCaller("Define filter for ".$oFilter->GetClass());
$oPage->add(implode(" / ", dialogstack::GetCurrentStack()));
Page2_ConfigFilters($oPage, $oFilter);
break;
case "makeit":
$oFilter = MakeFilterFromArgs();
Page3_ViewResults($oPage, $oFilter);
$oPage->add(dialogstack::RenderEndDialogForm(DLGSTACK_OK, "Use filter", $oFilter->serialize()));
$oPage->add(dialogstack::RenderEndDialogForm(DLGSTACK_CANCEL, "Annuler"));
break;
default:
trigger_error("Wrong value for arg <em>todo</em> ($sTodo)", E_USER_ERROR);
}
$oPage->output();
?>

40
trunk/pages/ajax.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
require_once('../application/application.class.inc.php');
require_once('../application/nicewebpage.class.inc.php');
require_once('../application/startup.inc.php');
function ReadParam($sName, $defaultValue = "")
{
return isset($_REQUEST[$sName]) ? $_REQUEST[$sName] : $defaultValue;
}
$oPage = new nice_web_page("Asynchronous versus asynchronous DisplayBlocks");
$oPage->no_cache();
$oPage->add("<h1>Asynchronous versus asynchronous DisplayBlocks</h1>\n");
$oContext = new UserContext();
$operation = ReadParam('operation', '');
$sClassName = ReadParam('class', 'bizContact');
$sOrganizationCode = ReadParam('org', 'ITOP');
$oPage->p("[Synchronous] Count of all $sClassName objects for organization '$sOrganizationCode'");
$oFilter = $oContext->NewFilter($sClassName);
$oFilter ->AddCondition('organization', $sOrganizationCode, '=');
$oBlock = new DisplayBlock($oFilter, 'count', false);
$oBlock->Display($oPage, "block1");
$oPage->p("[Asynchronous] All $sClassName objects for organization '$sOrganizationCode'");
$oFilter = $oContext->NewFilter($sClassName);
$oFilter ->AddCondition('organization', $sOrganizationCode, '=');
$oBlock = new DisplayBlock($oFilter, 'list', true);
$oBlock->Display($oPage, "block2");
$oPage->p("[Asynchronous] Details of all $sClassName objects for organization '$sOrganizationCode'");
$oFilter = $oContext->NewFilter($sClassName);
$oFilter ->AddCondition('organization', $sOrganizationCode, '=');
$oBlock = new DisplayBlock($oFilter, 'details', true);
$oBlock->Display($oPage, "block3");
$oPage->output();
?>

218
trunk/pages/ajax.render.php Normal file
View File

@@ -0,0 +1,218 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/webpage.class.inc.php');
require_once('../application/ajaxwebpage.class.inc.php');
require_once('../application/wizardhelper.class.inc.php');
require_once('../application/ui.linkswidget.class.inc.php');
require_once('../application/startup.inc.php');
if (isset($_SERVER['PHP_AUTH_USER']))
{
// Attempt to login, fails silently
UserRights::Login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
}
$oPage = new ajax_page("");
$oPage->no_cache();
$oContext = new UserContext();
$operation = utils::ReadParam('operation', '');
$sFilter = stripslashes(utils::ReadParam('filter', ''));
$sEncoding = utils::ReadParam('encoding', 'serialize');
$sClass = utils::ReadParam('class', 'bizContact');
$sStyle = utils::ReadParam('style', 'list');
switch($operation)
{
case 'wizard_helper_preview':
$sJson = utils::ReadParam('json_obj', '', 'post');
$oWizardHelper = WizardHelper::FromJSON($sJson);
$oObj = $oWizardHelper->GetTargetObject();
$oObj->DisplayBareDetails($oPage);
break;
case 'wizard_helper':
$sJson = utils::ReadParam('json_obj', '');
$oWizardHelper = WizardHelper::FromJSON($sJson);
$oObj = $oWizardHelper->GetTargetObject();
foreach($oWizardHelper->GetFieldsForDefaultValue() as $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$oWizardHelper->SetDefaultValue($sAttCode, $oAttDef->GetDefaultValue());
}
foreach($oWizardHelper->GetFieldsForAllowedValues() as $sAttCode)
{
$oWizardHelper->SetAllowedValuesHtml($sAttCode, "Possible values ($sAttCode)");
}
$oPage->add($oWizardHelper->ToJSON());
break;
case 'ajax':
if ($sFilter != "")
{
if ($sEncoding == 'sibusql')
{
$oFilter = CMDBSearchFilter::FromSibusQL($sFilter);
}
else
{
$oFilter = CMDBSearchFilter::unserialize($sFilter);
}
$oDisplayBlock = new DisplayBlock($oFilter, $sStyle, false);
$oDisplayBlock->RenderContent($oPage);
}
else
{
$oPage->p("Invalid query (empty filter).");
}
break;
case 'details':
$key = utils::ReadParam('id', 0);
$oFilter = $oContext->NewFilter($sClass);
$oFilter->AddCondition('pkey', $key, '=');
$oDisplayBlock = new DisplayBlock($oFilter, 'details', false);
$oDisplayBlock->RenderContent($oPage);
break;
case 'preview':
$key = utils::ReadParam('id', 0);
$oFilter = $oContext->NewFilter($sClass);
$oFilter->AddCondition('pkey', $key, '=');
$oDisplayBlock = new DisplayBlock($oFilter, 'preview', false);
$oDisplayBlock->RenderContent($oPage);
break;
case 'pie_chart':
$sGroupBy = utils::ReadParam('group_by', '');
if ($sFilter != '')
{
if ($sEncoding == 'oql')
{
$oFilter = CMDBSearchFilter::FromOQL($sFilter);
}
else
{
$oFilter = CMDBSearchFilter::unserialize($sFilter);
}
$oDisplayBlock = new DisplayBlock($oFilter, 'pie_chart_ajax', false);
$oDisplayBlock->RenderContent($oPage, array('group_by' => $sGroupBy));
}
else
{
$oPage->add("<chart>\n<chart_type>3d pie</chart_type><!-- empty filter '$sFilter' --></chart>\n.");
}
break;
case 'open_flash_chart':
$aParams = utils::ReadParam('params', array());
if ($sFilter != '')
{
if ($sEncoding == 'oql')
{
$oFilter = CMDBSearchFilter::FromOQL($sFilter);
}
else
{
$oFilter = CMDBSearchFilter::unserialize($sFilter);
}
$oDisplayBlock = new DisplayBlock($oFilter, 'open_flash_chart_ajax', false);
$oDisplayBlock->RenderContent($oPage, $aParams);
}
else
{
$oPage->add("<chart>\n<chart_type>3d pie</chart_type><!-- empty filter '$sFilter' --></chart>\n.");
}
break;
case 'modal_details':
$key = utils::ReadParam('id', 0);
$oFilter = $oContext->NewFilter($sClass);
$oFilter->AddCondition('pkey', $key, '=');
$oPage->Add("<p style=\"width:100%; margin-top:-5px;padding:3px; background-color:#33f; color:#fff;\">Object Details</p>\n");
$oDisplayBlock = new DisplayBlock($oFilter, 'details', false);
$oDisplayBlock->RenderContent($oPage);
$oPage->Add("<input type=\"button\" class=\"jqmClose\" value=\" Close \" />\n");
break;
case 'ui.linkswidget':
$sClass = utils::ReadParam('sclass', 'bizContact');
$sAttCode = utils::ReadParam('attCode', 'name');
$sOrg = utils::ReadParam('org_id', '');
$sName = utils::ReadParam('q', '');
$iMaxCount = utils::ReadParam('max', 30);
UILinksWidget::Autocomplete($oPage, $oContext, $sClass, $sAttCode, $sName, $iMaxCount);
break;
case 'ui.linkswidget.linkedset':
$sClass = utils::ReadParam('sclass', 'bizContact');
$sJSONSet = stripslashes(utils::ReadParam('sset', ''));
$sExtKeyToMe = utils::ReadParam('sextkeytome', '');
UILinksWidget::RenderSet($oPage, $sClass, $sJSONSet, $sExtKeyToMe);
break;
case 'autocomplete':
$key = utils::ReadParam('id', 0);
$sClass = utils::ReadParam('sclass', 'bizContact');
$sAttCode = utils::ReadParam('attCode', 'name');
$sOrg = utils::ReadParam('org_id', '');
$sName = utils::ReadParam('q', '');
$iMaxCount = utils::ReadParam('max', 30);
$aArgs = array();
if (!empty($key))
{
if ($oThis = MetaModel::GetObject($sClass, $key))
{
$aArgs['*this*'] = $oThis;
}
}
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs, $sName);
$iCount = 0;
foreach($aAllowedValues as $key => $value)
{
$oPage->add($value."|".$key."\n");
if ($iCount++) break;
}
break;
case 'link':
$sClass = utils::ReadParam('sclass', 'logInfra');
$sAttCode = utils::ReadParam('attCode', 'name');
//$sOrg = utils::ReadParam('org_id', '');
$sName = utils::ReadParam('q', '');
$iMaxCount = utils::ReadParam('max', 30);
$iCount = 0;
$oFilter = $oContext->NewFilter($sClass);
$oFilter->AddCondition($sAttCode, $sName, 'Begins with');
//$oFilter->AddCondition('org_id', $sOrg);
$oSet = new CMDBObjectSet($oFilter, array($sAttCode => true));
while( ($iCount < $iMaxCount) && ($oObj = $oSet->fetch()) )
{
$oPage->add($oObj->GetAsHTML($sAttCode)."|".$oObj->GetKey()."\n");
$iCount++;
}
break;
case 'create':
case 'create_menu':
$sClass = utils::ReadParam('class', '');
$sFilter = utils::ReadParam('filter', '');
menuNode::DisplayCreationForm($oPage, $sClass, $sFilter);
break;
case 'combo_options':
$oFilter = CMDBSearchFilter::FromSibusQL($sFilter);
$oSet = new CMDBObjectSet($oFilter);
while( $oObj = $oSet->fetch())
{
$oPage->add('<option title="Here is more information..." value="'.$oObj->GetKey().'">'.$oObj->GetDisplayName().'</option>');
}
break;
default:
$oPage->p("Invalid query.");
}
$oPage->output();
?>

149
trunk/pages/audit.php Normal file
View File

@@ -0,0 +1,149 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/startup.inc.php');
$currentOrganization = utils::ReadParam('org_id', '');
$operation = utils::ReadParam('operation', '');
$oAppContext = new ApplicationContext();
$oP = new iTopWebPage("iTop - CMDB Audit", $currentOrganization);
function GetRuleResultSet($iRuleId, $oDefinitionFilter)
{
$oContext = new UserContext();
$oRule = $oContext->GetObject('AuditRule', $iRuleId);
$sSibusql = $oRule->Get('query');
$oRuleFilter = DBObjectSearch::FromSibusQL($sSibusql);
if ($oRule->Get('valid_flag') == 'false')
{
// The query returns directly the invalid elements
$oFilter = $oRuleFilter;
$oFilter->MergeWith($oDefinitionFilter);
$oErrorObjectSet = new CMDBObjectSet($oFilter);
}
else
{
// The query returns only the valid elements, all the others are invalid
$oFilter = $oRuleFilter;
$oErrorObjectSet = new CMDBObjectSet($oFilter);
$aValidIds = array(0); // Make sure that we have at least one value in the list
while($oObj = $oErrorObjectSet->Fetch())
{
$aValidIds[] = $oObj->GetKey();
}
$oFilter = $oDefinitionFilter;
$oFilter->AddCondition('pkey', $aValidIds, 'NOTIN');
$oErrorObjectSet = new CMDBObjectSet($oFilter);
}
return $oErrorObjectSet;
}
function GetReportColor($iTotal, $iErrors)
{
$sResult = 'red';
if ( ($iTotal == 0) || ($iErrors / $iTotal) <= 0.05 )
{
$sResult = 'green';
}
else if ( ($iErrors / $iTotal) <= 0.25 )
{
$sResult = 'orange';
}
return $sResult;
}
switch($operation)
{
case 'errors':
$iCategory = utils::ReadParam('category', '');
$iRuleIndex = utils::ReadParam('rule', 0);
$oContext = new UserContext();
$oAuditCategory = $oContext->GetObject('AuditCategory', $iCategory);
$oDefinitionFilter = DBObjectSearch::FromSibusQL($oAuditCategory->Get('definition_set'));
if (!empty($currentOrganization))
{
$oDefinitionFilter->AddCondition('org_id', $currentOrganization);
}
$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
$oErrorObjectSet = GetRuleResultSet($iRuleIndex, $oDefinitionFilter);
$oAuditRule = $oContext->GetObject('AuditRule', $iRuleIndex);
$oP->add('<div class="page_header"><h1>Audit Errors: <span class="hilite">'.$oAuditRule->Get('description').'</span></h1><img style="margin-top: -20px; margin-right: 10px; float: right;" src="../images/stop.png"/></div>');
$oP->p('<a href="./audit.php?'.$oAppContext->GetForLink().'">[Back to audit results]</a>');
cmdbAbstractObject::DisplaySet($oP, $oErrorObjectSet);
break;
case 'audit':
default:
$oP->add('<div class="page_header"><h1>Interactive Audit</h1><img style="margin-top: -20px; margin-right: 10px; float: right;" src="../images/clean.png"/></div>');
$oAuditFilter = new CMDBSearchFilter('AuditCategory');
$oCategoriesSet = new DBObjectSet($oAuditFilter);
$oP->add("<table style=\"margin-top: 1em; padding: 0px; border-top: 3px solid #f6f6f1; border-left: 3px solid #f6f6f1; border-bottom: 3px solid #e6e6e1; border-right: 3px solid #e6e6e1;\">\n");
$oP->add("<tr><td>\n");
$oP->add("<table>\n");
$oP->add("<tr>\n");
$oP->add("<th><img src=\"../images/minus.gif\"></th><th class=\"alignLeft\">Audit Rule</th><th># Objects</th><th># Errors</th><th>% Ok</th>\n");
$oP->add("</tr>\n");
while($oAuditCategory = $oCategoriesSet->fetch())
{
$oDefinitionFilter = DBObjectSearch::FromSibusQL($oAuditCategory->Get('definition_set'));
$aObjectsWithErrors = array();
if (!empty($currentOrganization))
{
$oDefinitionFilter->AddCondition('org_id', $currentOrganization);
}
$aResults = array();
$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
$iCount = $oDefinitionSet->Count();
$oRulesFilter = new CMDBSearchFilter('AuditRule');
$oRulesFilter->AddCondition('category_id', $oAuditCategory->GetKey());
$oRulesSet = new DBObjectSet($oRulesFilter);
while($oAuditRule = $oRulesSet->fetch() )
{
$aRow = array();
$aRow['description'] = $oAuditRule->Get('name');
if ($iCount == 0)
{
// nothing to check, really !
$aRow['nb_errors'] = "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."\">0</a>";
$aRow['percent_ok'] = '100.00';
$aRow['class'] = GetReportColor($iCount, 0);
}
else
{
$oRuleFilter = DBObjectSearch::FromSibusQL($oAuditRule->Get('query'));
$oErrorObjectSet = GetRuleResultSet($oAuditRule->GetKey(), $oDefinitionFilter);
$iErrorsCount = $oErrorObjectSet->Count();
while($oObj = $oErrorObjectSet->Fetch())
{
$aObjectsWithErrors[$oObj->GetKey()] = true;
}
$aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\">$iErrorsCount</a>";
$aRow['percent_ok'] = sprintf('%.2f', 100.0 * (($iCount - $iErrorsCount) / $iCount));
$aRow['class'] = GetReportColor($iCount, $iErrorsCount);
}
$aResults[] = $aRow;
$iTotalErrors = count($aObjectsWithErrors);
$sOverallPercentOk = ($iCount == 0) ? '100.00' : sprintf('%.2f', 100.0 * (($iCount - $iTotalErrors) / $iCount));
$sClass = GetReportColor($iCount, $iTotalErrors);
}
$oP->add("<tr>\n");
$oP->add("<th><img src=\"../images/minus.gif\"></th><th class=\"alignLeft\">".$oAuditCategory->GetName()."</th><th class=\"alignRight\">$iCount</th><th class=\"alignRight\">$iTotalErrors</th><th class=\"alignRight $sClass\">$sOverallPercentOk %</th>\n");
$oP->add("</tr>\n");
foreach($aResults as $aRow)
{
$oP->add("<tr>\n");
$oP->add("<td>&nbsp;</td><td colspan=\"2\">".$aRow['description']."</td><td class=\"alignRight\">".$aRow['nb_errors']."</td><td class=\"alignRight ".$aRow['class']."\">".$aRow['percent_ok']." %</td>\n");
$oP->add("</tr>\n");
}
}
$oP->add("</table>\n");
$oP->add("</td></tr>\n");
$oP->add("</table>\n");
}
$oP->output();
?>

527
trunk/pages/csvimport.php Normal file
View File

@@ -0,0 +1,527 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/startup.inc.php');
require_once('../application/loginwebpage.class.inc.php');
login_web_page::DoLogin(); // Check user rights and prompt if needed
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', -1);
$currentOrganization = utils::ReadParam('org_id', 1);
$oPage = new iTopWebPage("iTop - Bulk import", $currentOrganization);
define ('EXTKEY_SEP', '::::');
define ('EXTKEY_LABELSEP', ' -> ');
///////////////////////////////////////////////////////////////////////////////
// External key/field naming conventions (sharing the naming space with std attributes
///////////////////////////////////////////////////////////////////////////////
function IsExtKeyField($sColDesc)
{
return ($iPos = strpos($sColDesc, EXTKEY_SEP));
}
function GetExtKeyFieldCodes($sColDesc)
{
$iPos = strpos($sColDesc, EXTKEY_SEP);
return array(
substr($sColDesc, 0, $iPos),
substr($sColDesc, $iPos + strlen(EXTKEY_SEP))
);
}
function MakeExtFieldLabel($sClass, $sExtKeyAttCode, $sForeignAttCode)
{
$oExtKeyAtt = MetaModel::GetAttributeDef($sClass, $sExtKeyAttCode);
$oForeignAtt = MetaModel::GetAttributeDef($oExtKeyAtt->GetTargetClass(), $sForeignAttCode);
return $oExtKeyAtt->GetLabel().EXTKEY_LABELSEP.$oForeignAtt->GetLabel();
}
function MakeExtFieldSelectValue($sAttCode, $sExtAttCode)
{
return $sAttCode.EXTKEY_SEP.$sExtAttCode;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
function ShowTableForm($oPage, $oCSVParser, $sClass)
{
$aData = $oCSVParser->ToArray(null, 3);
$aColToRow = array();
foreach($aData as $aRow)
{
foreach ($aRow as $sFieldId=>$sValue)
{
$aColToRow[$sFieldId][] = $sValue;
}
}
$aFields = array();
foreach($oCSVParser->ListFields() as $iFieldIndex=>$sFieldName)
{
$sSelField = "<select name=\"fmap[field$iFieldIndex]\">";
$sSelField .= "<option value=\"__none__\">None (ignore)</option>";
$sSELECTED = (strcasecmp($sFieldName, "pkey") == 0) ? " SELECTED" : "";
$sSelField .= "<option value=\"pkey\"$sSELECTED>Private Key</option>";
$sFoundAttCode = ""; // quick and dirty way to remind if a match has been found and suggest a reconciliation key if possible
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAtt)
{
if ($oAtt->IsExternalField()) continue;
$bIsThatField = (strcasecmp($sFieldName, $oAtt->GetLabel()) == 0);
//$sIsReconcKey = (MetaModel::IsValidFilterCode($sClass, $sAttCode)) ? " [key]" : "";
$sIsReconcKey = MetaModel::IsReconcKey($sClass, $sAttCode) ? " [rk!]" : "";
$sFoundAttCode = (MetaModel::IsValidFilterCode($sClass, $sAttCode) && $bIsThatField) ? $sAttCode : $sFoundAttCode;
$sSELECTED = $bIsThatField ? " SELECTED" : "";
if ($oAtt->IsExternalKey())
{
// An external key might be loaded by
// the pkey or a reconciliation key
//
$sSelField .= "<option value=\"$sAttCode\"$sSELECTED><em>".$oAtt->GetLabel()."</em> (pkey)$sIsReconcKey</option>";
$sRemoteClass = $oAtt->GetTargetClass();
foreach(MetaModel::GetReconcKeys($sRemoteClass) as $sExtAttCode)
{
$sValue = MakeExtFieldSelectValue($sAttCode, $sExtAttCode);
// Create two entries:
// - generic syntax (ext key label -> remote field label)
// - if an ext field exists that corresponds to it, allow its label
$sLabel1 = MakeExtFieldLabel($sClass, $sAttCode, $sExtAttCode);
$bFoundTwin = false;
foreach (MetaModel::GetExternalFields($sClass, $sAttCode) as $oExtFieldAtt)
{
if ($oExtFieldAtt->GetExtAttCode() == $sExtAttCode)
{
$sLabel2 = $oExtFieldAtt->GetLabel();
$bIsThatField = (strcasecmp($sFieldName, $sLabel2) == 0);
$sSELECTED = $bIsThatField ? " SELECTED" : "";
$sTITLE = " title=\"equivalent to '".htmlentities($sLabel1)."'\"";
$sSelField .= "<option value=\"$sValue\"$sTITLE $sSELECTED>".htmlentities($sLabel2)."</option>";
$bFoundTwin = true;
break;
}
}
$bIsThatField = (strcasecmp($sFieldName, $sLabel1) == 0);
$sSELECTED = $bIsThatField ? " SELECTED" : "";
$sTITLE = $bFoundTwin ? " title=\"equivalent to '".htmlentities($sLabel2)."'\"" : "";
$sSelField .= "<option value=\"$sValue\"$sTITLE $sSELECTED>".htmlentities($sLabel1)."</option>";
}
}
else
{
$sSelField .= "<option value=\"$sAttCode\"$sSELECTED>".$oAtt->GetLabel()."$sIsReconcKey</option>";
}
}
$sSelField .= "</select>";
$sCHECKED = ($sFieldName == "pkey" || MetaModel::IsReconcKey($sClass, $sFoundAttCode)) ? " CHECKED" : "";
$sSelField .= "&nbsp;<input type=\"checkbox\" name=\"iskey[field$iFieldIndex]\" value=\"yes\" $sCHECKED>";
$aFields["field$iFieldIndex"]["label"] = $sSelField;
$aFields["field$iFieldIndex"]["value"] = $aColToRow[$iFieldIndex];
}
$oPage->details($aFields);
}
function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CMDBChange $oChange = null)
{
// Note: $oChange can be null, in which case the aim is to check what would be done
// Setup field mapping: sort out between values and other specific columns
//
$iPKeyId = null;
$aReconcilKeys = array();
$aAttList = array();
$aExtKeys = array();
foreach($aFieldMap as $sFieldId=>$sColDesc)
{
$iFieldId = (int) substr($sFieldId, strlen("field"));
if ($sColDesc == "pkey")
{
// Skip !
$iPKeyId = $iFieldId;
}
elseif ($sColDesc == "__none__")
{
// Skip !
}
elseif (IsExtKeyField($sColDesc))
{
list($sExtKeyAttCode, $sExtReconcKeyAttCode) = GetExtKeyFieldCodes($sColDesc);
$aExtKeys[$sExtKeyAttCode][$sExtReconcKeyAttCode] = $iFieldId;
}
elseif (array_key_exists($sFieldId, $aIsReconcKey))
{
$aReconcilKeys[$sColDesc] = $iFieldId;
$aAttList[$sColDesc] = $iFieldId; // A reconciliation key is also a field
}
else
{
// $sColDesc is an attribute code
//
$aAttList[$sColDesc] = $iFieldId;
}
}
// Setup result presentation
//
$aDisplayConfig = array();
$aDisplayConfig["__RECONCILIATION__"] = array("label"=>"Reconciliation", "description"=>"");
$aDisplayConfig["__STATUS__"] = array("label"=>"Status", "description"=>"");
if (isset($iPKeyId))
{
$aDisplayConfig["col$iPKeyId"] = array("label"=>"<strong>pkey</strong>", "description"=>"");
}
foreach($aReconcilKeys as $sAttCode => $iCol)
{
$sLabel = MetaModel::GetAttributeDef($sClass, $sAttCode)->GetLabel();
$aDisplayConfig["col$iCol"] = array("label"=>"$sLabel", "description"=>"");
}
foreach($aExtKeys as $sAttCode=>$aKeyConfig)
{
$oExtKeyAtt = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sLabel = $oExtKeyAtt->GetLabel();
$aDisplayConfig[$sAttCode] = array("label"=>"$sLabel", "description"=>"");
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
{
// The foreign attribute is one of our reconciliation key
$sLabel = MakeExtFieldLabel($sClass, $sAttCode, $sForeignAttCode);
$aDisplayConfig["col$iCol"] = array("label"=>"$sLabel", "description"=>"");
}
}
foreach ($aAttList as $sAttCode => $iCol)
{
$sLabel = MetaModel::GetAttributeDef($sClass, $sAttCode)->GetLabel();
$aDisplayConfig["col$iCol"] = array("label"=>"$sLabel", "description"=>"");
}
// Compute the results
//
$aData = $oCSVParser->ToArray();
$oBulk = new BulkChange(
$sClass,
$aData,
$aAttList,
array_keys($aReconcilKeys),
$aExtKeys
);
$aRes = $oBulk->Process($oChange);
$aResultDisp = array(); // to be displayed
foreach($aRes as $iRow => $aRowData)
{
$aRowDisp = array();
$aRowDisp["__RECONCILIATION__"] = $aRowData["__RECONCILIATION__"];
$aRowDisp["__STATUS__"] = $aRowData["__STATUS__"]->GetDescription();
foreach($aRowData as $sKey => $value)
{
if ($sKey == '__RECONCILIATION__') continue;
if ($sKey == '__STATUS__') continue;
switch (get_class($value))
{
case 'CellChangeSpec_Void':
$sClass = '';
break;
case 'CellChangeSpec_Unchanged':
$sClass = '';
break;
case 'CellChangeSpec_Modify':
$sClass = 'csvimport_ok';
break;
case 'CellChangeSpec_Init':
$sClass = 'csvimport_init';
break;
case 'CellChangeSpec_Issue':
$sClass = 'csvimport_error';
break;
}
if (empty($sClass))
{
$aRowDisp[$sKey] = $value->GetDescription();
}
else
{
$aRowDisp[$sKey] = "<div class=\"$sClass\">".$value->GetDescription()."</div>";
}
}
$aResultDisp[$iRow] = $aRowDisp;
}
$oPage->table($aDisplayConfig, $aResultDisp);
}
///////////////////////////////////////////////////////////////////////////////
// Wizard entry points
///////////////////////////////////////////////////////////////////////////////
function Do_Welcome($oPage, $sClass)
{
$sWiztep = "1_welcome";
$oPage->p("<h1>Bulk load from CSV data / step 1</h1>");
$sCSVData = utils::ReadPostedParam('csvdata');
$oPage->add("<form method=\"post\" action=\"\">");
$oPage->MakeClassesSelect("class", $sClass, 50);
//$oPage->Add("<input type=\"text\" size=\"40\" name=\"initialsituation\" value=\"\">");
$oPage->add("</br>");
$oPage->add("<textarea rows=\"25\" cols=\"80\" name=\"csvdata\" wrap=\"soft\">$sCSVData</textarea>");
$oPage->add("</br>");
$oPage->add("<input type=\"hidden\" name=\"fromwiztep\" value=\"$sWiztep\">");
$oPage->add("<input type=\"submit\" name=\"todo\" value=\"Next\"><br/>\n");
$oPage->add("</form>");
// As a help to the end-user, let's display the list of possible fields
// for a class, that can be copied/pasted into the CSV area.
$sCurrentList = "";
$aHeadersList = array();
foreach(MetaModel::GetClasses('bizmodel') as $sClassName)
{
$aList = MetaModel::GetZListItems($sClassName, 'details');
$aHeader = array();
// $aHeader[] = MetaModel::GetKeyLabel($sClassName);
$aHeader[] = 'pkey'; // Should be what's coded on the line above... but there is a bug
foreach($aList as $sAttCode)
{
$aHeader[] = MetaModel::GetLabel($sClassName, $sAttCode);
}
$sAttributes = implode(",", $aHeader);
$aHeadersList[$sClassName] = $sAttributes;
if($sClassName == $sClass)
{
// this class is currently selected
$sCurrentList = $sAttributes;
}
}
// Store all the values in a variable client-side
$aScript = array();
foreach($aHeadersList as $sClassName => $sAttributes)
{
$aScript[] = "'$sClassName':'$sAttributes'";
}
$oPage->add("<script>
var oAttributes = {".implode(',', $aScript)."};
function DisplayFields(className)
{
$('#fields').val(oAttributes[className]);
}
</script>\n");
$oPage->add_ready_script("$('#select_class').change( function() {DisplayFields(this.value);} );");
$oPage->add("Fields for this object: <textarea readonly id=fields rows=\"3\" cols=\"60\" wrap=\"soft\">$sCurrentList</textarea>");
}
function Do_Format($oPage, $sClass)
{
$oPage->p("<h1>Bulk load from CSV data / step 2</h1>");
$sWiztep = "2_format";
$sCSVData = utils::ReadPostedParam('csvdata');
$oCSVParser = new CSVParser($sCSVData);
$sSep = $oCSVParser->GuessSeparator();
$iSkip = $oCSVParser->GuessSkipLines();
// No data ?
$aData = $oCSVParser->ToArray(null);
$iTarget = count($aData);
if ($iTarget == 0)
{
$oPage->add("Empty data set...");
$oPage->add("<form method=\"post\" action=\"\">");
$oPage->add("<input type=\"hidden\" name=\"csvdata\" value=\"$sCSVData\">");
$oPage->add("<input type=\"hidden\" name=\"fromwiztep\" value=\"$sWiztep\">");
$oPage->add("<input type=\"submit\" name=\"todo\" value=\"Back\">");
$oPage->add("</form>");
}
// Guess the format :
$oPage->p("Guessed separator: '<strong>$sSep</strong>' (ASCII=".ord($sSep).")");
$oPage->p("Guessed # of lines to skip: $iSkip");
$oPage->p("Target: $iTarget rows");
$oPage->Add("<form method=\"post\" action=\"\">");
ShowTableForm($oPage, $oCSVParser, $sClass);
$oPage->Add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">");
$oPage->Add("<input type=\"hidden\" name=\"csvdata\" value=\"$sCSVData\">");
$oPage->Add("<input type=\"hidden\" name=\"separator\" value=\"$sSep\">");
$oPage->Add("<input type=\"hidden\" name=\"skiplines\" value=\"$iSkip\">");
$oPage->Add("<input type=\"hidden\" name=\"fromwiztep\" value=\"$sWiztep\">");
$oPage->add("<input type=\"submit\" name=\"todo\" value=\"Back\">");
$oPage->Add("<input type=\"submit\" name=\"todo\" value=\"Next\">");
$oPage->Add("</form>");
}
function DoProcessOrVerify($oPage, $sClass, CMDBChange $oChange = null)
{
$sCSVData = utils::ReadPostedParam('csvdata');
$sSep = utils::ReadPostedParam('separator');
$iSkip = utils::ReadPostedParam('skiplines');
$aFieldMap = utils::ReadPostedParam('fmap');
$aIsReconcKey = utils::ReadPostedParam('iskey');
$oCSVParser = new CSVParser($sCSVData);
$oCSVParser->SetSeparator($sSep);
$oCSVParser->SetSkipLines($iSkip);
$aData = $oCSVParser->ToArray(null);
$iTarget = count($aData);
$oPage->p("<h2>Goal summary</h2>");
$oPage->p("Target: $iTarget rows");
$aSampleData = $oCSVParser->ToArray(array_keys($aFieldMap), 5);
$aDisplayConfig = array();
foreach ($aFieldMap as $sFieldId=>$sColDesc)
{
if (array_key_exists($sFieldId, $aIsReconcKey))
{
$sReconcKey = " [search]";
}
else
{
$sReconcKey = "";
}
if ($sColDesc == "pkey")
{
$aDisplayConfig[$sFieldId] = array("label"=>"Private key $sReconcKey", "description"=>"blah pkey");
}
elseif ($sColDesc == "__none__")
{
// Skip !
}
else if (MetaModel::IsValidAttCode($sClass, $sColDesc))
{
$sAttCode = $sColDesc;
$sLabel = MetaModel::GetAttributeDef($sClass, $sAttCode)->GetLabel();
$aDisplayConfig[$sFieldId] = array("label"=>"$sLabel$sReconcKey", "description"=>"");
}
elseif (IsExtKeyField($sColDesc))
{
list($sExtKeyAttCode, $sForeignAttCode) = GetExtKeyFieldCodes($sColDesc);
$aDisplayConfig[$sFieldId] = array("label"=>MakeExtFieldLabel($sClass, $sExtKeyAttCode, $sForeignAttCode), "description"=>"");
}
else
{
// ???
$aDisplayConfig[$sFieldId] = array("label"=>"-?-?-$sColDesc-?-?-", "description"=>"");
}
}
$oPage->table($aDisplayConfig, $aSampleData);
if ($oChange)
{
$oPage->p("<h2>Processing...</h2>");
}
else
{
$oPage->p("<h2>Check...</h2>");
}
ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, $oChange);
$oPage->add("<form method=\"post\" action=\"\">");
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">");
$oPage->add("<input type=\"hidden\" name=\"csvdata\" value=\"$sCSVData\">");
$oPage->add("<input type=\"hidden\" name=\"separator\" value=\"$sSep\">");
$oPage->add("<input type=\"hidden\" name=\"skiplines\" value=\"$iSkip\">");
$oPage->add_input_hidden("fmap", $aFieldMap);
$oPage->add_input_hidden("iskey", $aIsReconcKey);
}
function Do_Verify($oPage, $sClass)
{
$oPage->p("<h1>Bulk load from CSV data / step 3</h1>");
$sWiztep = "3_verify";
DoProcessOrVerify($oPage, $sClass, null);
// FORM started by DoProcessOrVerify...
$oPage->add("<input type=\"hidden\" name=\"fromwiztep\" value=\"$sWiztep\">");
$oPage->add("<input type=\"submit\" name=\"todo\" value=\"Back\">");
$oPage->add("<input type=\"submit\" name=\"todo\" value=\"Next\">");
$oPage->add("</form>");
}
function Do_Execute($oPage, $sClass)
{
$oPage->p("<h1>Bulk load from CSV data / step 4</h1>");
$sWiztep = "4_execute";
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "CSV Import");
$iChangeId = $oMyChange->DBInsert();
DoProcessOrVerify($oPage, $sClass, $oMyChange);
// FORM started by DoProcessOrVerify...
$oPage->add("<input type=\"hidden\" name=\"fromwiztep\" value=\"$sWiztep\">");
$oPage->add("<input type=\"submit\" name=\"todo\" value=\"Back\">");
$oPage->add("</form>");
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// M a i n P r o g r a m
//
///////////////////////////////////////////////////////////////////////////////////////////////////
$sFromWiztep = utils::ReadPostedParam('fromwiztep', '');
$sClass = utils::ReadPostedParam('class', '');
$sTodo = utils::ReadPostedParam('todo', '');
switch($sFromWiztep)
{
case '':
Do_Welcome($oPage, $sClass);
break;
case '1_welcome':
if ($sTodo == "Next") Do_Format($oPage, $sClass);
else trigger_error("Wrong argument todo='$sTodo'", E_USER_ERROR);
break;
case '2_format':
if ($sTodo == "Next") Do_Verify($oPage, $sClass);
else Do_Welcome($oPage, $sClass);
break;
case '3_verify':
if ($sTodo == "Next") Do_Execute($oPage, $sClass);
else Do_Format($oPage, $sClass);
break;
case '4_execute':
if ($sTodo == "Next") trigger_error("Wrong argument todo='$sTodo'", E_USER_ERROR);
else Do_Verify($oPage, $sClass);
break;
default:
trigger_error("Wrong argument fromwiztep='$sFromWiztep'", E_USER_ERROR);
}
$oPage->output();
?>

View File

@@ -0,0 +1,321 @@
<?php
require_once('../application/utils.inc.php');
require_once('../application/itopwebpage.class.inc.php');
//require_once('../application/menunode.class.inc.php');
require_once('../application/applicationcontext.class.inc.php');
require_once('../business/data.samples.inc.php');
require_once('../core/data.generator.class.inc.php');
require_once('../application/startup.inc.php');
// Display the menu on the left
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', -1);
$currentOrganization = utils::ReadParam('org_id', 1);
$operation = utils::ReadParam('operation', '');
if (!isset($_SERVER['PHP_AUTH_USER']))
{
header('WWW-Authenticate: Basic realm="iTop"');
header('HTTP/1.0 401 Unauthorized');
echo 'Sorry, this page requires authentication. (No user)';
echo "<pre>\n";
echo "DEBUG: \$_SERVER\n";
print_r($_SERVER);
echo "</pre>\n";
exit;
}
if (!UserRights::Login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']))
{
header('WWW-Authenticate: Basic realm="iTop"');
header('HTTP/1.0 401 Unauthorized');
echo 'Authentication failed !';
exit;
}
$oPage = new iTopWebPage("iTop Data Generator", $currentOrganization);
$oPage->no_cache();
// From now on the context is limited to the the selected organization ??
// Retrieve the root node for the menu
$oSearchFilter = $oContext->NewFilter("menuNode");
$oSearchFilter->AddCondition('parent_id', 0, '=');
// 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($oPage, $oContext, $iActiveNodeId, null, $oAppContext->GetAsHash());
}
/**
* The (ordered) list of classes for which to generate objects
*
* Each class in this list must implement a non-static Generate(cmdbDataGenerator $oGenerator) method
*/
//$aClassesToGenerate = array('bizOrganization' /* This one is special and must go first */, 'bizService', 'bizContact', 'bizPC', 'bizNetworkDevice');
$aClassesToGenerate = array('bizOrganization' /* This one is special and must go first */, 'bizLocation', 'bizPC', 'bizNetworkDevice', 'bizPerson', 'bizIncidentTicket', 'bizInfraGroup', 'bizInfraInfra');
/////////////////////////////////////////////////////////////////////////////////////
// Actual actions of the page
/////////////////////////////////////////////////////////////////////////////////////
/**
* Populate an organization with objects of each class listed in the (global) $aClassesToGenerate array
*
* @param web_page $oPage The object used for the HTML output
* @param cmdbGenerator $oGenerator The object used for the generation of the objects
* @param string $sSize An enum specifying (roughly) how many objects of each class to create: one of 'small', 'medium', 'big', 'huge' or 'max'
*/
function PopulateOrganization(CMDBChange $oMyChange, web_page $oPage, cmdbDataGenerator $oGenerator, $sSize = 'small')
{
global $aClassesToGenerate;
for ($i=1 /* skip the first one (i=0) which is the org itself */; $i<count($aClassesToGenerate); $i++)
{
switch($sSize)
{
case 'max':
$nbObjects = 50000;
break;
case 'huge':
$nbObjects = rand(1000,50000);
break;
case 'big':
$nbObjects = rand(30,500);
break;
case 'medium':
$nbObjects = rand(5,50);
break;
case 'small':
default:
$nbObjects = rand(2,20);
}
$sClass = $aClassesToGenerate[$i];
for($j=0; $j<$nbObjects; $j++)
{
$oObject = MetaModel::NewObject($sClass);
if (method_exists($oObject, 'Generate'))
{
$oObject->Generate($oGenerator);
// By rom
// $oObject->DBInsert();
$oObject->DBInsertTracked($oMyChange);
//$oObject->DisplayDetails($oPage);
}
}
$oPage->p("$nbObjects $sClass objects created.");
}
}
/**
* Delete an organization and all the instances of 'Object' belonging to this organization
*
* @param web_page $oPage The object used for the HTML output
* @param string $sOrganizationCode The code (pkey) of the organization to delete
*/
function DeleteOrganization($oMyChange, $oPage, $sOrganizationCode)
{
$oOrg = MetaModel::GetObject('bizOrganization', $sOrganizationCode);
if ($oOrg == null)
{
$oPage->p("<strong>Organization '$sOrganizationCode' already deleted!!</strong>");
}
else
{
// Delete all the objects linked to this organization
$oFilter = new CMDBSearchFilter('logRealObject');
$oFilter->AddCondition('organization', $sOrganizationCode, '=');
$oSet = new CMDBObjectSet($oFilter);
$countDeleted = $oSet->Count();
MetaModel::BulkDeleteTracked($oMyChange, $oFilter); // Should do a one by one delete to let the objects do their own cleanup !
$oPage->p("<strong>$countDeleted object(s) deleted!!</strong>");
$oOrg->DBDeleteTracked($oMyChange);
$oPage->p("<strong>Ok, organization '$sOrganizationCode' deleted!</strong>");
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// M a i n P r o g r a m
//
/////////////////////////////////////////////////////////////////////////////////////////////////
$operation = utils::ReadParam('operation', '');
$oPage->add("<div style=\"border:1px solid #ffffff; margin:0.5em;\">\n");
$oPage->add("<div style=\"padding:0.25em;text-align:center\">\n");
switch($operation)
{
case 'specify_generate':
// Display a form to specify what to generate
$oPage->p("<strong>iTop Data Generator</strong>\n");
$oPage->add("<form method=\"post\"\">\n");
$oPage->add("Number of organizations to generate: \n");
$oPage->add("<input name=\"org_count\" size=\"3\" value=\"\"> (max ".count($aCompanies).")&nbsp;\n");
$oPage->add("Size of the organizations\n");
$oPage->add("<select name=\"org_size\"\">\n");
$oPage->add("<option value=\"small\">Small (1 - 20 contacts)</option>\n");
$oPage->add("<option value=\"medium\">Medium (5 - 50 contacts)</option>\n");
$oPage->add("<option value=\"big\">Big (30 - 500 contacts)</option>\n");
$oPage->add("<option value=\"huge\">Huge (1000 - 50000 contacts)</option>\n");
$oPage->add("<option value=\"max\">Max (50000 contacts)</option>\n");
$oPage->add("</select>\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"generate\">\n");
$oPage->add("<input type=\"submit\" value=\" Generate ! \">\n");
$oPage->add("</form>\n");
break;
case 'generate':
// perform the actual generation
$iOrgCount = utils::ReadParam('org_count', 0);
$sOrgSize = utils::ReadParam('org_size', 'small');
// By rom
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by data generator ($iOrgCount orgs of size '$sOrgSize')");
$oMyChange->DBInsert();
while($iOrgCount > 0)
{
set_time_limit(5*60); // let it run for 5 minutes for each organization
$oGenerator = new cmdbDataGenerator();
// Create the new organization
$oOrg = MetaModel::NewObject('bizOrganization');
$oOrg->Generate($oGenerator);
// By rom
// $oOrg->DBInsert();
$oOrg->DBInsertTracked($oMyChange);
$oGenerator->SetOrganizationId($oOrg->GetKey());
$oPage->p("Organization '".$oOrg->GetKey()."' created\n");
$oOrg->DisplayDetails($oPage);
$oPage->add("<hr />\n");
PopulateOrganization($oMyChange, $oPage, $oGenerator, $sOrgSize);
$oPage->add("<hr />\n");
unset($oGenerator);
$iOrgCount--;
}
break;
case 'specify_update':
// Specify which organization to update
$oPage->add("<form method=\"post\"\">\n");
$oPage->add("Select the organization to update: \n");
$oPage->add("<select name=\"org\"\">\n");
$oSearchFilter = new CMDBSearchFilter("bizOrganization");
$oSet = new CMDBObjectSet($oSearchFilter); // All organizations
while($oOrg = $oSet->Fetch())
{
$oPage->add("<option value=\"".$oOrg->GetKey()."\">".$oOrg->Get('name')."</option>\n");
}
$oPage->add("</select>\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"update\">\n");
$oPage->p("");
$oPage->add("Quantity of of objects to add in each class: \n");
$oPage->add("<select name=\"org_size\"\">\n");
$oPage->add("<option value=\"small\">A few (1 - 20 objects)</option>\n");
$oPage->add("<option value=\"medium\">Some (5 - 50 objects)</option>\n");
$oPage->add("<option value=\"big\">Many (30 - 500 objects)</option>\n");
$oPage->add("<option value=\"huge\">Too many (1000 - 50000 objects)</option>\n");
$oPage->add("<option value=\"max\">Max (50000 objects)</option>\n");
$oPage->add("</select>\n");
$oPage->p("");
$oPage->add("<input type=\"button\" value=\" << Back \" onClick=\"javascript:window.history.back()\">&nbsp;&nbsp;\n");
$oPage->add("<input type=\"submit\" value=\" Update \">\n");
$oPage->add("</form>\n");
break;
case 'update':
// perform the actual update
set_time_limit(5*60); // let it run for 5 minutes
$sOrganizationCode = utils::ReadParam('org', '');
$sOrgSize = utils::ReadParam('org_size', 'small');
if ($sOrganizationCode == '')
{
$oPage->p("<strong>Error: please specify an organization (org).</strong>");
}
else
{
// By rom
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by data generator (update org '$sOrganizationCode', size '$sOrgSize')");
$oMyChange->DBInsert();
$oPage->p("<strong>Organization '$sOrganizationCode' updated.</strong>");
$oGenerator = new cmdbDataGenerator($sOrganizationCode);
PopulateOrganization($oMyChange, $oPage, $oGenerator, $sOrgSize);
}
break;
case 'specify_delete':
// Select an organization to be deleted
$oPage->add("<form method=\"post\"\">\n");
$oPage->add("Select the organization to delete: \n");
$oPage->add("<select name=\"org\"\">\n");
$oSearchFilter = new CMDBSearchFilter("bizOrganization");
$oSet = new CMDBObjectSet($oSearchFilter); // All organizations
while($oOrg = $oSet->Fetch())
{
$oPage->add("<option value=\"".$oOrg->GetKey()."\">".$oOrg->Get('name')."</option>\n");
}
$oPage->add("</select>\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"confirm_delete\">\n");
$oPage->p("");
$oPage->add("<input type=\"button\" value=\" << Back \" onClick=\"javascript:window.history.back()\">&nbsp;&nbsp;\n");
$oPage->add("<input type=\"submit\" value=\" Delete! \">\n");
$oPage->add("</form>\n");
break;
case 'confirm_delete':
// confirm the dangerous action
$sOrganizationCode = ReadParam('org', '');
$oPage->p("<strong>iTop Data Generator</strong>\n");
$oPage->p("<strong>Warning: you are about to delete the organization '$sOrganizationCode' and all its related objects</strong>\n");
$oPage->add("<form method=\"post\"\">\n");
$oPage->add("<input type=\"hidden\" name=\"org\" value=\"$sOrganizationCode\">\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"delete\">\n");
$oPage->add("<input type=\"button\" value=\" << Back \" onClick=\"javascript:window.history.back()\">&nbsp;&nbsp;\n");
$oPage->add("<input type=\"submit\" value=\" Delete them ! \">\n");
$oPage->add("</form>\n");
break;
case 'delete':
// perform the actual deletion
$sOrganizationCode = ReadParam('org', '');
if ($sOrganizationCode == '')
{
$oPage->p("<strong>Error: please specify an organization (org).</strong>");
}
else
{
// By rom
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by data generator (delete org '$sOrganizationCode'");
$oMyChange->DBInsert();
$oPage->p("<strong>Deleting '$sOrganizationCode'</strong>\n");
DeleteOrganization($oMyChange, $oPage, $sOrganizationCode);
}
break;
// display the menu of actions
case 'menu':
default:
$oPage->p("<strong>Data Generator Menu</strong>");
$oPage->p("<a href=\"?operation=specify_generate\">Generate one or more organizations</a>");
$oPage->p("<a href=\"?operation=specify_update\">Add more objects into an organization</a>");
$oPage->p("<a href=\"?operation=specify_delete\">Delete an organization</a>");
}
$oPage->add("</div>\n");
$oPage->add("</div>\n");
$oPage->p("<a href=\"?operation=menu\">Return to the data generator menu</a>");
$oPage->output();
?>

171
trunk/pages/db_importer.php Normal file
View File

@@ -0,0 +1,171 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/startup.inc.php');
require_once('../application/loginwebpage.class.inc.php');
login_web_page::DoLogin(); // Check user rights and prompt if needed
$sOperation = utils::ReadParam('operation', 'menu');
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', -1);
$currentOrganization = utils::ReadParam('org_id', '');
$oP = new iTopWebPage("iTop - Database backup & restore", $currentOrganization);
// Main program
switch($sOperation)
{
case 'create':
$oP->add('<form method="get">');
$oP->add('<p style="text-align:center; font-family:Georgia, \'Times New Roman\', Times, serif; font-size:24px;">Creation of an archive for the business model: '.$sBizModel.'</p>');
$oP->p('Title of the archive: <input type="text" name="title" size="40">');
$oP->p('Description of this archive: <textarea name="description" rows="5" cols="40"></textarea>');
$oP->p('Select the packages you want to include into this archive (When restoring the archive you will prompted to pick a package):');
$oP->p('<input type="checkbox" checked name="full" value="1"> The full database (schema + data).');
$oP->p('<input type="checkbox" checked name="full_schema" value="1"> Only the schema but of the complete database.');
$oP->p('<input type="checkbox" checked name="biz" value="1"> The complete business model (all the tables used by the business model, schema + data).');
$oP->p('<input type="checkbox" checked name="biz_schema" value="1"> Only the schema of the business model.');
$oP->add('<input type="hidden" name="biz_model" value="'.$sBizModel.'">');
$oP->add('<input type="hidden" name="operation" value="do_create">');
$oP->add('<input type="submit" name="" value=" Create the archive ">');
$oP->add($oAppContext->GetForForm());
$oP->add('</form>');
$oP->p('<a href="?operation=menu&biz_model='.$sBizModel.'">Back to menu</a>');
break;
case 'do_create':
$sTitle = utils::ReadParam('title', 'Unknown archive');
$sDescription = utils::ReadParam('description', 'No description provided for this archive.');
$bfullDump = utils::ReadParam('full', false);
$bfullSchemaDump = utils::ReadParam('full_schema', false);
$bBizDump = utils::ReadParam('biz', false);
$bBizSchemaDump = utils::ReadParam('biz_schema', false);
$sArchiveFile = '../tmp/archive1.zip';
$oArchive = new iTopArchive($sArchiveFile, iTopArchive::create);
$oArchive->SetTitle($sTitle);
$oArchive->SetDescription($sDescription);
if ($bfullDump)
{
$oArchive->AddDatabaseDump("Full Database Dump", "Choose this option to completely reload your database. All current data will be deleted and replaced by the backup", "full-db.sql", 'itop', array(), false);
}
if ($bfullSchemaDump)
{
$oArchive->AddDatabaseDump("Full Schema Dump", "Choose this option to completely wipe out your database and start from an empty database", "full-schema.sql", 'itop', array(), true);
}
if ($bBizDump || $bBizSchemaDump)
{
// compute the list of the tables involved in the business model
$aBizTables = array();
foreach(MetaModel::GetClasses('bizmodel') as $sClass)
{
$sTable = MetaModel::DBGetTable($sClass);
$aBizTables[$sTable] = $sTable;
}
unset($aBizTables['']);
if ($bfullDump)
{
$oArchive->AddDatabaseDump("Full Business Model Dump", "Choose this option to completely reload the business model part of your database. All current business data will be deleted and replaced by the backup. Application data (like menus...) are preserved.", "biz-db.sql", 'itop', $aBizTables, false);
}
if ($bfullSchemaDump)
{
$oArchive->AddDatabaseDump("Full Business Model Schema Dump", "Choose this option to wipe out the business data and start from an empty database. All current business data will be deleted. Application data (like menus...) are preserved.", "biz-schema.sql", 'itop', $aBizTables, true);
}
}
$oArchive->WriteCatalog();
$oP->p("The archive '$sTitle' has been created in <a href=\"$sArchiveFile\">$sArchiveFile</a>.");
$oP->p('<a href="?operation=menu&biz_model='.$sBizModel.'&'.$oAppContext->GetForLink().'">Back to menu</a>');
break;
case 'select_archive':
$sArchivesDir = '../tmp';
$oP->add('<form method="get">');
$oP->add('<p style="text-align:center; font-family:Georgia, \'Times New Roman\', Times, serif; font-size:24px;">Importation of an archive</p>');
$oP->p('Select the archive you want to import:');
$aArchives = array();
if ($handle = opendir($sArchivesDir))
{
while (false !== ($sFileName = readdir($handle)))
{
if (strtolower(substr($sFileName, -3, 3)) == 'zip')
{
$oArchive = new iTopArchive('../tmp/'.$sFileName, iTopArchive::read);
if ($oArchive->IsValid())
{
$oArchive->ReadCatalog();
$aArchives['../tmp/'.$sFileName] = $oArchive->GetTitle();
}
}
}
closedir($handle);
}
foreach($aArchives as $sFileName => $sTitle)
{
$oP->p('<input type="radio" name="archive_file" value="'.$sFileName.'">'.$sTitle);
}
$oP->add('<input type="hidden" name="biz_model" value="'.$sBizModel.'">');
$oP->add('<input type="hidden" name="operation" value="select_package">');
$oP->add('<input type="submit" name="" value=" Next >> ">');
$oP->add($oAppContext->GetForForm());
$oP->add('</form>');
$oP->p("<small>(Archives are searched into the directory: $sArchivesDir.)</small>");
$oP->p('<a href="?operation=menu&biz_model='.$sBizModel.'&'.$oAppContext->GetForLink().'">Cancel</a>');
break;
case 'select_package':
$sArchiveFile = utils::ReadParam('archive_file', '');
$oArchive = new iTopArchive($sArchiveFile, iTopArchive::read);
$oArchive->ReadCatalog();
$oP->add('<form method="post">');
$oP->add('<p style="text-align:center; font-family:Georgia, \'Times New Roman\', Times, serif; font-size:24px;">Selection of a package inside '.$oArchive->GetTitle().'</p>');
$oP->p('Select the package you want to apply:');
$aPackages = $oArchive->GetPackages();
foreach($aPackages as $sPackageName => $aPackage)
{
$oP->p('<input type="radio" name="package_name" value="'.$sPackageName.'">'.$aPackage['title']);
$oP->p($aPackage['description']);
}
$oP->add('<input type="hidden" name="archive_file" value="'.$sArchiveFile.'">');
$oP->add('<input type="hidden" name="biz_model" value="'.$sBizModel.'">');
$oP->add('<input type="hidden" name="operation" value="import_package">');
$oP->add('<input type="submit" name="" value=" Apply Package ! ">');
$oP->add($oAppContext->GetForForm());
$oP->add('</form>');
$oP->p('<a href="?operation=menu&biz_model='.$sBizModel.'">Cancel</a>');
break;
case 'import_package':
$sArchiveFile = utils::ReadParam('archive_file', '');
$sPackageName = utils::ReadParam('package_name', '');
$oArchive = new iTopArchive($sArchiveFile, iTopArchive::read);
$oArchive->ReadCatalog();
$oP->add('<p style="text-align:center; font-family:Georgia, \'Times New Roman\', Times, serif; font-size:24px;">Applying the package '.$sPackageName.'</p>');
if($oArchive->ImportSQL($sPackageName))
{
$oP->p('Done.');
}
else
{
$oP->p('Sorry, an error occured while applying the package...');
}
$oP->p('<a href="?operation=select_package&biz_model='.$sBizModel.'&archive_file='.$sArchiveFile.'&'.$oAppContext->GetForLink().'">Apply another package from the same archive</a>');
$oP->p('<a href="?operation=select_archive&biz_model='.$sBizModel.'&'.$oAppContext->GetForLink().'">Select another archive</a>');
$oP->p('<a href="?operation=menu&biz_model='.$sBizModel.'&'.$oAppContext->GetForLink().'">Back to the menu</a>');
break;
case 'menu':
default:
$oP->add('<p style="text-align:center; font-family:Georgia, \'Times New Roman\', Times, serif; font-size:24px;">Database backup &amp; restore</p>');
$oP->add('<p style="text-align:center;">Select one of the actions below:</p>');
$oP->add('<p style="text-align:center;"><a href="?operation=create&biz_model='.$sBizModel.'&'.$oAppContext->GetForLink().'">Export the database to an archive</a></p>');
$oP->add('<p style="text-align:center;"><a href="?operation=select_archive&biz_model='.$sBizModel.'&'.$oAppContext->GetForLink().'">Reload the database from an archive</a></p>');
}
$oP->output();
?>

82
trunk/pages/graphviz.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/startup.inc.php');
/**
* Helper to generate a Graphviz code for displaying the life cycle of a class
* @param string $sClass The class to display
* @return string The Graph description in Graphviz/Dot syntax
*/
function GraphvizLifecycle($sClass)
{
$sDotFileContent = "";
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
if (empty($sStateAttCode))
{
//$oPage->p("no lifecycle for this class");
}
else
{
$aStates = MetaModel::EnumStates($sClass);
$aStimuli = MetaModel::EnumStimuli($sClass);
$sDotFileContent .= "digraph finite_state_machine {
rankdir=LR;
size=\"12,12\"
node [ fontname=Verdana ];
edge [ fontname=Verdana ];
";
$aStatesLinks = array();
foreach ($aStates as $sStateCode => $aStateDef)
{
$aStatesLinks[$sStateCode] = array('in' => 0, 'out' => 0);
}
foreach ($aStates as $sStateCode => $aStateDef)
{
$sStateLabel = $aStates[$sStateCode]['label'];
$sStateDescription = $aStates[$sStateCode]['description'];
foreach(MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef)
{
$aStatesLinks[$sStateCode]['out']++;
$aStatesLinks[$aTransitionDef['target_state']]['in']++;
$sStimulusLabel = $aStimuli[$sStimulusCode]->Get('label');
$sTargetStateLabel = $aStates[$aTransitionDef['target_state']]['label'];
$sDotFileContent .= "\t$sStateCode -> {$aTransitionDef['target_state']} [ label=\"$sStimulusLabel\"];\n";
}
}
foreach($aStates as $sStateCode => $aStateDef)
{
$sStateLabel = str_replace(' ', '\n', $aStates[$sStateCode]['label']);
if ( ($aStatesLinks[$sStateCode]['in'] == 0) || ($aStatesLinks[$sStateCode]['out'] == 0))
{
$sDotFileContent .= "\t$sStateCode [ shape=doublecircle,label=\"$sStateLabel\"];\n";
}
else
{
$sDotFileContent .= "\t$sStateCode [ shape=circle,label=\"$sStateLabel\"];\n";
}
}
$sDotFileContent .= "}\n";
}
return $sDotFileContent;
}
$sClass = utils::ReadParam('class', 'bizIncidentTicket');
$sDir = dirname(__FILE__);
$sImageFilePath = realpath($sDir."/../images/lifecycle/$sClass.png");
if (!file_exists($sImageFilePath))
{
// create the file with Graphviz
$sDotDescription = GraphvizLifecycle($sClass);
$sDotFilePath = $sDir."/tmp-lifecycle.dot";
$rFile = fopen($sDotFilePath, "w");
fwrite($rFile, $sDotDescription);
fclose($rFile);
exec("/iTop/Graphviz/bin/dot.exe -Tpng < $sDotFilePath > $sImageFilePath");
}
header('Content-type: image/png');
echo file_get_contents($sImageFilePath);
?>

757
trunk/pages/incident.php Normal file
View File

@@ -0,0 +1,757 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/startup.inc.php');
require_once('../application/itopwizardwebpage.class.inc.php');
abstract class DialogWizard
{
protected $m_sCurrentStep;
protected $m_aSteps;
public function __construct($sStep)
{
$this->m_sCurrentStep = $sStep;
}
protected function GetFields($sStep = '')
{
if ($sStep == '')
{
$sStep = $this->m_sCurrentStep;
}
return $this->m_aSteps[$sStep];
}
protected function AddContextToForm(web_page $oPage)
{
// Store as hidden fields in the page all the variables from the previous steps
foreach($this->m_aSteps as $sStep => $aFields)
{
if ($sStep == $this->m_sCurrentStep) continue;
foreach($aFields as $sAttName => $sFieldName)
{
$oPage->add("<input type=\"hidden\" name=\"$sFieldName\" value=\"".htmlentities(Utils::ReadParam($sFieldName, ''))."\" />\n");
}
}
}
function GetObjectPicker(web_page $oPage, $sTitle, $sFieldName, $sClass)
{
$sScript =
<<<EOF
function UpdateObjectList(sClass)
{
var sRelatedObjectIds = new String($('#related_object_ids').val());
if (sRelatedObjectIds.length > 0)
{
aRelatedObjectIds = sRelatedObjectIds.split(' ');
}
else
{
aRelatedObjectIds = new Array();
aRelatedObjectIds[0] = 0;
}
var sibusql = sClass+": pkey IN {" + aRelatedObjectIds.join(", ") + "}";
$.get("ajax.render.php?filter=" + sibusql + "&style=list&encoding=sibusql",
{ operation: "ajax" },
function(data){
$("#related_objects").empty();
$("#related_objects").append(data);
$("#related_objects").removeClass("loading");
});
}
function AddObject(sClass)
{
var sRelatedObjectIds = new String($('#related_object_ids').val());
var sCurrentObjectId = new String($('#ac_current_object_id').val());
if (sRelatedObjectIds.length > 0)
{
aRelatedObjectIds = sRelatedObjectIds.split(' ');
}
else
{
aRelatedObjectIds = new Array();
}
// To do: check if the ID is not already in the list...
aRelatedObjectIds[aRelatedObjectIds.length] = sCurrentObjectId;
// Update the form & reload the list
$('#related_object_ids').val(aRelatedObjectIds.join(' '));
UpdateObjectList(sClass);
}
function ManageObjects(sTitle, sClass, sInputId)
{
$('#Manage_DlgTitle').text(sTitle);
sObjList = new String($('#'+sInputId).val());
if (sObjList == '')
{
sObjList = new String('0');
}
var aObjList = sObjList.split(' ');
Manage_LoadSelect('selected_objects', sClass+': pkey IN {' + aObjList.join(', ') + '}');
Manage_LoadSelect('available_objects', sClass);
$('#ManageObjectsDlg').jqmShow();
}
function Manage_LoadSelect(sSelectedId, sFilter)
{
$('#'+sSelectedId).addClass('loading');
$.get('ajax.render.php?filter=' + sFilter,
{ operation: 'combo_options' },
function(data){
$('#'+sSelectedId).empty();
$('#'+sSelectedId).append(data);
$('#'+sSelectedId).removeClass('loading');
}
);
}
function Manage_SwapSelectedObjects(oSourceSelect, oDestinationSelect)
{
for (i=oSourceSelect.length-1;i>=0;i--) // Count down because we are removing the indexes from the combo
{
if (oSourceSelect.options[i].selected)
{
var newOption = document.createElement('option');
newOption.text = oSourceSelect.options[i].text;
newOption.value = oSourceSelect.options[i].value;
oDestinationSelect.add(newOption, null);
oSourceSelect.remove(i);
}
}
Manage_UpdateButtons();
}
function Manage_UpdateButtons()
{
var oSrc = document.getElementById('available_objects');
var oAddBtn = document.getElementById('btn_add_objects')
var oDst = document.getElementById('selected_objects');
var oRemoveBtn = document.getElementById('btn_remove_objects')
if (oSrc.selectedIndex == -1)
{
oAddBtn.disabled = true;
}
else
{
oAddBtn.disabled = false;
}
if (oDst.selectedIndex == -1)
{
oRemoveBtn.disabled = true;
}
else
{
oRemoveBtn.disabled = false;
}
}
function Manage_AddObjects()
{
var oSrc = document.getElementById('available_objects');
var oDst = document.getElementById('selected_objects');
Manage_SwapSelectedObjects(oSrc, oDst);
}
function Manage_RemoveObjects()
{
var oSrc = document.getElementById('selected_objects');
var oDst = document.getElementById('available_objects');
Manage_SwapSelectedObjects(oSrc, oDst);
}
function Manage_Ok(sClass)
{
var objectsToAdd = document.getElementById('selected_objects');
var aSelectedObjects = new Array();
for (i=0; i<objectsToAdd.length;i++)
{
aSelectedObjects[aSelectedObjects.length] = objectsToAdd.options[i].value;
}
$('#related_object_ids').val(aSelectedObjects.join(' '));
UpdateObjectList(sClass);
}
function FilterLeft($sClass)
{
alert('Not Yet Implemented');
}
function FilterRight($sClass)
{
alert('Not Yet Implemented');
}
EOF;
$sManageObjectsDlg = <<< EOF
<div class="page_header"><h1 id="Manage_DlgTitle">Selected Objects</h1></div>
<table width="100%">
<tr>
<td>
<p>Selected objects:</p>
<button type="button" class="action" onClick="FilterLeft('$sClass');"><span> Filter... </span></button>
<p><select id="selected_objects" size="10" multiple onChange="Manage_UpdateButtons()" style="width:300px;">
</select></p>
</td>
<td style="text-align:center; valign:middle;">
<p><button type="button" id="btn_add_objects" onClick="Manage_AddObjects();"> &lt;&lt; Add </button></p>
<p><button type="button" id="btn_remove_objects" onClick="Manage_RemoveObjects();"> Remove &gt;&gt; </button></p>
</td>
<td>
<p>Available objects:</p>
<button type="button" class="action" onClick="FilterRight('$sClass');"><span> Filter... </span></button>
<p><select id="available_objects" size="10" multiple onChange="Manage_UpdateButtons()" style="width:300px;">
</select></p>
</td>
</tr>
<tr>
<td colspan="3">
<button type="button" class="jqmClose" onClick="Manage_Ok('$sClass')"> Ok </button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button type="button" class="jqmClose"> Cancel</button>
</td>
</tr>
</table>
EOF;
$sHTML = '<input type="text" name="" id="current_object_id" size="30"/>
<input type="hidden" id="related_object_ids" name="'.$sFieldName.'" value="">
&nbsp;<button type="button" class="action" onClick="return AddObject(\''.$sClass.'\');"><span> Add </span></button>
&nbsp;<button type="button" class="action" onClick="return ManageObjects(\''.$sTitle.'\', \''.$sClass.'\', \'related_object_ids\');"><span> ... </span></button>';
$sHTML .= '<input type="hidden" id="ac_current_object_id" name="" value="">';
$sHTML .= '<div class="jqmWindow" id="ManageObjectsDlg">'.$sManageObjectsDlg.'</div>';
$oPage->add_script($sScript);
$oPage->add_ready_script("\$('#current_object_id').autocomplete('./ajax.render.php', { minChars:3, onItemSelect:selectItem, onFindValue:findValue, formatItem:formatItem, autoFill:true, keyHolder:'#ac_current_object_id', extraParams:{operation:'link', sclass:'$sClass', attCode:'name'}});");
$oPage->add_ready_script("$('#ManageObjectsDlg').jqm({overlay:70, modal:true, toTop:true});"); // jqModal Window
$oPage->add_ready_script("UpdateObjectList('$sClass');");
return $sHTML;
}
function DisplayObjectPickerList(web_page $oPage, $sClass)
{
$oFilter = new CMDBSearchFilter($sClass);
$oFilter->AddCondition('pkey', array(0), 'IN');
//$oPage->p($oFilter->__DescribeHTML());
$oBlock = new DisplayBlock($oFilter, 'list', true /* Asynchronous */);
$oBlock->Display($oPage, 'related_objects');
}
}
class IncidentCreationWizard extends DialogWizard
{
public function __construct($sStep)
{
parent::__construct($sStep);
$this->m_aSteps =
array(
'1' => array('title' => 'attr_title', 'customer_id' => 'attr_customer_id', 'initial_situation' => 'attr_initial_situation', 'severity' => 'attr_severity', 'impact' => 'attr_impact', 'workgroup_id' => 'attr_workgroup_id', 'action_log' => 'attr_action_log'),
'2' => array('impacted_infra_ids' => 'impacted_infra_ids'),
'3' => array('additional_impacted_object_ids' => 'additional_impacted_object_ids'),
'4' => array('related_incident_ids' => 'related_incident_ids'),
'5' => array('contact_ids' => 'contact_ids'),
);
}
protected function AddContextToForm($oPage)
{
parent::AddContextToForm($oPage);
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"new\" />\n");
$oPage->add("<input type=\"hidden\" name=\"step\" value=\"".$this->m_sNextStep."\" />\n");
}
public function DisplayNewTicketForm(web_page $oPage)
{
assert($this->m_sCurrentStep == '1');
$this->m_sNextStep = '2';
$aFields = $this->GetFields();
$oPage->add('<form method="get">');
$aDetails = array();
$aAttributesDef = MetaModel::ListAttributeDefs('bizIncidentTicket');
foreach($aFields as $sAttCode => $sFieldName)
{
$oAttDef = $aAttributesDef[$sAttCode];
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, 'bizIncidentTicket', $sAttCode, $oAttDef);
$aDetails[] = array('label' => $oAttDef->GetLabel().' <span class="hilite">*</span>', 'value' => $sHTMLValue);
}
$oPage->details($aDetails);
$this->AddContextToForm($oPage);
$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>Next >></span></button>\n");
$oPage->add('</form>');
}
public function DisplayImpactedInfraForm(web_page $oPage)
{
assert($this->m_sCurrentStep == '2');
$this->m_sNextStep = '3';
$oPage->add('<form method="get">');
$aDetails = array();
$sHTML = $this->GetObjectPicker($oPage, 'Impacted Infrastructure', 'impacted_infra_ids', 'logInfra');
$aDetails[] = array('label' => 'Impacted element:', 'value' => $sHTML);
$oPage->details($aDetails);
$this->DisplayObjectPickerList($oPage, 'logInfra');
$this->AddContextToForm($oPage);
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span><< Back</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>Next >></span></button>\n");
$oPage->add('</form>');
}
public function DisplayAdditionalImpactedObjectForm(web_page $oPage)
{
assert($this->m_sCurrentStep == '3');
$this->m_sNextStep = '4';
$sImpactedInfraIds = Utils::ReadParam('impacted_infra_ids');
$sImpactedInfraIds = Utils::ReadParam('impacted_infra_ids', '');
if (!empty($sImpactedInfraIds))
{
$oPage->p('Impacted Infrastructure:');
$oFilter = new CMDBSearchFilter('logRealObject');
$oFilter->AddCondition('pkey', explode(' ', $sImpactedInfraIds), 'IN');
$oBlock = new DisplayBlock($oFilter, 'list', false /* Synchronous */);
$oBlock->Display($oPage, 'impacted_infra');
}
$aImpactedInfraIds = explode(' ', $sImpactedInfraIds);
$oInfraSet = CMDBObjectSet::FromScratch('logRealObject');
foreach($aImpactedInfraIds as $id)
{
$oObj = MetaModel::GetObject('logRealObject', $id);
$oInfraSet->AddObject($oObj);
}
$aImpactedObject = $oInfraSet->GetRelatedObjects('impacts');
$aAdditionalIds = array();
foreach($aImpactedObject as $sRootClass => $aObjects)
{
foreach($aObjects as $oObj)
{
$aAdditionalIds[] = $oObj->GetKey();
}
}
$sAdditionalIds = implode(' ', $aAdditionalIds);
$oPage->add_ready_script('$("#related_object_ids").val("'.$sAdditionalIds.'");');
$oPage->p('Additional Impact Computed:');
$this->DisplayObjectPickerList($oPage, 'logRealObject');
$oPage->add('<form method="get">');
$aDetails = array();
$sHTML = $this->GetObjectPicker($oPage, 'Additional Impacted Infrastructure', 'additional_impacted_object_ids', 'logRealObject');
$aDetails[] = array('label' => 'Impacted element:', 'value' => $sHTML);
$oPage->details($aDetails);
$this->AddContextToForm($oPage);
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span><< Back</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>Next >></span></button>\n");
$oPage->add('</form>');
}
public function DisplayRelatedTicketsForm(web_page $oPage)
{
assert($this->m_sCurrentStep == '4');
$this->m_sNextStep = '5';
$oRelatedTicketsFilter = new DBObjectSearch('bizIncidentTicket');
$sImpactedInfraIds = Utils::ReadParam('impacted_infra_ids', '');
$sAdditionalImpactedObjectIds = Utils::ReadParam('additional_impacted_object_ids', '');
$sIds = trim($sImpactedInfraIds.' '.$sAdditionalImpactedObjectIds);
$aTicketIds = array();
if (!empty($sIds))
{
$aIds = explode(' ', $sIds);
$sSibusQL = "bizIncidentTicket: PKEY IS ticket_id IN (lnkInfraTicket: infra_id IN (logRealObject: pkey IN {".implode(',', $aIds)."}))";
$oTicketSearch = DBObjectSearch::FromSibusQL($sSibusQL);
$oRelatedTicketSet = new DBObjectSet($oTicketSearch);
while ($oTicket = $oRelatedTicketSet->Fetch())
{
$aTicketIds[] = $oTicket->GetKey();
}
}
$sTicketIds = implode(' ', $aTicketIds);
$oPage->add_ready_script('$("#related_object_ids").val("'.$sTicketIds.'");');
$oPage->p('Potentially related incidents:');
$this->DisplayObjectPickerList($oPage, 'bizIncidentTicket');
$oPage->add('<form method="get">');
$sHTML = $this->GetObjectPicker($oPage, 'Related Incidents', 'related_incident_ids', 'bizIncidentTicket');
$aDetails[] = array('label' => 'Related Incident:', 'value' => $sHTML);
$oPage->details($aDetails);
$this->AddContextToForm($oPage);
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span><< Back</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>Next >></span></button>\n");
$oPage->add('</form>');
}
public function DisplayContactsToNotifyForm(web_page $oPage)
{
assert($this->m_sCurrentStep == '5');
$this->m_sNextStep = '6';
$oPage->add('<form method="get">');
$sHTML = $this->GetObjectPicker($oPage, 'Contacts to notify', 'contact_ids', 'bizContact');
$aDetails[] = array('label' => 'Additional contact:', 'value' => $sHTML);
$oPage->details($aDetails);
$this->DisplayObjectPickerList($oPage, 'bizContact');
$this->AddContextToForm($oPage);
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span><< Back</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>Next >></span></button>\n");
$oPage->add('</form>');
}
function DisplayFinalForm(web_page $oPage)
{
$oAppContext = new ApplicationContext();
assert($this->m_sCurrentStep == '6');
$this->m_sNextStep = '7';
$aDetails = array();
$aAttributesDef = MetaModel::ListAttributeDefs('bizIncidentTicket');
$aFields = $this->GetFields('1');
foreach($aFields as $sAttCode => $sFieldName)
{
$oAttDef = $aAttributesDef[$sAttCode];
$sValue = Utils::ReadParam($sFieldName, '');
if ($oAttDef->IsExternalKey() && isset($sValue) && ($sValue != 0))
{
$oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $sValue);
if (!is_object($oTargetObj))
{
trigger_error("Houston: could not find ".$oAttDef->GetTargetClass()."::$sValue");
}
$sPage = cmdbAbstractObject::ComputeUIPage($oAttDef->GetTargetClass());
$sHint = htmlentities($oAttDef->GetTargetClass()."::".$sValue);
$sHTMLValue = "<a href=\"$sPage?operation=details&class=".$oAttDef->GetTargetClass()."&id=$sValue&".$oAppContext->GetForLink()."\" title=\"$sHint\">".$oTargetObj->GetName()."</a>";
}
else
{
$sHTMLValue = $oAttDef->GetAsHTML($sValue);
}
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
}
$oPage->details($aDetails);
$oPage->AddTabContainer('LinkedObjects');
$oPage->SetCurrentTabContainer('LinkedObjects');
$sImpactedInfraIds = Utils::ReadParam('impacted_infra_ids', '');
$sImpactedInfraIds .= ' '.Utils::ReadParam('additional_impacted_object_ids', '');
$sImpactedInfraIds = trim($sImpactedInfraIds);
$oPage->SetCurrentTab("Infrastructure impacted");
if (!empty($sImpactedInfraIds))
{
$oFilter = new CMDBSearchFilter('logRealObject');
$oFilter->AddCondition('pkey', explode(' ', $sImpactedInfraIds), 'IN');
$oBlock = new DisplayBlock($oFilter, 'list', false /* Synchronous */);
$oBlock->Display($oPage, 'related_objects');
}
else
{
$oPage->p("There is no infrastructure impacted by this incident");
}
$sRelatedIncidentIds = Utils::ReadParam('related_incident_ids', '');
$oPage->SetCurrentTab("Related tickets");
if (!empty($sRelatedIncidentIds))
{
$oFilter = new CMDBSearchFilter('bizIncidentTicket');
$oFilter->AddCondition('pkey', explode(' ', $sRelatedIncidentIds), 'IN');
$oBlock = new DisplayBlock($oFilter, 'list', false /* Synchronous */);
$oBlock->Display($oPage, 'related_incidents');
}
else
{
$oPage->p("There is no other incident related to this one");
}
$oPage->SetCurrentTab("Contacts to notify");
$sContactIds = Utils::ReadParam('contact_ids', '');
if (!empty($sContactIds))
{
$oFilter = new CMDBSearchFilter('bizContact');
$oFilter->AddCondition('pkey', explode(' ', $sContactIds), 'IN');
$oBlock = new DisplayBlock($oFilter, 'list', false /* Synchronous */);
$oBlock->Display($oPage, 'contacts');
}
else
{
$oPage->p("There is no contact to notify");
}
$oPage->SetCurrentTab();
$oPage->add('<form method="post" action="incident.php">');
$this->AddContextToForm($oPage);
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span><< Back</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\" value=\"create\"><span> Create Ticket</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\" value=\"create_notify\"><span> Create Ticket and Send Notifications</span></button>\n");
$oPage->add('</form>');
}
public function CreateIncident(web_page $oPage)
{
$oAppContext = new ApplicationContext();
assert($this->m_sCurrentStep == '7');
$this->m_sNextStep = '1';
$oIncident = MetaModel::NewObject('bizIncidentTicket');
$oPage->p("Creation of Incident Ticket.");
$aFields = $this->GetFields('1');
foreach($aFields as $sAttCode => $sFieldName)
{
$sValue = Utils::ReadPostedParam($sFieldName, '');
$oIncident->Set($sAttCode, $sValue);
}
$oIncident->Set('ticket_status', 'New');
$oIncident->Set('start_date', time());
$oIncident->Set('name', 'ID not set');
if ($oIncident->CheckToInsert())
{
// Create the ticket itself
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Administrator");
$iChangeId = $oMyChange->DBInsert();
$oIncident->DBInsertTracked($oMyChange);
$sName = sprintf('I-%06d', $oIncident->GetKey());
$oIncident->Set('name', $sName);
$oIncident->DBUpdateTracked($oMyChange);
$oPage->p("Incident $sName created.\n");
// Now link the objects to the Incident:
// 1) the impacted infra
$sImpactedInfraIds = Utils::ReadParam('impacted_infra_ids', '');
$sImpactedInfraIds .= ' '.Utils::ReadParam('additional_impacted_object_ids', '');
$sImpactedInfraIds = trim($sImpactedInfraIds);
if (!empty($sImpactedInfraIds))
{
$aImpactedInfra = explode(' ', $sImpactedInfraIds);
foreach($aImpactedInfra as $iInfraId)
{
$oLink = MetaModel::NewObject('lnkInfraTicket');
$oLink->Set('infra_id', $iInfraId);
$oLink->Set('ticket_id', $oIncident->GetKey());
$oLink->Set('impact', 'automatic');
$oLink->DBInsertTracked($oMyChange);
}
}
// 2) the related incidents
$sRelatedIncidentsIds = Utils::ReadPostedParam('related_incident_ids');
if (!empty($sRelatedIncidentsIds))
{
$aRelatedIncidents = explode(' ', $sRelatedIncidentsIds);
foreach($aRelatedIncidents as $iIncidentId)
{
$oLink = MetaModel::NewObject('lnkRelatedTicket');
$oLink->Set('rel_ticket_id', $iIncidentId);
$oLink->Set('ticket_id', $oIncident->GetKey());
$oLink->Set('impact', 'automatic');
$oLink->DBInsertTracked($oMyChange);
}
}
// 3) the contacts to notify
$sContactsIds = Utils::ReadPostedParam('contact_ids');
if (!empty($sContactsIds))
{
$aContactsToNotify = explode(' ', $sContactsIds);
foreach($aContactsToNotify as $iContactId)
{
$oLink = MetaModel::NewObject('lnkContactRealObject');
$oLink->Set('contact_id', $iContactId);
$oLink->Set('object_id', $oIncident->GetKey());
$oLink->Set('role', 'notification');
$oLink->DBInsertTracked($oMyChange);
}
}
$oIncident->DisplayDetails($oPage, 'bizIncidentTicket', $oIncident->GetKey());
}
else
{
$oPage->p("<strong>Error: object can not be created!</strong>\n");
}
}
}
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$currentOrganization = utils::ReadParam('org_id', '');
$operation = utils::ReadParam('operation', '');
$oP = new iTopWebPage("ITop - Incident Management", $currentOrganization);
switch($operation)
{
case 'details':
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$oP->set_title("iTop - ".$oObj->GetName()." - $sClass details");
$oObj->DisplayDetails($oP);
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to view it).</p>\n");
}
}
break;
case 'new':
$step = utils::ReadParam('step', '1');
$aSteps = array(
'Ticket Information',
'Impacted Infrastructure',
'Additional Impact',
'Related Tickets',
'Contacts to Notify',
'Confirmation',
'Ticket Creation'
);
$oWizard = new IncidentCreationWizard($step);
$oP = new iTopWizardWebPage("ITop - Incident Management", $currentOrganization, $step, $aSteps);
switch($step)
{
case 1:
default:
//$oP->add('<div class="page_header"><h1><span class="hilite">New incident</span></h1></div>');
$oWizard->DisplayNewTicketForm($oP);
break;
case 2:
//$oP->add('<div class="page_header"><h1>New ticket: <span class="hilite">Select the Impacted Infrastructure</span></h1></div>');
$oWizard->DisplayImpactedInfraForm($oP);
break;
case 3:
//$oP->add('<div class="page_header"><h1>New ticket: <span class="hilite">Additional Impacted Objects</span></h1></div>');
$oWizard->DisplayAdditionalImpactedObjectForm($oP);
break;
case 4:
//$oP->add('<div class="page_header"><h1>New ticket: <span class="hilite">Select Related Incidents</span></h1></div>');
$oWizard->DisplayRelatedTicketsForm($oP);
break;
case 5:
//$oP->add('<div class="page_header"><h1>New ticket: <span class="hilite">Select the Contacts to Notify</span></h1></div>');
$oWizard->DisplayContactsToNotifyForm($oP);
break;
case 6:
//$oP->add('<div class="page_header"><h1>New ticket: <span class="hilite">Confirm and Create the Ticket</span></h1></div>');
$oWizard->DisplayFinalForm($oP);
break;
case 7:
$oWizard->CreateIncident($oP);
break;
}
break;
case 'modify':
$oP->add_linked_script("../js/json.js");
$oP->add_linked_script("../js/forms-json-utils.js");
$oP->add_linked_script("../js/wizardhelper.js");
$oP->add_linked_script("../js/wizard.utils.js");
$oP->add_linked_script("../js/linkswidget.js");
$oP->add_linked_script("../js/jquery.blockUI.js");
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$oP->set_title("iTop - ".$oObj->GetName()." - $sClass modification");
$oP->add("<h1>".$oObj->GetName()." - $sClass modification</h1>\n");
$oObj->DisplayModifyForm($oP);
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to view it).</p>\n");
}
}
break;
case 'apply_modify':
$sClass = utils::ReadPostedParam('class', '');
$id = utils::ReadPostedParam('id', '');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
{
$oP->add("<p>'class' and 'id' parameters must be specifed for this operation.</p>\n");
}
else if (!utils::IsTransactionValid($sTransactionId))
{
$oP->p("<strong>Error: object has already be updated!</strong>\n");
}
else
{
$oObj = $oContext->GetObject($sClass, $id);
if ($oObj != null)
{
$oP->set_title("iTop - ".$oObj->GetName()." - $sClass modification");
$oP->add("<h1>".$oObj->GetName()." - $sClass modification</h1>\n");
$bObjectModified = false;
foreach(MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode=>$oAttDef)
{
$iFlags = $oObj->GetAttributeFlags($sAttCode);
if ($iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))
{
// Non-visible, or read-only attribute, do nothing
}
else if (!$oAttDef->IsExternalField())
{
$aAttributes[$sAttCode] = trim(utils::ReadPostedParam("attr_$sAttCode", ''));
$previousValue = $oObj->Get($sAttCode);
if (!empty($aAttributes[$sAttCode]) && ($previousValue != $aAttributes[$sAttCode]))
{
$oObj->Set($sAttCode, $aAttributes[$sAttCode]);
$bObjectModified = true;
}
}
}
if (!$bObjectModified)
{
$oP->p("No modification detected. ".get_class($oObj)." has <strong>not</strong> been updated.\n");
}
else if ($oObj->CheckToUpdate())
{
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by somebody"); // TO DO put the correct user info here
$iChangeId = $oMyChange->DBInsert();
$oObj->DBUpdateTracked($oMyChange);
$oP->p(get_class($oObj)." updated.\n");
}
else
{
$oP->p("<strong>Error: object can not be updated!</strong>\n");
//$oObj->Reload(); // restore default values!
}
}
else
{
$oP->set_title("iTop - Error");
$oP->add("<p>Sorry this object does not exist (or you are not allowed to edit it).</p>\n");
}
}
$oP->add("<p>Alors ça roule ?</p>");
$oObj->DisplayDetails($oP);
break;
}
$oP->output();
?>

704
trunk/pages/index.php Normal file
View File

@@ -0,0 +1,704 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/nicewebpage.class.inc.php');
require_once('../application/dialogstack.class.inc.php');
require_once('../application/startup.inc.php');
$oPage = new nice_web_page("The very first iTop page");
$oPage->no_cache();
MetaModel::CheckDefinitions();
// new API - MetaModel::DBCheckFormat();
// not necessary, and time consuming!
// MetaModel::DBCheckIntegrity();
// Comment by Rom: MetaModel::GetSubclasses("logRealObject") retourne la totale
// utiliser IsRootClass pour savoir si une classe obtenue est une classe feuille ou non
$aTopLevelClasses = array('bizService', 'bizLocation', 'bizContact', 'logInfra', 'bizDocument', 'bizObject');
function ReadParam($sName, $defaultValue = "")
{
return isset($_REQUEST[$sName]) ? $_REQUEST[$sName] : $defaultValue;
}
function DisplaySelectOrg($oPage, $sCurrentOrganization, $iContext)
{
global $oContext;
//$oSearchFilter = new CMDBSearchFilter("bizOrganization");
$oSearchFilter = $oContext->NewFilter("bizOrganization");
$oPage->p($oSearchFilter->serialize());
$oSet = new CMDBObjectSet($oSearchFilter);
if ($oSet->Count() == 0)
{
$oPage->add("<div style=\"border:1px solid #97a5b0; margin-top:0.5em;\">\n");
$oPage->add("<div style=\"padding:0.25em;background-color:#f0f0f0;text-align:center\">\n");
$oPage->p("No organization found.\n");
$oPage->p($oSearchFilter->__DescribeHTML());
$oPage->add("</div>\n");
$oPage->add("</div>\n");
}
else
{
$oCurrentOrganization = null;
$oPage->add("<div style=\"border:1px solid #97a5b0; margin-top:0.5em;\">\n");
$oPage->add("<div style=\"padding:0.25em;background-color:#f0f0f0;text-align:center\">\n");
$oPage->add("<form method=\"get\"\">\n");
$oPage->add("Select the context:\n");
$oPage->add("<select name=\"ctx\">\n");
$oPage->add("<option value=\"1\"".($iContext == 1 ? "selected" : "").">See everything (no context)</option>\n");
$oPage->add("<option value=\"2\"".($iContext == 2 ? "selected" : "").">See only the iTop organization</option>\n");
$oPage->add("<option value=\"3\"".($iContext == 3 ? "selected" : "").">See only organizations which name contains 'o', and contact in France (tel. contains +33)</option>\n");
$oPage->add("</select>\n");
$oPage->p("");
$oPage->add("Select an organization: \n");
$oPage->add("<select name=\"org\"\">\n");
while($oOrg = $oSet->Fetch())
{
if ($sCurrentOrganization == $oOrg->GetKey())
{
$oCurrentOrganization = $oOrg;
$sSelected = " selected";
}
else
{
$sSelected = "";
}
$oPage->add("<option value=\"".$oOrg->GetKey()."\"$sSelected>".$oOrg->Get('name')."</option>\n");
}
$oPage->add("</select>\n");
$oPage->add("<input type=\"submit\" value=\" Search \">\n");
$oPage->add("</form>\n");
if ($oCurrentOrganization != null)
{
$oCurrentOrganization->DisplayDetails($oPage);
}
$oPage->add("</div>\n");
$oPage->add("</div>\n");
}
}
function DisplayDetails(web_page $oPage, $sClassName, $sKey)
{
global $oContext;
//$oObj = MetaModel::GetObject($sClassName, $sKey);
$oObj = $oContext->GetObject($sClassName, $sKey);
$oPage->p("Details of ".get_class($oObj)." - $sKey");
$oObj->DisplayDetails($oPage);
// Modified by rom
$aLinks = array();
$aLinks[] = "<a href=\"?operation=changeslog&class=$sClassName&key=$sKey\">View changes log</a>";
$aLinks[] = "<a href=\"?operation=edit&class=$sClassName&key=$sKey\">Edit this object</a>";
$aLinks[] = "<a href=\"?operation=delete&class=$sClassName&key=$sKey\">Delete this object (no confirmation!)</a>";
// By rom
foreach (MetaModel::EnumLinkingClasses($sClassName) as $sLinkClass => $aRemoteClasses)
{
foreach($aRemoteClasses as $sExtKeyAttCode => $sRemoteClass)
{
// #@# quick and dirty: guess the extkey attcode from link to current class
// later, this information should be part of the biz model
$sExtKeyToMe = "";
foreach(MetaModel::ListAttributeDefs($sLinkClass) as $sAttCode=>$oAttDef)
{
if ($oAttDef->IsExternalKey() && $oAttDef->GetTargetClass() == $sClassName)
{
$sExtKeyToMe = $sAttCode;
break;
}
}
if (empty($sExtKeyToMe))
{
$oPage->p("Houston... could not find the external key for $sClassName in $sLinkClass");
}
else
{
$oFilter = new CMDBSearchFilter($sRemoteClass); // just a dummy empty one for edition
$sButton = "<div>\n";
$sButton .= "<form action=\"./advanced_search.php\" method=\"post\">\n";
$aOnOKArgs = array("operation"=>"addlinks", "linkclass"=>$sLinkClass, "extkeytome"=>$sExtKeyToMe, "extkeytopartner"=>$sExtKeyAttCode);
$sButton .= dialogstack::RenderEditableField("Add links with $sRemoteClass", "filter", $oFilter->serialize(), true, "", $aOnOKArgs);
$sButton .= "</form>\n";
$sButton .= "</div>\n";
$aLinks[] = $sButton;
}
}
}
$sLinks = implode("&nbsp;/&nbsp;", $aLinks);
$oPage->p($sLinks);
}
// By Rom
function DisplayChangesLog(web_page $oPage, $sClassName, $sKey)
{
global $oContext;
//$oObj = MetaModel::GetObject($sClassName, $sKey);
$oObj = $oContext->GetObject($sClassName, $sKey);
$oPage->p("Changes log for ".get_class($oObj)." - $sKey");
$oObj->DisplayChangesLog($oPage);
$oPage->p("<a href=\"?operation=details&class=$sClassName&key=$sKey\">View details</a>");
$oPage->p("<a href=\"?operation=edit&class=$sClassName&key=$sKey\">Edit this object</a>");
$oPage->p("<a href=\"?operation=delete&class=$sClassName&key=$sKey\">Delete this object (no confirmation!)</a>");
}
function DumpObjectsAsCSV(web_page $oPage, $sClassName, $oSearchFilter = null, $sSeparator = ",")
{
global $oContext;
$aHeader = array();
$aHeader[] = 'pkey';
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode=>$oAttDef)
{
$aHeader[] = $oAttDef->GetLabel();
}
$oPage->Add(join($sSeparator, $aHeader)."\n");
if ($oSearchFilter == null)
{
$oSearchFilter = $oContext->NewFilter($sClassName);
}
$oObjectSet = new CMDBObjectSet($oSearchFilter);
while ($oObj = $oObjectSet->Fetch())
{
$aRow = array();
$aRow[] = $oObj->GetKey();
foreach($oObj->GetAttributesList($sClassName) as $sAttCode)
{
$aRow[] = $oObj->GetAsCSV($sAttCode);
}
$oPage->Add(join($sSeparator, $aRow)."\n");
}
}
function DumpObjects(web_page $oPage, $sClassName, CMDBSearchFilter $oSearchFilter = null)
{
global $oContext;
if ($oSearchFilter == null)
{
//$oSearchFilter = new CMDBSearchFilter($sClassName);
$oSearchFilter = $oContext->NewFilter($sClassName);
}
$aAttribs = array();
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode=>$oAttDef)
{
$aAttribs['key'] = array('label' => 'key', 'description' => 'Primary Key');
$aAttribs[$sAttCode] = array('label' => $oAttDef->GetLabel(), 'description' => $oAttDef->GetDescription());
}
$oObjectSet = new CMDBObjectSet($oSearchFilter);
$aValues = array();
while ($oObj = $oObjectSet->Fetch())
{
$aRow['key'] = "<a href=\"./index.php?operation=details&class=$sClassName&key=".$oObj->GetKey()."\">".$oObj->GetKey()."</a>";
foreach($oObj->GetAttributesList($sClassName) as $sAttCode)
{
$aRow[$sAttCode] = $oObj->GetAsHTML($sAttCode);
}
$aValues[] = $aRow;
}
$oPage->table($aAttribs, $aValues);
}
function DisplayEditForm(web_page $oPage, $sClassName, $sKey)
{
global $oContext;
//$oObj = MetaModel::GetObject($sClassName, $sKey);
$oObj = $oContext->GetObject($sClassName, $sKey);
if ($oObj == null)
{
$oPage->p("You are not allowed to edit this object.");
return;
}
$oPage->p("Edition of ".get_class($oObj)." - $sKey\n");
$aDetails = array();
$oPage->add("<form method=\"post\">\n");
foreach(MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode=>$oAttDef)
{
if (!$oAttDef->IsExternalField())
{
if ($oAttDef->IsExternalKey())
{
//External key, display a combo
$sTargetClass = $oAttDef->GetTargetClass();
//$oFilter = new CMDBSearchFilter($sTargetClass);
$oFilter = $oContext->NewFilter($sTargetClass);
$oSet = new CMDBObjectSet($oFilter);
$sValue = "<select name=\"attr[$sAttCode]\">\n";
while($oTargetObj = $oSet->Fetch())
{
if ($oObj->Get($sAttCode) == $oTargetObj->GetKey())
{
$sSelected = " selected";
}
else
{
$sSelected = "";
}
$sValue .= "<option value=\"".$oTargetObj->GetKey()."\"$sSelected>".$oTargetObj->Get('name')."</option>\n";
}
$sValue .= "</select>\n";
}
else
{
$sValue = "<input size=\"50\" name=\"attr[$sAttCode]\" value=\"".($oObj->Get($sAttCode))."\">";
}
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sValue);
}
}
$oPage->details($aDetails);
$oPage->add("<input type=\"hidden\" name=\"key\" value=\"$sKey\">\n");
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClassName\">\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"update\">\n");
$oPage->add("<input type=\"submit\" value=\" Update \">\n");
$oPage->add("<form method=\"post\">\n");
}
function DisplayCreationForm(web_page $oPage, $sClassName)
{
global $oContext;
$oPage->p("New $sClassName\n");
$aDetails = array();
$oPage->add("<form method=\"post\">\n");
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode=>$oAttDef)
{
if (!$oAttDef->IsExternalField())
{
if ($oAttDef->IsExternalKey())
{
//External key, display a combo
$sTargetClass = $oAttDef->GetTargetClass();
//$oFilter = new CMDBSearchFilter($sTargetClass);
$oFilter = $oContext->NewFilter($sTargetClass);
$oSet = new CMDBObjectSet($oFilter);
$sValue = "<select name=\"attr[$sAttCode]\">\n";
while($oTargetObj = $oSet->Fetch())
{
$sValue .= "<option value=\"".$oTargetObj->GetKey()."\">".$oTargetObj->Get('name')."</option>\n";
}
$sValue .= "</select>\n";
}
else
{
$sValue = "<input size=\"50\" name=\"attr[$sAttCode]\" value=\"".$oAttDef->GetDefaultValue()."\">";
}
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sValue);
}
}
$oPage->details($aDetails);
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClassName\">\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"create\">\n");
$oPage->add("<input type=\"submit\" value=\" Create \">\n");
$oPage->add("<form method=\"post\">\n");
}
function UpdateObject(web_page $oPage, $sClassName, $sKey, $aAttributes)
{
global $oContext;
//$oObj = MetaModel::GetObject($sClassName, $sKey);
$oObj = $oContext->GetObject($sClassName, $sKey);
if ($oObj == null)
{
$oPage->p("You are not allowed to edit this object.");
return;
}
$oPage->p("Update of $sClassName - $sKey");
foreach(MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode=>$oAttDef)
{
if (isset($aAttributes[$sAttCode]))
{
$oObj->Set($sAttCode, $aAttributes[$sAttCode]);
}
}
if ($oObj->CheckToUpdate())
{
// By rom
// $oObj->DBUpdate();
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by somebody");
$iChangeId = $oMyChange->DBInsert();
$oObj->DBUpdateTracked($oMyChange);
$oPage->p(get_class($oObj)." updated\n");
}
else
{
$oPage->p("<strong>Error: object can not be updated!</strong>\n");
$oObj->DBRevert(); // restore default values!
}
// By Rom
// $oObj->DisplayDetails($oPage);
// replaced by...
DisplayDetails($oPage, get_class($oObj), $oObj->GetKey());
$oPage->p("<a href=\"\">Return to main page</a>");
}
function DeleteObject(web_page $oPage, $sClassName, $sKey)
{
global $oContext;
//$oObj = MetaModel::GetObject($sClassName, $sKey);
$oObj = $oContext->GetObject($sClassName, $sKey);
if ($oObj == null)
{
$oPage->p("You are not allowed to delete this object.");
return;
}
$oPage->p("Deletion of $sClassName - $sKey");
if ($oObj->CheckToDelete())
{
// By Rom
//$oObj->DBDelete();
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by somebody");
$iChangeId = $oMyChange->DBInsert();
$oObj->DBDeleteTracked($oMyChange);
$oPage->p("$sClassName deleted\n");
}
else
{
$oPage->p("<strong>Error: object can not be deleted!</strong>\n");
// By Rom
DisplayDetails($oPage, get_class($oObj), $oObj->GetKey());
}
$oPage->p("<a href=\"\">Return to main page</a>");
}
function CreateObject(web_page $oPage, $sClassName, $aAttributes)
{
$oObj = MetaModel::NewObject($sClassName);
$oPage->p("Creation of ".get_class($oObj)." object.");
foreach(MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode=>$oAttDef)
{
if (isset($aAttributes[$sAttCode]))
{
$oObj->Set($sAttCode, $aAttributes[$sAttCode]);
}
}
if ($oObj->CheckToInsert())
{
// By rom
// $oObj->DBInsert();
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by somebody");
$iChangeId = $oMyChange->DBInsert();
$oObj->DBInsertTracked($oMyChange);
$oPage->p(get_class($oObj)." created\n");
// By Rom
// $oObj->DisplayDetails($oPage);
// replaced by...
DisplayDetails($oPage, get_class($oObj), $oObj->GetKey());
}
else
{
$oPage->p("<strong>Error: object can not be created!</strong>\n");
}
$oPage->p("<a href=\"\">Return to main page</a>");
}
// By Rom
function AddLinks($oPage, $sClassName, $sKey, $sLinkClass, $sExtKeyToMe, $sExtKeyToPartner, $sFilter)
{
global $oContext;
//$oObj = MetaModel::GetObject($sClassName, $sKey);
$oObj = $oContext->GetObject($sClassName, $sKey);
if ($oObj == null)
{
$oPage->p("You are not allowed to modify (create links on) this object.");
return;
}
$oPage->p("Creating links for $sClassName - $sKey");
$oFilter = CMDBSearchFilter::unserialize($sFilter);
$oPage->p("Linking to ".$oFilter->__DescribeHTML());
$oObjSet = new CMDBObjectSet($oFilter);
if ($oObjSet->Count() != 0)
{
while($oPartnerObj = $oObjSet->Fetch())
{
$oNewLink = MetaModel::NewObject($sLinkClass);
$oNewLink->Set($sExtKeyToMe, $sKey);
$oNewLink->Set($sExtKeyToPartner, $oPartnerObj->GetKey());
if ($oNewLink->CheckToInsert())
{
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Made by somebody");
$iChangeId = $oMyChange->DBInsert();
$oNewLink->DBInsertTracked($oMyChange);
$oPage->p(get_class($oNewLink)." created\n");
}
else
{
$oPage->p("<strong>Error: link can not be created!</strong>\n");
}
}
}
else
{}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// M a i n P r o g r a m
//
///////////////////////////////////////////////////////////////////////////////////////////////////
$operation = ReadParam('operation', '');
$iContext = ReadParam('ctx', 1);
$oContext = new UserContext();
switch($iContext)
{
case 2: // See only the organization 'ITOP'
$oContext->AddCondition('bizOrganization', 'pkey', 'ITOP', '=');
$oContext->AddCondition('logRealObject', 'organization', 'ITOP', '=');
break;
case 3: // See only the organization containing 'o' and contacts containing +33
$oContext->AddCondition('Organization', 'name', 'o', 'Contains');
//$oContext->AddCondition('Object', 'orgname', 'o', 'Contains');
$oContext->AddCondition('Contact', 'phone', '+33', 'Contains');
break;
case 1: // No limitation
default:
// nothing to do
}
dialogstack::DeclareCaller("Main navigation menu");
switch($operation)
{
case 'details':
$sClass = ReadParam('class');
$sKey = ReadParam('key');
DisplayDetails($oPage, $sClass, $sKey);
break;
// By rom
case 'changeslog':
$sClass = ReadParam('class');
$sKey = ReadParam('key');
DisplayChangesLog($oPage, $sClass, $sKey);
break;
case 'edit':
$sClass = ReadParam('class');
$sKey = ReadParam('key');
DisplayEditForm($oPage, $sClass, $sKey);
break;
case 'update':
$sClass = ReadParam('class');
$sKey = ReadParam('key');
$aAttributes = ReadParam('attr', array());
UpdateObject($oPage, $sClass, $sKey, $aAttributes);
break;
case 'new':
$sClass = ReadParam('class');
DisplayCreationForm($oPage, $sClass);
break;
case 'create':
$sClass = ReadParam('class');
$aAttributes = ReadParam('attr', array());
CreateObject($oPage, $sClass, $aAttributes);
break;
case 'delete':
$sClass = ReadParam('class');
$sKey = ReadParam('key');
DeleteObject($oPage, $sClass, $sKey);
break;
case 'direct':
$sFilter = ReadParam('filter');
$sFormat = ReadParam('format', 'html');
$oSearchFilter = CMDBSearchFilter::unserialize($sFilter);
switch($sFormat)
{
case 'csv':
$oPage->small_p($oSearchFilter->__DescribeHTML());
$oPage->Add("<TEXTAREA ROWS=\"30\" COLS=\"100\">");
DumpObjectsAsCSV($oPage, $oSearchFilter->GetClass(), $oSearchFilter);
$oPage->Add("</TEXTAREA>");
break;
case 'xls':
$oPage->add_header('Content-disposition: attachment;filename=served.xls'); // Will fool Excel
$oPage->add_header('Content-Type: application/vnd.ms-excel'); // Will fool Excel
DumpObjects($oPage, $oSearchFilter->GetClass(), $oSearchFilter);
break;
case 'html':
default:
$oSet = new CMDBObjectSet($oSearchFilter);
cmdbAbstractObject::DisplaySet($oPage, $oSet);
}
break;
case 'addlinks':
$sClass = ReadParam('class');
$sKey = ReadParam('key');
$sLinkClass = ReadParam('linkclass');
$sExtKeyToMe = ReadParam('extkeytome');
$sExtKeyToPartner = ReadParam('extkeytopartner');
$sFilter = ReadParam('filter');
AddLinks($oPage, $sClass, $sKey, $sLinkClass, $sExtKeyToMe, $sExtKeyToPartner, $sFilter);
break;
default:
$sCurrentOrganization = ReadParam('org', '');
$sActiveTab = ReadParam('classname', '');
DisplaySelectOrg($oPage, $sCurrentOrganization, $iContext);
if ($sCurrentOrganization != "")
{
$oPage->add("<div id=\"classesTabs\" class=\"light\">\n");
$oPage->add("<ul>\n");
$index = 1;
$iActiveTabIndex = 1; // By default the first tab is the active one
foreach( $aTopLevelClasses as $sClassName)
{
if ($sClassName == $sActiveTab)
{
$iActiveTabIndex = $index;
}
$oPage->add("\t<li><a href=\"#tab_$sClassName\">$sClassName</a></li>\n");
$index++;
}
$oPage->add("</ul>\n");
foreach( $aTopLevelClasses as $sClassName)
{
$oPage->add("<div id=\"tab_$sClassName\">");
if (count(MetaModel::GetSubclasses($sClassName)) > 0)
{
$sActiveSubclass = ReadParam('subclassname', '');
foreach(MetaModel::GetSubclasses($sClassName) as $sSubclassName)
{
//$oSearchFilter = new CMDBSearchFilter($sSubclassName);
$oSearchFilter = $oContext->NewFilter($sSubclassName);
$oSearchFilter ->AddCondition('org_id', $sCurrentOrganization, '=');
$oPage->add("<div style=\"border:1px solid #97a5b0; margin-top:0.5em;\">\n");
$oPage->add("<div style=\"padding:0.25em;background-color:#f0f0f0\">\n");
$oPage->p("<strong>$sSubclassName</strong> - ".MetaModel::GetClassDescription($sSubclassName));
$oPage->add("<form method=\"get\">\n");
$oPage->add("<input type=\"hidden\" name=\"classname\" value=\"$sClassName\">\n");
$oPage->add("<input type=\"hidden\" name=\"subclassname\" value=\"$sSubclassName\">\n");
$oPage->add("<input type=\"hidden\" name=\"ctx\" value=\"$iContext\">\n");
$oPage->add("<input type=\"hidden\" name=\"org\" value=\"$sCurrentOrganization\">\n");
foreach( MetaModel::GetClassFilterDefs($sSubclassName) as $sFilterCode=>$oFilterDef)
{
$sFilterValue = "";
if (($sActiveTab == $sClassName) && ($sActiveSubclass == $sSubclassName))
{
$sFilterValue = ReadParam($sFilterCode, '');
if (!empty($sFilterValue))
{
$oSearchFilter->AddCondition($sFilterCode, $sFilterValue, 'Contains');
}
}
$oPage->add($oFilterDef->GetLabel().": <input name=\"$sFilterCode\" value=\"$sFilterValue\"/>&nbsp;\n");
}
$oPage->add("<input type=\"submit\" value=\"Search\">\n");
$oPage->add("</form>\n");
$oPage->add("</div>\n");
$oSet = new CMDBObjectSet($oSearchFilter);
$iMatchesCount = $oSet->Count();
if ($iMatchesCount == 0)
{
$oPage->p("No $sSubclassName matches these criteria.");
$oPage->small_p("(".$oSearchFilter->__DescribeHTML().")");
}
else
{
$oPage->p("$iMatchesCount item(s) found.");
cmdbAbstractObject::DisplaySet($oPage, $oSet);
}
$oPage->p("<a href=\"?operation=new&class=$sSubclassName\">Create a new $sSubclassName</a>\n");
$oPage->add("</div>\n");
}
}
else
{
// No subclasses, list the form directly
//$oSearchFilter = new CMDBSearchFilter($sClassName);
$oSearchFilter = $oContext->NewFilter($sClassName);
$oSearchFilter ->AddCondition('org_id', $sCurrentOrganization, '=');
$oPage->add("<div style=\"border:1px solid #97a5b0; margin-top:0.5em;\">\n");
$oPage->add("<div style=\"padding:0.25em;background-color:#f0f0f0\">\n");
$oPage->p("<strong>$sClassName</strong> - ".MetaModel::GetClassDescription($sClassName));
$oPage->add("<form method=\"get\">\n");
$oPage->add("<input type=\"hidden\" name=\"classname\" value=\"$sClassName\">\n");
$oPage->add("<input type=\"hidden\" name=\"org\" value=\"$sCurrentOrganization\">\n");
$oPage->add("<input type=\"hidden\" name=\"ctx\" value=\"$iContext\">\n");
foreach( MetaModel::GetClassFilterDefs($sClassName) as $sFilterCode=>$oFilterDef)
{
$sFilterValue = "";
if ($sActiveTab == $sClassName)
{
$sFilterValue = ReadParam($sFilterCode, '');
if (!empty($sFilterValue))
{
$oSearchFilter->AddCondition($sFilterCode, $sFilterValue, 'Contains');
}
}
$oPage->add($oFilterDef->GetLabel().": <input name=\"$sFilterCode\" value=\"$sFilterValue\"/>&nbsp;\n");
}
$oPage->add("<input type=\"submit\" value=\"Search\">\n");
$oPage->add("</form>\n");
$oPage->add("</div>\n");
$oPage->add("<div style=\"padding:0.25em;background-color:#fff\">\n");
$oSet = new CMDBObjectSet($oSearchFilter);
$iMatchesCount = $oSet->Count();
if ($iMatchesCount == 0)
{
$oPage->p("No $sClassName matches these criteria.");
$oPage->small_p("(".$oSearchFilter->__DescribeHTML().")");
}
else
{
$oPage->p("$iMatchesCount item(s) found.");
cmdbAbstractObject::DisplaySet($oPage, $oSet);
$oPage->small_p("(".$oSearchFilter->__DescribeHTML().")");
}
$oPage->p("<a href=\"?operation=new&ctx=$iContext&class=$sClassName\">Create a new $sClassName</a>\n");
$oPage->add("</div>\n");
$oPage->add("</div>\n");
}
$oPage->add("</div>\n");
}
$oPage->add("</div>\n");
$oPage->add_script('$(function() {$("#classesTabs > ul").tabs( '.$iActiveTabIndex.', { fxFade: true, fxSpeed: \'fast\' } );});');
}
}
$oPage->output();
?>

View File

@@ -0,0 +1,8 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>iTop</ShortName>
<Contact>webmaster@itop.com</Contact>
<Description>Recherche dans iTop</Description>
<InputEncoding>ISO-8859-1</InputEncoding>
<Url type="text/html" method="get" template="http://localhost:81/pages/UI.php?text={searchTerms}&amp;operation=full_text"/>
<moz:SearchForm>http://localhost:81/pages/UI.php</moz:SearchForm>
</OpenSearchDescription>

View File

@@ -0,0 +1,16 @@
<?php
$sFullUrl = 'http'.(empty($_SERVER['HTTPS']) ? '' : 's').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/UI.php';
$sICOFullUrl = 'http'.(empty($_SERVER['HTTPS']) ? '' : 's').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../images/iTop-icon.ico';
$sPNGFullUrl = 'http'.(empty($_SERVER['HTTPS']) ? '' : 's').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../images/iTop-icon.png';
header('Content-type: text/xml');
?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>iTop</ShortName>
<Contact>webmaster@itop.com</Contact>
<Description>Search in iTop</Description>
<InputEncoding>ISO-8859-1</InputEncoding>
<Url type="text/html" method="get" template="<?php echo $sFullUrl;?>?text={searchTerms}&amp;operation=full_text"/>
<moz:SearchForm><?php echo $sFullUrl;?></moz:SearchForm>
<Image height="16" width="16" type="image/x-icon"><?php echo $sICOFullUrl;?></Image>
<Image height="64" width="64" type="image/png"><?php echo $sPNGFullUrl;?></Image>
</OpenSearchDescription>

View File

@@ -0,0 +1,806 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Converts to and from JSON format.
*
* JSON (JavaScript Object Notation) is a lightweight data-interchange
* format. It is easy for humans to read and write. It is easy for machines
* to parse and generate. It is based on a subset of the JavaScript
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
* This feature can also be found in Python. JSON is a text format that is
* completely language independent but uses conventions that are familiar
* to programmers of the C-family of languages, including C, C++, C#, Java,
* JavaScript, Perl, TCL, and many others. These properties make JSON an
* ideal data-interchange language.
*
* This package provides a simple encoder and decoder for JSON notation. It
* is intended for use with client-side Javascript applications that make
* use of HTTPRequest to perform server communication functions - data can
* be encoded into JSON notation for use in a client-side javascript, or
* decoded from incoming Javascript requests. JSON format is native to
* Javascript, and can be directly eval()'ed with no further parsing
* overhead
*
* All strings should be in ASCII or UTF-8 format!
*
* LICENSE: Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met: Redistributions of source code must retain the
* above copyright notice, this list of conditions and the following
* disclaimer. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* @category
* @package Services_JSON
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
* @copyright 2005 Michal Migurski
* @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
* @license http://www.opensource.org/licenses/bsd-license.php
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
*/
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_SLICE', 1);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_STR', 2);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_ARR', 3);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_OBJ', 4);
/**
* Marker constant for Services_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_CMT', 5);
/**
* Behavior switch for Services_JSON::decode()
*/
define('SERVICES_JSON_LOOSE_TYPE', 16);
/**
* Behavior switch for Services_JSON::decode()
*/
define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
/**
* Converts to and from JSON format.
*
* Brief example of use:
*
* <code>
* // create a new instance of Services_JSON
* $json = new Services_JSON();
*
* // convert a complexe value to JSON notation, and send it to the browser
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
* $output = $json->encode($value);
*
* print($output);
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
*
* // accept incoming POST data, assumed to be in JSON notation
* $input = file_get_contents('php://input', 1000000);
* $value = $json->decode($input);
* </code>
*/
class Services_JSON
{
/**
* constructs a new JSON instance
*
* @param int $use object behavior flags; combine with boolean-OR
*
* possible values:
* - SERVICES_JSON_LOOSE_TYPE: loose typing.
* "{...}" syntax creates associative arrays
* instead of objects in decode().
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
* Values which can't be encoded (e.g. resources)
* appear as NULL instead of throwing errors.
* By default, a deeply-nested resource will
* bubble up with an error, so all return values
* from encode() should be checked with isError()
*/
function Services_JSON($use = 0)
{
$this->use = $use;
}
/**
* convert a string from one UTF-16 char to one UTF-8 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf16 UTF-16 character
* @return string UTF-8 character
* @access private
*/
function utf162utf8($utf16)
{
// oh please oh please oh please oh please oh please
if(function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
}
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
switch(true) {
case ((0x7F & $bytes) == $bytes):
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x7F & $bytes);
case (0x07FF & $bytes) == $bytes:
// return a 2-byte UTF-8 character
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xC0 | (($bytes >> 6) & 0x1F))
. chr(0x80 | ($bytes & 0x3F));
case (0xFFFF & $bytes) == $bytes:
// return a 3-byte UTF-8 character
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xE0 | (($bytes >> 12) & 0x0F))
. chr(0x80 | (($bytes >> 6) & 0x3F))
. chr(0x80 | ($bytes & 0x3F));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* convert a string from one UTF-8 char to one UTF-16 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf8 UTF-8 character
* @return string UTF-16 character
* @access private
*/
function utf82utf16($utf8)
{
// oh please oh please oh please oh please oh please
if(function_exists('mb_convert_encoding')) {
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
}
switch(strlen($utf8)) {
case 1:
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return $utf8;
case 2:
// return a UTF-16 character from a 2-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x07 & (ord($utf8{0}) >> 2))
. chr((0xC0 & (ord($utf8{0}) << 6))
| (0x3F & ord($utf8{1})));
case 3:
// return a UTF-16 character from a 3-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr((0xF0 & (ord($utf8{0}) << 4))
| (0x0F & (ord($utf8{1}) >> 2)))
. chr((0xC0 & (ord($utf8{1}) << 6))
| (0x7F & ord($utf8{2})));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* encodes an arbitrary variable into JSON format
*
* @param mixed $var any number, boolean, string, array, or object to be encoded.
* see argument 1 to Services_JSON() above for array-parsing behavior.
* if var is a strng, note that encode() always expects it
* to be in ASCII or UTF-8 format!
*
* @return mixed JSON string representation of input var or an error if a problem occurs
* @access public
*/
function encode($var)
{
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
case 'NULL':
return 'null';
case 'integer':
return (int) $var;
case 'double':
case 'float':
return (float) $var;
case 'string':
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
$ascii = '';
$strlen_var = strlen($var);
/*
* Iterate over every character in the string,
* escaping with a slash or encoding to UTF-8 where necessary
*/
for ($c = 0; $c < $strlen_var; ++$c) {
$ord_var_c = ord($var{$c});
switch (true) {
case $ord_var_c == 0x08:
$ascii .= '\b';
break;
case $ord_var_c == 0x09:
$ascii .= '\t';
break;
case $ord_var_c == 0x0A:
$ascii .= '\n';
break;
case $ord_var_c == 0x0C:
$ascii .= '\f';
break;
case $ord_var_c == 0x0D:
$ascii .= '\r';
break;
case $ord_var_c == 0x22:
case $ord_var_c == 0x2F:
case $ord_var_c == 0x5C:
// double quote, slash, slosh
$ascii .= '\\'.$var{$c};
break;
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
// characters U-00000000 - U-0000007F (same as ASCII)
$ascii .= $var{$c};
break;
case (($ord_var_c & 0xE0) == 0xC0):
// characters U-00000080 - U-000007FF, mask 110XXXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
$c += 1;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF0) == 0xE0):
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}));
$c += 2;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF8) == 0xF0):
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}));
$c += 3;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFC) == 0xF8):
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}));
$c += 4;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFE) == 0xFC):
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}),
ord($var{$c + 5}));
$c += 5;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
}
return '"'.$ascii.'"';
case 'array':
/*
* As per JSON spec if any array key is not an integer
* we must treat the the whole array as an object. We
* also try to catch a sparsely populated associative
* array with numeric keys here because some JS engines
* will create an array with empty indexes up to
* max_index which can cause memory issues and because
* the keys, which may be relevant, will be remapped
* otherwise.
*
* As per the ECMA and JSON specification an object may
* have any string as a property. Unfortunately due to
* a hole in the ECMA specification if the key is a
* ECMA reserved word or starts with a digit the
* parameter is only accessible using ECMAScript's
* bracket notation.
*/
// treat as a JSON object
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
$properties = array_map(array($this, 'name_value'),
array_keys($var),
array_values($var));
foreach($properties as $property) {
if(Services_JSON::isError($property)) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
}
// treat it like a regular array
$elements = array_map(array($this, 'encode'), $var);
foreach($elements as $element) {
if(Services_JSON::isError($element)) {
return $element;
}
}
return '[' . join(',', $elements) . ']';
case 'object':
$vars = get_object_vars($var);
$properties = array_map(array($this, 'name_value'),
array_keys($vars),
array_values($vars));
foreach($properties as $property) {
if(Services_JSON::isError($property)) {
return $property;
}
}
return '{' . join(',', $properties) . '}';
default:
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
? 'null'
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
}
}
/**
* array-walking function for use in generating JSON-formatted name-value pairs
*
* @param string $name name of key to use
* @param mixed $value reference to an array element to be encoded
*
* @return string JSON-formatted name-value pair, like '"name":value'
* @access private
*/
function name_value($name, $value)
{
$encoded_value = $this->encode($value);
if(Services_JSON::isError($encoded_value)) {
return $encoded_value;
}
return $this->encode(strval($name)) . ':' . $encoded_value;
}
/**
* reduce a string by removing leading and trailing comments and whitespace
*
* @param $str string string value to strip of comments and whitespace
*
* @return string string value stripped of comments and whitespace
* @access private
*/
function reduce_string($str)
{
$str = preg_replace(array(
// eliminate single line comments in '// ...' form
'#^\s*//(.+)$#m',
// eliminate multi-line comments in '/* ... */' form, at start of string
'#^\s*/\*(.+)\*/#Us',
// eliminate multi-line comments in '/* ... */' form, at end of string
'#/\*(.+)\*/\s*$#Us'
), '', $str);
// eliminate extraneous space
return trim($str);
}
/**
* decodes a JSON string into appropriate variable
*
* @param string $str JSON-formatted string
*
* @return mixed number, boolean, string, array, or object
* corresponding to given JSON input string.
* See argument 1 to Services_JSON() above for object-output behavior.
* Note that decode() always returns strings
* in ASCII or UTF-8 format!
* @access public
*/
function decode($str)
{
$str = $this->reduce_string($str);
switch (strtolower($str)) {
case 'true':
return true;
case 'false':
return false;
case 'null':
return null;
default:
$m = array();
if (is_numeric($str)) {
// Lookie-loo, it's a number
// This would work on its own, but I'm trying to be
// good about returning integers where appropriate:
// return (float)$str;
// Return float or int, as appropriate
return ((float)$str == (integer)$str)
? (integer)$str
: (float)$str;
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
// STRINGS RETURNED IN UTF-8 FORMAT
$delim = substr($str, 0, 1);
$chrs = substr($str, 1, -1);
$utf8 = '';
$strlen_chrs = strlen($chrs);
for ($c = 0; $c < $strlen_chrs; ++$c) {
$substr_chrs_c_2 = substr($chrs, $c, 2);
$ord_chrs_c = ord($chrs{$c});
switch (true) {
case $substr_chrs_c_2 == '\b':
$utf8 .= chr(0x08);
++$c;
break;
case $substr_chrs_c_2 == '\t':
$utf8 .= chr(0x09);
++$c;
break;
case $substr_chrs_c_2 == '\n':
$utf8 .= chr(0x0A);
++$c;
break;
case $substr_chrs_c_2 == '\f':
$utf8 .= chr(0x0C);
++$c;
break;
case $substr_chrs_c_2 == '\r':
$utf8 .= chr(0x0D);
++$c;
break;
case $substr_chrs_c_2 == '\\"':
case $substr_chrs_c_2 == '\\\'':
case $substr_chrs_c_2 == '\\\\':
case $substr_chrs_c_2 == '\\/':
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
$utf8 .= $chrs{++$c};
}
break;
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
// single, escaped unicode character
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
. chr(hexdec(substr($chrs, ($c + 4), 2)));
$utf8 .= $this->utf162utf8($utf16);
$c += 5;
break;
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
$utf8 .= $chrs{$c};
break;
case ($ord_chrs_c & 0xE0) == 0xC0:
// characters U-00000080 - U-000007FF, mask 110XXXXX
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 2);
++$c;
break;
case ($ord_chrs_c & 0xF0) == 0xE0:
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 3);
$c += 2;
break;
case ($ord_chrs_c & 0xF8) == 0xF0:
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 4);
$c += 3;
break;
case ($ord_chrs_c & 0xFC) == 0xF8:
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 5);
$c += 4;
break;
case ($ord_chrs_c & 0xFE) == 0xFC:
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 6);
$c += 5;
break;
}
}
return $utf8;
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
// array, or object notation
if ($str{0} == '[') {
$stk = array(SERVICES_JSON_IN_ARR);
$arr = array();
} else {
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$stk = array(SERVICES_JSON_IN_OBJ);
$obj = array();
} else {
$stk = array(SERVICES_JSON_IN_OBJ);
$obj = new stdClass();
}
}
array_push($stk, array('what' => SERVICES_JSON_SLICE,
'where' => 0,
'delim' => false));
$chrs = substr($str, 1, -1);
$chrs = $this->reduce_string($chrs);
if ($chrs == '') {
if (reset($stk) == SERVICES_JSON_IN_ARR) {
return $arr;
} else {
return $obj;
}
}
//print("\nparsing {$chrs}\n");
$strlen_chrs = strlen($chrs);
for ($c = 0; $c <= $strlen_chrs; ++$c) {
$top = end($stk);
$substr_chrs_c_2 = substr($chrs, $c, 2);
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
// found a comma that is not inside a string, array, etc.,
// OR we've reached the end of the character list
$slice = substr($chrs, $top['where'], ($c - $top['where']));
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
if (reset($stk) == SERVICES_JSON_IN_ARR) {
// we are in an array, so just push an element onto the stack
array_push($arr, $this->decode($slice));
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
// we are in an object, so figure
// out the property name and set an
// element in an associative array,
// for now
$parts = array();
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// "name":value pair
$key = $this->decode($parts[1]);
$val = $this->decode($parts[2]);
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// name:value pair, where name is unquoted
$key = $parts[1];
$val = $this->decode($parts[2]);
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
}
}
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
// found a quote, and we are not inside a string
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
//print("Found start of string at {$c}\n");
} elseif (($chrs{$c} == $top['delim']) &&
($top['what'] == SERVICES_JSON_IN_STR) &&
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
// found a quote, we're in a string, and it's not escaped
// we know that it's not escaped becase there is _not_ an
// odd number of backslashes at the end of the string so far
array_pop($stk);
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '[') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a left-bracket, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
//print("Found start of array at {$c}\n");
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
// found a right-bracket, and we're in an array
array_pop($stk);
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '{') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a left-brace, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
//print("Found start of object at {$c}\n");
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
// found a right-brace, and we're in an object
array_pop($stk);
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($substr_chrs_c_2 == '/*') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a comment start, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
$c++;
//print("Found start of comment at {$c}\n");
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
// found a comment end, and we're in one now
array_pop($stk);
$c++;
for ($i = $top['where']; $i <= $c; ++$i)
$chrs = substr_replace($chrs, ' ', $i, 1);
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
}
}
if (reset($stk) == SERVICES_JSON_IN_ARR) {
return $arr;
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
return $obj;
}
}
}
}
/**
* @todo Ultimately, this should just call PEAR::isError()
*/
function isError($data, $code = null)
{
if (class_exists('pear')) {
return PEAR::isError($data, $code);
} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
is_subclass_of($data, 'services_json_error'))) {
return true;
}
return false;
}
}
if (class_exists('PEAR_Error')) {
class Services_JSON_Error extends PEAR_Error
{
function Services_JSON_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
}
}
} else {
/**
* @todo Ultimately, this class shall be descended from PEAR_Error
*/
class Services_JSON_Error
{
function Services_JSON_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
}
}
}
?>

View File

@@ -0,0 +1,16 @@
Open Flash Chart - PHP libraries. These help create data files for Open Flash Chart.
Copyright (C) 2007
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

View File

@@ -0,0 +1,86 @@
<?php
// Pretty print some JSON
function json_format($json)
{
$tab = " ";
$new_json = "";
$indent_level = 0;
$in_string = false;
/*
commented out by monk.e.boy 22nd May '08
because my web server is PHP4, and
json_* are PHP5 functions...
$json_obj = json_decode($json);
if($json_obj === false)
return false;
$json = json_encode($json_obj);
*/
$len = strlen($json);
for($c = 0; $c < $len; $c++)
{
$char = $json[$c];
switch($char)
{
case '{':
case '[':
if(!$in_string)
{
$new_json .= $char . "\n" . str_repeat($tab, $indent_level+1);
$indent_level++;
}
else
{
$new_json .= $char;
}
break;
case '}':
case ']':
if(!$in_string)
{
$indent_level--;
$new_json .= "\n" . str_repeat($tab, $indent_level) . $char;
}
else
{
$new_json .= $char;
}
break;
case ',':
if(!$in_string)
{
$new_json .= ",\n" . str_repeat($tab, $indent_level);
}
else
{
$new_json .= $char;
}
break;
case ':':
if(!$in_string)
{
$new_json .= ": ";
}
else
{
$new_json .= $char;
}
break;
case '"':
if($c > 0 && $json[$c-1] != '\\')
{
$in_string = !$in_string;
}
default:
$new_json .= $char;
break;
}
}
return $new_json;
}

View File

@@ -0,0 +1,66 @@
<?php
class area_base
{
function area_base()
{
$tmp = 'fill-alpha';
$this->$tmp = 0.35;
$this->values = array();
}
function set_width( $w )
{
$this->width = $w;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_fill_colour( $colour )
{
$this->fill = $colour;
}
function set_fill_alpha( $alpha )
{
$tmp = "fill-alpha";
$this->$tmp = $alpha;
}
function set_halo_size( $size )
{
$tmp = 'halo-size';
$this->$tmp = $size;
}
function set_values( $v )
{
$this->values = $v;
}
function set_dot_size( $size )
{
$tmp = 'dot-size';
$this->$tmp = $size;
}
function set_key( $text, $font_size )
{
$this->text = $text;
$tmp = 'font-size';
$this->$tmp = $font_size;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
function set_loop()
{
$this->loop = true;
}
}

View File

@@ -0,0 +1,10 @@
<?php
class area_hollow extends area_base
{
function area_hollow()
{
$this->type = "area_hollow";
parent::area_base();
}
}

View File

@@ -0,0 +1,10 @@
<?php
class area_line extends area_base
{
function area_line()
{
$this->type = "area_line";
parent::area_base();
}
}

View File

@@ -0,0 +1,34 @@
<?php
include_once 'ofc_bar_base.php';
class bar_value
{
function bar_value( $top, $bottom=null )
{
$this->top = $top;
if( isset( $bottom ) )
$this->bottom = $bottom;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}
class bar extends bar_base
{
function bar()
{
$this->type = "bar";
parent::bar_base();
}
}

View File

@@ -0,0 +1,31 @@
<?php
include_once 'ofc_bar_base.php';
class bar_3d_value
{
function bar_3d_value( $top )
{
$this->top = $top;
// $this->bottom = $bottom;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}
class bar_3d extends bar_base
{
function bar_3d()
{
$this->type = "bar_3d";
parent::bar_base();
}
}

View File

@@ -0,0 +1,41 @@
<?php
/* this is a base class */
class bar_base
{
function bar_base(){}
function set_key( $text, $size )
{
$this->text = $text;
$tmp = 'font-size';
$this->$tmp = $size;
}
function set_values( $v )
{
$this->values = $v;
}
function append_value( $v )
{
$this->values[] = $v;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_alpha( $alpha )
{
$this->alpha = $alpha;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}

View File

@@ -0,0 +1,39 @@
<?php
include_once 'ofc_bar_base.php';
class bar_filled_value extends bar_value
{
function bar_filled_value( $top, $bottom=null )
{
parent::bar_value( $top, $bottom );
}
function set_outline_colour( $outline_colour )
{
$tmp = 'outline-colour';
$this->$tmp = $outline_colour;
}
}
class bar_filled extends bar_base
{
function bar_filled( $colour=null, $outline_colour=null )
{
$this->type = "bar_filled";
parent::bar_base();
if( isset( $colour ) )
$this->set_colour( $colour );
if( isset( $outline_colour ) )
$this->set_outline_colour( $outline_colour );
}
function set_outline_colour( $outline_colour )
{
$tmp = 'outline-colour';
$this->$tmp = $outline_colour;
}
}

View File

@@ -0,0 +1,33 @@
<?php
include_once 'ofc_bar_base.php';
class bar_glass_value
{
function bar_glass_value( $top )
{
$this->top = $top;
// $this->bottom = $bottom;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}
class bar_glass extends bar_base
{
function bar_glass()
{
$this->type = "bar_glass";
parent::bar_base();
}
}

View File

@@ -0,0 +1,23 @@
<?php
include_once 'ofc_bar_base.php';
class bar_sketch extends bar_base
{
function bar_sketch( $colour, $outline_colour, $fun_factor )
{
$this->type = "bar_sketch";
parent::bar_base();
$this->set_colour( $colour );
$this->set_outline_colour( $outline_colour );
$this->offset = $fun_factor;
}
function set_outline_colour( $outline_colour )
{
$tmp = 'outline-colour';
$this->$tmp = $outline_colour;
}
}

View File

@@ -0,0 +1,50 @@
<?php
include_once 'ofc_bar_base.php';
class bar_stack extends bar_base
{
function bar_stack()
{
$this->type = "bar_stack";
parent::bar_base();
}
function append_stack( $v )
{
$this->append_value( $v );
}
// an array of HEX colours strings
// e.g. array( '#ff0000', '#00ff00' );
function set_colours( $colours )
{
$this->colours = $colours;
}
// an array of bar_stack_value
function set_keys( $keys )
{
$this->keys = $keys;
}
}
class bar_stack_value
{
function bar_stack_value( $val, $colour )
{
$this->val = $val;
$this->colour = $colour;
}
}
class bar_stack_key
{
function bar_stack_key( $colour, $text, $font_size )
{
$this->colour = $colour;
$this->text = $text;
$tmp = 'font-size';
$this->$tmp = $font_size;
}
}

View File

@@ -0,0 +1,64 @@
<?php
class hbar_value
{
function hbar_value( $left, $right=null )
{
if( isset( $right ) )
{
$this->left = $left;
$this->right = $right;
}
else
$this->right = $left;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}
class hbar
{
function hbar( $colour )
{
$this->type = "hbar";
$this->values = array();
$this->set_colour( $colour );
}
function append_value( $v )
{
$this->values[] = $v;
}
function set_values( $v )
{
foreach( $v as $val )
$this->append_value( new hbar_value( $val ) );
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_key( $text, $size )
{
$this->text = $text;
$tmp = 'font-size';
$this->$tmp = $size;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}

View File

@@ -0,0 +1,9 @@
<?php
class line extends line_base
{
function line()
{
$this->type = "line";
}
}

View File

@@ -0,0 +1,70 @@
<?php
class line_base
{
function line_base()
{
$this->type = "line_dot";
$this->text = "Page views";
$tmp = 'font-size';
$this->$tmp = 10;
$this->values = array(9,6,7,9,5,7,6,9,7);
}
function set_values( $v )
{
$this->values = $v;
}
function set_width( $width )
{
$this->width = $width;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_dot_size( $size )
{
$tmp = 'dot-size';
$this->$tmp = $size;
}
function set_halo_size( $size )
{
$tmp = 'halo-size';
$this->$tmp = $size;
}
function set_key( $text, $font_size )
{
$this->text = $text;
$tmp = 'font-size';
$this->$tmp = $font_size;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
function set_on_click( $text )
{
$tmp = 'on-click';
$this->$tmp = $text;
}
function loop()
{
$this->loop = true;
}
function line_style( $s )
{
$tmp = "line-style";
$this->$tmp = $s;
}
}

View File

@@ -0,0 +1,33 @@
<?php
class dot_value
{
function dot_value( $value, $colour )
{
$this->value = $value;
$this->colour = $colour;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_size( $size )
{
$this->size = $size;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
}
class line_dot extends line_base
{
function line_dot()
{
$this->type = "line_dot";
}
}

View File

@@ -0,0 +1,9 @@
<?php
class line_hollow extends line_base
{
function line_hollow()
{
$this->type = "line_hollow";
}
}

View File

@@ -0,0 +1,11 @@
<?php
class line_style
{
function line_style($on, $off)
{
$this->style = "dash";
$this->on = $on;
$this->off = $off;
}
}

View File

@@ -0,0 +1,109 @@
<?php
class pie_value
{
function pie_value( $value, $label )
{
$this->value = $value;
$this->label = $label;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_label( $label, $label_colour, $font_size )
{
$this->label = $label;
$tmp = 'label-colour';
$this->$tmp = $label_colour;
$tmp = 'font-size';
$this->$tmp = $font_size;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
function on_click( $event )
{
$tmp = 'on-click';
$this->$tmp = $event;
}
}
class pie
{
function pie()
{
$this->type = 'pie';
$this->colours = array("#d01f3c","#356aa0","#C79810");
$this->border = 2;
}
function set_colours( $colours )
{
$this->colours = $colours;
}
function set_alpha( $alpha )
{
$this->alpha = $alpha;
}
function set_values( $v )
{
$this->values = $v;
}
// boolean
function set_animate( $animate )
{
$this->animate = $animate;
}
// real
function set_start_angle( $angle )
{
$tmp = 'start-angle';
$this->$tmp = $angle;
}
function set_tooltip( $tip )
{
$this->tip = $tip;
}
function set_gradient_fill()
{
$tmp = 'gradient-fill';
$this->$tmp = true;
}
function set_label_colour( $label_colour )
{
$tmp = 'label-colour';
$this->$tmp = $label_colour;
}
/**
* Turn off the labels
*/
function set_no_labels()
{
$tmp = 'no-labels';
$this->$tmp = true;
}
function on_click( $event )
{
$tmp = 'on-click';
$this->$tmp = $event;
}
}

View File

@@ -0,0 +1,47 @@
<?php
class radar_axis
{
function radar_axis( $max )
{
$this->set_max( $max );
}
function set_max( $max )
{
$this->max = $max;
}
function set_steps( $steps )
{
$this->steps = $steps;
}
function set_stroke( $s )
{
$this->stroke = $s;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_grid_colour( $colour )
{
$tmp = 'grid-colour';
$this->$tmp = $colour;
}
function set_labels( $labels )
{
$this->labels = $labels;
}
function set_spoke_labels( $labels )
{
$tmp = 'spoke-labels';
$this->$tmp = $labels;
}
}

View File

@@ -0,0 +1,15 @@
<?php
class radar_axis_labels
{
// $labels : array
function radar_axis_labels( $labels )
{
$this->labels = $labels;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
}

View File

@@ -0,0 +1,15 @@
<?php
class radar_spoke_labels
{
// $labels : array
function radar_spoke_labels( $labels )
{
$this->labels = $labels;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
}

View File

@@ -0,0 +1,42 @@
<?php
class scatter_value
{
function scatter_value( $x, $y, $dot_size=-1 )
{
$this->x = $x;
$this->y = $y;
if( $dot_size > 0 )
{
$tmp = 'dot-size';
$this->$tmp = $dot_size;
}
}
}
class scatter
{
function scatter( $colour, $dot_size )
{
$this->type = "scatter";
$this->set_colour( $colour );
$this->set_dot_size( $dot_size );
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_dot_size( $dot_size )
{
$tmp = 'dot-size';
$this->$tmp = $dot_size;
}
function set_values( $values )
{
$this->values = $values;
}
}

View File

@@ -0,0 +1,27 @@
<?php
class scatter_line
{
function scatter_line( $colour, $dot_size )
{
$this->type = "scatter_line";
$this->set_colour( $colour );
$this->set_dot_size( $dot_size );
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_dot_size( $dot_size )
{
$tmp = 'dot-size';
$this->$tmp = $dot_size;
}
function set_values( $values )
{
$this->values = $values;
}
}

View File

@@ -0,0 +1,25 @@
<?php
class shape_point
{
function shape_point( $x, $y )
{
$this->x = $x;
$this->y = $y;
}
}
class shape
{
function shape( $colour )
{
$this->type = "shape";
$this->colour = $colour;
$this->values = array();
}
function append_value( $p )
{
$this->values[] = $p;
}
}

View File

@@ -0,0 +1,15 @@
<?php
class title
{
function title( $text='' )
{
$this->text = $text;
}
function set_style( $css )
{
$this->style = $css;
//"{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}";
}
}

View File

@@ -0,0 +1,51 @@
<?php
include_once 'ofc_bar_base.php';
class tooltip
{
function tooltip(){}
function set_shadow( $shadow )
{
$this->shadow = $shadow;
}
// stroke in pixels (e.g. 5 )
function set_stroke( $stroke )
{
$this->stroke = $stroke;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_background_colour( $bg )
{
$this->background = $bg;
}
// a css style
function set_title_style( $style )
{
$this->title = $style;
}
function set_body_style( $style )
{
$this->body = $style;
}
function set_proximity()
{
$this->mouse = 1;
}
function set_hover()
{
$this->mouse = 2;
}
}

View File

@@ -0,0 +1,61 @@
<?php
//
// In Open Flash Chart -> save_image debug mode, you
// will see the 'echo' text in a new window.
//
/*
print_r( $_GET );
print_r( $_POST );
print_r( $_FILES );
print_r( $GLOBALS );
print_r( $GLOBALS["HTTP_RAW_POST_DATA"] );
*/
// default path for the image to be stored //
$default_path = '../tmp-upload-images/';
if (!file_exists($default_path)) mkdir($default_path, 0777, true);
// full path to the saved image including filename //
$destination = $default_path . basename( $_GET[ 'name' ] );
echo 'Saving your image to: '. $destination;
$jfh = fopen($destination, 'w') or die("can't open file");
fwrite($jfh, $GLOBALS['HTTP_RAW_POST_DATA']);
fclose($jfh);
//
// LOOK:
//
exit();
//
// PHP5:
//
// default path for the image to be stored //
$default_path = 'tmp-upload-images/';
if (!file_exists($default_path)) mkdir($default_path, 0777, true);
// full path to the saved image including filename //
$destination = $default_path . basename( $_FILES[ 'Filedata' ][ 'name' ] );
// move the image into the specified directory //
if (move_uploaded_file($_FILES[ 'Filedata' ][ 'tmp_name' ], $destination)) {
echo "The file " . basename( $_FILES[ 'Filedata' ][ 'name' ] ) . " has been uploaded;";
} else {
echo "FILE UPLOAD FAILED";
}
?>

View File

@@ -0,0 +1,77 @@
<?php
class x_axis
{
function x_axis(){}
function set_stroke( $stroke )
{
$this->stroke = $stroke;
}
function set_colours( $colour, $grid_colour )
{
$this->set_colour( $colour );
$this->set_grid_colour( $grid_colour );
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_tick_height( $height )
{
$tmp = 'tick-height';
$this->$tmp = $height;
}
function set_grid_colour( $colour )
{
$tmp = 'grid-colour';
$this->$tmp = $colour;
}
// $o is a boolean
function set_offset( $o )
{
$this->offset = $o?true:false;
}
function set_steps( $steps )
{
$this->steps = $steps;
}
function set_3d( $val )
{
$tmp = '3d';
$this->$tmp = $val;
}
function set_labels( $x_axis_labels )
{
//$this->labels = $v;
$this->labels = $x_axis_labels;
}
//
// helper function to make the examples
// simpler.
//
function set_labels_from_array( $a )
{
$x_axis_labels = new x_axis_labels();
$x_axis_labels->set_labels( $a );
$this->labels = $x_axis_labels;
if( isset( $this->steps ) )
$x_axis_labels->set_steps( $this->steps );
}
function set_range( $min, $max )
{
$this->min = $min;
$this->max = $max;
}
}

View File

@@ -0,0 +1,42 @@
<?php
class x_axis_label
{
function x_axis_label( $text, $colour, $size, $rotate )
{
$this->set_text( $text );
$this->set_colour( $colour );
$this->set_size( $size );
$this->set_rotate( $rotate );
}
function set_text( $text )
{
$this->text = $text;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_size( $size )
{
$this->size = $size;
}
function set_rotate( $rotate )
{
$this->rotate = $rotate;
}
function set_vertical()
{
$this->rotate = "vertical";
}
function set_visible()
{
$this->visible = true;
}
}

View File

@@ -0,0 +1,34 @@
<?php
class x_axis_labels
{
function x_axis_labels(){}
function set_steps( $steps )
{
$this->steps = $steps;
}
//
// An array of [x_axis_label or string]
//
function set_labels( $labels )
{
$this->labels = $labels;
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_size( $size )
{
$this->size = $size;
}
function set_vertical()
{
$this->rotate = "vertical";
}
}

View File

@@ -0,0 +1,15 @@
<?php
class x_legend
{
function x_legend( $text='' )
{
$this->text = $text;
}
function set_style( $css )
{
$this->style = $css;
//"{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}";
}
}

View File

@@ -0,0 +1,17 @@
<?php
class y_axis extends y_axis_base
{
function y_axis(){}
//
// y axis right does NOT control
// grid colour, the left axis does
//
function set_grid_colour( $colour )
{
$tmp = 'grid-colour';
$this->$tmp = $colour;
}
}

View File

@@ -0,0 +1,56 @@
<?php
class y_axis_base
{
function y_axis_base(){}
function set_stroke( $s )
{
$this->stroke = $s;
}
function set_tick_length( $val )
{
$tmp = 'tick-length';
$this->$tmp = $val;
}
function set_colours( $colour, $grid_colour )
{
$this->set_colour( $colour );
$this->set_grid_colour( $grid_colour );
}
function set_colour( $colour )
{
$this->colour = $colour;
}
function set_grid_colour( $colour )
{
$tmp = 'grid-colour';
$this->$tmp = $colour;
}
function set_range( $min, $max, $steps=1 )
{
$this->min = $min;
$this->max = $max;
$this->set_steps( $steps );
}
function set_offset( $off )
{
$this->offset = $off?1:0;
}
function set_labels( $labels )
{
$this->labels = $labels;
}
function set_steps( $steps )
{
$this->steps = $steps;
}
}

View File

@@ -0,0 +1,6 @@
<?php
class y_axis_right extends y_axis_base
{
function y_axis_right(){}
}

View File

@@ -0,0 +1,15 @@
<?php
class y_legend
{
function y_legend( $text='' )
{
$this->text = $text;
}
function set_style( $css )
{
$this->style = $css;
//"{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}";
}
}

View File

@@ -0,0 +1,109 @@
<?php
function open_flash_chart_object_str( $width, $height, $url, $use_swfobject=true, $base='' )
{
//
// return the HTML as a string
//
return _ofc( $width, $height, $url, $use_swfobject, $base );
}
function open_flash_chart_object( $width, $height, $url, $use_swfobject=true, $base='' )
{
//
// stream the HTML into the page
//
echo _ofc( $width, $height, $url, $use_swfobject, $base );
}
function _ofc( $width, $height, $url, $use_swfobject, $base )
{
//
// I think we may use swfobject for all browsers,
// not JUST for IE...
//
//$ie = strstr(getenv('HTTP_USER_AGENT'), 'MSIE');
//
// escape the & and stuff:
//
$url = urlencode($url);
//
// output buffer
//
$out = array();
//
// check for http or https:
//
if (isset ($_SERVER['HTTPS']))
{
if (strtoupper ($_SERVER['HTTPS']) == 'ON')
{
$protocol = 'https';
}
else
{
$protocol = 'http';
}
}
else
{
$protocol = 'http';
}
//
// if there are more than one charts on the
// page, give each a different ID
//
global $open_flash_chart_seqno;
$obj_id = 'chart';
$div_name = 'flashcontent';
//$out[] = '<script type="text/javascript" src="'. $base .'js/ofc.js"></script>';
if( !isset( $open_flash_chart_seqno ) )
{
$open_flash_chart_seqno = 1;
$out[] = '<script type="text/javascript" src="'. $base .'js/swfobject.js"></script>';
}
else
{
$open_flash_chart_seqno++;
$obj_id .= '_'. $open_flash_chart_seqno;
$div_name .= '_'. $open_flash_chart_seqno;
}
if( $use_swfobject )
{
// Using library for auto-enabling Flash object on IE, disabled-Javascript proof
$out[] = '<div id="'. $div_name .'"></div>';
$out[] = '<script type="text/javascript">';
$out[] = 'var so = new SWFObject("'. $base .'open-flash-chart.swf", "'. $obj_id .'", "'. $width . '", "' . $height . '", "9", "#FFFFFF");';
$out[] = 'so.addVariable("data-file", "'. $url . '");';
$out[] = 'so.addParam("allowScriptAccess", "always" );//"sameDomain");';
$out[] = 'so.write("'. $div_name .'");';
$out[] = '</script>';
$out[] = '<noscript>';
}
$out[] = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="' . $protocol . '://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" ';
$out[] = 'width="' . $width . '" height="' . $height . '" id="ie_'. $obj_id .'" align="middle">';
$out[] = '<param name="allowScriptAccess" value="sameDomain" />';
$out[] = '<param name="movie" value="'. $base .'open-flash-chart.swf?data='. $url .'" />';
$out[] = '<param name="quality" value="high" />';
$out[] = '<param name="bgcolor" value="#FFFFFF" />';
$out[] = '<embed src="'. $base .'open-flash-chart.swf?data=' . $url .'" quality="high" bgcolor="#FFFFFF" width="'. $width .'" height="'. $height .'" name="'. $obj_id .'" align="middle" allowScriptAccess="sameDomain" ';
$out[] = 'type="application/x-shockwave-flash" pluginspage="' . $protocol . '://www.macromedia.com/go/getflashplayer" id="'. $obj_id .'"/>';
$out[] = '</object>';
if ( $use_swfobject ) {
$out[] = '</noscript>';
}
return implode("\n",$out);
}
?>

View File

@@ -0,0 +1,138 @@
<?php
// var_dump(debug_backtrace());
//
// Omar Kilani's php C extension for encoding JSON has been incorporated in stock PHP since 5.2.0
// http://www.aurore.net/projects/php-json/
//
// -- Marcus Engene
//
if (! function_exists('json_encode'))
{
include_once 'JSON.php';
}
include_once 'json_format.php';
// ofc classes
include_once 'ofc_title.php';
include_once 'ofc_y_axis_base.php';
include_once 'ofc_y_axis.php';
include_once 'ofc_y_axis_right.php';
include_once 'ofc_x_axis.php';
include_once 'ofc_area_base.php';
include_once 'ofc_area_hollow.php';
include_once 'ofc_area_line.php';
include_once 'ofc_pie.php';
include_once 'ofc_bar.php';
include_once 'ofc_bar_filled.php';
include_once 'ofc_bar_glass.php';
include_once 'ofc_bar_stack.php';
include_once 'ofc_bar_3d.php';
include_once 'ofc_hbar.php';
include_once 'ofc_line_base.php';
include_once 'ofc_line.php';
include_once 'ofc_line_dot.php';
include_once 'ofc_line_hollow.php';
include_once 'ofc_x_legend.php';
include_once 'ofc_y_legend.php';
include_once 'ofc_bar_sketch.php';
include_once 'ofc_scatter.php';
include_once 'ofc_scatter_line.php';
include_once 'ofc_x_axis_labels.php';
include_once 'ofc_x_axis_label.php';
include_once 'ofc_tooltip.php';
include_once 'ofc_shape.php';
include_once 'ofc_radar_axis.php';
include_once 'ofc_radar_axis_labels.php';
include_once 'ofc_radar_spoke_labels.php';
include_once 'ofc_line_style.php';
class open_flash_chart
{
function open_flash_chart()
{
//$this->title = new title( "Many data lines" );
$this->elements = array();
}
function set_title( $t )
{
$this->title = $t;
}
function set_x_axis( $x )
{
$this->x_axis = $x;
}
function set_y_axis( $y )
{
$this->y_axis = $y;
}
function add_y_axis( $y )
{
$this->y_axis = $y;
}
function set_y_axis_right( $y )
{
$this->y_axis_right = $y;
}
function add_element( $e )
{
$this->elements[] = $e;
}
function set_x_legend( $x )
{
$this->x_legend = $x;
}
function set_y_legend( $y )
{
$this->y_legend = $y;
}
function set_bg_colour( $colour )
{
$this->bg_colour = $colour;
}
function set_radar_axis( $radar )
{
$this->radar_axis = $radar;
}
function set_tooltip( $tooltip )
{
$this->tooltip = $tooltip;
}
function toString()
{
if (function_exists('json_encode'))
{
return json_encode($this);
}
else
{
$json = new Services_JSON();
return $json->encode( $this );
}
}
function toPrettyString()
{
return json_format( $this->toString() );
}
}
//
// there is no PHP end tag so we don't mess the headers up!
//

475
trunk/pages/schema.php Normal file
View File

@@ -0,0 +1,475 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/startup.inc.php');
/**
* Helper for this page -> link to a class
*/
function MakeClassHLink($sClass)
{
return "<a href=\"?operation=details_class&class=$sClass\" title=\"".MetaModel::GetClassDescription($sClass)."\">".MetaModel::GetName($sClass)."</a>";
}
/**
* Helper for this page -> link to a class
*/
function MakeRelationHLink($sRelCode)
{
$sDec = MetaModel::GetRelationProperty($sRelCode, 'description');
//$sVerbDown = MetaModel::GetRelationProperty($sRelCode, 'verb_down');
//$sVerbUp = MetaModel::GetRelationProperty($sRelCode, 'verb_up');
return "<a href=\"?operation=details_relation&relcode=$sRelCode\" title=\"$sDec\">".$sRelCode."</a>";
}
/**
* Helper for the global list and the details of a given class
*/
function DisplaySubclasses($oPage, $sClass)
{
$aChildClasses = MetaModel::EnumChildClasses($sClass);
if (count($aChildClasses) != 0)
{
$oPage->add("<ul>\n");
foreach($aChildClasses as $sClassName)
{
// Skip indirect childs, they will be handled somewhere else
if (MetaModel::GetParentPersistentClass($sClassName) == $sClass)
{
$oPage->add("<li>".MakeClassHLink($sClassName)."\n");
DisplaySubclasses($oPage, $sClassName);
$oPage->add("</li>\n");
}
}
$oPage->add("</ul>\n");
}
}
/**
* Helper for the global list and the details of a given class
*/
function DisplayReferencingClasses($oPage, $sClass)
{
$bSkipLinkingClasses = false;
$aRefs = MetaModel::EnumReferencingClasses($sClass, $bSkipLinkingClasses);
if (count($aRefs) != 0)
{
$oPage->add("<ul>\n");
foreach ($aRefs as $sRemoteClass => $aRemoteKeys)
{
foreach ($aRemoteKeys as $sExtKeyAttCode)
{
$oPage->add("<li>".MakeClassHLink($sRemoteClass)." by <em>$sExtKeyAttCode</em></li>\n");
}
}
$oPage->add("</ul>\n");
}
}
/**
* Helper for the global list and the details of a given class
*/
function DisplayLinkingClasses($oPage, $sClass)
{
$bSkipLinkingClasses = false;
$aRefs = MetaModel::EnumLinkingClasses($sClass);
if (count($aRefs) != 0)
{
$oPage->add("<ul>\n");
foreach ($aRefs as $sLinkClass => $aRemoteClasses)
{
foreach($aRemoteClasses as $sExtKeyAttCode => $sRemoteClass)
{
$oPage->add("<li>".MakeClassHLink($sRemoteClass)." by <em>".MakeClassHLink($sLinkClass)."::$sExtKeyAttCode</em></li>\n");
}
}
$oPage->add("</ul>\n");
}
}
/**
* Helper for the global list and the details of a given class
*/
function DisplayRelatedClassesBestInClass($oPage, $sClass, $iLevels = 20, &$aVisitedClasses = array(), $bSubtree = true)
{
if ($iLevels <= 0) return;
$iLevels--;
if (array_key_exists($sClass, $aVisitedClasses)) return;
$aVisitedClasses[$sClass] = true;
if ($bSubtree) $oPage->add("<ul class=\"treeview\">\n");
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
DisplayRelatedClassesBestInClass($oPage, $sParentClass, $iLevels, $aVisitedClasses, false);
}
////$oPage->add("<div style=\"background-color:#ccc; border: 1px dashed #333;\">");
foreach (MetaModel::EnumReferencedClasses($sClass) as $sExtKeyAttCode => $sRemoteClass)
{
$sVisited = (array_key_exists($sRemoteClass, $aVisitedClasses)) ? " ..." : "";
if (MetaModel::GetAttributeOrigin($sClass, $sExtKeyAttCode) == $sClass)
{
$oPage->add("<li>$sClass| <em>$sExtKeyAttCode</em> =&gt;".MakeClassHLink($sRemoteClass)."$sVisited</li>\n");
DisplayRelatedClassesBestInClass($oPage, $sRemoteClass, $iLevels, $aVisitedClasses);
}
}
foreach (MetaModel::EnumReferencingClasses($sClass) as $sRemoteClass => $aRemoteKeys)
{
foreach ($aRemoteKeys as $sExtKeyAttCode)
{
$sVisited = (array_key_exists($sRemoteClass, $aVisitedClasses)) ? " ..." : "";
$oPage->add("<li>$sClass| &lt;=".MakeClassHLink($sRemoteClass)."::<em>$sExtKeyAttCode</em>$sVisited</li>\n");
DisplayRelatedClassesBestInClass($oPage, $sRemoteClass, $iLevels, $aVisitedClasses);
}
}
////$oPage->add("</div>");
if ($bSubtree) $oPage->add("</ul>\n");
}
/**
* Helper for the list of classes related to the given class
*/
function DisplayRelatedClasses($oPage, $sClass)
{
$oPage->add("<h3>Childs</h3>\n");
DisplaySubclasses($oPage, $sClass);
$oPage->add("<h3>Pointed to by...</h3>\n");
DisplayReferencingClasses($oPage, $sClass);
$oPage->add("<h3>Linked to ...</h3>\n");
DisplayLinkingClasses($oPage, $sClass);
$oPage->add("<h3>ZE Graph ...</h3>\n");
DisplayRelatedClassesBestInClass($oPage, $sClass, 4);
}
/**
* Helper for the lifecycle details of a given class
*/
function DisplayLifecycle($oPage, $sClass)
{
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
if (empty($sStateAttCode))
{
$oPage->p("no lifecycle for this class");
}
else
{
$aStates = MetaModel::EnumStates($sClass);
$aStimuli = MetaModel::EnumStimuli($sClass);
$oPage->add("<img src=\"/pages/graphviz.php?class=$sClass\">\n");
$oPage->add("<h3>Transitions</h3>\n");
$oPage->add("<ul>\n");
foreach ($aStates as $sStateCode => $aStateDef)
{
$sStateLabel = $aStates[$sStateCode]['label'];
$sStateDescription = $aStates[$sStateCode]['description'];
$oPage->add("<li title=\"code: $sStateCode\">$sStateLabel <span style=\"color:grey;\">($sStateDescription)</span></li>\n");
$oPage->add("<ul>\n");
foreach(MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef)
{
$sStimulusLabel = $aStimuli[$sStimulusCode]->Get('label');
$sTargetStateLabel = $aStates[$aTransitionDef['target_state']]['label'];
if (count($aTransitionDef['actions']) > 0)
{
$sActions = " <em>(".implode(', ', $aTransitionDef['actions']).")</em>";
}
else
{
$sActions = "";
}
$oPage->add("<li><span style=\"color:red;font-weight=bold;\">$sStimulusLabel</span> =&gt; $sTargetStateLabel $sActions</li>\n");
}
$oPage->add("</ul>\n");
}
$oPage->add("</ul>\n");
$oPage->add("<h3>Attribute options</h3>\n");
$oPage->add("<ul>\n");
foreach ($aStates as $sStateCode => $aStateDef)
{
$sStateLabel = $aStates[$sStateCode]['label'];
$sStateDescription = $aStates[$sStateCode]['description'];
$oPage->add("<li title=\"code: $sStateCode\">$sStateLabel <span style=\"color:grey;\">($sStateDescription)</span></li>\n");
if (count($aStates[$sStateCode]['attribute_list']) > 0)
{
$oPage->add("<ul>\n");
foreach($aStates[$sStateCode]['attribute_list'] as $sAttCode => $iOptions)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sAttLabel = $oAttDef->GetLabel();
$aOptions = array();
if ($iOptions & OPT_ATT_HIDDEN) $aOptions[] = 'Hidden';
if ($iOptions & OPT_ATT_READONLY) $aOptions[] = 'Read-only';
if ($iOptions & OPT_ATT_MANDATORY) $aOptions[] = 'Mandatory';
if ($iOptions & OPT_ATT_MUSTCHANGE) $aOptions[] = 'Must change';
if ($iOptions & OPT_ATT_MUSTPROMPT) $aOptions[] = 'Must be proposed for changing';
if (count($aOptions))
{
$sOptions = implode(', ', $aOptions);
}
else
{
$sOptions = "";
}
$oPage->add("<li><span style=\"color:purple;font-weight=bold;\">$sAttLabel</span> $sOptions</li>\n");
}
$oPage->add("</ul>\n");
}
else
{
$oPage->p("<em>empty list</em>");
}
}
$oPage->add("</ul>\n");
}
}
/**
* Display the list of classes from the business model
*/
function DisplayClassesList($oPage)
{
$oPage->add("<h1>iTop objects schema</h1>\n");
$oPage->add("<ul id=\"ClassesList\" class=\"treeview fileview\">\n");
foreach(MetaModel::EnumCategories() as $sCategory)
{
if (empty($sCategory)) continue; // means 'all' -> skip
$sClosed = ($sCategory == 'bizmodel') ? '' : ' class="closed"';
$oPage->add("<li$sClosed>Category <b>$sCategory</b>\n");
$oPage->add("<ul>\n");
foreach(MetaModel::GetClasses($sCategory) as $sClassName)
{
if (MetaModel::IsStandaloneClass($sClassName))
{
$oPage->add("<li>".MakeClassHLink($sClassName)."</li>\n");
}
else if (MetaModel::IsRootClass($sClassName))
{
$oPage->add("<li class=\"closed\">".MakeClassHLink($sClassName)."\n");
DisplaySubclasses($oPage, $sClassName);
$oPage->add("</li>\n");
}
}
$oPage->add("</ul>\n");
$oPage->add("</li>\n");
}
$oPage->add("</ul>\n");
$oPage->add("<h1>Relationships</h1>\n");
$oPage->add("<ul id=\"ClassesRelationships\" class=\"treeview\">\n");
foreach (MetaModel::EnumRelations() as $sRelCode)
{
$oPage->add("<li>".MakeRelationHLink($sRelCode)."\n");
$oPage->add("<ul>\n");
foreach (MetaModel::EnumRelationProperties($sRelCode) as $sProp => $sValue)
{
$oPage->add("<li>$sProp: ".htmlentities($sValue)."</li>\n");
}
$oPage->add("</ul>\n");
$oPage->add("</li>\n");
}
$oPage->add("</ul>\n");
$oPage->add_ready_script('$("#ClassesList").treeview();');
$oPage->add_ready_script('$("#ClassesRelationships").treeview();');
}
/**
* Display the details of a given class of objects
*/
function DisplayClassDetails($oPage, $sClass)
{
$oPage->p("<h2>$sClass</h2><br/>\n".MetaModel::GetClassDescription($sClass)."<br/>\n");
$oPage->p("<h3>Class Hierarchy</h3>");
$oPage->p("[<a href=\"?operation='list'\">All classes</a>]");
// List the parent classes
$sParent = MetaModel::GetParentPersistentClass($sClass);
$aParents = array();
$aParents[] = $sClass;
while($sParent != "" && $sParent != 'cmdbAbstractObject')
{
$aParents[] = $sParent;
$sParent = MetaModel::GetParentPersistentClass($sParent);
}
$iIndex = count($aParents);
$sSpace ="";
$oPage->add("<ul id=\"ClassHierarchy\">");
while ($iIndex > 0)
{
$iIndex--;
$oPage->add("<li>".MakeClassHLink($aParents[$iIndex])."\n");
$oPage->add("<ul>\n");
}
for($iIndex = 0; $iIndex < count($aParents); $iIndex++)
{
$oPage->add("</ul>\n</li>\n");
}
$oPage->add("</ul>\n");
$oPage->add_ready_script('$("#ClassHierarchy").treeview();');
$oPage->p('');
$oPage->AddTabContainer('details');
$oPage->SetCurrentTabContainer('details');
// List the attributes of the object
$aDetails = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
{
if ($oAttDef->IsExternalKey())
{
$sValue = "External key to ".MakeClassHLink($oAttDef->GetTargetClass());
}
else
{
$sValue = $oAttDef->GetDescription();
}
$sType = $oAttDef->GetType().' ('.$oAttDef->GetTypeDesc().')';
$sOrigin = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
$sAllowedValues = "";
$oAllowedValuesDef = $oAttDef->GetValuesDef();
$sMoreInfo = "";
if (is_subclass_of($oAttDef, 'AttributeDBFieldVoid'))
{
$aMoreInfo = array();
$aMoreInfo[] = "Column: <em>".$oAttDef->GetSQLExpr()."</em>";
$aMoreInfo[] = "Default: '".$oAttDef->GetDefaultValue()."'";
$aMoreInfo[] = $oAttDef->IsNullAllowed() ? "Null allowed" : "Null NOT allowed";
//$aMoreInfo[] = $oAttDef->DBGetUsedFields();
$sMoreInfo .= implode(', ', $aMoreInfo);
}
if (is_object($oAllowedValuesDef)) $sAllowedValues = $oAllowedValuesDef->GetValuesDescription();
else $sAllowedValues = '';
$aDetails[] = array('code' => $oAttDef->GetCode(), 'type' => $sType, 'origin' => $sOrigin, 'label' => $oAttDef->GetLabel(), 'description' => $sValue, 'values' => $sAllowedValues, 'moreinfo' => $sMoreInfo);
}
$oPage->SetCurrentTab('Attributes');
$aConfig = array( 'code' => array('label' => 'Attribute code', 'description' => 'Code of this attribute'),
'label' => array('label' => 'Label', 'description' => 'Label of this attribute'),
'type' => array('label' => 'Type', 'description' => 'Data type of this attribute'),
'origin' => array('label' => 'Origin', 'description' => 'The base class for this attribute'),
'description' => array('label' => 'Description', 'description' => 'Description of this attribute'),
'values' => array('label' => 'Allowed Values', 'description' => 'Restrictions on the possible values for this attribute'),
'moreinfo' => array('label' => 'More info', 'description' => 'More info for the fields related to a Database field'),
);
$oPage->table($aConfig, $aDetails);
// List the search criteria for this object
$aDetails = array();
foreach (MetaModel::GetClassFilterDefs($sClass) as $sFilterCode => $oFilterDef)
{
$aOpDescs = array();
foreach ($oFilterDef->GetOperators() as $sOpCode => $sOpDescription)
{
$sIsTheLooser = ($sOpCode == $oFilterDef->GetLooseOperator()) ? " (loose search)" : "";
$aOpDescs[] = "$sOpCode ($sOpDescription)$sIsTheLooser";
}
$aDetails[] = array( 'code' => $sFilterCode, 'description' => $oFilterDef->GetLabel(),'operators' => implode(" / ", $aOpDescs));
}
$oPage->SetCurrentTab('Search criteria');
$aConfig = array( 'code' => array('label' => 'Filter code', 'description' => 'Code of this search criteria'),
'description' => array('label' => 'Description', 'description' => 'Description of this search criteria'),
'operators' => array('label' => 'Available operators', 'description' => 'Possible operators for this search criteria')
);
$oPage->table($aConfig, $aDetails);
$oPage->SetCurrentTab('Child classes');
DisplaySubclasses($oPage, $sClass);
$oPage->SetCurrentTab('Referencing classes');
DisplayReferencingClasses($oPage, $sClass);
$oPage->SetCurrentTab('Related classes');
DisplayRelatedClasses($oPage, $sClass);
$oPage->SetCurrentTab('Lifecycle');
DisplayLifecycle($oPage, $sClass);
$oPage->SetCurrentTab();
$oPage->SetCurrentTabContainer();
}
/**
* Display the details of a given relation (e.g. "impacts")
*/
function DisplayRelationDetails($oPage, $sRelCode)
{
$sDesc = MetaModel::GetRelationProperty($sRelCode, 'description');
$sVerbDown = MetaModel::GetRelationProperty($sRelCode, 'verb_down');
$sVerbUp = MetaModel::GetRelationProperty($sRelCode, 'verb_up');
$oPage->add("<h1>Relation <em>$sRelCode</em> ($sDesc)</h1>");
$oPage->p("Down: $sVerbDown");
$oPage->p("Up: $sVerbUp");
$oPage->add("<ul id=\"RelationshipDetails\" class=\"treeview\">\n");
foreach(MetaModel::GetClasses() as $sClass)
{
$aRelQueries = MetaModel::EnumRelationQueries($sClass, $sRelCode);
if (count($aRelQueries) > 0)
{
$oPage->add("<li>class ".MakeClassHLink($sClass)."\n");
$oPage->add("<ul>\n");
foreach ($aRelQueries as $sRelKey => $aQuery)
{
$sQuery = $aQuery['sQuery'];
$bPropagate = $aQuery['bPropagate'] ? "Propagate" : "Do not propagate";
$iDistance = $aQuery['iDistance'];
$oPage->add("<li>$sRelKey: $bPropagate ($iDistance) ".DBObjectSearch::SibuSQLAsHtml($sQuery)."</li>\n");
}
$oPage->add("</ul>\n");
$oPage->add("</li>\n");
}
}
$oPage->add_ready_script('$("#RelationshipDetails").treeview();');
}
require_once('../application/loginwebpage.class.inc.php');
login_web_page::DoLogin(); // Check user rights and prompt if needed
// Display the menu on the left
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', -1);
$currentOrganization = utils::ReadParam('org_id', 1);
$operation = utils::ReadParam('operation', '');
$oPage = new iTopWebPage("iTop objects schema", $currentOrganization);
$oPage->no_cache();
$operation = utils::ReadParam('operation', '');
switch($operation)
{
case 'details_class':
$sClass = utils::ReadParam('class', 'logRealObject');
DisplayClassDetails($oPage, $sClass);
break;
case 'details_relation':
$sRelCode = utils::ReadParam('relcode', '');
DisplayRelationDetails($oPage, $sRelCode);
break;
case 'details':
$oPage->p('operation=details has been deprecated, please use details_class');
break;
case 'list':
default:
DisplayClassesList($oPage);
}
$oPage->output();
?>

57
trunk/pages/sibusql.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
require_once('../application/application.inc.php');
require_once('../application/itopwebpage.class.inc.php');
require_once('../application/startup.inc.php');
require_once('../application/loginwebpage.class.inc.php');
login_web_page::DoLogin(); // Check user rights and prompt if needed
$sOperation = utils::ReadParam('operation', 'menu');
$oContext = new UserContext();
$oAppContext = new ApplicationContext();
$iActiveNodeId = utils::ReadParam('menu', -1);
$currentOrganization = utils::ReadParam('org_id', '');
$oP = new iTopWebPage("iTop - Expression Evaluation", $currentOrganization);
// Main program
$sExpression = utils::ReadParam('expression', '');
$sEncoding = utils::ReadParam('encoding', 'oql');
if ($sEncoding == 'crypted')
{
// Translate $sExpression into a oql expression
$sClearText = base64_decode($sExpression);
echo "<strong>FYI: '$sClearText'</strong><br/>\n";
$oFilter = DBObjectSearch::unserialize($sExpression);
$sExpression = $oFilter->ToOQL();
exit;
}
else
{
// leave $sExpression as is
}
$oP->add('<form method="get">'."\n");
$oP->add('Expression to evaluate:<br/>'."\n");
$oP->add('<textarea cols="50" rows="20" name="expression">'.$sExpression.'</textarea>'."<p> Example:<br/>SELECT bizPerson AS B WHERE B.name LIKE '%A%'</p>\n");
$oP->add('<input type="submit" value=" Evaluate ">'."\n");
$oP->add('</form>'."\n");
if (!empty($sExpression))
{
$oFilter = DBObjectSearch::FromOQL($sExpression);
if ($oFilter)
{
$oP->p('Query expression: '.$oFilter->ToOQL());
$oP->p('Serialized filter: '.$oFilter->serialize());
$oSet = new CMDBObjectSet($oFilter);
$oP->p('The query returned '.$oSet->count().' results(s)');
cmdbAbstractObject::DisplaySet($oP, $oSet);
}
}
$oP->output();
?>

126
trunk/pages/test.php Normal file
View File

@@ -0,0 +1,126 @@
<?php
///////////////////////////////////////////////////////////////////////////////
// Helpers
///////////////////////////////////////////////////////////////////////////////
function ReadMandatoryParam($sName)
{
$value = utils::ReadParam($sName, null);
if (is_null($value))
{
echo "<p>Missing mandatory argument <b>$sName</b></p>";
exit;
}
return $value;
}
function IsAValidTestClass($sClassName)
{
// Must be a child of TestHandler
//
if (!is_subclass_of($sClassName, 'TestHandler')) return false;
// Must not be abstract
//
$oReflectionClass = new ReflectionClass($sClassName);
if (!$oReflectionClass->isInstantiable()) return false;
return true;
}
function DisplayEvents($aEvents, $sTitle)
{
echo "<h4>$sTitle</h4>\n";
if (count($aEvents) > 0)
{
echo "<ul>\n";
foreach ($aEvents as $sEvent)
{
echo "<li>$sEvent</li>\n";
}
echo "</ul>\n";
}
else
{
echo "<p>none</p>\n";
}
}
///////////////////////////////////////////////////////////////////////////////
// Main
///////////////////////////////////////////////////////////////////////////////
require_once('../application/utils.inc.php');
require_once('../core/test.class.inc.php');
require_once('testlist.inc.php');
require_once('../core/cmdbobject.class.inc.php');
$sTodo = utils::ReadParam("todo", "");
if ($sTodo == '')
{
// Show the list of tests
//
echo "<h3>Existing tests</h3>\n";
echo "<ul>\n";
foreach (get_declared_classes() as $sClassName)
{
if (!IsAValidTestClass($sClassName)) continue;
$sName = call_user_func(array($sClassName, 'GetName'));
$sDescription = call_user_func(array($sClassName, 'GetDescription'));
echo "<li><a href=\"?todo=exec&testid=$sClassName\">$sName</a> ($sDescription)</li\n";
}
echo "</ul>\n";
}
else if ($sTodo == 'exec')
{
// Execute a test
//
$sTestClass = ReadMandatoryParam("testid");
if (!IsAValidTestClass($sTestClass))
{
echo "<p>Wrong value for testid, expecting a valid class name</p>\n";
}
else
{
$oTest = new $sTestClass();
echo "<h3>Testing: ".$oTest->GetName()."</h3>\n";
$bRes = $oTest->Execute();
}
/*
MyHelpers::var_dump_html($oTest->GetResults());
MyHelpers::var_dump_html($oTest->GetWarnings());
MyHelpers::var_dump_html($oTest->GetErrors());
*/
if ($bRes)
{
echo "<p>Success :-)</p>\n";
DisplayEvents($oTest->GetResults(), 'Results');
}
else
{
echo "<p>Failure :-(</p>\n";
}
DisplayEvents($oTest->GetErrors(), 'Errors');
DisplayEvents($oTest->GetWarnings(), 'Warnings');
// Render the output
//
echo "<h4>Actual output</h4>\n";
echo "<div style=\"border: dashed; background-color:light-grey;\">\n";
echo $oTest->GetOutput();
echo "</div>\n";
}
else
{
}
?>

1132
trunk/pages/testlist.inc.php Normal file

File diff suppressed because it is too large Load Diff