commit 02a9fe642982e570f7a11aec945b3f8d74525ded Author: Denis Flaven Date: Fri Mar 13 16:49:47 2009 +0000 Initial import on SourceForge SVN:code[1] diff --git a/addons/userrights/userrightsmatrix.class.inc.php b/addons/userrights/userrightsmatrix.class.inc.php new file mode 100644 index 000000000..cb9d0fab1 --- /dev/null +++ b/addons/userrights/userrightsmatrix.class.inc.php @@ -0,0 +1,340 @@ + + * @author Denis Flaven + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.itop.com + * @since 1.0 + * @version 1.1.1.1 $ + */ + + +class UserRightsMatrixUsers extends DBObject +{ + public static function Init() + { + $aParams = array + ( + "category" => "addon/userrights", + "name" => "user", + "description" => "users and credentials", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "login", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_ur_matrixusers", + "db_key_field" => "id", + "db_finalclass_field" => "", + ); + MetaModel::Init_Params($aParams); + //MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeInteger("userid", array("label"=>"User id", "description"=>"User identifier (depends on the business model)", "allowed_values"=>null, "sql"=>"userid", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("login", array("label"=>"login", "description"=>"user identification string", "allowed_values"=>null, "sql"=>"login", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("password", array("label"=>"password", "description"=>"user authentication string", "allowed_values"=>null, "sql"=>"pwd", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + //MetaModel::Init_InheritFilters(); + MetaModel::Init_AddFilterFromAttribute("userid"); + MetaModel::Init_AddFilterFromAttribute("login"); + } +} + +class UserRightsMatrixClassGrant extends DBObject +{ + public static function Init() + { + $aParams = array + ( + "category" => "addon/userrights", + "name" => "change", + "description" => "permissions on classes", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_ur_matrixclasses", + "db_key_field" => "id", + "db_finalclass_field" => "", + ); + MetaModel::Init_Params($aParams); + //MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"UserRightsMatrixUsers", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("label"=>"Login", "description"=>"Login", "allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); + MetaModel::Init_AddAttribute(new AttributeString("class", array("label"=>"class", "description"=>"class name", "allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + MetaModel::Init_AddAttribute(new AttributeString("action", array("label"=>"action", "description"=>"operations to perform on the given class", "allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("label"=>"permission", "description"=>"allowed or not allowed?", "allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); + + //MetaModel::Init_InheritFilters(); + MetaModel::Init_AddFilterFromAttribute("userid"); + MetaModel::Init_AddFilterFromAttribute("login"); + MetaModel::Init_AddFilterFromAttribute("class"); + MetaModel::Init_AddFilterFromAttribute("action"); + } +} + +class UserRightsMatrixClassStimulusGrant extends DBObject +{ + public static function Init() + { + $aParams = array + ( + "category" => "addon/userrights", + "name" => "change", + "description" => "permissions on classes (stimulus on state machine)", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_ur_matrixclassesstimulus", + "db_key_field" => "id", + "db_finalclass_field" => "", + ); + MetaModel::Init_Params($aParams); + //MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"UserRightsMatrixUsers", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("label"=>"Login", "description"=>"Login", "allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); + MetaModel::Init_AddAttribute(new AttributeString("class", array("label"=>"class", "description"=>"class name", "allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + MetaModel::Init_AddAttribute(new AttributeString("stimulus", array("label"=>"action", "description"=>"operations to perform on the given class", "allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("label"=>"permission", "description"=>"allowed or not allowed?", "allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); + + //MetaModel::Init_InheritFilters(); + MetaModel::Init_AddFilterFromAttribute("userid"); + MetaModel::Init_AddFilterFromAttribute("login"); + MetaModel::Init_AddFilterFromAttribute("class"); + MetaModel::Init_AddFilterFromAttribute("stimulus"); + } +} + +class UserRightsMatrixAttributeGrant extends DBObject +{ + public static function Init() + { + $aParams = array + ( + "category" => "addon/userrights", + "name" => "change", + "description" => "permissions on classes", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_ur_matrixattributes", + "db_key_field" => "id", + "db_finalclass_field" => "", + ); + MetaModel::Init_Params($aParams); + //MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeExternalKey("userid", array("targetclass"=>"UserRightsMatrixUsers", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"userid", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeExternalField("login", array("label"=>"Login", "description"=>"Login", "allowed_values"=>null, "extkey_attcode"=> 'userid', "target_attcode"=>"login"))); + MetaModel::Init_AddAttribute(new AttributeString("class", array("label"=>"class", "description"=>"class name", "allowed_values"=>null, "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("attcode", array("label"=>"attribute", "description"=>"attribute code", "allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + MetaModel::Init_AddAttribute(new AttributeString("action", array("label"=>"action", "description"=>"operations to perform on the given class", "allowed_values"=>null, "sql"=>"action", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("label"=>"permission", "description"=>"allowed or not allowed?", "allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array()))); + + //MetaModel::Init_InheritFilters(); + MetaModel::Init_AddFilterFromAttribute("userid"); + MetaModel::Init_AddFilterFromAttribute("login"); + MetaModel::Init_AddFilterFromAttribute("class"); + MetaModel::Init_AddFilterFromAttribute("attcode"); + MetaModel::Init_AddFilterFromAttribute("action"); + } +} + + + + +class UserRightsMatrix extends UserRightsAddOnAPI +{ + static public $m_aActionCodes = array( + UR_ACTION_READ => 'read', + UR_ACTION_MODIFY => 'modify', + UR_ACTION_DELETE => 'delete', + UR_ACTION_BULK_READ => 'bulk read', + UR_ACTION_BULK_MODIFY => 'bulk modify', + UR_ACTION_BULK_DELETE => 'bulk delete', + ); + + public function Setup() + { + // Users must be added manually + // This procedure will then update the matrix when a new user is found or a new class/attribute appears + $oUserSet = new DBObjectSet(DBObjectSearch::FromSibuSQL("UserRightsMatrixUsers")); + while ($oUser = $oUserSet->Fetch()) + { + $iUserId = $oUser->GetKey(); + foreach (MetaModel::GetClasses('bizmodel') as $sClass) + { + foreach (self::$m_aActionCodes as $iActionCode => $sAction) + { + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant AS cg WHERE cg.class = '$sClass' AND cg.action = '$sAction' AND cg.userid = $iUserId")); + if ($oSet->Count() < 1) + { + // Create a new entry + $oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant"); + $oMyClassGrant->Set("userid", $oUser->GetKey()); + $oMyClassGrant->Set("class", $sClass); + $oMyClassGrant->Set("action", $sAction); + $oMyClassGrant->Set("permission", "yes"); + $iId = $oMyClassGrant->DBInsert(); + } + } + foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) + { + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant AS sg WHERE sg.class = '$sClass' AND sg.stimulus = '$sStimulusCode' AND sg.userid = $iUserId")); + if ($oSet->Count() < 1) + { + // Create a new entry + $oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant"); + $oMyClassGrant->Set("userid", $oUser->GetKey()); + $oMyClassGrant->Set("class", $sClass); + $oMyClassGrant->Set("stimulus", $sStimulusCode); + $oMyClassGrant->Set("permission", "yes"); + $iId = $oMyClassGrant->DBInsert(); + } + } + foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) + { + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE UserRightsMatrixAttributeGrant.class = '$sClass' AND UserRightsMatrixAttributeGrant.attcode = '$sAttCode' AND UserRightsMatrixAttributeGrant.userid = $iUserId")); + if ($oSet->Count() < 1) + { + foreach (array('read', 'modify') as $sAction) + { + // Create a new entry + $oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant"); + $oMyAttGrant->Set("userid", $oUser->GetKey()); + $oMyAttGrant->Set("class", $sClass); + $oMyAttGrant->Set("attcode", $sAttCode); + $oMyAttGrant->Set("action", $sAction); + $oMyAttGrant->Set("permission", "yes"); + $iId = $oMyAttGrant->DBInsert(); + } + } + } + } + } + return true; + } + + public function Init() + { + // Could be loaded in a shared memory (?) + return true; + } + + public function CheckCredentials($sUserName, $sPassword) + { + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixUsers WHERE UserRightsMatrixUsers.login = '$sUserName'")); + if ($oSet->Count() < 1) + { + // todo: throw an exception? + return false; + } + + $oLogin = $oSet->Fetch(); + if ($oLogin->Get('password') == $sPassword) + { + return true; + } + // todo: throw an exception? + return false; + } + + public function GetFilter($sUserName, $sClass) + { + $oNullFilter = new DBObjectSearch($sClass); + return $oNullFilter; + } + + public function IsActionAllowed($sUserName, $sClass, $iActionCode, dbObjectSet $aInstances) + { + if (!array_key_exists($iActionCode, self::$m_aActionCodes)) + { + return UR_ALLOWED_NO; + } + $sAction = self::$m_aActionCodes[$iActionCode]; + + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant AS cg WHERE cg.class = '$sClass' AND cg.action = '$sAction' AND cg.login = '$sUserName'")); + if ($oSet->Count() < 1) + { + return UR_ALLOWED_NO; + } + + $oGrantRecord = $oSet->Fetch(); + switch ($oGrantRecord->Get('permission')) + { + case 'yes': + $iRetCode = UR_ALLOWED_YES; + break; + case 'no': + default: + $iRetCode = UR_ALLOWED_NO; + break; + } + return $iRetCode; + } + + public function IsActionAllowedOnAttribute($sUserName, $sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances) + { + if (!array_key_exists($iActionCode, self::$m_aActionCodes)) + { + return UR_ALLOWED_NO; + } + $sAction = self::$m_aActionCodes[$iActionCode]; + + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE UserRightsMatrixAttributeGrant.class = '$sClass' AND UserRightsMatrixAttributeGrant.attcode = '$sAttCode' AND UserRightsMatrixAttributeGrant.action = '$sAction' AND UserRightsMatrixAttributeGrant.login = '$sUserName'")); + if ($oSet->Count() < 1) + { + return UR_ALLOWED_NO; + } + + $oGrantRecord = $oSet->Fetch(); + switch ($oGrantRecord->Get('permission')) + { + case 'yes': + $iRetCode = UR_ALLOWED_YES; + break; + case 'no': + default: + $iRetCode = UR_ALLOWED_NO; + break; + } + return $iRetCode; + } + + public function IsStimulusAllowed($sUserName, $sClass, $sStimulusCode, dbObjectSet $aInstances) + { + $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant AS sg WHERE sg.class = '$sClass' AND sg.stimulus = '$sStimulusCode' AND sg.login = '$sUserName'")); + if ($oSet->Count() < 1) + { + return UR_ALLOWED_NO; + } + + $oGrantRecord = $oSet->Fetch(); + switch ($oGrantRecord->Get('permission')) + { + case 'yes': + $iRetCode = UR_ALLOWED_YES; + break; + case 'no': + default: + $iRetCode = UR_ALLOWED_NO; + break; + } + return $iRetCode; + } +} + +UserRights::SelectModule('UserRightsMatrix'); + +?> diff --git a/addons/userrights/userrightsnull.class.inc.php b/addons/userrights/userrightsnull.class.inc.php new file mode 100644 index 000000000..28077c6f8 --- /dev/null +++ b/addons/userrights/userrightsnull.class.inc.php @@ -0,0 +1,58 @@ + + * @author Denis Flaven + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.itop.com + * @since 1.0 + * @version 1.1.1.1 $ + */ + + +class UserRightsNull extends UserRightsAddOnAPI +{ + public function Setup() + { + return true; + } + + public function Init() + { + return true; + } + + public function CheckCredentials($sUserName, $sPassword) + { + return true; + } + + public function GetFilter($sUserName, $sClass) + { + $oNullFilter = new DBObjectSearch($sClass); + return $oNullFilter; + } + + public function IsActionAllowed($sUserName, $sClass, $iActionCode, dbObjectSet $aInstances) + { + return UR_ALLOWED_YES; + } + + public function IsStimulusAllowed($sUserName, $sClass, $sStimulusCode, dbObjectSet $aInstances) + { + return UR_ALLOWED_YES; + } + + public function IsActionAllowedOnAttribute($sUserName, $sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances) + { + return UR_ALLOWED_YES; + } +} + +UserRights::SelectModule('UserRightsNull'); + +?> diff --git a/application/ajaxwebpage.class.inc.php b/application/ajaxwebpage.class.inc.php new file mode 100644 index 000000000..3d061f69a --- /dev/null +++ b/application/ajaxwebpage.class.inc.php @@ -0,0 +1,145 @@ + + * @author Denis Flaven + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + */ + +class ajax_page extends web_page +{ + /** + * Jquery style ready script + * @var Hash + */ + protected $m_sReadyScript; + + /** + * constructor for the web page + * @param string $s_title Not used + */ + function __construct($s_title) + { + parent::__construct($s_title); + $this->m_sReadyScript = ""; + } + + + /** + * Echoes the content of the whole page + * @return void + */ + public function output() + { + foreach($this->a_headers as $s_header) + { + header($s_header); + } + $s_captured_output = ob_get_contents(); + ob_end_clean(); + echo trim($this->s_content); + if (!empty($this->m_sReadyScript)) + { + echo "\n"; + } + if (trim($s_captured_output) != "") + { + echo $s_captured_output; + } + } + + /** + * Adds a paragraph with a smaller font into the page + * NOT implemented (i.e does nothing) + * @param string $sText Content of the (small) paragraph + * @return void + */ + public function small_p($sText) + { + } + + /** + * Adds a tabular content to the web page + * @param Hash $aConfig Configuration of the table: hash array of 'column_id' => 'Column Label' + * @param Hash $aData Hash array. Data to display in the table: each row is made of 'column_id' => Data. A column 'pkey' is expected for each row + * @param Hash $aParams Hash array. Extra parameters for the table. Entry 'class' holds the class of the objects listed in the table + * @return void + */ + public function table($aConfig, $aData, $aParams = array()) + { + // WARNING WARNING WARNING + // This whole function is actually a copy paste from iTopWebPage::table + $oAppContext = new ApplicationContext(); + + static $iNbTables = 0; + $iNbTables++; + $sHtml = ""; + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + foreach($aConfig as $sName=>$aDef) + { + $sHtml .= "\n"; + } + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + foreach($aData as $aRow) + { + if (false) //(isset($aParams['preview']) && $aParams['preview']) + { + $sHtml .= "\n"; + } + else if (isset($aRow['key'])) + { + $sHtml .= "\n"; + } + else + { + $sHtml .= "\n"; + } + foreach($aConfig as $sName=>$aVoid) + { + if ($sName != 'key') + { + $sValue = empty($aRow[$sName]) ? ' ' : $aRow[$sName]; + $sHtml .= "\n"; + } + else + { + $sUIPage = cmdbAbstractObject::ComputeUIPage($aParams['class']); + $sHtml .= "\n"; + } + } + $sHtml .= "\n"; + } + $sHtml .= "\n"; + $sHtml .= "
".$aDef['label']."
$sValueGetForLink()."\">
\n"; + if (isset($aParams['preview']) && $aParams['preview']) + { + $sHtml .= "
Preview Pane
"; + } + $this->add($sHtml); + } + /** + * Adds a script to be executed when the DOM is ready (typical JQuery use) + * NOT implemented in this version of the class. + * @return void + */ + public function add_ready_script($sScript) + { + // Does nothing in ajax rendered content.. for now... + // Maybe we should add this as a simple '); // TO DO: add support for $aExtraParams in asynchronous/Ajax mode + } + } + + public function GetDisplay(web_page $oPage, $sId, $aExtraParams = array()) + { + $sHtml = ''; + $aExtraParams = array_merge($aExtraParams, $this->m_aParams); + if (!$this->m_bAsynchronous) + { + // render now + $sHtml .= "
\n"; + $sHtml .= $this->GetRenderContent($oPage, $aExtraParams); + $sHtml .= "
\n"; + } + else + { + // render it as an Ajax (asynchronous) call + $sFilter = $this->m_oFilter->serialize(); + $sHtml .= "
\n"; + $sHtml .= $oPage->GetP(" Loading..."); + $sHtml .= "
\n"; + $sHtml .= ' + '; // TO DO: add support for $aExtraParams in asynchronous/Ajax mode + } + return $sHtml; + } + + public function RenderContent(web_page $oPage, $aExtraParams = array()) + { + $oPage->add($this->GetRenderContent($oPage, $aExtraParams)); + } + + public function GetRenderContent(web_page $oPage, $aExtraParams = array()) + { + $sHtml = ''; + // Add the extra params into the filter if they make sense for such a filter + $bDoSearch = utils::ReadParam('dosearch', false); + if ($this->m_oSet == null) + { + $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass())); + foreach($aFilterCodes as $sFilterCode) + { + $sExternalFilterValue = utils::ReadParam($sFilterCode, ''); + if (isset($aExtraParams[$sFilterCode])) + { + $this->m_oFilter->AddCondition($sFilterCode, $aExtraParams[$sFilterCode]); // Use the default 'loose' operator + } + else if ($bDoSearch && $sExternalFilterValue != "") + { + $this->m_oFilter->AddCondition($sFilterCode, $sExternalFilterValue); // Use the default 'loose' operator + } + } + $this->m_oSet = new CMDBObjectSet($this->m_oFilter); + } + switch($this->m_sStyle) + { + case 'count': + if (isset($aExtraParams['group_by'])) + { + $sGroupByField = $aExtraParams['group_by']; + $aGroupBy = array(); + while($oObj = $this->m_oSet->Fetch()) + { + $sValue = $oObj->Get($sGroupByField); + $aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1; + } + $sFilter = urlencode($this->m_oFilter->serialize()); + $aData = array(); + foreach($aGroupBy as $sValue => $iCount) + { + $aData[] = array ( 'group' => $sValue, + 'value' => "$iCount"); // TO DO: add the context information + } + $sHtml .= $oPage->GetTable(array('group' => array('label' => MetaModel::GetLabel($this->m_oFilter->GetClass(), $sGroupByField), 'description' => ''), 'value' => array('label'=>'Count', 'description' => 'Number of elements')), $aData); + } + else + { + // Simply count the number of elements in the set + $iCount = $oSet->Count(); + $sHtml .= $oPage->GetP("$iCount objects matching the criteria."); + } + + break; + + case 'list': + $bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false; + if ( ($this->m_oSet->Count()> 0) && (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) ) + { + if (!$bDashboardMode) + { + $sHtml .= $oPage->GetP($this->m_oSet->Count()." object(s)."); + } + $sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : ''; + $sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $sLinkage, !$bDashboardMode /* bDisplayMenu */); + } + else + { + $sHtml .= $oPage->GetP("No object to display."); + $sClass = $this->m_oFilter->GetClass(); + if (!$bDashboardMode) + { + if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES) + { + $sHtml .= $oPage->GetP("Click here to create a new ".Metamodel::GetName($sClass)."\n"); + } + } + } + break; + + case 'details': + if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) + { + while($oObj = $this->m_oSet->Fetch()) + { + $sHtml .= $oObj->GetDetails($oPage); + } + } + break; + + case 'bare_details': + if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) + { + while($oObj = $this->m_oSet->Fetch()) + { + $sHtml .= $oObj->GetBareDetails($oPage); + } + } + break; + + case 'csv': + if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) + { + $sHtml .= "\n"; + } + break; + + case 'modify': + if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES) + { + while($oObj = $this->m_oSet->Fetch()) + { + $sHtml .= $oObj->GetModifyForm($oPage); + } + } + break; + + case 'search': + $iSearchSectionId = 1; + $sStyle = (isset($aExtraParams['open']) && ($aExtraParams['open'] == 'true')) ? 'SearchDrawer' : 'SearchDrawer DrawerClosed'; + $sHtml .= "
\n"; + $sHtml .= "

Search form for ".Metamodel::GetName($this->m_oSet->GetClass())."

\n"; + $oPage->add_ready_script("\$(\"#LnkSearch_$iSearchSectionId\").click(function() {\$(\"#Search_$iSearchSectionId\").slideToggle('normal'); $(\"#LnkSearch_$iSearchSectionId\").toggleClass('open');});"); + $sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams); + $sHtml .= "
\n"; + $sHtml .= "
\n"; + $sHtml .= "
Search
\n"; + break; + + case 'pie_chart': + $sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : ''; + $sFilter = $this->m_oFilter->ToSibusQL(); + $sHtml .= " + + + + + + + + + "; + break; + + case 'pie_chart_ajax': + if (isset($aExtraParams['group_by'])) + { + $sGroupByField = $aExtraParams['group_by']; + $aGroupBy = array(); + while($oObj = $this->m_oSet->Fetch()) + { + $sValue = $oObj->Get($sGroupByField); + $aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1; + } + $sFilter = urlencode($this->m_oFilter->serialize()); + $aData = array(); + $sHtml .= "\n"; + $sHtml .= "3d pie\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + foreach($aGroupBy as $sValue => $void) + { + $sHtml .= "$sValue\n"; + } + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + foreach($aGroupBy as $void => $iCount) + { + $sHtml .= "$iCount\n"; + } + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= " + + + + ||||||||||||||||||||||||||||||||||||||||||||||| + + + + + + ddaa41 + 88dd11 + 4e62dd + ff8811 + 4d4d4d + 5a4b6e + 1188ff + + "; + $sHtml .= "\n"; + } + else + { + // Simply count the number of elements in the set + $iCount = $oSet->Count(); + $sHtml .= "\n\n"; + } + break; + + case 'open_flash_chart': + static $iChartCounter = 0; + $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie'; + $sTitle = isset($aExtraParams['chart_title']) ? $aExtraParams['chart_title'] : ''; + $sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : ''; + $sFilter = $this->m_oFilter->ToSibusQL(); + $sHtml .= "\n"; + $sHtml .= "
Here goes the chart
\n"; + $iChartCounter++; + break; + + case 'open_flash_chart_ajax': + include './php-ofc-library/open-flash-chart.php'; + $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie'; + + $oChart = new open_flash_chart(); + switch($sChartType) + { + case 'bars': + $oChartElement = new bar_glass(); + + if (isset($aExtraParams['group_by'])) + { + $sGroupByField = $aExtraParams['group_by']; + $aGroupBy = array(); + while($oObj = $this->m_oSet->Fetch()) + { + $sValue = $oObj->Get($sGroupByField); + $aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1; + } + $sFilter = urlencode($this->m_oFilter->serialize()); + $aData = array(); + $aLabels = array(); + foreach($aGroupBy as $sValue => $iValue) + { + $aData[] = $iValue; + $aLabels[] = $sValue; + } + $maxValue = max($aData); + $oYAxis = new y_axis(); + $aMagicValues = array(1,2,5,10); + $iMultiplier = 1; + $index = 0; + $iTop = $aMagicValues[$index % count($aMagicValues)]*$iMultiplier; + while($maxValue > $iTop) + { + $index++; + $iTop = $aMagicValues[$index % count($aMagicValues)]*$iMultiplier; + if (($index % count($aMagicValues)) == 0) + { + $iMultiplier = $iMultiplier * 10; + } + } + //echo "oYAxis->set_range(0, $iTop, $iMultiplier);\n"; + $oYAxis->set_range(0, $iTop, $iMultiplier); + $oChart->set_y_axis( $oYAxis ); + + $oChartElement->set_values( $aData ); + $oXAxis = new x_axis(); + $oXLabels = new x_axis_labels(); + // set them vertical + $oXLabels->set_vertical(); + // set the label text + $oXLabels->set_labels($aLabels); + // Add the X Axis Labels to the X Axis + $oXAxis->set_labels( $oXLabels ); + $oChart->set_x_axis( $oXAxis ); + } + break; + + case 'pie': + default: + $oChartElement = new pie(); + $oChartElement->set_start_angle( 35 ); + $oChartElement->set_animate( true ); + $oChartElement->set_tooltip( '#label# - #val# (#percent#)' ); + if (isset($aExtraParams['group_by'])) + { + $sGroupByField = $aExtraParams['group_by']; + $aGroupBy = array(); + while($oObj = $this->m_oSet->Fetch()) + { + $sValue = $oObj->Get($sGroupByField); + $aGroupBy[$sValue] = isset($aGroupBy[$sValue]) ? $aGroupBy[$sValue]+1 : 1; + } + $sFilter = urlencode($this->m_oFilter->serialize()); + $aData = array(); + foreach($aGroupBy as $sValue => $iValue) + { + $aData[] = new pie_value($iValue, $sValue); + } + + + $oChartElement->set_values( $aData ); + $oChart->x_axis = null; + } + } + if (isset($aExtraParams['chart_title'])) //@@ BUG: not passed via ajax !!! + { + $oTitle = new title( $aExtraParams['chart_title'] ); + $oChart->set_title( $oTitle ); + } + $oChart->set_bg_colour('#FFFFFF'); + $oChart->add_element( $oChartElement ); + + $sHtml = $oChart->toPrettyString(); + break; + + default: + // Unsupported style, do nothing. + $sHtml .= "Error: unsupported style of block: ".$this->m_sStyle; + } + return $sHtml; + } +} + +/** + * Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects + * + * Each block is actually rendered as a
tag that can be rendered synchronously + * or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php). + * The list of cmdbObjects to be displayed into the block is defined by a filter + * Right now the type of display is either: list, count or details + * - list produces a table listing the objects + * - count produces a paragraphs with a sentence saying 'cont' objects found + * - details display (as table) the details of each object found (best if only one) + */ +class HistoryBlock extends DisplayBlock +{ + public function GetRenderContent(web_page $oPage, $aExtraParams = array()) + { + $sHtml = ''; + // Add the extra params into the filter if they make sense for such a filter + $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass())); + foreach($aFilterCodes as $sFilterCode) + { + $sExternalFilterValue = utils::ReadParam($sFilterCode, ''); + if (isset($aExtraParams[$sFilterCode])) + { + $this->m_oFilter->AddCondition($sFilterCode, $aExtraParams[$sFilterCode]); // Use the default 'loose' operator + } + else if ($sExternalFilterValue != "") + { + $this->m_oFilter->AddCondition($sFilterCode, $sExternalFilterValue); // Use the default 'loose' operator + } + } + $oSet = new CMDBObjectSet($this->m_oFilter, array('date'=>false)); + switch($this->m_sStyle) + { + case 'toggle': + $oLatestChangeOp = $oSet->Fetch(); + if (is_object($oLatestChangeOp)) + { + global $oContext; // User Context.. should be statis instead of global... + // There is one change in the list... only when the object has been created ! + $sDate = $oLatestChangeOp->GetAsHTML('date'); + $oChange = $oContext->GetObject('CMDBChange', $oLatestChangeOp->Get('change')); + $sUserInfo = $oChange->GetAsHTML('userinfo'); + $oSet->Load(); // Reset the pointer to the beginning of the set: there should be a better way to do this... + $sHtml .= $oPage->GetStartCollapsibleSection("Last modified on $sDate by $sUserInfo."); + $sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $oSet); + $sHtml .= $oPage->GetEndCollapsibleSection(); + } + break; + + default: + $sHtml .= parent::GetRenderContent($oPage, $aExtraParams); + } + return $sHtml; + } +} + +class MenuBlock extends DisplayBlock +{ + public function GetRenderContent(web_page $oPage, $aExtraParams = array()) + { + $sHtml = ''; + $oAppContext = new ApplicationContext(); + $sContext = $oAppContext->GetForLink(); + $sClass = $this->m_oFilter->GetClass(); + $oSet = new CMDBObjectSet($this->m_oFilter); + $sFilter = $this->m_oFilter->serialize(); + $aActions = array(); + $sUIPage = cmdbAbstractObject::ComputeUIPage($sClass); + switch($oSet->Count()) + { + case 0: + // No object in the set, the only possible action is "new" + $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet); + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New', 'url' => "../page/$sUIPage?operation=new&class=$sClass&$sContext"); } + break; + + case 1: + $oObj = $oSet->Fetch(); + $id = $oObj->GetKey(); + $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet); + $bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet); + $bIsBulkModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet); + $bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet); + // Just one object in the set, possible actions are "new / clone / modify and delete" + if (isset($aExtraParams['linkage'])) + { + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "#"); } + if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "#"); } + if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All', 'url' => "#"); } + if ($bIsModifyAllowed | $bIsDeleteAllowed) { $aActions[] = array ('label' => 'Manage Links...', 'url' => "#"); } + } + else + { + $aActions[] = array ('label' => 'eMail', 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("http://localhost:81/pages/UI.php?operation=search&filter=$sFilter&$sContext")); + $aActions[] = array ('label' => 'CSV Export', 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext"); + $aActions[] = array ('label' => 'Bookmark...', 'url' => "../pages/ajax.render.php?operation=create&class=$sClass&filter=$sFilter", 'class' => 'jqmTrigger'); + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext"); } + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'Clone...', 'url' => "../pages/$sUIPage?operation=clone&class=$sClass&id=$id&$sContext"); } + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'Modify...', 'url' => "../pages/$sUIPage?operation=modify&class=$sClass&id=$id&$sContext"); } + if ($bIsDeleteAllowed) { $aActions[] = array ('label' => 'Delete', 'url' => "../pages/$sUIPage?operation=delete&class=$sClass&id=$id&$sContext"); } + } + $aTransitions = $oObj->EnumTransitions(); + $aStimuli = Metamodel::EnumStimuli($sClass); + foreach($aTransitions as $sStimulusCode => $aTransitionDef) + { + $iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet); + switch($iActionAllowed) + { + case UR_ALLOWED_YES: + $aActions[] = array('label' => $aStimuli[$sStimulusCode]->Get('label'), 'url' => "../pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id&$sContext"); + break; + + case UR_ALLOWED_DEPENDS: + $aActions[] = array('label' => $aStimuli[$sStimulusCode]->Get('label').' (*)', 'url' => "../pages/UI.php?operation=stimulus&stimulus=$sStimulusCode&class=$sClass&id=$id&$sContext"); + break; + + default: + // Do nothing + } + } + //print_r($aTransitions); + break; + + default: + // Check rights + // New / Modify + $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet); + $bIsBulkModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet); + $bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet); + if (isset($aExtraParams['linkage'])) + { + $bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet); + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "#"); } + if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "#"); } + if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All', 'url' => "#"); } + if ($bIsModifyAllowed | $bIsDeleteAllowed) { $aActions[] = array ('label' => 'Manage Links...', 'url' => "#"); } + } + else + { + // many objects in the set, possible actions are: new / modify all / delete all + $aActions[] = array ('label' => 'eMail', 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("http://localhost:81/pages/UI.php?operation=search&filter=$sFilter&$sContext")); + $aActions[] = array ('label' => 'CSV Export', 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext"); + $aActions[] = array ('label' => 'Bookmark...', 'url' => "../pages/ajax.render.php?operation=create&class=$sClass&filter=$sFilter", 'class' => 'jqmTrigger'); + if ($bIsModifyAllowed) { $aActions[] = array ('label' => 'New...', 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext"); } + if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "../pages/$sUIPage?operation=modify_all&filter=$sFilter&$sContext"); } + if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Delete All', 'url' => "../pages/$sUIPage?operation=delete_all&filter=$sFilter&$sContext"); } + } + } + $sHtml .= "
    \n
  • Actions\n
      \n"; + foreach ($aActions as $aAction) + { + $sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : ""; + $sHtml .= "
    • {$aAction['label']}
    • \n
    • \n"; + } + $sHtml .= "
    \n
  • \n
\n"; + $oPage->add_ready_script("$(\"ul.jd_menu\").jdMenu();\n"); + return $sHtml; + } + +} +?> diff --git a/application/iotask.class.inc.php b/application/iotask.class.inc.php new file mode 100644 index 000000000..32eb33400 --- /dev/null +++ b/application/iotask.class.inc.php @@ -0,0 +1,54 @@ + "application", + "name" => "IOTask", + "description" => "Input / Output Task for synchronizing information with external data sources", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "name", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_iotask", + "db_key_field" => "id", + "db_finalclass_field" => "", + "display_template" => "../business/templates/default.html", + ); + MetaModel::Init_Params($aParams); + MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Task Name", "description"=>"Short name for this task", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("description", array("label"=>"Task Description", "description"=>"Long description for this task", "allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("category", array("label"=>"Category", "description"=>"Type of task", "allowed_values"=>new ValueSetEnum('Input, Ouput'), "sql"=>"category", "default_value"=>"Input", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("source_type", array("label"=>"Source Type", "description"=>"Type of data source", "allowed_values"=>new ValueSetEnum('File, Database, Web Service'), "sql"=>"source_type", "default_value"=>"File", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("source_subtype", array("label"=>"Source Subtype", "description"=>"Subtype of Data Source", "allowed_values"=>new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql"=>"source_subtype", "default_value"=>"CSV", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("source_path", array("label"=>"Source Path", "description"=>"Path to the icon o the menu", "allowed_values"=>null, "sql"=>"source_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("objects_class", array("label"=>"Objects Class", "description"=>"Class of the objects processed by this task", "allowed_values"=>new ValueSetEnum('bizOrganization, bizContact, bizTeam, bizPerson, bizLocation, bizServer, bizPC, bizNetworkDevice, bizInterface, bizService, bizContract, bizInfraGroup, bizIncidentTicket, bizSoftware, bizApplication, bizPatch, bizWorkgroup, lnkContactRealObject, lnkInterfaces, bizInfraGrouping' ), "sql"=>"objects_class", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", array("label"=>"Test Mode", "description"=>"If set to 'Yes' the modifications are not applied", "allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"test_mode", "default_value"=>'No', "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", array("label"=>"Verbose Mode", "description"=>"If set to 'Yes' extra debug information is added to the log", "allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"verbose_mode", "default_value" => 'No', "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("options", array("label"=>"Options", "description"=>"Reconciliation options", "allowed_values"=>new ValueSetEnum('Full, Update Only, Creation Only'), "sql"=>"options", "default_value"=> 'Full', "is_null_allowed"=>true, "depends_on"=>array()))); + + MetaModel::Init_AddFilterFromAttribute("name"); + MetaModel::Init_AddFilterFromAttribute("description"); + MetaModel::Init_AddFilterFromAttribute("category"); + MetaModel::Init_AddFilterFromAttribute("source_type"); + MetaModel::Init_AddFilterFromAttribute("source_subtype"); + MetaModel::Init_AddFilterFromAttribute("objects_class"); + + // Display lists + MetaModel::Init_SetZListItems('details', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'source_path' , 'options', 'test_mode', 'verbose_mode')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype', 'options')); // Attributes to be displayed for a list + // Search criteria + MetaModel::Init_SetZListItems('standard_search', array('name', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the std search form + MetaModel::Init_SetZListItems('advanced_search', array('name', 'description', 'category', 'objects_class', 'source_type', 'source_subtype')); // Criteria of the advanced search form + } +} +?> diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php new file mode 100644 index 000000000..df1cd5b39 --- /dev/null +++ b/application/itopwebpage.class.inc.php @@ -0,0 +1,414 @@ +m_sCurrentTabContainer = ''; + $this->m_sCurrentTab = ''; + $this->m_aTabs = array(); + $this->m_sMenu = ""; + $oAppContext = new ApplicationContext(); + $sExtraParams = $oAppContext->GetForLink(); + $this->add_header("Content-type: text/html; charset=utf-8"); + $this->add_header("Cache-control: no-cache"); + $this->m_currentOrganization = $currentOrganization; + $this->add_linked_script("../js/jquery.dimensions.js"); + $this->add_linked_script("../js/splitter.js"); + $this->add_linked_script("../js/jquery.tablehover.js"); + $this->add_linked_script("../js/jquery.treeview.js"); + $this->add_linked_script("../js/jquery.autocomplete.js"); + $this->add_linked_script("../js/jquery.bgiframe.js"); + $this->add_linked_script("../js/jquery.jdMenu.js"); + $this->add_linked_script("../js/date.js"); + $this->add_linked_script("../js/jquery.date.picker.js"); + $this->add_linked_script("../js/jquery.tablesorter.min.js"); + //$this->add_linked_script("../js/jquery-ui-personalized-1.5.3.js"); + $this->add_linked_script("../js/swfobject.js"); + $this->add_linked_stylesheet("../css/jquery.treeview.css"); + $this->add_linked_stylesheet("../css/jquery.autocomplete.css"); + $this->add_linked_stylesheet("../css/date.picker.css"); + $this->add_ready_script( +<< 0) + { + $("#RightPane").splitter({ + type: "h" //, + //minA: 100, initA: 150, maxA: 500, + //accessKey: "_" + }); + } + + // Manually set the outer splitter's height to fill the browser window. + // This must be re-done any time the browser window is resized. + $(window).bind("resize", function(){ + var ms = $("#MySplitter"); + var top = ms.offset().top; // from dimensions.js + var wh = $(window).height(); + // Account for margin or border on the splitter container + var mrg = parseInt(ms.css("marginBottom")) || 0; + var brd = parseInt(ms.css("borderBottomWidth")) || 0; + ms.css("height", (wh-top-mrg-brd)+"px"); + + // IE fires resize for splitter; others don't so do it here + if ( !jQuery.browser.msie ) + ms.trigger("resize"); + + + }).trigger("resize"); + + var ms = $("#MySplitter"); + ms.trigger("resize"); + + if ( $("#TopPane").length > 0) + { + $("#RightPane").trigger("resize"); + } + + $("#tabbedContent > ul").tabs( 1, { fxFade: true, fxSpeed: 'fast' } ); // tabs + $("table.listResults").tableHover(); // hover tables + $(".listResults").tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables + $(".date-pick").datePicker( {clickInput: false, createButton: true, startDate: '2000-01-01'} ); // Date picker + $('#ModalDlg').jqm({ajax: '@href', trigger: 'a.jqmTrigger', overlay:70, modal:true, toTop:true}); // jqModal Window + //$('.display_block').draggable(); // make the blocks draggable +EOF +); + $this->add_script(" + // For automplete + function findValue(li) { + if( li == null ) return alert(\"No match!\"); + + // if coming from an AJAX call, let's use the CityId as the value + if( !!li.extra ) var sValue = li.extra[0]; + + // otherwise, let's just display the value in the text box + else var sValue = li.selectValue; + + //alert(\"The value you selected was: \" + sValue); + } + + function selectItem(li) { + findValue(li); + } + + function formatItem(row) { + return row[0]; + } + + function goBack() + { + window.history.back(); + } + "); + $this->DisplayMenu(); + } + + public function AddToMenu($sHtml) + { + $this->m_sMenu .= $sHtml; + } + + public function DisplayMenu() + { + // Combo box to select the organization + $this->AddToMenu("
+
\n"); + $this->AddToMenu("
\n"); + $this->AddToMenu("
    \n"); + $oAppContext = new ApplicationContext(); + // Display the menu + // 1) Application defined menus + $oSearchFilter = $oContext->NewFilter("menuNode"); + $oSearchFilter->AddCondition('parent_id', 0, '='); + $oSearchFilter->AddCondition('type', 'application', '='); + // There may be more criteria added later to have a specific menu based on the user's profile + $oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true)); + while ($oRootMenuNode = $oSet->Fetch()) + { + $oRootMenuNode->DisplayMenu($this, 'application', $oAppContext->GetAsHash()); + } + // 2) User defined menus (Bookmarks) + $oSearchFilter = $oContext->NewFilter("menuNode"); + $oSearchFilter->AddCondition('parent_id', 0, '='); + $oSearchFilter->AddCondition('type', 'user', '='); + $oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '='); + // There may be more criteria added later to have a specific menu based on the user's profile + $oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true)); + while ($oRootMenuNode = $oSet->Fetch()) + { + $oRootMenuNode->DisplayMenu($this, 'user', $oAppContext->GetAsHash()); + } + $this->AddToMenu("
\n"); + } + + /** + * Outputs (via some echo) the complete HTML page by assembling all its elements + */ + public function output() + { + foreach($this->a_headers as $s_header) + { + header($s_header); + } + $s_captured_output = ob_get_contents(); + ob_end_clean(); + echo "\n"; + echo "\n"; + echo "\n"; + echo "{$this->s_title}\n"; + foreach($this->a_linked_scripts as $s_script) + { + echo "\n"; + } + if (count($this->m_aReadyScripts)>0) + { + $this->add_script("\$(document).ready(function() {\n".implode("\n", $this->m_aReadyScripts)."\n});"); + } + if (count($this->a_scripts)>0) + { + echo "\n"; + } + foreach($this->a_linked_stylesheets as $a_stylesheet) + { + if ($a_stylesheet['condition'] != "") + { + echo "\n"; + } + } + + if (count($this->a_styles)>0) + { + echo "\n"; + } + echo "\n"; + echo "\n"; + echo "\n"; + + // Display the header + echo "
\n"; + echo "
iTop
\n"; + //echo "
\n"; + $sText = Utils::ReadParam('text', ''); + $sOnClick = ""; + if (empty($sText)) + { + // if no search text is supplied then + // 1) the search text is filled with "your search" + // 2) clicking on it will erase it + $sText = "Your search"; + $sOnClick = " onclick=\"this.value='';this.onclick=null;\""; + } + echo "
"; + echo "
+
\n"; + echo "
\n"; + + echo "
\n"; + + // Display the menu + echo "
\n"; + echo "
\n"; + echo $this->m_sMenu; + echo "
\n"; + + echo "
\n"; + + // Render the tabs in the page (if any) + foreach($this->m_aTabs as $sTabContainerName => $m_aTabs) + { + $sTabs = ''; + if (count($m_aTabs) > 0) + { + $sTabs = "\n
\n"; + $sTabs .= "
    \n"; + // Display the unordered list that will be rendered as the tabs + $i = 0; + foreach($m_aTabs as $sTabName => $sTabContent) + { + $sTabs .= "
  • ".htmlentities($sTabName)."
  • \n"; + $i++; + } + $sTabs .= "
\n"; + // Now add the content of the tabs themselves + $i = 0; + foreach($m_aTabs as $sTabName => $sTabContent) + { + $sTabs .= "
".$sTabContent."
\n"; + $i++; + } + $sTabs .= "
\n\n"; + } + $this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content); + } + + // Display the page's content + echo $this->s_content; + + // Add the captured output + if (trim($s_captured_output) != "") + { + echo "
$s_captured_output
\n"; + } + echo "
Please wait...
\n"; // jqModal Window + echo "
\n"; + echo "
\n"; + echo "
"; + echo "\n"; + echo "\n"; + } + + public function AddTabContainer($sTabContainer) + { + $this->m_aTabs[$sTabContainer] = array(); + $this->add("\$Tabs:$sTabContainer\$"); + } + + public function AddToTab($sTabContainer, $sTabLabel, $sHtml) + { + if (!isset($this->m_aTabs[$sTabContainer][$sTabLabel])) + { + // Set the content of the tab + $this->m_aTabs[$sTabContainer][$sTabLabel] = $sHtml; + } + else + { + // Append to the content of the tab + $this->m_aTabs[$sTabContainer][$sTabLabel] .= $sHtml; + } + } + + public function SetCurrentTabContainer($sTabContainer = '') + { + $sPreviousTabContainer = $this->m_sCurrentTabContainer; + $this->m_sCurrentTabContainer = $sTabContainer; + return $sPreviousTabContainer; + } + + public function SetCurrentTab($sTabLabel = '') + { + $sPreviousTab = $this->m_sCurrentTab; + $this->m_sCurrentTab = $sTabLabel; + return $sPreviousTab; + } + + public function StartCollapsibleSection($sSectionLabel, $bOpen = false) + { + $this->add($this->GetStartCollapsibleSection($sSectionLabel, $bOpen)); + } + + public function GetStartCollapsibleSection($sSectionLabel, $bOpen = false) + { + $sHtml = ''; + static $iSectionId = 0; + $sHtml .= "$sSectionLabel
\n"; + $sStyle = $bOpen ? '' : 'style="display:none" '; + $sHtml .= "
"; + $this->add_ready_script("\$(\"#LnkCollapse_$iSectionId\").click(function() {\$(\"#Collapse_$iSectionId\").slideToggle('normal'); $(\"#LnkCollapse_$iSectionId\").toggleClass('open');});"); + //$this->add_ready_script("$('#LnkCollapse_$iSectionId').hide();"); + $iSectionId++; + return $sHtml; + } + + public function EndCollapsibleSection() + { + $this->add($this->GetEndCollapsibleSection()); + } + + public function GetEndCollapsibleSection() + { + return "
"; + } + + public function add($sHtml) + { + if (!empty($this->m_sCurrentTabContainer) && !empty($this->m_sCurrentTab)) + { + $this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml); + } + else + { + parent::add($sHtml); + } + } + + /* + public function AddSearchForm($sClassName, $bOpen = false) + { + $iSearchSectionId = 0; + + $sStyle = $bOpen ? 'SearchDrawer' : 'SearchDrawer DrawerClosed'; + $this->add("
\n"); + $this->add("

Search form for ".Metamodel::GetName($sClassName)."

\n"); + $this->add_ready_script("\$(\"#LnkSearch_$iSearchSectionId\").click(function() {\$(\"#Search_$iSearchSectionId\").slideToggle('normal'); $(\"#LnkSearch_$iSearchSectionId\").toggleClass('open');});"); + $oFilter = new DBObjectSearch($sClassName); + $sFilter = $oFilter->serialize(); + $oSet = new CMDBObjectSet($oFilter); + cmdbAbstractObject::DisplaySearchForm($this, $oSet, array('operation' => 'search', 'filter' => $sFilter, 'search_form' => true)); + $this->add("
\n"); + $this->add("
\n"); + $this->add("
Search
\n"); + + + $iSearchSectionId++; + } + */ +} + +?> diff --git a/application/itopwizardwebpage.class.inc.php b/application/itopwizardwebpage.class.inc.php new file mode 100644 index 000000000..aadaf30c7 --- /dev/null +++ b/application/itopwizardwebpage.class.inc.php @@ -0,0 +1,32 @@ +m_iCurrentStep = $iCurrentStep; + $this->m_aSteps = $aSteps; + } + + public function output() + { + $aSteps = array(); + $iIndex = 0; + foreach($this->m_aSteps as $sStepTitle) + { + $iIndex++; + $sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep'; + $aSteps[] = "
$sStepTitle
"; + } + $sWizardHeader = "

{$this->s_title}

\n".implode("
", $aSteps)."
\n"; + $this->s_content = "$sWizardHeader
".$this->s_content."
"; + parent::output(); + } +} +?> diff --git a/application/loginwebpage.class.inc.php b/application/loginwebpage.class.inc.php new file mode 100644 index 000000000..bbe0cb977 --- /dev/null +++ b/application/loginwebpage.class.inc.php @@ -0,0 +1,106 @@ +add_style(" +body { + background-color: #eee; + margin: 0; + padding: 0; +} +#login { + width: 230px; + margin-left: auto; + margin-right: auto; + margin-top: 150px; + padding: 20px; + background-color: #fff; + border: 1px solid #000; +} +.center { + text-align: center; +} + +h1 { + color: #83b217; + font-size: 16pt; +} +.v-spacer { + padding-top: 1em; +} + "); + } + + public function DisplayLoginForm($bFailedLogin = false) + { + $sAuthUser = utils::ReadParam('auth_user', ''); + $sAuthPwd = utils::ReadParam('suggest_pwd', ''); + + $this->add("
\n"); + $this->add("

Welcome to iTop!

\n"); + if ($bFailedLogin) + { + $this->add("

Incorrect login/password, please try again.

\n"); + } + else + { + $this->add("

Please identify yourself before continuing.

\n"); + } + $this->add("
\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + $this->add("
\n"); + $this->add("\n"); + $this->add("
\n"); + $this->add("
\n"); + } + + static function DoLogin() + { + $operation = utils::ReadParam('operation', ''); + session_start(); + + if (!session_is_registered('auth_user') || !session_is_registered('auth_pwd')) + { + if ($operation == 'login') + { + $sAuthUser = utils::ReadParam('auth_user', '', 'post'); + $sAuthPwd = utils::ReadParam('auth_pwd', '', 'post'); + } + else + { + $oPage = new login_web_page(); + $oPage->DisplayLoginForm(); + $oPage->output(); + exit; + } + } + else + { + $sAuthUser = $_SESSION['auth_user']; + $sAuthPwd = $_SESSION['auth_pwd']; + } + if (!UserRights::Login($sAuthUser, $sAuthPwd)) + { + $oPage = new login_web_page(); + $oPage->DisplayLoginForm( true /* failed attempt */); + $oPage->output(); + exit; + } + else + { + $_SESSION['auth_user'] = $sAuthUser ; + $_SESSION['auth_pwd'] = $sAuthPwd; + + } + } +} // End of class +?> diff --git a/application/menunode.class.inc.php b/application/menunode.class.inc.php new file mode 100644 index 000000000..4297092f4 --- /dev/null +++ b/application/menunode.class.inc.php @@ -0,0 +1,219 @@ + "gui", + "name" => "menuNode", + "description" => "Main menu configuration elements", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "name", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_menunode", + "db_key_field" => "id", + "db_finalclass_field" => "", + ); + MetaModel::Init_Params($aParams); +// MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("label"=>"change", "description"=>"change", "allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "jointype"=>"closed"))); +// MetaModel::Init_AddAttribute(new AttributeExternalField("date", array("label"=>"date", "description"=>"date and time of the change", "allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"date"))); + MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Menu Name", "description"=>"Short name for this menu", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("label", array("label"=>"Menu Description", "description"=>"Long description for this menu", "allowed_values"=>null, "sql"=>"label", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("hyperlink", array("label"=>"Hyperlink", "description"=>"Hyperlink to the page", "allowed_values"=>null, "sql"=>"hyperlink", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("icon_path", array("label"=>"Menu Icon", "description"=>"Path to the icon o the menu", "allowed_values"=>null, "sql"=>"icon_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("template", array("label"=>"Template", "description"=>"HTML template for the view", "allowed_values"=>null, "sql"=>"template", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("type", array("label"=>"Type", "description"=>"Type of menu", "allowed_values"=>new ValueSetEnum('application,user'), "sql"=>"type", "default_value"=>"application", "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeInteger("rank", array("label"=>"Display rank", "description"=>"Sort order for displaying the menu", "allowed_values"=>null, "sql"=>"rank", "default_value" => 999, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeExternalKey("parent_id", array("label"=>"Parent Menu Item", "description"=>"Parent Menu Item", "allowed_values"=>null, "sql"=>"parent_id", "targetclass"=>"menuNode", "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeExternalField("parent_name", array("label"=>"Parent Menu Item", "description"=>"Parent Menu Item", "allowed_values"=>null, "extkey_attcode"=>"parent_id", "target_attcode"=>"name"))); + MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("label"=>"Owner of the menu", "description"=>"User who owns this menu (for user defined menus)", "allowed_values"=>null, "sql"=>"user_id", "targetclass"=>"UserRightsMatrixUsers", "is_null_allowed"=>true, "depends_on"=>array('type')))); + + MetaModel::Init_AddFilterFromAttribute("label"); + MetaModel::Init_AddFilterFromAttribute("parent_id"); + MetaModel::Init_AddFilterFromAttribute("rank"); + MetaModel::Init_AddFilterFromAttribute("type"); + MetaModel::Init_AddFilterFromAttribute("user_id"); + + MetaModel::Init_SetZListItems('details', array('parent_id', 'name', 'label', 'hyperlink', 'template', 'rank', 'type')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('parent_id', 'name', 'label', 'rank', 'type')); // Attributes to be displayed for a list + } + + public function IsVisible() + { + return true; + } + + public function GetMenuName() + { + return $this->Get('name'); + } + + public function GetMenuIcon() + { + return $this->Get('icon_path'); + } + + public function GetMenuLabel() + { + return $this->Get('label'); + } + + public function GetMenuLink($aExtraParams) + { + $aExtraParams['menu'] = $this->GetKey(); // Make sure we overwrite the current menu id (if any) + $aParams = array(); + foreach($aExtraParams as $sName => $sValue) + { + $aParams[] = urlencode($sName)."=".urlencode($sValue); + } + return $this->Get('hyperlink')."?".implode("&", $aParams); + } + + public function GetChildNodesSet($sType) + { + $oSearchFilter = new DBObjectSearch("menuNode"); + $oSearchFilter->AddCondition('parent_id', $this->GetKey(), '='); + $oSearchFilter->AddCondition('type', $sType, '='); + if ($sType == 'user') + { + $oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '='); + } + $oSet = new CMDBObjectSet($oSearchFilter, array('rank' => true)); + return $oSet; + } + + public function RenderContent(web_page $oPage, $aExtraParams = array()) + { + $sTemplate = $this->Get('template'); + $this->ProcessTemplate($sTemplate, $oPage, $aExtraParams); + } + + protected function ProcessTemplate($sTemplate, web_page $oPage, $aExtraParams = array()) + { + $iStartPos = stripos($sTemplate, '<'.DisplayBlock::TAG_BLOCK.' ',0); + $index = 0; + while(($iStartPos = stripos($sTemplate, '<'.DisplayBlock::TAG_BLOCK.' ',0)) !== false) + { + $iEndPos = stripos($sTemplate, '', $iStartPos); + + $sBlockDefinition = substr($sTemplate, $iStartPos, $iEndPos - $iStartPos + strlen('')); + $oBlock = DisplayBlock::FromTemplate($sBlockDefinition); + + $oPage->add(substr($sTemplate, 0, $iStartPos)); + if ($oBlock) // Protects agains invalid XML templates + { + $oBlock->Display($oPage, "block{$index}", $aExtraParams); // Values from $aExtraParams have precedence over $aParams + } + $index++; + $sTemplate = substr($sTemplate, $iEndPos + strlen('')); + } + // What remains is purely static (without any block inside), just output as it is + $oPage->add($sTemplate); + } + + public function DisplayMenu(iTopWebPage $oP, $sType, $aExtraParams) + { + $oP->AddToMenu("
  • GetMenuLink($aExtraParams)."\" title=\"".$this->GetMenuLabel()."\">".$this->GetMenuName().""); + $oSet = $this->GetChildNodesSet($sType); + if ($oSet->Count() > 0) + { + $oP->AddToMenu("\n
      \n"); + while($oChildNode = $oSet->Fetch()) + { + $oChildNode->DisplayMenu($oP, $sType, $aExtraParams); + } + $oP->AddToMenu("
    \n"); + } + $oP->AddToMenu("
  • \n"); + } + static public function DisplayCreationForm(web_page $oP, $sClass, $sFilter, $aExtraParams = array()) + { + $oFilter = DBObjectSearch::unserialize($sFilter); + $oP->p('Create a new menu item for: '.$oFilter->__DescribeHTML()); + $oP->add('
    '); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->p('Menu Label: '); + $oP->p('Description: '); + $oP->add('

    Insert after:

    '); + $oP->p(' Create as a child menu item'); + $oP->p('      '); + $oP->add('
    '); + } + + static public function GetMenuAsArray($oRootNode = null, $sType = 'application', $iDepth = 0) + { + $aNodes = array(); + if (is_object($oRootNode)) + { + $oChildSet = $oRootNode->GetChildNodesSet($sType); + while($oNode = $oChildSet->Fetch()) + { + $aNodes[] = array('depth' => $iDepth, 'id' => $oNode->GetKey(), 'label' => $oNode->GetName()); + $aNodes = array_merge($aNodes, self::GetMenuAsArray($oNode, $sType, $iDepth+1)); + } + } + else + { + $oSearchFilter = new DbObjectSearch("menuNode"); + $oSearchFilter->AddCondition('parent_id', 0, '='); + $oSearchFilter->AddCondition('type', $sType, '='); + if ($sType == 'user') + { + $oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '='); + } + $oRootSet = new CMDBObjectSet($oSearchFilter, array('rank' => true)); + while($oNode = $oRootSet->Fetch()) + { + $aNodes[] = array('depth' => $iDepth, 'id' => $oNode->GetKey(), 'label' => $oNode->GetName()); + $aNodes = array_merge($aNodes, self::GetMenuAsArray($oNode, $sType, $iDepth+1)); + } + } + return $aNodes; + } + /** + * Returns a set of all the nodes following the current node in the tree + * (i.e. nodes with the same parent but with a greater rank) + */ + public function GetNextNodesSet($sType = 'application') + { + $oSearchFilter = new DBObjectSearch("menuNode"); + $oSearchFilter->AddCondition('parent_id', $this->Get('parent_id')); + $oSearchFilter->AddCondition('rank', $this->Get('rank'), '>'); + $oSearchFilter->AddCondition('type', $sType, '='); + if ($sType == 'user') + { + $oSearchFilter->AddCondition('user_id', UserRights::GetUserId(), '='); + } + $oSet = new DBObjectSet($oSearchFilter, array('rank'=> true)); // Order by rank (true means ascending) + return $oSet; + } +} +?> diff --git a/application/nicewebpage.class.inc.php b/application/nicewebpage.class.inc.php new file mode 100644 index 000000000..bd29966ed --- /dev/null +++ b/application/nicewebpage.class.inc.php @@ -0,0 +1,76 @@ +m_aReadyScripts = array(); + $this->add_linked_script("../js/jquery.latest.js"); + $this->add_linked_script("../js/jquery.history_remote.pack.js"); + //$this->add_linked_script("../js/ui.resizable.js"); + $this->add_linked_script("../js/ui.tabs.js"); + $this->add_linked_script("../js/hovertip.js"); + $this->add_linked_script("../js/jqModal.js"); + $this->add_linked_stylesheet("../css/light-grey.css"); + $this->add_linked_stylesheet("../js/themes/light/light.tabs.css"); + //$this->add_linked_stylesheet("../css/jquery.tabs-ie.css", "lte IE 7"); + $this->add_linked_stylesheet("../css/jqModal.css"); + $this->add_ready_script(' window.setTimeout(hovertipInit, 1);'); + } + + public function small_p($sText) + { + $this->add("

    $sText

    \n"); + } + + // By Rom, used by CSVImport and Advanced search + public function MakeClassesSelect($sName, $sDefaultValue, $iWidthPx) + { + // $aTopLevelClasses = array('bizService', 'bizContact', 'logInfra', 'bizDocument'); + // These are classes wich root class is cmdbAbstractObject ! + $this->add(""); + } + + // By Rom, used by Advanced search + public function add_select($aChoices, $sName, $sDefaultValue, $iWidthPx) + { + $this->add(""); + } + + public function add_ready_script($sScript) + { + $this->m_aReadyScripts[] = $sScript; + } + + /** + * Outputs (via some echo) the complete HTML page by assembling all its elements + */ + public function output() + { + if (count($this->m_aReadyScripts)>0) + { + $this->add_script("\$(document).ready(function() {\n".implode("\n", $this->m_aReadyScripts)."\n});"); + } + parent::output(); + } +} + +?> diff --git a/application/startup.inc.php b/application/startup.inc.php new file mode 100644 index 000000000..83ea90c2a --- /dev/null +++ b/application/startup.inc.php @@ -0,0 +1,7 @@ + diff --git a/application/template.class.inc.php b/application/template.class.inc.php new file mode 100644 index 000000000..99b538e04 --- /dev/null +++ b/application/template.class.inc.php @@ -0,0 +1,220 @@ +m_aTags = array('itopblock', 'itoptabs', 'itoptab', 'itoptoggle'); + $this->m_sTemplate = $sTemplate; + } + + public function Render(web_page $oPage, $aParams = array()) + { + $this->ApplyParams($aParams); + $iStart = 0; + $iEnd = strlen($this->m_sTemplate); + $iCount = 0; + $iBeforeTagPos = $iStart; + $iAfterTagPos = $iStart; + while($sTag = $this->GetNextTag($iStart, $iEnd)) + { + $sContent = $this->GetTagContent($sTag, $iStart, $iEnd); + $aAttributes = $this->GetTagAttributes($sTag, $iStart, $iEnd); + //$oPage->p("Tag: $sTag - ($iStart, $iEnd)"); + $oPage->add(substr($this->m_sTemplate, $iBeforeTagPos, $iStart - $iBeforeTagPos)); + $this->RenderTag($oPage, $sTag, $aAttributes, $sContent); + + $iAfterTagPos = $iEnd + strlen(''); + $iBeforeTagPos = $iAfterTagPos; + $iStart = $iEnd; + $iEnd = strlen($this->m_sTemplate); + $iCount++; + if ($iCount > 10) break; + } + $oPage->add(substr($this->m_sTemplate, $iAfterTagPos)); + } + + /** + * Replaces all the parameters by the values passed in the hash array + */ + public function ApplyParams($aParams) + { + $aSearches = array(); + $aReplacements = array(); + foreach($aParams as $sSearch => $sReplace) + { + $aSearches[] = '$'.$sSearch.'$'; + $aReplacements[] = $sReplace; + } + $this->m_sTemplate = str_replace($aSearches, $aReplacements, $this->m_sTemplate); + } + + public function GetNextTag(&$iStartPos, &$iEndPos) + { + $iChunkStartPos = $iStartPos; + $sNextTag = null; + $iStartPos = $iEndPos; + foreach($this->m_aTags as $sTag) + { + // Search for the opening tag + $iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.' ', $iChunkStartPos); + if ($iOpeningPos === false) + { + $iOpeningPos = stripos($this->m_sTemplate, '<'.$sTag.'>', $iChunkStartPos); + } + if ($iOpeningPos !== false) + { + $iClosingPos = stripos($this->m_sTemplate, '', $iOpeningPos); + } + if ( ($iOpeningPos !== false) && ($iClosingPos !== false)) + { + if ($iOpeningPos < $iStartPos) + { + // This is the next tag + $iStartPos = $iOpeningPos; + $iEndPos = $iClosingPos; + $sNextTag = $sTag; + } + } + } + return $sNextTag; + } + + public function GetTagContent($sTag, $iStartPos, $iEndPos) + { + $sContent = ""; + $iContentStart = strpos($this->m_sTemplate, '>', $iStartPos); // Content of tag start immediatly after the first closing bracket + if ($iContentStart !== false) + { + $sContent = substr($this->m_sTemplate, 1+$iContentStart, $iEndPos - $iContentStart - 1); + } + return $sContent; + } + + public function GetTagAttributes($sTag, $iStartPos, $iEndPos) + { + $aAttr = array(); + $iAttrStart = strpos($this->m_sTemplate, ' ', $iStartPos); // Attributes start just after the first space + $iAttrEnd = strpos($this->m_sTemplate, '>', $iStartPos); // Attributes end just before the first closing bracket + if ( ($iAttrStart !== false) && ($iAttrEnd !== false) && ($iAttrEnd > $iAttrStart)) + { + $sAttributes = substr($this->m_sTemplate, 1+$iAttrStart, $iAttrEnd - $iAttrStart - 1); + $aAttributes = explode(' ', $sAttributes); + foreach($aAttributes as $sAttr) + { + if ( preg_match('/(.+) *= *"(.+)"$/', $sAttr, $aMatches) ) + { + $aAttr[strtolower($aMatches[1])] = $aMatches[2]; + } + } + } + return $aAttr; + } + + protected function RenderTag($oPage, $sTag, $aAttributes, $sContent) + { + static $iTabContainerCount = 0; + static $iBlockCount = 0; + switch($sTag) + { + case 'itoptabs': + $oPage->AddTabContainer('Tabs_'.$iTabContainerCount); + $oPage->SetCurrentTabContainer('Tabs_'.$iTabContainerCount); + $iTabContainerCount++; + //$oPage->p('Content:
    '.htmlentities($sContent).'
    '); + $oTemplate = new DisplayTemplate($sContent); + $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied + $oPage->SetCurrentTabContainer(''); + break; + + case 'itoptab': + $oPage->SetCurrentTab($aAttributes['name']); + $oTemplate = new DisplayTemplate($sContent); + $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied + //$oPage->p('iTop Tab Content:
    '.htmlentities($sContent).'
    '); + $oPage->SetCurrentTab(''); + break; + + case 'itoptoggle': + $oPage->StartCollapsibleSection($aAttributes['name']); + $oTemplate = new DisplayTemplate($sContent); + $oTemplate->Render($oPage, array()); // no params to apply, they have already been applied + //$oPage->p('iTop Tab Content:
    '.htmlentities($sContent).'
    '); + $oPage->EndCollapsibleSection(); + break; + + case 'itopblock': + $sBlockClass = $aAttributes['blockclass']; + $sBlockType = $aAttributes['type']; + $aExtraParams = array(); + if (isset($aAttributes['linkage'])) + { + $aExtraParams['linkage'] = $aAttributes['linkage']; + } + + switch($aAttributes['encoding']) + { + case 'text/sibusql': + $oFilter = CMDBSearchFilter::FromSibusQL($sContent); + break; + + case 'text/serialize': + default: + $oFilter = CMDBSearchFilter::unserialize($sContent); + break; + } + $oBlock = new $sBlockClass($oFilter, $sBlockType, false, $aExtraParams); + $oBlock->Display($oPage, 'block_'.$iBlockCount); + $iBlockCount++; + break; + + default: + // Unknown tab, just ignore it or now -- output an HTML comment + $oPage->add(""); + } + } + + /** + * Unit test + */ + static public function UnitTest() + { + require_once('../application/startup.inc.php'); + require_once("../application/itopwebpage.class.inc.php"); + + $sTemplate = ' + + bizNetworkDevice: pkey = $pkey$ + + + bizInterface: device_id = $pkey$ + + + bizContact: PKEY IS contact_id IN (ContactsLinks: object_id = $pkey$) + + + bizDocument: PKEY IS doc_id IN (lnkDocumentRealObject: object_id = $pkey$) + + '; + + $oPage = new iTopWebPage('Unit Test', 3); + //$oPage->add("Template content:
    ".htmlentities($sTemplate)."
    \n"); + $oTemplate = new DisplayTemplate($sTemplate); + $oTemplate->Render($oPage, array('class'=>'Network device','pkey'=> 271, 'name' => 'deliversw01.mecanorama.fr', 'org_id' => 3)); + $oPage->output(); + } +} + +//DisplayTemplate::UnitTest(); + +?>