123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580 |
- <?php
- // Copyright (C) 2010 Combodo SARL
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; version 3 of the License.
- //
- // This program 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 General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- /**
- * ITop consultant home page
- * tool box
- * object model analysis
- * DB integrity check and repair
- *
- * @author Erwan Taloc <erwan.taloc@combodo.com>
- * @author Romain Quetiez <romain.quetiez@combodo.com>
- * @author Denis Flaven <denis.flaven@combodo.com>
- * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
- */
- 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["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(false))
- {
- $sRes .= "<p>It appears that the DB already exists (at least one table).</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()
- }
- function DumpDatabase()
- {
- $aData = MetaModel::DBDump();
- foreach ($aData as $sTable => $aRows)
- {
- echo "<h1>".htmlentities($sTable)."</h1>\n";
- if (count($aRows) == 0)
- {
- echo "<p>no data</p>\n";
- }
- else
- {
- echo "<p>".count($aRows)." row(s)</p>\n";
- // Table header
- echo "<table border=\"1\">\n";
- echo "<tr>\n";
- foreach (reset($aRows) as $key => $value)
- {
- echo "<th>".htmlentities($key)."</th>";
- }
- echo "</tr>\n";
-
- // Table body
- foreach ($aRows as $aRow)
- {
- echo "<tr>\n";
- foreach ($aRow as $key => $value)
- {
- echo "<td>".htmlentities($value)."</td>";
- }
- echo "</tr>\n";
- }
-
- echo "</table>\n";
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // Helper functions
- /////////////////////////////////////////////////////////////////////////////////////
- function printMenu($sConfigFile)
- {
- $sClassCount = count(MetaModel::GetClasses());
- $bHasDB = MetaModel::DBExists(false); // no need to be complete to consider that something already exists
- $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=checkdictionary&categories=bizmodel&outputfilter=NotInDictionary\">Dictionary - missing entries (EN US)</a></li>";
- echo " <li><a href=\"$sUrl&todo=dictionarystats\">Dictionary - statistics by language</a></li>";
- 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 <b>DB format</b></a></li>";
- echo " <li><a href=\"$sUrl&todo=checkmodeltoviews\">Concordance between Biz model and <b>Views</b></a></li>";
- echo " <li><a href=\"$sUrl&todo=checkdb\">DB integrity check</a></li>";
- echo " <li><a href=\"$sUrl&todo=checkall\">Any check at once (see list above)</a></li>";
- echo " <li><a href=\"$sUrl&todo=userrightssetup\">Setup userrights (init DB)</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><a href=\"$sUrl&todo=dumpdb\">Dump database</a></li>";
- // echo " <li>".htmlentities($sUrl)."&<b>todo=execsql</b>&<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 => $aTarget)
- {
- echo "<p>Wrong declaration (or DB format ?) for class <b>$sClass</b></p>\n";
- echo "<ul class=\"treeview\">\n";
- $i = 0;
- foreach ($aTarget as $sTarget => $aMessages)
- {
- if ($sTarget != '*')
- {
- echo "<p>Wrong declaration for attribute <b>$sTarget</b></p>\n";
- }
- $sMsg = implode(' AND ', $aMessages);
- if (!empty($sRepairUrl))
- {
- $aSQLFixes = array_merge($aSQLFixes, $aSugFix[$sClass][$sTarget]);
- $aCleanFixes = array();
- foreach($aSugFix[$sClass][$sTarget] as $sSQLFix)
- {
- if (!empty($sSQLFix))
- {
- $aCleanFixes[] = $sSQLFix;
- }
- }
- if (count($aCleanFixes) > 0)
- {
- $sSQLFixes = implode('; ', $aCleanFixes);
- $sUrl = "$sRepairUrl&$sSQLStatementArgName=".urlencode($sSQLFixes);
- echo "<li>$sMsg (<a href=\"$sUrl\" title=\"".htmlentities($sSQLFixes)."\" target=\"_blank\">fix it now!</a>)</li>\n";
- }
- else
- {
- echo "<li>$sMsg</li>\n";
- }
- }
- else
- {
- echo "<li>$sMsg (".htmlentities($sSQLFixes).")</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 "dictionarystats":
- echo "Dictionary: statistics by language<br/>\n";
- foreach (Dict::GetLanguages() as $sLanguageCode => $aLanguageData)
- {
- list($aMissing, $aUnexpected, $aNotTranslated, $aOK) = Dict::MakeStats($sLanguageCode, 'EN US');
- echo "<p>Stats for language: $sLanguageCode</p>\n";
- echo "<ul><li>Missing:".count($aMissing)."</li><li>Unexpected:".count($aUnexpected)."</li><li>NotTranslated:".count($aNotTranslated)."</li><li>OK:".count($aOK)."</li></ul>\n";
- }
- break;
- case "checkdictionary":
- $sCategories = ReadMandatoryParam("categories");
- $sOutputFilter = ReadParam("outputfilter", '');
- echo "Dictionary: missing entries (categories: $sCategories, output: '$sOutputFilter')</br>\n";
- echo "<pre>\n";
- echo MetaModel::MakeDictionaryTemplate($sCategories, $sOutputFilter);
- echo "</pre>\n";
- 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 "checkmodeltoviews":
- echo "Check Views...</br>\n";
- list($aErrors, $aSugFix) = MetaModel::DBCheckViews();
- 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 "dumpdb":
- echo "Dump DB data...</br>\n";
- DumpDatabase();
- 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 Views...</br>\n";
- list($aErrors, $aSugFix) = MetaModel::DBCheckViews();
- 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;
- }
- }
- ?>
|