Initial import on SourceForge

SVN:code[2]
This commit is contained in:
Denis Flaven
2009-03-13 17:13:48 +00:00
parent 02a9fe6429
commit ec48618573
347 changed files with 47666 additions and 0 deletions

View File

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

284
business/ChangeMgmt.php Normal file
View File

@@ -0,0 +1,284 @@
<?php
////////////////////////////////////////////////////////////////////////////////////
/**
* A Change Ticket
*/
////////////////////////////////////////////////////////////////////////////////////
class bizChangeTicket extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Change",
"description" => "Change ticket",
"key_type" => "autoincrement",
"key_label" => "id",
"name_attcode" => "name",
"state_attcode" => "ticket_status",
"reconc_keys" => array("title"),
"db_table" => "change_ticket",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/change.html",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"TicketID", "description"=>"Refence number ofr this change", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("title", array("label"=>"Title", "description"=>"Overview of the Change", "allowed_values"=>null, "sql"=>"title", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("type", array("label"=>"Change Type", "description"=>"Type of the Change", "allowed_values"=>new ValueSetEnum("Routine, Normal, Emergency"), "sql"=>"type", "default_value"=>"Routine", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("domain", array("label"=>"Domain", "description"=>"Domain for the Change", "allowed_values"=>new ValueSetEnum("Network,Server,Desktop,Application"), "sql"=>"domain", "default_value"=>"Desktop", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("reason", array("label"=>"Reason for change", "description"=>"Reason for the Change", "allowed_values"=>null, "sql"=>"reason", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("requestor_id", array("targetclass"=>"bizPerson", "jointype"=> "", "label"=>"Requestor", "description"=>"who is requesting this change", "allowed_values"=>null, "sql"=>"requestor_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("requestor_mail", array("label"=>"Requested by", "description"=>"mail of user requesting this change", "allowed_values"=>null, "extkey_attcode"=> 'requestor_id', "target_attcode"=>"email")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("customer_id", array("targetclass"=>"bizOrganization", "label"=>"Customer", "description"=>"who is impacted by the ticket", "allowed_values"=>null, "sql"=>"customer", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("customer_name", array("label"=>"Customer", "description"=>"Name of the customer impacted by this ticket", "allowed_values"=>null, "extkey_attcode"=> 'customer_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeEnum("ticket_status", array("label"=>"Status", "description"=>"Status of the ticket", "allowed_values"=>new ValueSetEnum("New, Validated,Rejected,PlannedScheduled,Approved,NotApproved,Implemented,Monitored, Closed"), "sql"=>"change_status", "default_value"=>"New", "is_null_allowed"=>false, "depends_on"=>array())));
// SetPossibleValues("status",array("Open","Monitored","Closed"));
MetaModel::Init_AddAttribute(new AttributeDate("creation_date", array("label"=>"Creation date", "description"=>"Change creation date", "allowed_values"=>null, "sql"=>"creation_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
// définir une date de défaut à maintenant, alias creation ou modification du ticket
MetaModel::Init_AddAttribute(new AttributeDate("last_update", array("label"=>"Last update", "description"=>"last time the Ticket was modified", "allowed_values"=>null, "sql"=>"last_update", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("start_date", array("label"=>"Start date", "description"=>"Time the change is expected to start", "allowed_values"=>null, "sql"=>"start_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("end_date", array("label"=>"End Date", "description"=>"Date when the change is supposed to end", "allowed_values"=>null, "sql"=>"end_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("close_date", array("label"=>"Closed Date", "description"=>"Date when the Ticket was closed", "allowed_values"=>null, "sql"=>"closed_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("impact", array("label"=>"Risk Assessment", "description"=>"Impact of the change", "allowed_values"=>null, "sql"=>"impact", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("workgroup_id", array("targetclass"=>"bizWorkgroup", "jointype"=> "", "label"=>"Workgroup", "description"=>"which workgroup is owning ticket", "allowed_values"=>null, "sql"=>"workgroup_id", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("workgroup_name", array("label"=>"Managed by Workgroup", "description"=>"name of workgroup managing the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'workgroup_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("agent_id", array("targetclass"=>"bizPerson", "jointype"=> "", "label"=>"Agent", "description"=>"who is managing the ticket", "allowed_values"=>null, "sql"=>"agent_id", "is_null_allowed"=>true, "depends_on"=>array('workgroup_id'))));
MetaModel::Init_AddAttribute(new AttributeExternalField("agent_name", array("label"=>"Managed by Agent", "description"=>"name of agent managing the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'agent_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("supervisorgroup_id", array("targetclass"=>"bizWorkgroup", "jointype"=> "", "label"=>"Supervisor group", "description"=>"which workgroup is supervising ticket", "allowed_values"=>null, "sql"=>"supervisorgroup_id", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("supervisorgroup_name", array("label"=>"Supervise by Workgroup", "description"=>"name of the group supervising the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'supervisorgroup_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("supervisor_id", array("targetclass"=>"bizPerson", "jointype"=> "", "label"=>"Supervisor", "description"=>"who is managing the ticket", "allowed_values"=>null, "sql"=>"supervisor_id", "is_null_allowed"=>true, "depends_on"=>array('supervisorgroup_id'))));
MetaModel::Init_AddAttribute(new AttributeExternalField("supervisor_name", array("label"=>"Managed by Supervisor", "description"=>"name of agent supervising the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'supervisor_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("managergroup_id", array("targetclass"=>"bizWorkgroup", "jointype"=> "", "label"=>"Manager group", "description"=>"which workgroup is approving ticket", "allowed_values"=>null, "sql"=>"managergroup_id", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("managergroup_name", array("label"=>"Approved by group", "description"=>"name of workgroup approving the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'managergroup_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("manager_id", array("targetclass"=>"bizPerson", "jointype"=> "", "label"=>"Manager", "description"=>"who is approving the ticket", "allowed_values"=>null, "sql"=>"manager_id", "is_null_allowed"=>true, "depends_on"=>array('managergroup_id'))));
MetaModel::Init_AddAttribute(new AttributeExternalField("manager_name", array("label"=>"Approved by Agent", "description"=>"name of agent approving the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'manager_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeEnum("outage", array("label"=>"Planned Outage", "description"=>"Flag to define if there is a planned outage", "allowed_values"=>new ValueSetEnum("Yes,No"), "sql"=>"outage", "default_value"=>"No", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("change_request", array("label"=>"Change Request", "description"=>"Description of Change required", "allowed_values"=>null, "sql"=>"change_req", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("change_log", array("label"=>"Implementation log", "description"=>"List all action performed during the change", "allowed_values"=>null, "sql"=>"change_log", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("fallback", array("label"=>"Fallback plan", "description"=>"Instruction to come back to former situation", "allowed_values"=>null, "sql"=>"fallback", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("assignment_count", array("label"=>"Assignment Count", "description"=>"Number of times this ticket was assigned or reassigned", "allowed_values"=>null, "sql"=>"assignment_count", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("impacted_infra_manual", array("label"=>"Impacted Infrastructure", "description"=>"CIs that are impacted by this change", "linked_class"=>"lnkInfraChangeTicket", "ext_key_to_me"=>"ticket_id", "ext_key_to_remote"=>"infra_id", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("title");
MetaModel::Init_AddFilterFromAttribute("type");
MetaModel::Init_AddFilterFromAttribute("domain");
MetaModel::Init_AddFilterFromAttribute("customer_id");
MetaModel::Init_AddFilterFromAttribute("requestor_id");
MetaModel::Init_AddFilterFromAttribute("ticket_status");
MetaModel::Init_AddFilterFromAttribute("creation_date");
MetaModel::Init_AddFilterFromAttribute("start_date");
MetaModel::Init_AddFilterFromAttribute("last_update");
MetaModel::Init_AddFilterFromAttribute("end_date");
MetaModel::Init_AddFilterFromAttribute("close_date");
MetaModel::Init_AddFilterFromAttribute("workgroup_id");
MetaModel::Init_AddFilterFromAttribute("workgroup_name");
MetaModel::Init_AddFilterFromAttribute("supervisorgroup_id");
MetaModel::Init_AddFilterFromAttribute("managergroup_id");
MetaModel::Init_AddFilterFromAttribute("supervisor_id");
MetaModel::Init_AddFilterFromAttribute("manager_id");
MetaModel::Init_AddFilterFromAttribute("agent_id");
MetaModel::Init_AddFilterFromAttribute("impact");
MetaModel::Init_AddFilterFromAttribute("assignment_count");
MetaModel::Init_AddFilterFromAttribute("outage");
// doit-on aussi ajouter un filtre sur les extfields lié à une extkey ? ici le name de l'agent?
// Display lists
MetaModel::Init_SetZListItems('details', array('name','title', 'customer_id','type','domain','requestor_id','change_request','ticket_status', 'outage','impact', 'last_update', 'start_date','end_date', 'assignment_count', 'workgroup_id','agent_id','supervisorgroup_id','supervisor_id','managergroup_id','manager_id','change_log','fallback')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('name', 'title', 'customer_id', 'ticket_status','outage','start_date','type')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'title', 'customer_id', 'ticket_status','type', 'outage','requestor_id','workgroup_id','agent_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'title', 'customer_id', 'ticket_status','type', 'outage','workgroup_id','agent_id')); // Criteria of the advanced search form
// State machine
MetaModel::Init_DefineState("New", array("label"=>"New (Unassigned)", "description"=>"Newly created ticket", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY,'customer_id' => OPT_ATT_MANDATORY, 'title' => OPT_ATT_MANDATORY, 'reason' => OPT_ATT_MANDATORY, 'impacted_infra_manual' => OPT_ATT_MANDATORY,
'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN)));
MetaModel::Init_DefineState("Validated", array("label"=>"Validated", "description"=>"Ticket is approved", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY, 'customer_id' => OPT_ATT_READONLY,'assignment_count' => OPT_ATT_READONLY,'managergroup_id' => OPT_ATT_MANDATORY, 'supervisorgroup_id' => OPT_ATT_MANDATORY)));
MetaModel::Init_DefineState("Rejected", array("label"=>"Rejected", "description"=>"This ticket is not approved", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY, 'customer_id' => OPT_ATT_READONLY,'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN)));
MetaModel::Init_DefineState("PlannedScheduled", array("label"=>"Planned&Scheduled", "description"=>"Evaluation is done for this change", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY, 'customer_id' => OPT_ATT_READONLY,'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_MANDATORY, 'impact' => OPT_ATT_MANDATORY, 'workgroup_id' => OPT_ATT_MANDATORY, 'change_log' => OPT_ATT_MUSTCHANGE,'fallback' => OPT_ATT_MANDATORY)));
MetaModel::Init_DefineState("Approved", array("label"=>"Approved", "description"=>"Ticket is approved by CAB", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY,'customer_id' => OPT_ATT_READONLY, 'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN)));
MetaModel::Init_DefineState("NotApproved", array("label"=>"Not Approved", "description"=>"Ticket has not been approved by CAB", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY,'customer_id' => OPT_ATT_READONLY, 'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN)));
MetaModel::Init_DefineState("Implemented", array("label"=>"Implementation", "description"=>"Work is in progress for this ticket", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY,'customer_id' => OPT_ATT_READONLY, 'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN)));
MetaModel::Init_DefineState("Monitored", array("label"=>"Monitored", "description"=>"Change performed is now monitored", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY,'customer_id' => OPT_ATT_READONLY,'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN)));
MetaModel::Init_DefineState("Closed", array("label"=>"Closed", "description"=>"Ticket is closed", "attribute_inherit"=>null, "attribute_list"=>array('customer_id' => OPT_ATT_READONLY,"workgroup_id"=>OPT_ATT_MANDATORY, "agent_id"=>OPT_ATT_MANDATORY)));
MetaModel::Init_DefineStimulus("ev_validate", new StimulusUserAction(array("label"=>"Validate this change", "description"=>"Make sure it is a valid change request")));
MetaModel::Init_DefineStimulus("ev_reject", new StimulusUserAction(array("label"=>"Reject this change", "description"=>"This change request is rejected because it is a non valid one")));
MetaModel::Init_DefineStimulus("ev_reopen", new StimulusUserAction(array("label"=>"Modify this change", "description"=>"Update change request to make it valid")));
MetaModel::Init_DefineStimulus("ev_plan", new StimulusUserAction(array("label"=>"Plan this change", "description"=>"Plan and Schedule this change for validation")));
MetaModel::Init_DefineStimulus("ev_approve", new StimulusUserAction(array("label"=>"Approve this change", "description"=>"This change is approved by CAB")));
MetaModel::Init_DefineStimulus("ev_replan", new StimulusUserAction(array("label"=>"Update planning and schedule", "description"=>"Modify Plan and Schedule in order to have this change re-validated")));
MetaModel::Init_DefineStimulus("ev_notapprove", new StimulusUserAction(array("label"=>"Not approve this change", "description"=>"This change is not approved by CAB")));
MetaModel::Init_DefineStimulus("ev_implement", new StimulusUserAction(array("label"=>"Implement this change", "description"=>"Implementation pahse for current change")));
MetaModel::Init_DefineStimulus("ev_monitor", new StimulusUserAction(array("label"=>"Monitor this change", "description"=>"Starting monitoring period for this change")));
MetaModel::Init_DefineStimulus("ev_finish", new StimulusUserAction(array("label"=>"Close change", "description"=>"Change is done, and can be closed")));
MetaModel::Init_DefineTransition("New", "ev_validate", array("target_state"=>"Validated", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("New", "ev_reject", array("target_state"=>"Rejected", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Rejected", "ev_reopen", array("target_state"=>"New", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Validated", "ev_plan", array("target_state"=>"PlannedScheduled", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("PlannedScheduled", "ev_approve", array("target_state"=>"Approved", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("PlannedScheduled", "ev_notapprove", array("target_state"=>"NotApproved", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("NotApproved", "ev_replan", array("target_state"=>"PlannedScheduled", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Approved", "ev_implement", array("target_state"=>"Implemented", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Implemented", "ev_monitor", array("target_state"=>"Monitored", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Implemented", "ev_finish", array("target_state"=>"Closed", "actions"=>array('SetLastUpDate'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Monitored", "ev_finish", array("target_state"=>"Closed", "actions"=>array(), "user_restriction"=>null));
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('customer_id', $oGenerator->GetOrganizationId());
$this->Set('title', $oGenerator->GenerateString("enum(Site,Server,Line)| |enum(is down,is flip-flopping,is not responding)"));
$this->Set('agent_id', $oGenerator->GenerateKey("bizPerson", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('ticket_status', $oGenerator->GenerateString("enum(Open,Closed,Closed,Monitored)"));
$this->Set('start_date', $oGenerator->GenerateString("2007-|number(07-12)|-|number(01-30)| |number(07-12)|:|number(00-59)|:|number(00-59)"));
$this->Set('last_update', $oGenerator->GenerateString("2007-|number(07-12)|-|number(01-30)| |number(07-12)|:|number(00-59)|:|number(00-59)"));
$this->Set('end_date', $oGenerator->GenerateString("2007-|number(07-12)|-|number(01-30)| |number(07-12)|:|number(00-59)|:|number(00-59)"));
}
// State machine actions
public function IncrementAssignmentCount($sStimulusCode)
{
$this->Set('assignment_count', $this->Get('assignment_count') + 1);
return true;
}
public function SetClosureDate($sStimulusCode)
{
$this->Set('end_date', time());
return true;
}
public function SetLastUpDate($sStimulusCode)
{
$this->Set('last_update', time());
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Infra and a Change Ticket
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkInfraChangeTicket extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Infra Change Ticket",
"description" => "Infra impacted by a Change ticket",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "impact", // ????
"state_attcode" => "",
"reconc_keys" => array("impact"), // ????
"db_table" => "infra_changeticket",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("infra_id", array("targetclass"=>"logInfra", "jointype"=> '', "label"=>"Infrastructure", "description"=>"The infrastructure impacted", "allowed_values"=>null, "sql"=>"infra_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("infra_name", array("label"=>"Infrastructure name", "description"=>"Name of the impacted infrastructure", "allowed_values"=>null, "extkey_attcode"=> 'infra_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("ticket_id", array("targetclass"=>"bizChangeTicket", "jointype"=> '', "label"=>"Ticket #", "description"=>"Ticket number", "allowed_values"=>null, "sql"=>"ticket_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("ticket_name", array("label"=>"Ticket name", "description"=>"Name of the ticket", "allowed_values"=>null, "extkey_attcode"=> 'ticket_id', "target_attcode"=>"title")));
MetaModel::Init_AddAttribute(new AttributeString("impact", array("label"=>"Impact", "description"=>"Level of impact of the infra by the related ticket", "allowed_values"=>null, "sql"=>"impact", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("infra_id");
MetaModel::Init_AddFilterFromAttribute("ticket_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('infra_id', 'ticket_id', 'impact')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('infra_id', 'ticket_id', 'impact')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('infra_id', 'ticket_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('infra_id', 'ticket_id')); // Criteria of the advanced search form
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('infra_id', $oGenerator->GenerateKey("logInfra", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('ticket_id', $oGenerator->GenerateKey("bizIncidentTicket", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('impact', $oGenerator->GenerateString("enum(none,mandatory,partial)"));
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any contact and a Contract
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkContactChange extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "ContactChangeLink",
"description" => "Contact associated to a change",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "role", // ????
"state_attcode" => "",
"reconc_keys" => array("role"), // ????
"db_table" => "contact_change",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("contact_id", array("targetclass"=>"bizContact", "jointype"=> '', "label"=>"Contact", "description"=>"The contact linked to contract", "allowed_values"=>null, "sql"=>"contact_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_mail", array("label"=>"Contact E-mail", "description"=>"Mail for the contact", "allowed_values"=>null, "extkey_attcode"=> 'contact_id', "target_attcode"=>"email")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("change_id", array("targetclass"=>"bizChangeTicket", "jointype"=> '', "label"=>"Change Ticket", "description"=>"Change ticket ID", "allowed_values"=>null, "sql"=>"change_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("change_number", array("label"=>"change number", "description"=>"Ticket number for this change", "allowed_values"=>null, "extkey_attcode"=> 'change_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("role", array("label"=>"Role", "description"=>"Role of this contact for this change", "allowed_values"=>null, "sql"=>"role", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("change_id");
MetaModel::Init_AddFilterFromAttribute("contact_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('change_id', 'contact_id', 'role')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('change_id', 'contact_id', 'role')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('change_id', 'contact_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('change_id', 'contact_id')); // Criteria of the advanced search form
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('contract_id', $oGenerator->GenerateKey("logInfra", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('contact_id', $oGenerator->GenerateKey("bizIncidentTicket", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('role', $oGenerator->GenerateString("enum(none,mandatory,partial)"));
}
}
?>

View File

@@ -0,0 +1,32 @@
Changements principaux:
- la classe AbstractObject est sortie du biz model
- join_type remplacé par is_null_allowed (placé à la fin pour être + facile à retrouver)
- j'ai enlevé toute la classe logLocatedObject qui était en commentaire
- Enlevé 'address' de l'advanced search sur une location car ce n'est plus un critère de recherche possible (remplacé par country)
- Ajouté des critères de recherche sur bizCircuit
- Ajouté les ZList sur bizCircuit
- Ajouté les Zlist pour bizInterface
- Ajouté les Zlist pour lnkInfraInfra
- Ajouté les Zlist pour lnkInfraTicket
Dans AbstractObject: désactivé l'affichage des contacts liés qui ne marche pas pour les tickets.
Bug fix ?
- J'ai rajouté un blindage if (is_object($proposedValue) &&... dans AttributeDate::MakeRealValue mais je ne comprends pas d' sort la classe DateTime... et pourtant il y en a...
Améliorations:
- Ajouter une vérification des ZList (les attributs/critèresde recherche déclarés dans la liste existent-ils pour cet objet)
Ne marche pas:
- Objets avec des clefs externes vides
- Enums !!!!
Data Generator:
Organization '1' updated.
5 Location objects created.
19 PC objects created.
19 Network Device objects created.
42 Person objects created.
6 Incident objects created.
17 Infra Group objects created.
34 Infra Infra objects created.

165
business/KEDB.php Normal file
View File

@@ -0,0 +1,165 @@
<?php
$oAllowedStatuses = new ValueSetEnum('production,implementation,obsolete');
////////////////////////////////////////////////////////////////////////////////////
/**
* Description of known error
*/
////////////////////////////////////////////////////////////////////////////////////
class bizKnownError extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Known Error",
"description" => "Error documented for a known issue",
"key_type" => "autoincrement",
"key_label" => "id",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array("cust_id", "name"), // inherited attributes
"db_table" => "known_error",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/knownError.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Name", "description"=>"Name to identify this error", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("cust_id", array("targetclass"=>"bizOrganization", "label"=>"Organization", "description"=>"Organization for this known error", "allowed_values"=>null, "sql"=>"cust_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("cust_name", array("label"=>"Organization", "description"=>"Company / Department owning this object", "allowed_values"=>null, "extkey_attcode"=> 'cust_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeText("symptom", array("label"=>"Symptom", "description"=>"Description of this error", "allowed_values"=>null, "sql"=>"symptom", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("root_cause", array("label"=>"Root cause", "description"=>"Original cause for this known error", "allowed_values"=>null, "sql"=>"rootcause", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("workaround", array("label"=>"Work around", "description"=>"Work around to fix this error", "allowed_values"=>null, "sql"=>"workaround", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("solution", array("label"=>"Solution", "description"=>"Description of this contract", "allowed_values"=>null, "sql"=>"solution", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("error_code", array("label"=>"Error Code", "description"=>"Key word to identify error", "allowed_values"=>null, "sql"=>"error_code", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("domain", array("label"=>"Domain", "description"=>"Domain for this known error, network, desktop, ...", "allowed_values"=>new ValueSetEnum("Network, Server, Application, Desktop"), "sql"=>"domain", "default_value"=>"Application", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("vendor", array("label"=>"Vendor", "description"=>"Vendor concerned by this known error", "allowed_values"=>null, "sql"=>"vendor", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("model", array("label"=>"Model", "description"=>"Model concerned by this known error, it may be an application, a device ...", "allowed_values"=>null, "sql"=>"model", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("version", array("label"=>"Version", "description"=>"Version related to model impacted by known error", "allowed_values"=>null, "sql"=>"version", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("cust_id");
MetaModel::Init_AddFilterFromAttribute("cust_name");
MetaModel::Init_AddFilterFromAttribute("error_code");
MetaModel::Init_AddFilterFromAttribute("domain");
MetaModel::Init_SetZListItems('details', array('name', 'cust_id','error_code','domain','vendor','model','version', 'symptom','root_cause','workaround','solution')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'cust_id','error_code', 'symptom')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'error_code','domain')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'cust_id','error_code', 'error_code','symptom')); // Criteria of the advanced search form
}
// State machine actions
public function IncrementVersion($sStimulusCode)
{
$this->Set('version_number', $this->Get('version_number') + 1);
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Infra and a Known Error
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkInfraError extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "InfraErrorLinks",
"description" => "Infra related to a known error",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "", // ????
"state_attcode" => "",
"reconc_keys" => array("infra_id","error_id"), // ????
"db_table" => "infra_error_links",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("infra_id", array("targetclass"=>"logInfra", "jointype"=> '', "label"=>"Infrastructure", "description"=>"The infrastructure impacted", "allowed_values"=>null, "sql"=>"infra_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("infra_name", array("label"=>"Infrastructure name", "description"=>"Name of the impacted infrastructure", "allowed_values"=>null, "extkey_attcode"=> 'infra_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalField("infra_status", array("label"=>"Status", "description"=>"Status of the impacted infrastructure", "allowed_values"=>null, "extkey_attcode"=> 'infra_id', "target_attcode"=>"status")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("error_id", array("targetclass"=>"bizKnownError", "jointype"=> '', "label"=>"Error name", "description"=>"Error id", "allowed_values"=>null, "sql"=>"error_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("error_name", array("label"=>"Error name", "description"=>"Name of the error", "allowed_values"=>null, "extkey_attcode"=> 'error_id', "target_attcode"=>"name")));
MetaModel::Init_AddFilterFromAttribute("infra_id");
MetaModel::Init_AddFilterFromAttribute("error_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('infra_id', 'error_id')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('infra_id', 'infra_status','error_id')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('infra_id', 'error_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('infra_id', 'error_id')); // Criteria of the advanced search form
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Contract and a Document
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkDocumentError extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "DocumentsErrorLinks",
"description" => "A link between a document and a known error",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "link_type",
"state_attcode" => "",
"reconc_keys" => array("doc_name", "error_name"),
"db_table" => "documents_error_link",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("doc_id", array("targetclass"=>"bizDocument", "label"=>"Document Name", "description"=>"id of the Document", "allowed_values"=>null, "sql"=>"doc_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("doc_name", array("label"=>"Document", "description"=>"name of the document", "allowed_values"=>null, "extkey_attcode"=> 'doc_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("error_id", array("targetclass"=>"bizKnownError", "label"=>"Error", "description"=>"Error linked to this document", "allowed_values"=>null, "sql"=>"error_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("error_name", array("label"=>"Error name", "description"=>"name of the linked error", "allowed_values"=>null, "extkey_attcode"=> 'error_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("link_type", array("label"=>"link_type", "description"=>"Type of the link", "allowed_values"=>null, "sql"=>"link_type", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("doc_id");
MetaModel::Init_AddFilterFromAttribute("doc_name");
MetaModel::Init_AddFilterFromAttribute("error_id");
MetaModel::Init_AddFilterFromAttribute("error_name");
MetaModel::Init_AddFilterFromAttribute("link_type");
// Display lists
MetaModel::Init_SetZListItems('details', array('doc_id', 'error_name', 'link_type')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('doc_id', 'error_name', 'link_type')); // Attributes to be displayed for a list
}
}
?>

View File

@@ -0,0 +1,259 @@
<?php
////////////////////////////////////////////////////////////////////////////////////
/**
* Description of a contract signed with a customer
*/
////////////////////////////////////////////////////////////////////////////////////
class bizContract extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Contract",
"description" => "Contract signed by an organization",
"key_type" => "autoincrement",
"key_label" => "id",
"name_attcode" => "name",
"state_attcode" => "status",
"reconc_keys" => array("customer_id", "name"), // inherited attributes
"db_table" => "contracts",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/contract.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Name", "description"=>"Name of the contract", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("customer_id", array("targetclass"=>"bizOrganization", "label"=>"Customer", "description"=>"Customer for this contract", "allowed_values"=>null, "sql"=>"customer_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("customer_name", array("label"=>"Customer", "description"=>"name of the Customer", "allowed_values"=>null, "extkey_attcode"=> 'customer_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("provider_id", array("targetclass"=>"bizOrganization", "label"=>"Provider", "description"=>"Provider for this contract", "allowed_values"=>null, "sql"=>"provider_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("provider_name", array("label"=>"Provider", "description"=>"name of the service provider", "allowed_values"=>null, "extkey_attcode"=> 'provider_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("service_name", array("label"=>"Service Name", "description"=>"Name of service for this contract", "allowed_values"=>null, "sql"=>"service_name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("team_id", array("targetclass"=>"bizTeam", "label"=>"Team", "description"=>"Team managing this contract", "allowed_values"=>null, "sql"=>"team_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("team_name", array("label"=>"Team", "description"=>"name of the team managing this contract", "allowed_values"=>null, "extkey_attcode"=> 'team_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeEnum("service_level", array("label"=>"Service Level", "description"=>"Level of service for this contract", "allowed_values"=>new ValueSetEnum("Gold,Silver,Bronze"), "sql"=>"service_level", "default_value"=>"Bronze", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("cost_unit", array("label"=>"Cost unit", "description"=>"Cost unit to compute global cost for this contract", "allowed_values"=>new ValueSetEnum("Devices,Persons,Applications,Global"), "sql"=>"cost_unit", "default_value"=>"Global", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("cost_freq", array("label"=>"Cost frequency", "description"=>"Frequency of cost for this contract", "allowed_values"=>new ValueSetEnum("Monthly,Yearly,Once"), "sql"=>"cost_freq", "default_value"=>"Once", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("cost", array("label"=>"Cost", "description"=>"Cost of this contract", "allowed_values"=>null, "sql"=>"cost", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("currency", array("label"=>"Currency", "description"=>"Currency of cost for this contract", "allowed_values"=>new ValueSetEnum("Euros,Dollars"), "sql"=>"currency", "default_value"=>"Euros", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("description", array("label"=>"Description", "description"=>"Description of this contract", "allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("move2prod_date", array("label"=>"Date of move to production", "description"=>"Date when the contract is on production", "allowed_values"=>null, "sql"=>"move2prod_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("end_prod", array("label"=>"Date of end of production", "description"=>"Date when the contract is stopped", "allowed_values"=>null, "sql"=>"end_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("label"=>"Status", "description"=>"Status of the contract", "allowed_values"=>new ValueSetEnum("New, Negotiating, Signed, Production, Notice, Finished"), "sql"=>"status", "default_value"=>"New", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("type", array("label"=>"Type", "description"=>"Type of the contract", "allowed_values"=>new ValueSetEnum("Hardware,Software,Support,Licence"), "sql"=>"type", "default_value"=>"Support", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("version_number", array("label"=>"Version number", "description"=>"Revision number for this contract", "allowed_values"=>null, "sql"=>"version_number", "default_value"=>1, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("service_name");
MetaModel::Init_AddFilterFromAttribute("provider_id");
MetaModel::Init_AddFilterFromAttribute("customer_id");
MetaModel::Init_AddFilterFromAttribute("team_id");
MetaModel::Init_AddFilterFromAttribute("team_name");
MetaModel::Init_AddFilterFromAttribute("service_level");
MetaModel::Init_AddFilterFromAttribute("end_prod");
MetaModel::Init_AddFilterFromAttribute("status");
MetaModel::Init_AddFilterFromAttribute("version_number");
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("type");
// Life cycle
MetaModel::Init_DefineState("New", array("label"=>"New", "description"=>"Newly created contract", "attribute_inherit"=>null,
"attribute_list"=>array()));
MetaModel::Init_DefineState("Negotiating", array("label"=>"Negotiating", "description"=>"The contract is being worked on", "attribute_inherit"=>null,
"attribute_list"=>array()));
MetaModel::Init_DefineState("Signed", array("label"=>"Signed", "description"=>"The contract has been signed", "attribute_inherit"=>null,
"attribute_list"=>array()));
MetaModel::Init_DefineState("Production", array("label"=>"Production", "description"=>"The contract is effective in production", "attribute_inherit"=>null,
"attribute_list"=>array()));
MetaModel::Init_DefineState("Notice", array("label"=>"Notice", "description"=>"The contract is about to be terminated", "attribute_inherit"=>null,
"attribute_list"=>array()));
MetaModel::Init_DefineState("Finished", array("label"=>"Finished", "description"=>"The contract is terminated", "attribute_inherit"=>null,
"attribute_list"=>array()));
MetaModel::Init_DefineStimulus("ev_freeze_version", new StimulusUserAction(array("label"=>"Freeze this version", "description"=>"This version of the contract is published")));
MetaModel::Init_DefineStimulus("ev_sign", new StimulusUserAction(array("label"=>"Sign this contract", "description"=>"This contract is being signed")));
MetaModel::Init_DefineStimulus("ev_begin", new StimulusUserAction(array("label"=>"Move to production", "description"=>"The contract becomes applicable in production")));
MetaModel::Init_DefineStimulus("ev_notice", new StimulusUserAction(array("label"=>"Start notice period", "description"=>"The end date of the contract is approaching")));
MetaModel::Init_DefineStimulus("ev_terminate", new StimulusUserAction(array("label"=>"Ends this contract", "description"=>"The contract is ending")));
MetaModel::Init_DefineStimulus("ev_elapsed", new StimulusUserAction(array("label"=>"Times up [Do not click!]", "description"=>"The contract over")));
MetaModel::Init_DefineTransition("New", "ev_freeze_version", array("target_state"=>"Negotiating", "actions"=>array('IncrementVersion'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Negotiating", "ev_freeze_version", array("target_state"=>"Negotiating", "actions"=>array('IncrementVersion'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Negotiating", "ev_sign", array("target_state"=>"Signed", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Negotiating", "ev_terminate", array("target_state"=>"Finished", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Signed", "ev_freeze_version", array("target_state"=>"Signed", "actions"=>array('IncrementVersion'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Signed", "ev_begin", array("target_state"=>"Production", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Signed", "ev_terminate", array("target_state"=>"Finished", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Production", "ev_freeze_version", array("target_state"=>"Production", "actions"=>array('IncrementVersion'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Production", "ev_elapsed", array("target_state"=>"Notice", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Production", "ev_terminate", array("target_state"=>"Finished", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Notice", "ev_elapsed", array("target_state"=>"Finished", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Notice", "ev_terminate", array("target_state"=>"Finished", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_SetZListItems('details', array('name', 'status', 'customer_id', 'service_name','provider_id','type','description','team_id','service_level','cost','currency','cost_unit','cost_freq','move2prod_date','end_prod', 'version_number')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'status', 'customer_id', 'provider_id','service_name','service_level','type')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'status','service_name','provider_id','team_name','service_level','type')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'status', 'service_name','provider_id','team_name', 'service_level', 'org_id')); // Criteria of the advanced search form
}
// State machine actions
public function IncrementVersion($sStimulusCode)
{
$this->Set('version_number', $this->Get('version_number') + 1);
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Infra and a Contract
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkInfraContract extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "InfraContractLinks",
"description" => "Infra covered by a contract",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "coverage", // ????
"state_attcode" => "",
"reconc_keys" => array("infra_id","contract_id"), // ????
"db_table" => "infra_contract_links",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("infra_id", array("targetclass"=>"logInfra", "jointype"=> '', "label"=>"Infrastructure", "description"=>"The infrastructure impacted", "allowed_values"=>null, "sql"=>"infra_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("infra_name", array("label"=>"Infrastructure name", "description"=>"Name of the impacted infrastructure", "allowed_values"=>null, "extkey_attcode"=> 'infra_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalField("infra_status", array("label"=>"Status", "description"=>"Status of the impacted infrastructure", "allowed_values"=>null, "extkey_attcode"=> 'infra_id', "target_attcode"=>"status")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("contract_id", array("targetclass"=>"bizContract", "jointype"=> '', "label"=>"Contract name", "description"=>"Contract id", "allowed_values"=>null, "sql"=>"contract_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contract_name", array("label"=>"Contract name", "description"=>"Name of the contract", "allowed_values"=>null, "extkey_attcode"=> 'contract_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("coverage", array("label"=>"coverage", "description"=>"coverage for the given infra", "allowed_values"=>null, "sql"=>"coverage", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("infra_id");
MetaModel::Init_AddFilterFromAttribute("contract_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('infra_id', 'contract_id', 'coverage')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('infra_id', 'infra_status','contract_id' , 'coverage')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('infra_id', 'contract_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('infra_id', 'contract_id')); // Criteria of the advanced search form
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any contact and a Contract
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkContactContract extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "ContactContractLink",
"description" => "Contact associated to a contract",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "role", // ????
"state_attcode" => "",
"reconc_keys" => array("role"), // ????
"db_table" => "contact_contract",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("contact_id", array("targetclass"=>"bizContact", "jointype"=> '', "label"=>"Contact", "description"=>"The contact linked to contract", "allowed_values"=>null, "sql"=>"contact_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_mail", array("label"=>"Contact E-mail", "description"=>"Mail for the contact", "allowed_values"=>null, "extkey_attcode"=> 'contact_id', "target_attcode"=>"email")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("contract_id", array("targetclass"=>"bizContract", "jointype"=> '', "label"=>"Contract", "description"=>"Contract ID", "allowed_values"=>null, "sql"=>"contract_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contract_name", array("label"=>"Contract name", "description"=>"Name of the contract", "allowed_values"=>null, "extkey_attcode"=> 'contract_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("role", array("label"=>"Role", "description"=>"Role of this contact for this contract", "allowed_values"=>null, "sql"=>"role", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("contract_id");
MetaModel::Init_AddFilterFromAttribute("contact_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('contract_id', 'contact_id', 'role')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('contract_id', 'contact_id', 'role')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('contract_id', 'contact_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('contract_id', 'contact_id')); // Criteria of the advanced search form
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('contract_id', $oGenerator->GenerateKey("logInfra", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('contact_id', $oGenerator->GenerateKey("bizIncidentTicket", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('role', $oGenerator->GenerateString("enum(none,mandatory,partial)"));
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Contract and a Document
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkDocumentContract extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "DocumentsContractLinks",
"description" => "A link between a document and another contract",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "link_type",
"state_attcode" => "",
"reconc_keys" => array("doc_name", "contract_name"),
"db_table" => "documents_contracts",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("doc_id", array("targetclass"=>"bizDocument", "label"=>"Document Name", "description"=>"id of the Document", "allowed_values"=>null, "sql"=>"doc_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("doc_name", array("label"=>"Document", "description"=>"name of the document", "allowed_values"=>null, "extkey_attcode"=> 'doc_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("contract_id", array("targetclass"=>"bizContract", "label"=>"Contract", "description"=>"Contract linked to this document", "allowed_values"=>null, "sql"=>"contract_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contract_name", array("label"=>"contract name", "description"=>"name of the linked contract", "allowed_values"=>null, "extkey_attcode"=> 'contract_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("link_type", array("label"=>"link_type", "description"=>"Type of the link", "allowed_values"=>null, "sql"=>"link_type", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("doc_id");
MetaModel::Init_AddFilterFromAttribute("doc_name");
MetaModel::Init_AddFilterFromAttribute("contract_id");
MetaModel::Init_AddFilterFromAttribute("contract_name");
MetaModel::Init_AddFilterFromAttribute("link_type");
// Display lists
MetaModel::Init_SetZListItems('details', array('doc_id', 'contract_name', 'link_type')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('doc_id', 'contract_name', 'link_type')); // Attributes to be displayed for a list
}
}
?>

View File

@@ -0,0 +1,261 @@
<?php
require_once('../core/MyHelpers.class.inc.php');
require_once('../core/cmdbobject.class.inc.php');
/**
* business_itopbegins.class.inc.php
* User defined objects, for unit testing
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
///////////////////////////////////////////////////////////////////////////////
// Business implementation demo
///////////////////////////////////////////////////////////////////////////////
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbContact extends CMDBObject
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "klassContact",
"description" => "klass contact description",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "att_contact_name",
"state_attcode" => "",
"reconc_keys" => array("att_contact_name"),
"db_table" => "contact",
"db_key_field" => "contactid",
"db_finalclass_field" => "actualclass",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("att_contact_name", array("label"=>"name of the contact", "description"=>"blah", "allowed_values"=>null, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"name")));
MetaModel::Init_AddAttribute(new AttributeInteger("att_contact_availability", array("label"=>"degree of availability in percent", "description"=>"blah", "allowed_values"=>null, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"availability")));
MetaModel::Init_AddAttribute(new AttributeDate("start_date", array("label"=>"Starting date", "description"=>"Incident starting date", "allowed_values"=>null, "sql"=>"start_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("att_contact_name");
MetaModel::Init_AddFilterFromAttribute("att_contact_availability");
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbPerson extends cmdbContact
{
public static function Init()
{
$oValsDunsNumber = new ValueSetObjects("cmdbCompany: att_company_dunsnumber Begins with '$[duns_prm::]'", "att_company_dunsnumber", array("att_company_dunsnumber"=>true));
$aParams = array
(
"category" => "blah",
"name" => "klassPerson",
"description" => "klass person description",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "att_contact_name",
"state_attcode" => "",
"reconc_keys" => array("att_contact_name"),
"db_table" => "person",
"db_key_field" => "personid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("att_person_email", array("label"=>"iMaile", "description"=>"imelle", "allowed_values"=>$oValsDunsNumber, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"email")));
MetaModel::Init_AddAttribute(new AttributeString("att_person_name", array("label"=>"secName", "description"=>"secondary name", "allowed_values"=>new ValueSetEnum(array("nom1", "nom2", "nom10", "no", "noms", "")), "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"name")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("att_person_email");
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbSubcontractor extends cmdbPerson
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "klassSubcontractor",
"description" => "klass subcontractor description",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "att_contact_name",
"state_attcode" => "",
"reconc_keys" => array("att_contact_name"),
"db_table" => "subcontractor",
"db_key_field" => "subcontractorid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("att_contractinfo", array("label"=>"contract info", "description"=>"blah", "allowed_values"=>null, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"contractinfo")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("ext_subcontractor_provider", array("label"=>"ssii", "description"=>"blah", "allowed_values"=>null, "sql"=>"provider", "targetclass"=>"cmdbProvider", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("extatt_subcontractor_provider_ref", array("label"=>"ref", "description"=>"blah", "allowed_values"=>null, "extkey_attcode"=>"ext_subcontractor_provider", "target_attcode"=>"att_provider_ref")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("ext_subcontractor_tutor", array("label"=>"tutor", "description"=>"blah", "allowed_values"=>null, "sql"=>"tutor", "targetclass"=>"cmdbPerson", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("extatt_subcontractor_tutor_email", array("label"=>"tutor email", "description"=>"blah", "allowed_values"=>null, "extkey_attcode"=>"ext_subcontractor_tutor", "target_attcode"=>"att_person_email")));
MetaModel::Init_AddAttribute(new AttributeExternalField("extatt_subcontractor_tutor_secondname", array("label"=>"2ndname (ext field)", "description"=>"blah", "allowed_values"=>null, "extkey_attcode"=>"ext_subcontractor_tutor", "target_attcode"=>"att_person_name")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("extatt_subcontractor_tutor_secondname");
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbCrowd extends cmdbObject
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "klassCrowd",
"description" => "klass crowd description",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "att_crowd_peoplecount",
"state_attcode" => "",
"reconc_keys" => array("att_crowd_peoplecount"),
"db_table" => "crowd",
"db_key_field" => "crowdid",
"db_finalclass_field" => "crowdclass",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeInteger("att_crowd_peoplecount", array("label"=>"people count", "description"=>"blah", "allowed_values"=>null, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"peoplecount")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("att_crowd_peoplecount");
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbCompany extends cmdbCrowd
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "klassCompany",
"description" => "klass company description",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "att_company_dunsnumber",
"state_attcode" => "",
"reconc_keys" => array("att_company_dunsnumber"),
"db_table" => "company",
"db_key_field" => "companyid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("att_company_dunsnumber", array("label"=>"duns number", "description"=>"blah", "allowed_values"=>null, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"dunsnumber")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("att_company_dunsnumber");
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbProvider extends cmdbCompany
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "klassProvider",
"description" => "klass provider description",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "att_provider_ref",
"state_attcode" => "",
"reconc_keys" => array("att_provider_ref"),
"db_table" => "provider",
"db_key_field" => "providerid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeInteger("att_provider_ref", array("label"=>"provider ref", "description"=>"blah", "allowed_values"=>null, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array(), "sql"=>"providerref")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("att_provider_ref");
}
}
?>

View File

@@ -0,0 +1,372 @@
<?php
require_once('../core/MyHelpers.class.inc.php');
require_once('../core/cmdbobject.class.inc.php');
/**
* business_test.class.inc.php
* User defined objects, for unit testing
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
///////////////////////////////////////////////////////////////////////////////
// Business implementation demo
///////////////////////////////////////////////////////////////////////////////
MetaModel::RegisterRelation("Potes", array("description"=>"ceux dont l'email ressemble au mien", "verb_down"=>"est pote de", "verb_up"=>"est pote de"));
MetaModel::RegisterZList("list1", array("description"=>"une premiere list, just for fun", "type"=>"attributes"));
MetaModel::RegisterZList("list2", array("description"=>"la secunda e meliora", "type"=>"attributes"));
MetaModel::RegisterZList("list3", array("description"=>"la variante qui tue", "type"=>"filters"));
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbObjectHomeMade extends cmdbObject
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "anyObject",
"description" => "std object",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(""),
"db_table" => "",
"db_key_field" => "",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
}
protected static function MakeHyperLink($sObjClass, $sObjKey, $aAvailableFields)
{
$sLabel = htmlentities(implode(' / ', $aAvailableFields));
$sHint = htmlentities("$sObjClass::$sObjKey");
return "<a href=\".blahforINFRA/?objclass=$sObjClass&objkey=$sObjKey\" title=\"$sHint\">$sLabel</a>";
}
public static function GetRelationQueries($sRelCode)
{
//trigger_error("GetRelationQueries: cmdbObjectHomeMade");
switch ($sRelCode)
{
case "Potes":
$aRels = array("xxxx" => array("sQuery"=>"cmdbContact: pkey = 40", "bPropagate"=>true, "iDistance"=>3));
return $aRels;
}
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbContact extends cmdbObjectHomeMade
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Contact",
"description" => "Un object que l'on peut communiquer avec",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "etat",
"reconc_keys" => array("name"),
"db_table" => "contact",
"db_key_field" => "contactid",
"db_finalclass_field" => "actualclass",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("etat", array("label"=>"l'etat", "description"=>"les etats d'ame d'eric", "allowed_values"=>new ValueSetEnum('justborn, 15, 21'), "sql"=>"etat", "default_value"=>"justborn", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"nom", "description"=>"ze equipe", "allowed_values"=>null, "sql"=>"name", "default_value"=>"XXXX", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("email", array("label"=>"iMaile", "description"=>"imelle", "allowed_values"=>null, "sql"=>"email", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("owner", array("label"=>"owned by", "description"=>"organization owning the team", "allowed_values"=>null, "sql"=>"ownerorg", "targetclass"=>"cmdbOrga", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("ownername", array("label"=>"owned by", "description"=>"name of organization owning the team", "allowed_values"=>null, "extkey_attcode"=>"owner", "target_attcode"=>"_name_")));
MetaModel::Init_AddAttribute(new AttributeExternalField("ownertnut", array("label"=>"owntnut", "description"=>"blah tnut blah", "allowed_values"=>null, "extkey_attcode"=>"owner", "target_attcode"=>"_dunsnumber_")));
MetaModel::Init_AddAttribute(new AttributeLinkedSet("myworkshops", array("label"=>"held workshops", "description"=>"blah tnut blah", "depends_on"=>array(), "linked_class"=>"cmdbLiens", "ext_key_to_me"=>"tocontact", "count_min"=>1, "count_max"=>10, "allowed_values"=>null)));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("owner");
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("ownername");
MetaModel::Init_SetZListItems("list1", array("name", "email"));
MetaModel::Init_SetZListItems("list2", array());
MetaModel::Init_SetZListItems("list3", array("ownername"));
MetaModel::Init_DefineState("justborn", array("label"=>"just born", "description"=>"too young to die", "attribute_inherit"=>null, "attribute_list"=>array("owner"=>OPT_ATT_MANDATORY)));
MetaModel::Init_DefineState("15", array("label"=>"student", "description"=>"stupid age", "attribute_inherit"=>"justborn", "attribute_list"=>array("owner"=>OPT_ATT_MUSTPROMPT, "email"=>OPT_ATT_MUSTPROMPT)));
MetaModel::Init_DefineState("21", array("label"=>"old", "description"=>"one foot in the grave", "attribute_inherit"=>"15", "attribute_list"=>array("email"=>OPT_ATT_READONLY|OPT_ATT_MUSTCHANGE)));
MetaModel::Init_DefineStimulus("toschool", new StimulusUserAction(array("label"=>"go to school", "description"=>"start learning stupid things")));
MetaModel::Init_DefineStimulus("raise", new StimulusUserAction(array("label"=>"grow!", "description"=>"eat tons of BigMACs")));
MetaModel::Init_DefineTransition("justborn", "toschool", array("target_state"=>"15", "actions"=>array('MyLifecycleHandler', 'MyLifecycleHandler2'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("15", "raise", array("target_state"=>"21", "actions"=>null, "user_restriction"=>null));
}
public static function GetRelationQueries($sRelCode)
{
//trigger_error("GetRelationQueries: cmdbContact");
switch ($sRelCode)
{
case "Potes":
$aRels = array(
"zz1" => array("sQuery"=>"cmdbContact: name Begins with '\$[this.name::]' AND pkey != \$[this.pkey::]", "bPropagate"=>false, "iDistance"=>3),
"zz2" => array("sQuery"=>"cmdbContact: owner = \$[this.owner::] AND owner != 2", "bPropagate"=>false, "iDistance"=>3),
);
return array_merge($aRels, parent::GetRelationQueries($sRelCode));
}
}
public function MyLifecycleHandler($sStimulusCode)
{
echo "<p>youhou!</p>";
return true;
}
public function MyLifecycleHandler2($sStimulusCode)
{
echo "<p>... les papous...</p>";
return true;
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbTeam extends cmdbContact
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Equipado",
"description" => "Un regroupement de gens",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "email",
"state_attcode" => "",
"reconc_keys" => array("email"),
"db_table" => "team",
"db_key_field" => "teamid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_OverloadAttributeParams("email", array("label"=>"email2", "description"=>"emailleu22"));
MetaModel::Init_AddAttribute(new AttributeInteger("headcount", array("label"=>"nombre", "description"=>"combien ils sont", "allowed_values"=>null, "sql"=>"headcount", "default_value"=>654321, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("headcount");
MetaModel::Init_SetZListItems("noneditable", array("name"));
}
public function ComputeValues()
{
//echo "Set(), function ComputeValues has been found for ".get_class($this)."<br/>\n";
$this->Set("name", $this->Get("email")." and ".$this->Get("headcount"));
}
public static function GetRelationQueries($sRelCode)
{
//trigger_error("GetRelationQueries: cmdbTeam");
switch ($sRelCode)
{
case "Potes":
//$aRels = array("Relies on" => array("sQuery"=>"cmdbContact: name Begins with 'Louis'", "bPropagate"=>false, "iDistance"=>3));
return array_merge(array(), parent::GetRelationQueries($sRelCode));
}
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbOrga extends cmdbObjectHomeMade
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Organization",
"description" => "Une entite qui possede des choses",
"key_type" => "",
"key_label" => "",
"name_attcode" => "_name_",
"state_attcode" => "",
"reconc_keys" => array("_name_"),
"db_table" => "organization",
"db_key_field" => "orgid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("_name_", array("label"=>"namo", "description"=>"official company name", "allowed_values"=>null, "sql"=>"name", "default_value"=>"XXXX", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("_status_", array("label"=>"step", "description"=>"step or status, etc.", "allowed_values"=>null, "sql"=>"status", "default_value"=>"XXXX", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("_dunsnumber_", array("label"=>"duns debile number", "description"=>"une bonne idee a OVSD", "allowed_values"=>null, "sql"=>"dunsnumber", "default_value"=>99007, "is_null_allowed"=>false, "depends_on"=>array())));
// not yet allowed MetaModel::Init_AddAttribute(new AttributeInteger("_dunsnumberBY2_", array("label"=>"dummy duns", "description"=>"deux fois plus debile", "allowed_values"=>null, "sql"=>"dunsnumber * 3.141592654")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("_name_");
MetaModel::Init_SetZListItems("list1", array("_status_"));
MetaModel::Init_SetZListItems("list2", array());
MetaModel::Init_SetZListItems("list3", array("_name_"));
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbLiens extends cmdbObjectHomeMade
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Liens_entre_contacts_et_workshop",
"description" => "Une entite qui lie des contacts et workshops",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "function",
"state_attcode" => "",
"reconc_keys" => array("function"),
"db_table" => "role_ws",
"db_key_field" => "linkid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("function", array("label"=>"fonction", "description"=>"la fonction...", "allowed_values"=>null, "sql"=>"function", "default_value"=>"XXXX", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("a1", array("label"=>"a1", "description"=>"a1", "allowed_values"=>null, "sql"=>"a1", "default_value"=>"XXXX", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("a2", array("label"=>"a1", "description"=>"a2", "allowed_values"=>null, "sql"=>"a2", "default_value"=>"XXXX", "is_null_allowed"=>true, "depends_on"=>array())));
// What makes it being a link...
MetaModel::Init_AddAttribute(new AttributeExternalKey("toworkshop", array("label"=>"participates in", "description"=>"workshop in wich the person is participating", "allowed_values"=>null, "sql"=>"ws_id", "targetclass"=>"cmdbWorkshop", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("ws_info", array("label"=>"name", "description"=>"namedescription", "allowed_values"=>null, "extkey_attcode"=>"toworkshop", "target_attcode"=>"namitus")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("tocontact", array("label"=>"is held by", "description"=>"people involved in that mess", "allowed_values"=>null, "sql"=>"contactid", "targetclass"=>"cmdbContact", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_info", array("label"=>"name", "description"=>"namedescription", "allowed_values"=>null, "extkey_attcode"=>"tocontact", "target_attcode"=>"name")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("function");
MetaModel::Init_SetZListItems("list1", array("toworkshop", "contact_info"));
MetaModel::Init_SetZListItems("list2", array("function"));
MetaModel::Init_SetZListItems("list3", array("function"));
}
public static function GetRelationQueries($sRelCode)
{
trigger_error("GetRelationQueries: cmdbLiens");
return array("Relies on" => array("sQuery"=>"", "bPropagate"=>true, "iDistance"=>3));
}
}
/**
* blah blah
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class cmdbWorkshop extends cmdbObjectHomeMade
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Workshop",
"description" => "Une entite qui pond des theories insensees",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "namitus",
"state_attcode" => "",
"reconc_keys" => array("namitus"),
"db_table" => "workshop",
"db_key_field" => "ws_id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("namitus", array("label"=>"namo", "description"=>"nom imbitique pour pondeurs de debilites", "allowed_values"=>null, "sql"=>"name", "default_value"=>"XXXX", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("namitus");
MetaModel::Init_SetZListItems("list1", array("namitus"));
MetaModel::Init_SetZListItems("list2", array());
MetaModel::Init_SetZListItems("list3", array("namitus"));
}
public static function GetRelationQueries($sRelCode)
{
trigger_error("GetRelationQueries: cmdbWorkshop");
return array("Relies on" => array("sQuery"=>"", "bPropagate"=>true, "iDistance"=>3));
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,367 @@
<?php
/**
* incident<business<php
* Define business model for incident mgmt module
*
* @package iTopBizModelSamples
* @author Erwan Taloc <erwan.taloc@gmail.com>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
////////////////////////////////////////////////////////////////////////////////////
/**
* An Incident Ticket
*/
////////////////////////////////////////////////////////////////////////////////////
class bizIncidentTicket extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Incident",
"description" => "Incident ticket",
"key_type" => "autoincrement",
"key_label" => "id",
"name_attcode" => "name",
"state_attcode" => "ticket_status",
"reconc_keys" => array("title"),
"db_table" => "incident",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/ticket.html",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"TicketID", "description"=>"Refence number ofr this incident", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("title", array("label"=>"Title", "description"=>"Overview of the Incident", "allowed_values"=>null, "sql"=>"title", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("type", array("label"=>"Type", "description"=>"Type of the Incident", "allowed_values"=>new ValueSetEnum("Network,Server,Desktop,Application"), "sql"=>"type", "default_value"=>"Server", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("customer_id", array("targetclass"=>"bizOrganization", "label"=>"Customer", "description"=>"who is impacted by the ticket", "allowed_values"=>null, "sql"=>"customer", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("customer_name", array("label"=>"Customer", "description"=>"Name of the customer impacted by this ticket", "allowed_values"=>null, "extkey_attcode"=> 'customer_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeEnum("ticket_status", array("label"=>"Status", "description"=>"Status of the ticket", "allowed_values"=>new ValueSetEnum("New, Assigned, WorkInProgress, Closed"), "sql"=>"ticket_status", "default_value"=>"New", "is_null_allowed"=>false, "depends_on"=>array())));
// SetPossibleValues("status",array("Open","Monitored","Closed"));
MetaModel::Init_AddAttribute(new AttributeText("initial_situation", array("label"=>"Initial Situation", "description"=>"Initial situation of the Incident", "allowed_values"=>null, "sql"=>"initial_situation", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("current_situation", array("label"=>"Current Situation", "description"=>"Current situation of the Incident", "allowed_values"=>null, "sql"=>"current_situation", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("start_date", array("label"=>"Starting date", "description"=>"Incident starting date", "allowed_values"=>null, "sql"=>"start_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
// définir une date de défaut à maintenant, alias creation ou modification du ticket
MetaModel::Init_AddAttribute(new AttributeDate("last_update", array("label"=>"Last update", "description"=>"last time the Ticket was modified", "allowed_values"=>null, "sql"=>"last_update", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("next_update", array("label"=>"Next update", "description"=>"next time the Ticket is expected to be modified", "allowed_values"=>null, "sql"=>"next_update", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("end_date", array("label"=>"Closed Date", "description"=>"Date when the Ticket was closed", "allowed_values"=>null, "sql"=>"closed_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("caller_id", array("targetclass"=>"bizPerson", "jointype"=> "", "label"=>"Caller", "description"=>"person that trigger incident", "allowed_values"=>null, "sql"=>"caller_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("caller_mail", array("label"=>"Caller", "description"=>"Person that trigger this incident", "allowed_values"=>null, "extkey_attcode"=> 'caller_id', "target_attcode"=>"email")));
MetaModel::Init_AddAttribute(new AttributeString("impact", array("label"=>"Impact", "description"=>"Impact of the Incident", "allowed_values"=>null, "sql"=>"impact", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("workgroup_id", array("targetclass"=>"bizWorkgroup", "jointype"=> "", "label"=>"Workgroup", "description"=>"which workgroup is owning ticket", "allowed_values"=>null, "sql"=>"workgroup_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("workgroup_name", array("label"=>"Managed by Workgroup", "description"=>"name of workgroup managing the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'workgroup_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("agent_id", array("targetclass"=>"bizPerson", "jointype"=> "", "label"=>"Agent", "description"=>"who is managing the ticket", "allowed_values"=>null, "sql"=>"agent_id", "is_null_allowed"=>true, "depends_on"=>array("workgroup_id"))));
MetaModel::Init_AddAttribute(new AttributeExternalField("agent_mail", array("label"=>"Managed by Agent", "description"=>"mail of agent managing the Ticket", "allowed_values"=>null, "extkey_attcode"=> 'agent_id', "target_attcode"=>"email")));
// Comment afficher le first + last name de l'agent ? Est-ce utile d'ajouter ce champ?
MetaModel::Init_AddAttribute(new AttributeText("action_log", array("label"=>"Action Logs", "description"=>"List all action performed during the incident", "allowed_values"=>null, "sql"=>"action_log", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("severity", array("label"=>"Severity", "description"=>"Field defining the criticity if the incident", "allowed_values"=>new ValueSetEnum("critical,medium,low"), "sql"=>"criticity", "default_value"=>"low", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("assignment_count", array("label"=>"Assignment Count", "description"=>"Number of times this ticket was assigned or reassigned", "allowed_values"=>null, "sql"=>"assignment_count", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("resolution", array("label"=>"Resolution", "description"=>"Description of the resolution", "allowed_values"=>null, "sql"=>"resolution", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("impacted_infra_manual", array("label"=>"Impacted Infrastructure", "description"=>"CIs that are not meeting the SLA", "linked_class"=>"lnkInfraTicket", "ext_key_to_me"=>"ticket_id", "ext_key_to_remote"=>"infra_id", "allowed_values"=>null, "count_min"=>1, "count_max"=>0, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("related_tickets", array("label"=>"Related Tickets", "description"=>"Other incident tickets related to this one", "linked_class"=>"lnkRelatedTicket", "ext_key_to_me"=>"ticket_id", "ext_key_to_remote"=>"rel_ticket_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array(/*'impacted_infra_computed',*/ 'impacted_infra_manual'))));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("title");
MetaModel::Init_AddFilterFromAttribute("type");
MetaModel::Init_AddFilterFromAttribute("customer_id");
MetaModel::Init_AddFilterFromAttribute("caller_id");
MetaModel::Init_AddFilterFromAttribute("ticket_status");
MetaModel::Init_AddFilterFromAttribute("start_date");
MetaModel::Init_AddFilterFromAttribute("last_update");
MetaModel::Init_AddFilterFromAttribute("end_date");
MetaModel::Init_AddFilterFromAttribute("workgroup_id");
MetaModel::Init_AddFilterFromAttribute("agent_id");
MetaModel::Init_AddFilterFromAttribute("severity");
MetaModel::Init_AddFilterFromAttribute("assignment_count");
// doit-on aussi ajouter un filtre sur les extfields lié à une extkey ? ici le name de l'agent?
// Display lists
MetaModel::Init_SetZListItems('details', array('name','title', 'customer_id', 'type','ticket_status', 'severity','start_date', 'initial_situation', 'current_situation','caller_id', 'impact', 'last_update', 'next_update','end_date', 'assignment_count', 'workgroup_id','agent_id','action_log','resolution')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('name', 'title', 'customer_id', 'type','ticket_status','severity','start_date', 'initial_situation')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'title', 'customer_id', 'caller_id','type', 'ticket_status', 'severity','start_date', 'last_update','end_date','agent_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'title', 'customer_id','caller_id','type','ticket_status', 'severity','start_date', 'last_update', 'end_date','agent_id')); // Criteria of the advanced search form
// State machine
MetaModel::Init_DefineState("New", array("label"=>"New (Unassigned)", "description"=>"Newly created ticket", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY, 'assignment_count' => OPT_ATT_HIDDEN, 'end_date' => OPT_ATT_HIDDEN, 'next_update' => OPT_ATT_HIDDEN, 'last_update' => OPT_ATT_HIDDEN,
"title"=>OPT_ATT_MANDATORY, "customer_id"=>OPT_ATT_MANDATORY, "caller_id"=>OPT_ATT_MANDATORY, "initial_situation"=>OPT_ATT_MANDATORY, "start_date"=>OPT_ATT_MANDATORY, "workgroup_id"=>OPT_ATT_MANDATORY,
"severity"=>OPT_ATT_MANDATORY, "agent_id"=>OPT_ATT_HIDDEN,"impacted_infra_manual"=>OPT_ATT_MANDATORY, "related_tickets"=>OPT_ATT_MUSTPROMPT)));
MetaModel::Init_DefineState("Assigned", array("label"=>"Assigned", "description"=>"Ticket is assigned to somebody", "attribute_inherit"=>null,
"attribute_list"=>array('name' => OPT_ATT_READONLY, "title"=>OPT_ATT_READONLY, "customer_id"=>OPT_ATT_READONLY, "caller_id"=>OPT_ATT_READONLY, "initial_situation"=>OPT_ATT_READONLY, "start_date"=>OPT_ATT_READONLY,'assignment_count' => OPT_ATT_READONLY,'end_date' => OPT_ATT_HIDDEN, "workgroup_id"=>OPT_ATT_MUSTCHANGE, "agent_id"=>OPT_ATT_MUSTCHANGE)));
MetaModel::Init_DefineState("WorkInProgress", array("label"=>"Work In Progress", "description"=>"Work is in progress", "attribute_inherit"=>null, "attribute_list"=>array("title"=>OPT_ATT_READONLY, "customer_id"=>OPT_ATT_READONLY, "caller_id"=>OPT_ATT_READONLY, "initial_situation"=>OPT_ATT_READONLY,'end_date' => OPT_ATT_HIDDEN, "start_date"=>OPT_ATT_READONLY,"workgroup_id"=>OPT_ATT_MANDATORY, "agent_id"=>OPT_ATT_MANDATORY)));
MetaModel::Init_DefineState("Closed", array("label"=>"Closed", "description"=>"Ticket is closed", "attribute_inherit"=>null, "attribute_list"=>array("workgroup_id"=>OPT_ATT_MANDATORY, "agent_id"=>OPT_ATT_MANDATORY, "resolution"=>OPT_ATT_MANDATORY, "end_date"=>OPT_ATT_MANDATORY)));
MetaModel::Init_DefineStimulus("ev_assign", new StimulusUserAction(array("label"=>"Assign this ticket", "description"=>"Assign this ticket to a group and an agent")));
MetaModel::Init_DefineStimulus("ev_reassign", new StimulusUserAction(array("label"=>"Reassign this ticket", "description"=>"Reassign this ticket to a different group and agent")));
MetaModel::Init_DefineStimulus("ev_start_working", new StimulusUserAction(array("label"=>"Work on this ticket", "description"=>"Start working on this ticket")));
MetaModel::Init_DefineStimulus("ev_close", new StimulusUserAction(array("label"=>"Close this ticket", "description"=>"Close/resolve this ticket")));
MetaModel::Init_DefineTransition("New", "ev_assign", array("target_state"=>"Assigned", "actions"=>array('IncrementAssignmentCount'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Assigned", "ev_reassign", array("target_state"=>"Assigned", "actions"=>array('IncrementAssignmentCount'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("Assigned", "ev_start_working", array("target_state"=>"WorkInProgress", "actions"=>array(), "user_restriction"=>null));
MetaModel::Init_DefineTransition("WorkInProgress", "ev_reassign", array("target_state"=>"Assigned", "actions"=>array('IncrementAssignmentCount'), "user_restriction"=>null));
MetaModel::Init_DefineTransition("WorkInProgress", "ev_close", array("target_state"=>"Closed", "actions"=>array('SetClosureDate'), "user_restriction"=>null));
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('customer_id', $oGenerator->GetOrganizationId());
$this->Set('title', $oGenerator->GenerateString("enum(Site,Server,Line)| |enum(is down,is flip-flopping,is not responding)"));
$this->Set('agent_id', $oGenerator->GenerateKey("bizPerson", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('ticket_status', $oGenerator->GenerateString("enum(Open,Closed,Closed,Monitored)"));
$this->Set('start_date', $oGenerator->GenerateString("2007-|number(07-12)|-|number(01-30)| |number(07-12)|:|number(00-59)|:|number(00-59)"));
$this->Set('last_update', $oGenerator->GenerateString("2007-|number(07-12)|-|number(01-30)| |number(07-12)|:|number(00-59)|:|number(00-59)"));
$this->Set('end_date', $oGenerator->GenerateString("2007-|number(07-12)|-|number(01-30)| |number(07-12)|:|number(00-59)|:|number(00-59)"));
}
public static function GetUIPage()
{
return './UI.php';
}
// State machine actions
public function IncrementAssignmentCount($sStimulusCode)
{
$this->Set('assignment_count', $this->Get('assignment_count') + 1);
return true;
}
public function SetClosureDate($sStimulusCode)
{
$this->Set('end_date', time());
return true;
}
public function ComputeFields()
{
if ($this->GetKey() > 0)
{
$sName = sprintf('I-%06d', $this->GetKey());
}
else
{
$sName = "Id not set";
}
$this->Set('name', $sName);
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Infra and a Incident
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkRelatedTicket extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Related Ticket",
"description" => "Ticket related to a ticket",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "impact", // ????
"state_attcode" => "",
"reconc_keys" => array("impact"), // ????
"db_table" => "related_ticket",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("rel_ticket_id", array("targetclass"=>"bizIncidentTicket", "jointype"=> '', "label"=>"Related Ticket id", "description"=>"The related ticket", "allowed_values"=>null, "sql"=>"rel_ticket_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("rel_ticket_name", array("label"=>"Related ticket", "description"=>"Name of the related ticket", "allowed_values"=>null, "extkey_attcode"=> 'rel_ticket_id', "target_attcode"=>"title")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("ticket_id", array("targetclass"=>"bizIncidentTicket", "jointype"=> '', "label"=>"Ticket #", "description"=>"Ticket number", "allowed_values"=>null, "sql"=>"ticket_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("ticket_name", array("label"=>"Ticket name", "description"=>"Name of the ticket", "allowed_values"=>null, "extkey_attcode"=> 'ticket_id', "target_attcode"=>"title")));
MetaModel::Init_AddAttribute(new AttributeString("impact", array("label"=>"Impact", "description"=>"Impact on the related ticket", "allowed_values"=>null, "sql"=>"impact", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("rel_ticket_id");
MetaModel::Init_AddFilterFromAttribute("ticket_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('rel_ticket_id', 'ticket_id', 'impact')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('rel_ticket_id', 'ticket_id', 'impact')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('rel_ticket_id', 'ticket_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('rel_ticket_id', 'ticket_id')); // Criteria of the advanced search form
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('infra_id', $oGenerator->GenerateKey("logInfra", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('ticket_id', $oGenerator->GenerateKey("bizIncidentTicket", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('impact', $oGenerator->GenerateString("enum(none,mandatory,partial)"));
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Infra and a Incident
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkInfraTicket extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Infra Ticket",
"description" => "Infra impacted by a ticket",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "impact", // ????
"state_attcode" => "",
"reconc_keys" => array("impact"), // ????
"db_table" => "infra_ticket",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("infra_id", array("targetclass"=>"logInfra", "jointype"=> '', "label"=>"Infrastructure", "description"=>"The infrastructure impacted", "allowed_values"=>null, "sql"=>"infra_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("infra_name", array("label"=>"Infrastructure name", "description"=>"Name of the impacted infrastructure", "allowed_values"=>null, "extkey_attcode"=> 'infra_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("ticket_id", array("targetclass"=>"bizIncidentTicket", "jointype"=> '', "label"=>"Ticket #", "description"=>"Ticket number", "allowed_values"=>null, "sql"=>"ticket_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("ticket_name", array("label"=>"Ticket name", "description"=>"Name of the ticket", "allowed_values"=>null, "extkey_attcode"=> 'ticket_id', "target_attcode"=>"title")));
MetaModel::Init_AddAttribute(new AttributeString("impact", array("label"=>"Impact", "description"=>"Level of impact of the infra by the related ticket", "allowed_values"=>null, "sql"=>"impact", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("infra_id");
MetaModel::Init_AddFilterFromAttribute("ticket_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('infra_id', 'ticket_id', 'impact')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('infra_id', 'ticket_id', 'impact')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('infra_id', 'ticket_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('infra_id', 'ticket_id')); // Criteria of the advanced search form
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('infra_id', $oGenerator->GenerateKey("logInfra", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('ticket_id', $oGenerator->GenerateKey("bizIncidentTicket", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('impact', $oGenerator->GenerateString("enum(none,mandatory,partial)"));
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Contqct and a Incident
*/
////////////////////////////////////////////////////////////////////////////////////
class lnkContactTicket extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Contact Ticket",
"description" => "Contacts to be notify for a ticket",
"key_type" => "autoincrement",
"key_label" => "link_id",
"name_attcode" => "role", // ????
"state_attcode" => "",
"reconc_keys" => array("role"), // ????
"db_table" => "contact_ticket",
"db_key_field" => "link_id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("contact_id", array("targetclass"=>"bizContact", "jointype"=> '', "label"=>"Contact", "description"=>"Contact to Notify", "allowed_values"=>null, "sql"=>"contact_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("contact_email", array("label"=>"Contact email", "description"=>"Mail for the contact", "allowed_values"=>null, "extkey_attcode"=> 'contact_id', "target_attcode"=>"email")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("ticket_id", array("targetclass"=>"bizIncidentTicket", "jointype"=> '', "label"=>"Ticket #", "description"=>"Ticket number", "allowed_values"=>null, "sql"=>"ticket_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("ticket_name", array("label"=>"Ticket name", "description"=>"Name of the ticket", "allowed_values"=>null, "extkey_attcode"=> 'ticket_id', "target_attcode"=>"title")));
MetaModel::Init_AddAttribute(new AttributeString("role", array("label"=>"Role", "description"=>"Role of the contact", "allowed_values"=>null, "sql"=>"role", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("contact_id");
MetaModel::Init_AddFilterFromAttribute("ticket_id");
// Display lists
MetaModel::Init_SetZListItems('details', array('contact_id', 'ticket_id', 'role')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('contact_id', 'ticket_id', 'role')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('contact_id', 'ticket_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('contact_id', 'ticket_id')); // Criteria of the advanced search form
}
public function Generate(cmdbDataGenerator $oGenerator)
{
$this->Set('infra_id', $oGenerator->GenerateKey("logInfra", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('ticket_id', $oGenerator->GenerateKey("bizIncidentTicket", array('org_id' =>$oGenerator->GetOrganizationId() )));
$this->Set('impact', $oGenerator->GenerateString("enum(none,mandatory,partial)"));
}
}
////////////////////////////////////////////////////////////////////////////////////
//**
//* A workgroup is a queue in a given call tracking system
//* It belongs to a team and a given organization
////////////////////////////////////////////////////////////////////////////////////
class bizWorkgroup extends logRealObject
{
public static function Init()
{
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "Workgroup",
"description" => "Call tracking workgroup",
"key_type" => "",
"key_label" => "id",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array("org_name", "name"), // inherited attributes
"db_table" => "workgroups",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalField("org_name", array("label"=>"Organization", "description"=>"Company / Department owning this object", "allowed_values"=>null, "extkey_attcode"=> 'org_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalKey("team_id", array("targetclass"=>"bizTeam", "label"=>"Team", "description"=>"Team owning the workgroup", "allowed_values"=>null, "sql"=>"team_id", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("team_name", array("label"=>"Team name", "description"=>"name of the team", "allowed_values"=>null, "extkey_attcode"=> 'team_id', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("role", array("label"=>"Role", "description"=>"Role of this work group", "allowed_values"=>new ValueSetEnum("1st level support,2nd level support,3rd level support"), "sql"=>"role", "default_value"=>"1st level support", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("org_name");
MetaModel::Init_AddFilterFromAttribute("team_id");
MetaModel::Init_AddFilterFromAttribute("role");
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'status', 'org_id', 'team_id', 'role')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'team_id','role')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'status', 'team_id')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'status', 'team_id','role')); // Criteria of the advanced search form
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/WanLinks.jpg" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizInterface: PKEY IS interface_id IN (bizCircuit: pkey = $pkey$)</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,19 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/software.jpg" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizApplication: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Impacted_Client_Application">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizApplication: PKEY IS client_id IN (lnkClientServer: server_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Application_Server">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizApplication: PKEY IS server_id IN (lnkClientServer: client_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Contracts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkInfraContract: infra_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,17 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/imageChange.gif" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Impacted_Infrastructure">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkInfraChangeTicket: ticket_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts_to_Notify">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkContactChange: change_id = $pkey$</itopblock>
</itoptab>
</itoptabs>
<br style="clear:both"/>

View File

@@ -0,0 +1,18 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/erwanContracts.jpg" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizContract: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Covered_Infrastructures">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkInfraContract: contract_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contact">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkContactContract: contract_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Document">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkDocumentContract: contract_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,8 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/tar.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>

View File

@@ -0,0 +1,13 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/folder_documents.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Version">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizDocVersion: document = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,16 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/tar.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizInfraGroup: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Infrastructures">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkInfraGrouping: infra_group_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkContactRealObject: object_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,14 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/tar.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizInterface: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Linked_interfaces">
<itopblock blockclass="DisplayBlock" type="list" linkage="interface1_id" encoding="text/sibusql">lnkInterfaces: interface1_id = $pkey$</itopblock>
<itopblock blockclass="DisplayBlock" type="list" linkage="interface2_id" encoding="text/sibusql">lnkInterfaces: interface2_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,25 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/starthere.png" style="margin-top:-20px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizLocation: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizContact: location_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Servers">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizServer: location_id = $pkey$</itopblock>
</itoptab>
<itoptab name="PCs">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizPC: location_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Network_Devices">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizNetworkDevice: location_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkDocumentRealObject: object_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,20 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizNetworkDevice: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizInterface: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizContact: PKEY IS contact_id IN (lnkContactRealObject: object_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkDocumentRealObject: object_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,24 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/laptop_pcmcia.png" style="margin-top:-20px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizPC: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Installed_Application">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizApplication: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Installed_Patches">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizPatch: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkContactRealObject: object_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizInterface: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizDocument: PKEY IS doc_id IN (lnkDocumentRealObject: object_id = $pkey$)</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,18 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/users2-big.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizPerson: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Teams">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkContactRealObject: object_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Infrastructure">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">logRealObject: PKEY IS object_id IN (lnkContactRealObject: contact_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizDocument: PKEY IS doc_id IN (lnkDocumentRealObject: object_id = $pkey$)</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,24 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/network-server.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizServer: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Applications">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizApplication: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Patches">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizPatch: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizInterface: device_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts">
<itopblock blockclass="DisplayBlock" type="list" linkage="object_id" encoding="text/sibusql">lnkContactRealObject: object_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizDocument: PKEY IS doc_id IN (lnkDocumentRealObject: object_id = $pkey$)</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,13 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/kservices-big.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Contracts">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="list" encoding="text/sibusql">bizContract: service_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,13 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/software.jpg" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">bizSoftware: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Installed_Instances">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizApplication: soft_id = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,21 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/users2-big.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Members">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizContact: PKEY IS object_id IN (lnkContactRealObject: contact_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Teams">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizTeam: PKEY IS object_id IN (lnkContactRealObject: contact_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Infrastructure">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">logInfra: PKEY IS object_id IN (lnkContactRealObject: contact_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Documents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">bizDocument: PKEY IS doc_id IN (lnkDocumentRealObject: object_id = $pkey$)</itopblock>
</itoptab>
</itoptabs>

View File

@@ -0,0 +1,21 @@
<div class="page_header">
<itopblock blockclass="MenuBlock" type="popup" encoding="text/sibusql" label="Actions">$class$: pkey = $pkey$</itopblock>
<h1>$class$: <span class="hilite">$name$</span></h1>
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/sibusql">CMDBChangeOpSetAttribute: objkey = $pkey$</itopblock>
</div>
<img src="../images/messagebox_warning.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/sibusql">$class$: pkey = $pkey$</itopblock>
<itoptabs>
<itoptab name="Impacted_Infrastructure">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">logInfra: PKEY IS infra_id IN (lnkInfraTicket: ticket_id = $pkey$)</itopblock>
</itoptab>
<itoptab name="Related_Incidents">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkRelatedTicket: ticket_id = $pkey$</itopblock>
</itoptab>
<itoptab name="Contacts_to_Notify">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/sibusql">lnkContactTicket: ticket_id = $pkey$</itopblock>
</itoptab>
</itoptabs>
<br style="clear:both"/>

View File

@@ -0,0 +1,272 @@
<?php
/**
* test_farm.class.inc.php
* User defined objects, for unit testing - SQL generation oriented (complex links)
*
* @package iTopUnitTests
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
///////////////////////////////////////////////////////////////////////////////
// Business implementation demo
///////////////////////////////////////////////////////////////////////////////
//todo MetaModel::RegisterRelation("Potes", array("description"=>"ceux dont l'email ressemble au mien", "verb_down"=>"est pote de", "verb_up"=>"est pote de"));
//todo MetaModel::RegisterZList("list1", array("description"=>"une premiere list, just for fun", "type"=>"attributes"));
//todo MetaModel::RegisterZList("list2", array("description"=>"la secunda e meliora", "type"=>"attributes"));
//todo MetaModel::RegisterZList("list3", array("description"=>"la variante qui tue", "type"=>"filters"));
class Animal extends dbObject
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Animal",
"description" => "An animal",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(""),
"db_table" => "animals",
"db_key_field" => "animalid",
"db_finalclass_field" => "actualclass",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeEnum("sex", array("label"=>"sex", "description"=>"sex", "allowed_values"=>new ValueSetEnum('male, female'), "sql"=>"sex", "default_value"=>"male", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("species", array("label"=>"species", "description"=>"species", "allowed_values"=>null, "sql"=>"species", "default_value"=>"xxx", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("speed", array("label"=>"walk speed", "description"=>"maximum possible speed m.s-1", "allowed_values"=>null, "sql"=>"speed", "default_value"=>4, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("mother", array("label"=>"mother", "description"=>"mother", "allowed_values"=>null, "sql"=>"mother", "targetclass"=>"Animal", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("father", array("label"=>"father", "description"=>"father", "allowed_values"=>null, "sql"=>"father", "targetclass"=>"Animal", "is_null_allowed"=>true, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("sex");
MetaModel::Init_AddFilterFromAttribute("species");
MetaModel::Init_AddFilterFromAttribute("speed");
MetaModel::Init_AddFilterFromAttribute("mother");
MetaModel::Init_AddFilterFromAttribute("father");
}
}
class Mammal extends Animal
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Mammal",
"description" => "An animal with some characteristics",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "mammals",
"db_key_field" => "mammalid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"name", "description"=>"name", "allowed_values"=>null, "sql"=>"name", "default_value"=>"xxx", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("height", array("label"=>"height", "description"=>"size in centimeters", "allowed_values"=>null, "sql"=>"height", "default_value"=>1, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("birth", array("label"=>"birth date", "description"=>"birth date", "allowed_values"=>null, "sql"=>"birth", "default_value"=>1, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("member", array("label"=>"member", "description"=>"leader", "allowed_values"=>null, "sql"=>"member", "targetclass"=>"Group", "is_null_allowed"=>true, "depends_on"=>array())));
// ? MetaModel::Init_AddAttribute(new AttributeLinkedSet("a2a", array("label"=>"animal to animal", "description"=>"interanimal relations", "depends_on"=>array(), "linked_class"=>"Animal2animal", "ext_key_to_me"=>"animal1", "count_min"=>0, "count_max"=>10, "allowed_values"=>null)));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("height");
MetaModel::Init_AddFilterFromAttribute("birth");
MetaModel::Init_AddFilterFromAttribute("member");
}
}
class Bird extends Animal
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Bird",
"description" => "Un regroupement de gens",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "birds",
"db_key_field" => "birdid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_OverloadAttributeParams("species", array("allowed_values"=>array('geese', 'rooster', 'chicken', 'turckey', 'pie', 'corbeau')));
MetaModel::Init_InheritFilters();
}
}
class WalkingBird extends Bird
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "WalkingBird",
"description" => "A bird which nevers flies",
"key_type" => "",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "walkingbirds",
"db_key_field" => "walkingbirdid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_OverloadAttributeParams("species", array("allowed_values"=>array('geese', 'rooster', 'chicken', 'turckey')));
MetaModel::Init_InheritFilters();
}
}
class FlyingBird extends Bird
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "FlyingBird",
"description" => "A bird which nevers flies",
"key_type" => "",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "flyingbirds",
"db_key_field" => "flyingbirdid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_OverloadAttributeParams("species", array("allowed_values"=>array('pie', 'corbeau')));
MetaModel::Init_AddAttribute(new AttributeInteger("flyingspeed", array("label"=>"flying speed", "description"=>"flying at ms.s-1", "allowed_values"=>null, "sql"=>"headcount", "default_value"=>10, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("flyingspeed");
}
}
class AnimalRelation extends dbObject
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "AnimalRelation",
"description" => "Link between two animals",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "a2a",
"db_key_field" => "linkid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
// What makes it being a link...
MetaModel::Init_AddAttribute(new AttributeExternalKey("animal1", array("label"=>"source", "description"=>"the animal which does ...", "allowed_values"=>null, "sql"=>"a1", "targetclass"=>"Animal", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("animal2", array("label"=>"target", "description"=>"the animal to which something is done...", "allowed_values"=>null, "sql"=>"a2", "targetclass"=>"Animal", "is_null_allowed"=>false, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("animal1");
MetaModel::Init_AddFilterFromAttribute("animal2");
}
}
class EaterToEaten extends AnimalRelation
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "EaterToEaten",
"description" => "Animal 1 eats animal 2",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "eatertoeaten",
"db_key_field" => "eatertoeatonid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeEnum("DeadOrAlive", array("label"=>"DeadOrAlive", "description"=>"State in which it is ok for the eater to proceed", "allowed_values"=>new ValueSetEnum('dead, fresh, cooked'), "sql"=>"deadoralive", "default_value"=>"fresh", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("DeadOrAlive");
}
}
class Group extends dbObject
{
public static function Init()
{
$aParams = array
(
"category" => "blah",
"name" => "Group",
"description" => "Group of animals",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "groups",
"db_key_field" => "groupid",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"name", "description"=>"name", "allowed_values"=>null, "sql"=>"name", "default_value"=>"xxx", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("leader", array("label"=>"leader", "description"=>"leader", "allowed_values"=>null, "sql"=>"leader", "targetclass"=>"Mammal", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("leader_name", array("label"=>"Leader Name", "description"=>"Name of the leader (defined on Mammal)", "allowed_values"=>null, "extkey_attcode"=> 'leader', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeExternalField("leader_speed", array("label"=>"Leader Name", "description"=>"Speed of the leader (defined on Animal)", "allowed_values"=>null, "extkey_attcode"=> 'leader', "target_attcode"=>"speed")));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("name");
MetaModel::Init_AddFilterFromAttribute("leader");
MetaModel::Init_AddFilterFromAttribute("leader_name");
MetaModel::Init_AddFilterFromAttribute("leader_speed");
}
}
?>

38
config-dist.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
//
// phpMyORM configuration file
//
// To be manually edited (or generated by the configuration wizard)
//
// The file is used in MetaModel::LoadConfig() which does all the necessary initialization job
//
$MySettings = array(
'db_host' => 'localhost',
'db_user' => 'itop',
'db_pwd' => '1T0p',
'db_name' => 'itopv06',
'db_subname' => '', // use it to differentiate two applications instances running on the same DB
);
// Modules: file names should be specified as a absolute paths
$MyModules = array(
'application' => array (
'../application/menunode.class.inc.php',
'../application/audit.rule.class.inc.php',
// to be continued...
),
'business' => array (
'../business/itop.business.class.inc.php'
// to be continued...
),
'addons' => array (
'user rights' => '../addons/userrights/userrightsmatrix.class.inc.php',
// other modules to come later
)
);
?>

35
config-test-farm.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
//
// phpMyORM configuration file
//
// To be manually edited (or generated by the configuration wizard)
//
// The file is used in MetaModel::LoadConfig() which does all the necessary initialization job
//
$MySettings = array(
'db_host' => 'localhost',
'db_user' => 'RomainDBLogin',
'db_pwd' => '',
'db_name' => 'TestFarm',
'db_subname' => '', // use it to differentiate two applications instances running on the same DB
);
// Modules: file names should be specified as a absolute paths
$MyModules = array(
'application' => array (
// to be continued...
),
'business' => array (
'../business/test_farm.class.inc.php',
// to be continued...
),
'addons' => array (
//'user rights' => '/addons/userrights/userrightsnull.class.inc.php', // or userrightsmatrix.class.inc.php
// other modules to come later
)
);
?>

36
config-test-mymodel.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
//
// phpMyORM configuration file
//
// To be manually edited (or generated by the configuration wizard)
//
// The file is used in MetaModel::LoadConfig() which does all the necessary initialization job
//
$MySettings = array(
'db_host' => 'localhost',
'db_user' => 'itop',
'db_pwd' => '1T0p',
'db_name' => 'TestBizModelGenericItop',
'db_subname' => 'tribute2itop', // use it to differentiate two applications instances running on the same DB
);
// Modules: file names should be specified as a absolute paths
$MyModules = array(
'application' => array (
// to be continued...
),
'business' => array (
'../business/business_test.class.inc.php'
// to be continued...
),
'addons' => array (
// other modules to come later
)
);
?>

View File

@@ -0,0 +1,383 @@
<?php
/**
* MyHelpers
* various dev/debug helpers, to cleanup or at least re-organize
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class MyHelpers
{
public static function CheckValueInArray($sDescription, $value, $aData)
{
if (!in_array($value, $aData))
{
self::HandleWrongValue($sDescription, $value, $aData);
}
}
public static function CheckKeyInArray($sDescription, $key, $aData)
{
if (!array_key_exists($key, $aData))
{
self::HandleWrongValue($sDescription, $key, array_keys($aData));
}
}
public static function HandleWrongValue($sDescription, $value, $aData)
{
if (count($aData) == 0)
{
$sArrayDesc = "{}";
}
else
{
$sArrayDesc = "{".implode(", ", $aData)."}";
}
// exit!
trigger_error("Wrong value for $sDescription, found '$value' while expecting a value in $sArrayDesc", E_USER_ERROR);
}
// getmicrotime()
// format sss.mmmuuupppnnn
public static function getmicrotime()
{
list($usec, $sec) = explode(" ",microtime());
return ((float)$usec + (float)$sec);
}
/*
* MakeSQLComment
* converts hash into text comment which we can use in a (mySQL) query
*/
public static function MakeSQLComment ($aHash)
{
if (empty($aHash)) return "";
$sComment = "";
{
foreach($aHash as $sKey=>$sValue)
{
$sComment .= "\n-- ". $sKey ."=>" . $sValue;
}
}
return $sComment;
}
public static function var_dump_html($aWords, $bFullDisplay = false)
{
echo "<pre>\n";
if ($bFullDisplay)
{
print_r($aWords); // full dump!
}
else
{
var_dump($aWords); // truncate things when they are too big
}
echo "\n</pre>\n";
}
public static function arg_dump_html()
{
echo "<pre>\n";
echo "GET:\n";
var_dump($_GET);
echo "POST:\n";
var_dump($_POST);
echo "\n</pre>\n";
}
public static function get_callstack_html($iLevelsToIgnore = 0, $aCallStack = null)
{
if ($aCallStack == null) $aCallStack = debug_backtrace();
$aCallStack = array_slice($aCallStack, $iLevelsToIgnore);
$aDigestCallStack = array();
$bFirstLine = true;
foreach ($aCallStack as $aCallInfo)
{
$sLine = empty($aCallInfo['line']) ? "" : $aCallInfo['line'];
$sFile = empty($aCallInfo['file']) ? "" : $aCallInfo['file'];
$sClass = empty($aCallInfo['class']) ? "" : $aCallInfo['class'];
$sType = empty($aCallInfo['type']) ? "" : $aCallInfo['type'];
$sFunction = empty($aCallInfo['function']) ? "" : $aCallInfo['function'];
if ($bFirstLine)
{
$bFirstLine = false;
// For this line do not display the "function name" because
// that will be the name of our error handler for sure !
$sFunctionInfo = "N/A";
}
else
{
$args = '';
if (empty($aCallInfo['args'])) $aCallInfo['args'] = array();
foreach ($aCallInfo['args'] as $a)
{
if (!empty($args))
{
$args .= ', ';
}
switch (gettype($a))
{
case 'integer':
case 'double':
$args .= $a;
break;
case 'string':
$a = Str::pure2html(self::beautifulstr($a, 1024, true, true));
$args .= "\"$a\"";
break;
case 'array':
$args .= 'Array('.count($a).')';
break;
case 'object':
$args .= 'Object('.get_class($a).')';
break;
case 'resource':
$args .= 'Resource('.strstr($a, '#').')';
break;
case 'boolean':
$args .= $a ? 'True' : 'False';
break;
case 'NULL':
$args .= 'Null';
break;
default:
$args .= 'Unknown';
}
}
$sFunctionInfo = "$sClass $sType $sFunction($args)";
}
$aDigestCallStack[] = array('File'=>$sFile, 'Line'=>$sLine, 'Function'=>$sFunctionInfo);
}
return self::make_table_from_assoc_array($aDigestCallStack);
}
public static function dump_callstack($iLevelsToIgnore = 0, $aCallStack = null)
{
return self::get_callstack_html($iLevelsToIgnore, $aCallStack);
}
///////////////////////////////////////////////////////////////////////////////
// Source: New
// Last modif: 2004/12/20 RQU
///////////////////////////////////////////////////////////////////////////////
public static function make_table_from_assoc_array(&$aData)
{
if (!is_array($aData)) trigger_error("make_table_from_assoc_array: Error - the passed argument is not an array", E_USER_ERROR);
$aFirstRow = reset($aData);
if (!is_array($aFirstRow)) trigger_error("make_table_from_assoc_array: Error - the passed argument is not a bi-dimensional array", E_USER_ERROR);
$sOutput = "";
$sOutput .= "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"1\">\n";
// Table header
//
$sOutput .= " <TR CLASS=celltitle>\n";
foreach ($aFirstRow as $fieldname=>$trash) {
$sOutput .= " <TD><B>".$fieldname."</B></TD>\n";
}
$sOutput .= " </TR>\n";
// Table contents
//
$iCount = 0;
foreach ($aData as $aRow) {
$sStyle = ($iCount++ % 2 ? "STYLE=\"background-color : #eeeeee\"" : "");
$sOutput .= " <TR $sStyle CLASS=cell>\n";
foreach ($aRow as $data) {
if (strlen($data) == 0) {
$data = "&nbsp;";
}
$sOutput .= " <TD>".$data."</TD>\n";
}
$sOutput .= " </TR>\n";
}
$sOutput .= "</TABLE>\n";
return $sOutput;
}
public static function debug_breakpoint($arg)
{
echo "<H1> Debug breakpoint </H1>\n";
MyHelpers::var_dump_html($arg);
MyHelpers::dump_callstack();
exit;
}
public static function debug_breakpoint_notempty($arg)
{
if (empty($arg)) return;
echo "<H1> Debug breakpoint (triggered on non-empty value) </H1>\n";
MyHelpers::var_dump_html($arg);
MyHelpers::dump_callstack();
exit;
}
/**
* utf8... converts non ASCII chars into '?'
* Decided after some complex investigations, to have the tools work fine (Oracle+Perl vs mySQL+PHP...)
*/
public static function utf8($strText)
{
return iconv("WINDOWS-1252", "ASCII//TRANSLIT", $strText);
}
/**
* xmlentities()
* ... same as htmlentities, but designed for xml !
*/
public static function xmlentities($string)
{
return str_replace( array( '&', '"', "'", '<', '>' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ), $string );
}
/**
* xmlencode()
* Encodes a string so that for sure it can be output as an xml data string
*/
public static function xmlencode($string)
{
return xmlentities(iconv("UTF-8", "UTF-8//IGNORE",$string));
}
///////////////////////////////////////////////////////////////////////////////
// Source: New - format strings for output
// Last modif: 2005/01/18 RQU
///////////////////////////////////////////////////////////////////////////////
public static function beautifulstr($sLongString, $iMaxLen, $bShowLen=false, $bShowTooltip=true)
{
if (!is_string($sLongString)) trigger_error("beautifulstr: expect a string as 1st argument", E_USER_ERROR);
// Nothing to do if the string is short
if (strlen($sLongString) <= $iMaxLen) return $sLongString;
// Truncate the string
$sSuffix = "...";
if ($bShowLen) {
$sSuffix .= "(".strlen($sLongString)." chars)...";
}
$sOutput = substr($sLongString, 0, $iMaxLen - strlen($sSuffix)).$sSuffix;
$sOutput = htmlspecialchars($sOutput);
// Add tooltip if required
//if ($bShowTooltip) {
// $oTooltip = new gui_tooltip($sLongString);
// $sOutput = "<SPAN ".$oTooltip->get_mouseOver_code().">".$sOutput."</SPAN>";
//}
return $sOutput;
}
}
/**
Utility class: static methods for cleaning & escaping untrusted (i.e.
user-supplied) strings.
Any string can (usually) be thought of as being in one of these 'modes':
pure = what the user actually typed / what you want to see on the page /
what is actually stored in the DB
gpc = incoming GET, POST or COOKIE data
sql = escaped for passing safely to RDBMS via SQL (also, data from DB
queries and file reads if you have magic_quotes_runtime on--which
is rare)
html = safe for html display (htmlentities applied)
Always knowing what mode your string is in--using these methods to
convert between modes--will prevent SQL injection and cross-site scripting.
This class refers to its own namespace (so it can work in PHP 4--there is no
self keyword until PHP 5). Do not change the name of the class w/o changing
all the internal references.
Example usage: a POST value that you want to query with:
$username = Str::gpc2sql($_POST['username']);
*/
//This sets SQL escaping to use slashes; for Sybase(/MSSQL)-style escaping
// ( ' --> '' ), set to true.
define('STR_SYBASE', false);
class Str
{
public static function gpc2sql($gpc, $maxLength = false)
{
return self::pure2sql(self::gpc2pure($gpc), $maxLength);
}
public static function gpc2html($gpc, $maxLength = false)
{
return self::pure2html(self::gpc2pure($gpc), $maxLength);
}
public static function gpc2pure($gpc)
{
if (ini_get('magic_quotes_sybase')) $pure = str_replace("''", "'", $gpc);
else $pure = get_magic_quotes_gpc() ? stripslashes($gpc) : $gpc;
return $pure;
}
public static function html2pure($html)
{
return html_entity_decode($html);
}
public static function html2sql($html, $maxLength = false)
{
return self::pure2sql(self::html2pure($html), $maxLength);
}
public static function pure2html($pure, $maxLength = false)
{
return $maxLength
? htmlentities(substr($pure, 0, $maxLength))
: htmlentities($pure);
}
public static function pure2sql($pure, $maxLength = false)
{
if ($maxLength) $pure = substr($pure, 0, $maxLength);
return (STR_SYBASE)
? str_replace("'", "''", $pure)
: addslashes($pure);
}
public static function sql2html($sql, $maxLength = false)
{
$pure = self::sql2pure($sql);
if ($maxLength) $pure = substr($pure, 0, $maxLength);
return self::pure2html($pure);
}
public static function sql2pure($sql)
{
return (STR_SYBASE)
? str_replace("''", "'", $sql)
: stripslashes($sql);
}
public static function xml2pure($xml)
{
// #@# - not implemented
return $xml;
}
public static function pure2xml($pure)
{
return self::xmlencode($pure);
}
protected static function xmlentities($string)
{
return str_replace( array( '&', '"', "'", '<', '>' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;' ), $string );
}
/**
* xmlencode()
* Encodes a string so that for sure it can be output as an xml data string
*/
protected static function xmlencode($string)
{
return self::xmlentities(iconv("ISO-8859-1", "UTF-8//IGNORE",$string));
}
public static function islowcase($sString)
{
return (strtolower($sString) == $sString);
}
}
?>

323
core/archive.class.inc.php Normal file
View File

@@ -0,0 +1,323 @@
<?php
/**
* archive.class.inc.php
* Utility to import/export the DB from/to a ZIP file
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
/**
* iTopArchive a class to manipulate (read/write) iTop archives with their catalog
* Each iTop archive is a zip file that contains (at the root of the archive)
* a file called catalog.xml holding the description of the archive
*/
class iTopArchive
{
const read = 0;
const create = ZipArchive::CREATE;
protected $m_sZipPath;
protected $m_oZip;
protected $m_sVersion;
protected $m_sTitle;
protected $m_sDescription;
protected $m_aPackages;
protected $m_aErrorMessages;
/**
* Construct an iTopArchive object
* @param $sArchivePath string The full path the archive file
* @param $iMode integrer Either iTopArchive::read for reading an existing archive or iTopArchive::create for creating a new one. Updating is not supported (yet)
*/
public function __construct($sArchivePath, $iMode = iTopArchive::read)
{
$this->m_sZipPath = $sArchivePath;
$this->m_oZip = new ZipArchive();
$this->m_oZip->open($this->m_sZipPath, $iMode);
$this->m_aErrorMessages = array();
$this->m_sVersion = '1.0';
$this->m_sTitle = '';
$this->m_sDescription = '';
$this->m_aPackages = array();
}
public function SetTitle($sTitle)
{
$this->m_sTitle = $sTitle;
}
public function SetDescription($sDescription)
{
$this->m_sDescription = $sDescription;
}
public function GetTitle()
{
return $this->m_sTitle;
}
public function GetDescription()
{
return $this->m_sDescription;
}
public function GetPackages()
{
return $this->m_aPackages;
}
public function __destruct()
{
$this->m_oZip->close();
}
/**
* Get the error message explaining the latest error encountered
* @return array All the error messages encountered during the validation
*/
public function GetErrors()
{
return $this->m_aErrorMessages;
}
/**
* Read the catalog from the archive (zip) file
* @param sPath string Path the the zip file
* @return boolean True in case of success, false otherwise
*/
public function ReadCatalog()
{
if ($this->IsValid())
{
$sXmlCatalog = $this->m_oZip->getFromName('catalog.xml');
$oParser = xml_parser_create();
xml_parse_into_struct($oParser, $sXmlCatalog, $aValues, $aIndexes);
xml_parser_free($oParser);
$iIndex = $aIndexes['ARCHIVE'][0];
$this->m_sVersion = $aValues[$iIndex]['attributes']['VERSION'];
$iIndex = $aIndexes['TITLE'][0];
$this->m_sTitle = $aValues[$iIndex]['value'];
$iIndex = $aIndexes['DESCRIPTION'][0];
if (array_key_exists('value', $aValues[$iIndex]))
{
// #@# implement a get_array_value(array, key, default) ?
$this->m_sDescription = $aValues[$iIndex]['value'];
}
foreach($aIndexes['PACKAGE'] as $iIndex)
{
$this->m_aPackages[$aValues[$iIndex]['attributes']['HREF']] = array( 'type' => $aValues[$iIndex]['attributes']['TYPE'], 'title'=> $aValues[$iIndex]['attributes']['TITLE'], 'description' => $aValues[$iIndex]['value']);
}
//echo "Archive path: {$this->m_sZipPath}<br/>\n";
//echo "Archive format version: {$this->m_sVersion}<br/>\n";
//echo "Title: {$this->m_sTitle}<br/>\n";
//echo "Description: {$this->m_sDescription}<br/>\n";
//foreach($this->m_aPackages as $aFile)
//{
// echo "{$aFile['title']} ({$aFile['type']}): {$aFile['description']}<br/>\n";
//}
}
return true;
}
public function WriteCatalog()
{
$sXml = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?".">\n"; // split the XML closing tag that disturbs PSPad's syntax coloring
$sXml .= "<archive version=\"1.0\">\n";
$sXml .= "<title>{$this->m_sTitle}</title>\n";
$sXml .= "<description>{$this->m_sDescription}</description>\n";
foreach($this->m_aPackages as $sFileName => $aFile)
{
$sXml .= "<package title=\"{$aFile['title']}\" type=\"{$aFile['type']}\" href=\"$sFileName\">{$aFile['description']}</package>\n";
}
$sXml .= "</archive>";
$this->m_oZip->addFromString('catalog.xml', $sXml);
}
/**
* Add a package to the archive
* @param string $sExternalFilePath The path to the file to be added to the archive as a package (directories are not yet implemented)
* @param string $sFilePath The name of the file inside the archive
* @param string $sTitle A short title for this package
* @param string $sType Type of the package. SQL scripts must be of type 'text/sql'
* @param string $sDescription A longer description of the purpose of this package
* @return none
*/
public function AddPackage($sExternalFilePath, $sFilePath, $sTitle, $sType, $sDescription)
{
$this->m_aPackages[$sFilePath] = array('title' => $sTitle, 'type' => $sType, 'description' => $sDescription);
$this->m_oZip->addFile($sExternalFilePath, $sFilePath);
}
/**
* Reads the contents of the given file from the archive
* @param string $sFileName The path to the file inside the archive
* @return string The content of the file read from the archive
*/
public function GetFileContents($sFileName)
{
return $this->m_oZip->getFromName($sFileName);
}
/**
* Extracts the contents of the given file from the archive
* @param string $sFileName The path to the file inside the archive
* @param string $sDestinationFileName The path of the file to write
* @return none
*/
public function ExtractToFile($sFileName, $sDestinationFileName)
{
$iBufferSize = 64 * 1024; // Read 64K at a time
$oZipStream = $this->m_oZip->getStream($sFileName);
$oDestinationStream = fopen($sDestinationFileName, 'wb');
while (!feof($oZipStream)) {
$sContents = fread($oZipStream, $iBufferSize);
fwrite($oDestinationStream, $sContents);
}
fclose($oZipStream);
fclose($oDestinationStream);
}
/**
* Apply a SQL script taken from the archive. The package must be listed in the catalog and of type text/sql
* @param string $sFileName The path to the SQL package inside the archive
* @return boolean false in case of error, true otherwise
*/
public function ImportSql($sFileName, $sDatabase = 'itop')
{
if ( ($this->m_oZip->locateName($sFileName) == false) || (!isset($this->m_aPackages[$sFileName])) || ($this->m_aPackages[$sFileName]['type'] != 'text/sql'))
{
// invalid type or not listed in the catalog
return false;
}
$sTempName = tempnam("../tmp/", "sql");
//echo "Extracting to: '$sTempName'<br/>\n";
$this->ExtractToFile($sFileName, $sTempName);
// Note: the command line below works on Windows with the right path to mysql !!!
$sCommandLine = 'type "'.$sTempName.'" | "/iTop/MySQL Server 5.0/bin/mysql.exe" -u root '.$sDatabase;
//echo "Executing: '$sCommandLine'<br/>\n";
exec($sCommandLine, $aOutput, $iRet);
//echo "Return code: $iRet<br/>\n";
//echo "Output:<br/><pre>\n";
//print_r($aOutput);
//echo "</pre><br/>\n";
unlink($sTempName);
return ($iRet == 0);
}
/**
* Dumps some part of the specified MySQL database into the archive as a text/sql package
* @param $sTitle string A short title for this SQL script
* @param $sDescription string A longer description of the purpose of this SQL script
* @param $sFileName string The name of the package inside the archive
* @param $sDatabase string name of the database
* @param $aTables array array or table names. If empty, all tables are dumped
* @param $bStructureOnly boolean Whether or not to dump the data or just the schema
* @return boolean False in case of error, true otherwise
*/
public function AddDatabaseDump($sTitle, $sDescription, $sFileName, $sDatabase = 'itop', $aTables = array(), $bStructureOnly = true)
{
$sTempName = tempnam("../tmp/", "sql");
$sNoData = $bStructureOnly ? "--no-data" : "";
$sCommandLine = "\"/iTop/MySQL Server 5.0/bin/mysqldump.exe\" --user=root --opt $sNoData --result-file=$sTempName $sDatabase ".implode(" ", $aTables);
//echo "Executing command: '$sCommandLine'<br/>\n";
exec($sCommandLine, $aOutput, $iRet);
//echo "Return code: $iRet<br/>\n";
//echo "Output:<br/><pre>\n";
//print_r($aOutput);
//echo "</pre><br/>\n";
if ($iRet == 0)
{
$this->AddPackage($sTempName, $sFileName, $sTitle, 'text/sql', $sDescription);
}
//unlink($sTempName);
return ($iRet == 0);
}
/**
* Check the consistency of the archive
* @return boolean True if the archive file is consistent
*/
public function IsValid()
{
// TO DO: use a DTD to validate the XML instead of this hand-made validation
$bResult = true;
$aMandatoryTags = array('ARCHIVE' => array('VERSION'),
'TITLE' => array(),
'DESCRIPTION' => array(),
'PACKAGE' => array('TYPE', 'HREF', 'TITLE'));
$sXmlCatalog = $this->m_oZip->getFromName('catalog.xml');
$oParser = xml_parser_create();
xml_parse_into_struct($oParser, $sXmlCatalog, $aValues, $aIndexes);
xml_parser_free($oParser);
foreach($aMandatoryTags as $sTag => $aAttributes)
{
// Check that all the required tags are present
if (!isset($aIndexes[$sTag]))
{
$this->m_aErrorMessages[] = "The XML catalog does not contain the mandatory tag $sTag.";
$bResult = false;
}
else
{
foreach($aIndexes[$sTag] as $iIndex)
{
switch($aValues[$iIndex]['type'])
{
case 'complete':
case 'open':
// Check that all the required attributes are present
foreach($aAttributes as $sAttribute)
{
if (!isset($aValues[$iIndex]['attributes'][$sAttribute]))
{
$this->m_aErrorMessages[] = "The tag $sTag ($iIndex) does not contain the required attribute $sAttribute.";
}
}
break;
default:
// ignore other type of tags: close or cdata
}
}
}
}
return $bResult;
}
}
/*
// Unit test - reading an archive
$sArchivePath = '../tmp/archive.zip';
$oArchive = new iTopArchive($sArchivePath, iTopArchive::read);
$oArchive->ReadCatalog();
$oArchive->ImportSql('full_backup.sql');
// Writing an archive --
$sArchivePath = '../tmp/archive2.zip';
$oArchive = new iTopArchive($sArchivePath, iTopArchive::create);
$oArchive->SetTitle('First Archive !');
$oArchive->SetDescription('This is just a test. Does not contain a lot of useful data.');
$oArchive->AddPackage('../tmp/schema.sql', 'test.sql', 'this is just a test', 'text/sql', 'My first attempt at creating an archive from PHP...');
$oArchive->WriteCatalog();
$sArchivePath = '../tmp/archive2.zip';
$oArchive = new iTopArchive($sArchivePath, iTopArchive::create);
$oArchive->SetTitle('First Archive !');
$oArchive->SetDescription('This is just a test. Does not contain a lot of useful data.');
$oArchive->AddDatabaseDump('Test', 'This is my first automatic dump', 'schema.sql', 'itop', array('objects'));
$oArchive->WriteCatalog();
*/
?>

View File

@@ -0,0 +1,989 @@
<?php
require_once('MyHelpers.class.inc.php');
/**
* add some description here...
*
* @package iTopORM
*/
define('EXTKEY_RELATIVE', 1);
/**
* add some description here...
*
* @package iTopORM
*/
define('EXTKEY_ABSOLUTE', 2);
/**
* Attribute definition API, implemented in and many flavours (Int, String, Enum, etc.)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
abstract class AttributeDefinition
{
abstract public function GetType();
abstract public function GetTypeDesc();
abstract public function GetEditClass();
abstract public function GetDBFieldType();
protected $m_sCode;
private $m_aParams = array();
private $m_sHostClass = array();
protected function Get($sParamName) {return $this->m_aParams[$sParamName];}
public function __construct($sCode, $aParams)
{
$this->m_sCode = $sCode;
$this->m_aParams = $aParams;
$this->ConsistencyCheck();
}
public function OverloadParams($aParams)
{
foreach ($aParams as $sParam => $value)
{
if (!array_key_exists($sParam, $this->m_aParams))
{
trigger_error("Unknown attribute definition parameter '$sParam', please select a value in {".implode(", ", $this->m_aParams)."}");
}
else
{
$this->m_aParams[$sParam] = $value;
}
}
}
public function SetHostClass($sHostClass)
{
$this->m_sHostClass = $sHostClass;
}
public function GetHostClass()
{
return $this->m_sHostClass;
}
// Note: I could factorize this code with the parameter management made for the AttributeDef class
// to be overloaded
static protected function ListExpectedParams()
{
return array("label", "description", "allowed_values");
}
private function ConsistencyCheck()
{
// Check that any mandatory param has been specified
//
$aExpectedParams = $this->ListExpectedParams();
foreach($aExpectedParams as $sParamName)
{
if (!array_key_exists($sParamName, $this->m_aParams))
{
$aBacktrace = debug_backtrace();
$sTargetClass = $aBacktrace[2]["class"];
$sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"];
trigger_error("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)</br>\n", E_USER_ERROR);
}
}
}
// table, key field, name field
public function ListDBJoins()
{
return "";
// e.g: return array("Site", "infrid", "name");
}
public function IsDirectField() {return false;}
public function IsScalar() {return false;}
public function IsLinkSet() {return false;}
public function IsExternalKey($iType = EXTKEY_RELATIVE) {return false;}
public function IsExternalField() {return false;}
public function IsWritable() {return false;}
public function GetCode() {return $this->m_sCode;}
public function GetLabel() {return $this->Get("label");}
public function GetDescription() {return $this->Get("description");}
public function GetValuesDef() {return $this->Get("allowed_values");}
public function GetPrerequisiteAttributes() {return $this->Get("depends_on");}
//public function IsSearchableStd() {return $this->Get("search_std");}
//public function IsSearchableGlobal() {return $this->Get("search_global");}
//public function IsMandatory() {return $this->Get("is_mandatory");}
//public function GetMinVal() {return $this->Get("min");}
//public function GetMaxVal() {return $this->Get("max");}
//public function GetSize() {return $this->Get("size");}
//public function GetCheckRegExp() {return $this->Get("regexp");}
//public function GetCheckFunc() {return $this->Get("checkfunc");}
// Definition: real value is what will be stored in memory and maintained by MetaModel
// DBObject::Set() relies on MakeRealValue()
// MetaModel::MakeQuery() relies on RealValueToSQLValue()
// DBObject::FromRow() relies on SQLToRealValue()
public function MakeRealValue($proposedValue) {return $proposedValue;} // force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing!)
public function RealValueToSQLValue($value) {return $value;} // format value as a valuable SQL literal (quoted outside)
public function SQLValueToRealValue($value) {return $value;} // take the result of a fetch... and make it a PHP variable
public function GetJSCheckFunc()
{
$sRegExp = $this->Get("regexp");
if (empty($sRegExp)) return 'return true;';
return "return regexp('$sRegExp', myvalue);";
}
public function CheckValue($value)
{
$sRegExp = $this->Get("regexp");
if (empty($sRegExp)) return true;
return preg_match(preg_escape($this->Get("regexp")), $value);
}
public function MakeValue()
{
$sComputeFunc = $this->Get("compute_func");
if (empty($sComputeFunc)) return null;
return call_user_func($sComputeFunc);
}
abstract public function DBGetUsedFields();
abstract public function GetDefaultValue();
//
// To be overloaded in subclasses
//
abstract public function GetBasicFilterOperators(); // returns an array of "opCode"=>"description"
abstract public function GetBasicFilterLooseOperator(); // returns an "opCode"
//abstract protected GetBasicFilterHTMLInput();
abstract public function GetBasicFilterSQLExpr($sOpCode, $value);
public function GetAsHTML($sValue)
{
return Str::pure2html($sValue);
}
public function GetAsXML($sValue)
{
return Str::pure2xml($sValue);
}
public function GetAsCSV($sValue, $sSeparator = ';', $sSepEscape = ',')
{
return str_replace($sSeparator, $sSepEscape, $sValue);
}
}
/**
* Set of objects directly linked to an object, and being part of its definition
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeLinkedSet extends AttributeDefinition
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("depends_on", "linked_class", "ext_key_to_me", "count_min", "count_max"));
}
public function GetType() {return "Array of objects";}
public function GetTypeDesc() {return "Any kind of objects [subclass] of the same class";}
public function GetEditClass() {return "List";}
public function GetDBFieldType() {return "N/A";} // should be moved out of the AttributeDef root class
public function IsWritable() {return true;}
public function IsLinkSet() {return true;}
public function GetDefaultValue() {return DBObjectSet::FromScratch($this->Get('linked_class'));}
public function GetLinkedClass() {return $this->Get('linked_class');}
public function GetExtKeyToMe() {return $this->Get('ext_key_to_me');}
public function DBGetUsedFields() {return array();}
public function GetBasicFilterOperators() {return array();}
public function GetBasicFilterLooseOperator() {return '';}
public function GetBasicFilterSQLExpr($sOpCode, $value) {return '';}
public function GetAsHTML($sValue)
{
return "ERROR: LIST OF OBJECTS";
}
public function GetAsXML($sValue)
{
return "ERROR: LIST OF OBJECTS";
}
public function GetAsCSV($sValue, $sSeparator = ';', $sSepEscape = ',')
{
return "ERROR: LIST OF OBJECTS";
}
}
/**
* Set of objects linked to an object (n-n), and being part of its definition
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeLinkedSetIndirect extends AttributeLinkedSet
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("ext_key_to_remote"));
}
public function GetExtKeyToRemote() { return $this->Get('ext_key_to_remote'); }
}
/**
* Abstract class implementing default filters for a DB column
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeDBFieldVoid extends AttributeDefinition
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("depends_on", "sql"));
}
public function GetType() {return "Void";}
public function GetTypeDesc() {return "Any kind of value, from the DB";}
public function GetEditClass() {return "String";}
public function GetDBFieldType() {return "VARCHAR(255)";}
public function IsDirectField() {return true;}
public function IsScalar() {return true;}
public function IsWritable() {return true;}
public function GetSQLExpr() {return $this->Get("sql");}
public function GetDefaultValue() {return "";}
public function IsNullAllowed() {return false;}
public function DBGetUsedFields()
{
// #@# bugge a mort... a suivre...
return array($this->Get("sql"));
}
public function GetBasicFilterOperators()
{
return array("="=>"equals", "!="=>"differs from");
}
public function GetBasicFilterLooseOperator()
{
return "=";
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
$sQValue = CMDBSource::Quote($value);
switch ($sOpCode)
{
case '!=':
return $this->GetSQLExpr()." != $sQValue";
break;
case '=':
default:
return $this->GetSQLExpr()." = $sQValue";
}
}
}
/**
* Base class for all kind of DB attributes, with the exception of external keys
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeDBField extends AttributeDBFieldVoid
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("default_value", "is_null_allowed"));
}
public function GetDefaultValue() {return $this->Get("default_value");}
public function IsNullAllowed() {return strtolower($this->Get("is_null_allowed"));}
}
/**
* Map an integer column to an attribute
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeInteger extends AttributeDBField
{
static protected function ListExpectedParams()
{
return parent::ListExpectedParams();
//return array_merge(parent::ListExpectedParams(), array());
}
public function GetType() {return "Integer";}
public function GetTypeDesc() {return "Numeric value (could be negative)";}
public function GetEditClass() {return "String";}
public function GetDBFieldType() {return "INT";}
public function GetBasicFilterOperators()
{
return array(
"!="=>"differs from",
"="=>"equals",
">"=>"greater (strict) than",
">="=>"greater than",
"<"=>"less (strict) than",
"<="=>"less than",
"in"=>"in"
);
}
public function GetBasicFilterLooseOperator()
{
// Unless we implement an "equals approximately..." or "same order of magnitude"
return "=";
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
$sQValue = CMDBSource::Quote($value);
switch ($sOpCode)
{
case '!=':
return $this->GetSQLExpr()." != $sQValue";
break;
case '>':
return $this->GetSQLExpr()." > $sQValue";
break;
case '>=':
return $this->GetSQLExpr()." >= $sQValue";
break;
case '<':
return $this->GetSQLExpr()." < $sQValue";
break;
case '<=':
return $this->GetSQLExpr()." <= $sQValue";
break;
case 'in':
if (!is_array($value)) trigger_error("Expected an array for argument value (sOpCode='$sOpCode')");
return $this->GetSQLExpr()." IN ('".implode("', '", $value)."')";
break;
case '=':
default:
return $this->GetSQLExpr()." = \"$value\"";
}
}
public function MakeRealValue($proposedValue)
{
//return intval($proposedValue); could work as well
return (int)$proposedValue;
}
public function RealValueToSQLValue($value)
{
assert(is_numeric($value));
return $value; // supposed to be an int
}
public function SQLValueToRealValue($value)
{
// Use cast (int) or intval() ?
return (int)$value;
}
}
/**
* Map a varchar column (size < ?) to an attribute
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeString extends AttributeDBField
{
static protected function ListExpectedParams()
{
return parent::ListExpectedParams();
//return array_merge(parent::ListExpectedParams(), array());
}
public function GetType() {return "String";}
public function GetTypeDesc() {return "Alphanumeric string";}
public function GetEditClass() {return "String";}
public function GetDBFieldType() {return "VARCHAR(255)";}
public function GetBasicFilterOperators()
{
return array(
"="=>"equals",
"!="=>"differs from",
"Like"=>"equals (no case)",
"NotLike"=>"differs from (no case)",
"Contains"=>"contains",
"Begins with"=>"begins with",
"Finishes with"=>"finishes with"
);
}
public function GetBasicFilterLooseOperator()
{
return "Contains";
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
$sQValue = CMDBSource::Quote($value);
switch ($sOpCode)
{
case '=':
case '!=':
return $this->GetSQLExpr()." $sOpCode $sQValue";
case 'Begins with':
return $this->GetSQLExpr()." LIKE ".CMDBSource::Quote("$value%");
case 'Finishes with':
return $this->GetSQLExpr()." LIKE ".CMDBSource::Quote("%$value");
case 'Contains':
return $this->GetSQLExpr()." LIKE ".CMDBSource::Quote("%$value%");
case 'NotLike':
return $this->GetSQLExpr()." NOT LIKE $sQValue";
case 'Like':
default:
return $this->GetSQLExpr()." LIKE $sQValue";
}
}
public function MakeRealValue($proposedValue)
{
return (string)$proposedValue;
// if (!settype($proposedValue, "string"))
// {
// trigger_error("Failed to change the type of '$proposedValue' to a string", E_USER_WARNING);
// }
}
public function RealValueToSQLValue($value)
{
assert(is_string($value));
return $value;
}
public function SQLValueToRealValue($value)
{
return $value;
}
}
/**
* Map a text column (size > ?) to an attribute
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeText extends AttributeString
{
public function GetType() {return "Text";}
public function GetTypeDesc() {return "Multiline character string";}
public function GetEditClass() {return "Text";}
public function GetDBFieldType() {return "TEXT";}
public function GetAsHTML($sValue)
{
return str_replace("\n", "<br>\n", parent::GetAsHTML($sValue));
}
public function GetAsXML($value)
{
return Str::pure2xml($value);
}
public function GetAsCSV($value, $sSeparator = ';', $sSepEscape = ',')
{
return str_replace("\n", "[newline]", parent::GetAsCSV($sValue, $sSeparator, $sSepEscape));
}
}
/**
* Map a enum column to an attribute
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeEnum extends AttributeString
{
static protected function ListExpectedParams()
{
return parent::ListExpectedParams();
//return array_merge(parent::ListExpectedParams(), array());
}
public function GetType() {return "Enum";}
public function GetTypeDesc() {return "List of predefined alphanumeric strings";}
public function GetEditClass() {return "String";}
public function GetDBFieldType()
{
$oValDef = $this->GetValuesDef();
if ($oValDef)
{
$aValues = CMDBSource::Quote($oValDef->GetValues(array(), ""), true);
}
else
{
$aValues = array();
}
if (count($aValues) > 0)
{
return "ENUM(".implode(", ", $aValues).")";
}
else
{
return "VARCHAR(255)"; // ENUM() is not an allowed syntax!
}
}
public function GetBasicFilterOperators()
{
return parent::GetBasicFilterOperators();
}
public function GetBasicFilterLooseOperator()
{
return parent::GetBasicFilterLooseOperator();
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
return parent::GetBasicFilterSQLExpr($sOpCode, $value);
}
}
/**
* Map a date+time column to an attribute
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeDate extends AttributeDBField
{
const MYDATEFORMAT = "Y-m-d H:i:s";
//const MYDATETIMEZONE = "UTC";
const MYDATETIMEZONE = "Europe/Paris";
static protected $const_TIMEZONE = null; // set once for all upon object construct
static public function InitStatics()
{
// Init static constant once for all (remove when PHP allows real static const)
self::$const_TIMEZONE = new DateTimeZone(self::MYDATETIMEZONE);
// #@# Init default timezone -> do not get a notice... to be improved !!!
date_default_timezone_set(self::MYDATETIMEZONE);
}
static protected function ListExpectedParams()
{
return parent::ListExpectedParams();
//return array_merge(parent::ListExpectedParams(), array());
}
public function GetType() {return "Date";}
public function GetTypeDesc() {return "Date and time";}
public function GetEditClass() {return "Date";}
public function GetDBFieldType() {return "TIMESTAMP";}
public function GetBasicFilterOperators()
{
return array(
"="=>"equals",
"!="=>"differs from",
"<"=>"before",
"<="=>"before",
">"=>"after (strictly)",
">="=>"after",
"SameDay"=>"same day (strip time)",
"SameMonth"=>"same year/month",
"SameYear"=>"same year",
"Today"=>"today",
">|"=>"after today + N days",
"<|"=>"before today + N days",
"=|"=>"equals today + N days",
);
}
public function GetBasicFilterLooseOperator()
{
// Unless we implement a "same xxx, depending on given precision" !
return "=";
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
$sQValue = CMDBSource::Quote($value);
switch ($sOpCode)
{
case '=':
case '!=':
case '<':
case '<=':
case '>':
case '>=':
return $this->GetSQLExpr()." $sOpCode $sQValue";
case 'SameDay':
return "DATE(".$this->GetSQLExpr().") = DATE($sQValue)";
case 'SameMonth':
return "DATE_FORMAT(".$this->GetSQLExpr().", '%Y-%m') = DATE_FORMAT($sQValue, '%Y-%m')";
case 'SameYear':
return "MONTH(".$this->GetSQLExpr().") = MONTH($sQValue)";
case 'Today':
return "DATE(".$this->GetSQLExpr().") = CURRENT_DATE()";
case '>|':
return "DATE(".$this->GetSQLExpr().") > DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)";
case '<|':
return "DATE(".$this->GetSQLExpr().") < DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)";
case '=|':
return "DATE(".$this->GetSQLExpr().") = DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)";
default:
return $this->GetSQLExpr()." = $sQValue";
}
}
public function MakeRealValue($proposedValue)
{
if (!is_numeric($proposedValue))
{
return $proposedValue;
}
else
{
return date("Y-m-d H:i:s", $proposedValue);
}
trigger_error("Invalid type for a date (found ".gettype($proposedValue)." and accepting string/int/DateTime)", E_USER_ERROR);
return null;
}
public function RealValueToSQLValue($value)
{
if (empty($value))
{
// Make a valid date for MySQL. TO DO: support NULL as a literal value for fields that can be null.
return '0000-00-00 00:00:00';
}
return $value;
}
public function SQLValueToRealValue($value)
{
return $value;
}
public function GetAsHTML($value)
{
return Str::pure2html($value);
}
public function GetAsXML($value)
{
return Str::pure2xml($value);
}
public function GetAsCSV($value, $sSeparator = ';', $sSepEscape = ',')
{
return str_replace($sSeparator, $sSepEscape, $value);
}
}
// Init static constant once for all (remove when PHP allows real static const)
AttributeDate::InitStatics();
/**
* Map a foreign key to an attribute
* AttributeExternalKey and AttributeExternalField may be an external key
* the difference is that AttributeExternalKey corresponds to a column into the defined table
* where an AttributeExternalField corresponds to a column into another table (class)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeExternalKey extends AttributeDBFieldVoid
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("targetclass", "is_null_allowed"));
}
public function GetType() {return "Extkey";}
public function GetTypeDesc() {return "Link to another object";}
public function GetEditClass() {return "ExtKey";}
public function GetDBFieldType() {return "INT";}
public function IsExternalKey($iType = EXTKEY_RELATIVE) {return true;}
public function GetTargetClass($iType = EXTKEY_RELATIVE) {return $this->Get("targetclass");}
public function GetKeyAttDef($iType = EXTKEY_RELATIVE){return $this;}
public function GetKeyAttCode() {return $this->GetCode();}
public function GetDefaultValue() {return 0;}
public function IsNullAllowed() {return $this->Get("is_null_allowed");}
public function GetBasicFilterOperators()
{
return parent::GetBasicFilterOperators();
}
public function GetBasicFilterLooseOperator()
{
return parent::GetBasicFilterLooseOperator();
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
return parent::GetBasicFilterSQLExpr($sOpCode, $value);
}
// overloaded here so that an ext key always have the answer to
// "what are you possible values?"
public function GetValuesDef()
{
$oValSetDef = $this->Get("allowed_values");
if (!$oValSetDef)
{
// Let's propose every existing value
$oValSetDef = new ValueSetObjects($this->GetTargetClass());
}
return $oValSetDef;
}
}
/**
* An attribute which corresponds to an external key (direct or indirect)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeExternalField extends AttributeDefinition
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("extkey_attcode", "target_attcode"));
}
public function GetType() {return "ExtkeyField";}
public function GetTypeDesc() {return "Field of an object pointed to by the current object";}
public function GetEditClass() {return "ExtField";}
public function GetDBFieldType()
{
trigger_error("external attribute: does it make any sense to request its type ?", E_USER_WARNING);
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetDBFieldType();
}
public function IsExternalKey($iType = EXTKEY_RELATIVE)
{
switch($iType)
{
case EXTKEY_ABSOLUTE:
// see further
$oRemoteAtt = $this->GetExtAttDef();
return $oRemoteAtt->IsExternalKey($iType);
case EXTKEY_RELATIVE:
return false;
default:
trigger_error("Unexpected value for argument iType: '$iType'", E_USER_ERROR);
}
}
public function GetTargetClass($iType = EXTKEY_RELATIVE)
{
return $this->GetKeyAttDef($iType)->GetTargetClass();
}
public function IsExternalField() {return true;}
public function GetKeyAttCode() {return $this->Get("extkey_attcode");}
public function GetExtAttCode() {return $this->Get("target_attcode");}
public function GetKeyAttDef($iType = EXTKEY_RELATIVE)
{
switch($iType)
{
case EXTKEY_ABSOLUTE:
// see further
$oRemoteAtt = $this->GetExtAttDef();
if ($oRemoteAtt->IsExternalField())
{
return $oRemoteAtt->GetKeyAttDef(EXTKEY_ABSOLUTE);
}
else if ($oRemoteAtt->IsExternalKey())
{
return $oRemoteAtt;
}
return $this->GetKeyAttDef(EXTKEY_RELATIVE); // which corresponds to the code hereafter !
case EXTKEY_RELATIVE:
return MetaModel::GetAttributeDef($this->GetHostClass(), $this->Get("extkey_attcode"));
default:
trigger_error("Unexpected value for argument iType: '$iType'", E_USER_ERROR);
}
}
public function GetExtAttDef()
{
$oKeyAttDef = $this->GetKeyAttDef();
$oExtAttDef = MetaModel::GetAttributeDef($oKeyAttDef->Get("targetclass"), $this->Get("target_attcode"));
return $oExtAttDef;
}
public function GetSQLExpr()
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetSQLExpr();
}
public function DBGetUsedFields()
{
// No field is used but the one defined in the field of the external class
// #@# so what ?
return array();
}
public function GetDefaultValue()
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetDefaultValue();
}
public function IsNullAllowed()
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->IsNullAllowed();
}
public function GetBasicFilterOperators()
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetBasicFilterOperators();
}
public function GetBasicFilterLooseOperator()
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetBasicFilterLooseOperator();
}
public function GetBasicFilterSQLExpr($sOpCode, $value)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetBasicFilterSQLExpr($sOpCode, $value);
}
public function MakeRealValue($proposedValue)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->MakeRealValue($proposedValue);
}
public function RealValueToSQLValue($value)
{
// This one could be used in case of filtering only
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->RealValueToSQLValue($value);
}
public function SQLValueToRealValue($value)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->SQLValueToRealValue($value);
}
public function GetAsHTML($value)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetAsHTML($value);
}
public function GetAsXML($value)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetAsXML($value);
}
public function GetAsCSV($value, $sSeparator = ';', $sSepEscape = ',')
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetAsCSV($value);
}
}
/**
* Map a varchar column to an URL (formats the ouput in HMTL)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeURL extends AttributeString
{
static protected function ListExpectedParams()
{
//return parent::ListExpectedParams();
return array_merge(parent::ListExpectedParams(), array("target", "label"));
}
public function GetType() {return "Url";}
public function GetTypeDesc() {return "Absolute or relative URL as a text string";}
public function GetEditClass() {return "String";}
public function GetAsHTML($sValue)
{
$sTarget = $this->Get("target");
if (empty($sTarget)) $sTarget = "_blank";
$sLabel = Str::pure2html($sValue);
if (strlen($sLabel) > 40)
{
// Truncate the length to about 40 characters, by removing the middle
$sLabel = substr($sLabel, 0, 25).'...'.substr($sLabel, -15);
}
return "<a target=\"$sTarget\" href=\"$sValue\">$sLabel</a>";
}
}
?>

View File

@@ -0,0 +1,44 @@
<?php
/**
* A change as requested/validated at once by user, may groups many atomic changes
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class CMDBChange extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "change",
"description" => "Changes tracking",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "date",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_change",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeDate("date", array("label"=>"date", "description"=>"date and time at which the changes have been recorded", "allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("label"=>"misc. info", "description"=>"caller's defined information", "allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("date");
MetaModel::Init_AddFilterFromAttribute("userinfo");
}
}
?>

View File

@@ -0,0 +1,165 @@
<?php
/**
* Various atomic change operations, to be tracked
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class CMDBChangeOp extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "change operation",
"description" => "Change operations tracking",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop",
"db_key_field" => "id",
"db_finalclass_field" => "optype",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("label"=>"change", "description"=>"change", "allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "is_null_allowed"=>false, "depends_on"=>array())));
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 AttributeExternalField("userinfo", array("label"=>"user", "description"=>"who made this change", "allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"userinfo")));
MetaModel::Init_AddAttribute(new AttributeString("objclass", array("label"=>"object class", "description"=>"object class", "allowed_values"=>null, "sql"=>"objclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("objkey", array("label"=>"object id", "description"=>"object id", "allowed_values"=>null, "sql"=>"objkey", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("objclass");
MetaModel::Init_AddFilterFromAttribute("objkey");
MetaModel::Init_AddFilterFromAttribute("date");
MetaModel::Init_AddFilterFromAttribute("userinfo");
}
}
/**
* Record the creation of an object
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class CMDBChangeOpCreate extends CMDBChangeOp
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "object creation",
"description" => "Object creation tracking",
"key_type" => "",
"key_label" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_create",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_InheritFilters();
}
}
/**
* Record the deletion of an object
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class CMDBChangeOpDelete extends CMDBChangeOp
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "object deletion",
"description" => "Object deletion tracking",
"key_type" => "",
"key_label" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_delete",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_InheritFilters();
}
}
/**
* Record the modification of an attribute
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class CMDBChangeOpSetAttribute extends CMDBChangeOp
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "object change",
"description" => "Object properties change tracking",
"key_type" => "",
"key_label" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_setatt",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("label"=>"Attribute", "description"=>"code of the modified property", "allowed_values"=>null, "sql"=>"attcode", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("newvalue", array("label"=>"New value", "description"=>"new value of the attribute", "allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("attcode");
MetaModel::Init_AddFilterFromAttribute("newvalue");
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'newvalue')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'newvalue')); // Attributes to be displayed for a list
}
}
?>

View File

@@ -0,0 +1,424 @@
<?php
/**
* cmdbObjectClass
* the file to include, then the core is yours
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
require_once('coreexception.class.inc.php');
require_once('config.class.inc.php');
require_once('attributedef.class.inc.php');
require_once('filterdef.class.inc.php');
require_once('stimulus.class.inc.php');
require_once('valuesetdef.class.inc.php');
require_once('MyHelpers.class.inc.php');
require_once('expression.class.inc.php');
require_once('cmdbsource.class.inc.php');
require_once('sqlquery.class.inc.php');
require_once('oql/oqlquery.class.inc.php');
require_once('oql/oqlexception.class.inc.php');
require_once('oql/oql-parser.php');
require_once('oql/oql-lexer.php');
require_once('oql/oqlinterpreter.class.inc.php');
require_once('dbobject.class.php');
require_once('dbobjectsearch.class.php');
require_once('dbobjectset.class.php');
require_once('cmdbchange.class.inc.php');
require_once('cmdbchangeop.class.inc.php');
require_once('userrights.class.inc.php');
//
// Error handling
// To be finalized... or removed ?
//
function cmdbErrorHandler($errno, $errstr, $errfile, $errline)
{
// font-family: Courier-New, Courier, Arial, Helevtica;
$sErrorStyle = "
background-color: #ffaaaa;
color: #000000;
border: 1px dashed #000000;
padding: 0.25em;
margin-top: 1em;
";
$sCallStackStyle = "
font-size: smaller;
background-color: #ffcccc;
color: #000000;
border: 1px dashed #000000;
padding: 0.25em;
margin-top: 1em;
";
switch ($errno)
{
case E_USER_ERROR:
case E_ERROR:
echo "<div style=\"$sErrorStyle\">\n";
echo "<b>Error</b> [$errno] $errstr<br />\n";
echo "<div style=\"$sCallStackStyle\">\n";
MyHelpers::dump_callstack(1);
echo "</div>\n";
echo "Hereafter the biz model internals:<br />\n";
echo "<pre>\n";
MetaModel::static_var_dump();
echo "</pre>\n";
echo "Aborting...<br />\n";
echo "</div>\n";
exit(1);
break;
case E_USER_WARNING:
case E_WARNING:
echo "<div style=\"background-color:#FAA;\">\n";
echo "<b>Warning</b> [$errno] $errstr<br />\n";
echo "<div style=\"background-color:#FCC;\">\n";
MyHelpers::dump_callstack(1);
echo "</div>\n";
echo "</div>\n";
break;
case E_USER_NOTICE:
case E_NOTICE:
echo "<div style=\"background-color:#FAA;\">\n";
echo "<b>Notice</b> [$errno] $errstr<br />\n";
echo "<div style=\"background-color:#FCC;\">\n";
MyHelpers::dump_callstack(1);
echo "</div>\n";
echo "</div>\n";
break;
default:
echo "Unknown error type: [$errno] $errstr<br />\n";
MyHelpers::dump_callstack(1);
break;
}
}
error_reporting(E_ALL | E_STRICT);
//set_error_handler("cmdbErrorHandler");
//
//
//
/**
* A persistent object, which changes are accurately recorded
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
abstract class CMDBObject extends DBObject
{
protected $m_datCreated;
protected $m_datUpdated;
protected static $m_oCurrChange = null;
private function RecordObjCreation(CMDBChange $oChange)
{
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpCreate");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$iId = $oMyChangeOp->DBInsert();
}
private function RecordObjDeletion(CMDBChange $oChange, $objkey)
{
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpDelete");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $objkey);
$iId = $oMyChangeOp->DBInsert();
}
private function RecordAttChanges(CMDBChange $oChange, array $aValues = array())
{
// $aValues is an array of $sAttCode => $value
// ... some values...
//
if (empty($aValues))
{
// ... or every object values
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if ($oAttDef->IsLinkSet()) continue; // #@# temporary
$aValues[$sAttCode] = $this->Get($sAttCode);
}
}
foreach ($aValues as $sAttCode=> $value)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($oAttDef->IsLinkSet()) continue; // #@# temporary
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttribute");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
$oMyChangeOp->Set("newvalue", $value);
$iId = $oMyChangeOp->DBInsert();
}
}
public function DBInsert()
{
if(!is_object(self::$m_oCurrChange))
{
trigger_error("DBInsert() could not be used here, please use DBInsertTracked() instead", E_USER_ERROR);
}
return $this->DBInsertTracked_Internal();
}
public function DBInsertTracked(CMDBChange $oChange)
{
self::$m_oCurrChange = $oChange;
$this->DBInsertTracked_Internal();
self::$m_oCurrChange = null;
}
protected function DBInsertTracked_Internal()
{
$ret = parent::DBInsert();
$this->RecordObjCreation(self::$m_oCurrChange);
$this->RecordAttChanges(self::$m_oCurrChange);
return $ret;
}
public function DBClone($newKey = null)
{
if(!self::$m_oCurrChange)
{
trigger_error("DBClone() could not be used here, please use DBCloneTracked() instead", E_USER_ERROR);
}
return $this->DBCloneTracked_Internal();
}
public function DBCloneTracked(CMDBChange $oChange, $newKey = null)
{
self::$m_oCurrChange = $oChange;
$this->DBCloneTracked_Internal($newKey);
self::$m_oCurrChange = null;
}
protected function DBCloneTracked_Internal($newKey = null)
{
$newKey = parent::DBClone($newKey);
$oClone = MetaModel::GetObject(get_class($this), $newKey);
$oClone->RecordObjCreation(self::$m_oCurrChange);
$oClone->RecordAttChanges(self::$m_oCurrChange);
return $newKey;
}
public function DBUpdate()
{
if(!self::$m_oCurrChange)
{
trigger_error("DBUpdate() could not be used here, please use DBUpdateTracked() instead", E_USER_ERROR);
}
return $this->DBUpdateTracked_internal();
}
public function DBUpdateTracked(CMDBChange $oChange)
{
self::$m_oCurrChange = $oChange;
$this->DBUpdateTracked_Internal();
self::$m_oCurrChange = null;
}
protected function DBUpdateTracked_Internal()
{
// Copy the changes list before the update (the list should be reset afterwards)
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
trigger_error("Attempting to update an unchanged object", E_USER_NOTICE);
return;
}
$ret = parent::DBUpdate();
$this->RecordAttChanges(self::$m_oCurrChange, $aChanges);
return $ret;
}
public function DBDelete()
{
if(!self::$m_oCurrChange)
{
trigger_error("DBDelete() could not be used here, please use DBDeleteTracked() instead", E_USER_ERROR);
}
return $this->DBDeleteTracked_Internal();
}
public function DBDeleteTracked(CMDBChange $oChange)
{
self::$m_oCurrChange = $oChange;
$this->DBDeleteTracked_Internal();
self::$m_oCurrChange = null;
}
protected function DBDeleteTracked_Internal()
{
$prevkey = $this->GetKey();
$ret = parent::DBDelete();
$this->RecordObjDeletion(self::$m_oCurrChange, $prevkey);
return $ret;
}
public static function BulkDelete(DBObjectSearch $oFilter)
{
if(!self::$m_oCurrChange)
{
trigger_error("BulkDelete() could not be used here, please use BulkDeleteTracked() instead", E_USER_ERROR);
}
return $this->BulkDeleteTracked_Internal($oFilter);
}
public static function BulkDeleteTracked(CMDBChange $oChange, DBObjectSearch $oFilter)
{
self::$m_oCurrChange = $oChange;
$this->BulkDeleteTracked_Internal($oFilter);
self::$m_oCurrChange = null;
}
protected static function BulkDeleteTracked_Internal(DBObjectSearch $oFilter)
{
trigger_error("Change tracking not tested for bulk operations", E_USER_WARNING);
// Get the list of objects to delete (and record data before deleting the DB records)
$oObjSet = new CMDBObjectSet($oFilter);
$aObjAndKeys = array(); // array of pkey=>object
while ($oItem = $oObjSet->Fetch())
{
$aObjAndKeys[$oItem->GetKey()] = $oItem;
}
$oObjSet->FreeResult();
// Delete in one single efficient query
$ret = parent::BulkDelete($oFilter);
// Record... in many queries !!!
foreach($aObjAndKeys as $prevkey=>$oItem)
{
$oItem->RecordObjDeletion(self::$m_oCurrChange, $prevkey);
}
return $ret;
}
public static function BulkUpdate(DBObjectSearch $oFilter, array $aValues)
{
if(!self::$m_oCurrChange)
{
trigger_error("BulkUpdate() could not be used here, please use BulkUpdateTracked() instead", E_USER_ERROR);
}
return $this->BulkUpdateTracked_Internal($oFilter, $aValues);
}
public static function BulkUpdateTracked(CMDBChange $oChange, DBObjectSearch $oFilter, array $aValues)
{
self::$m_oCurrChange = $oChange;
$this->BulkUpdateTracked_Internal($oFilter, $aValues);
self::$m_oCurrChange = null;
}
protected static function BulkUpdateTracked_Internal(DBObjectSearch $oFilter, array $aValues)
{
// $aValues is an array of $sAttCode => $value
// Get the list of objects to update (and load it before doing the change)
$oObjSet = new CMDBObjectSet($oFilter);
$oObjSet->Load();
// Update in one single efficient query
$ret = parent::BulkUpdate($oFilter, $aValues);
// Record... in many queries !!!
while ($oItem = $oObjSet->Fetch())
{
$aChangedValues = $oItem->ListChangedValues($aValues);
$oItem->RecordAttChanges(self::$m_oCurrChange, $aChangedValues);
}
return $ret;
}
}
/**
* TODO: investigate how to get rid of this class that was made to workaround some language limitation... or a poor design!
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class CMDBObjectSet extends DBObjectSet
{
// this is the public interface (?)
// I have to define those constructors here... :-(
// just to get the right object class in return.
// I have to think again to those things: maybe it will work fine if a have a constructor define here (?)
static public function FromScratch($sClass)
{
$oFilter = new CMDBSearchFilter($sClass);
$oRetSet = new CMDBObjectSet($oFilter); // THE ONLY DIFF IS HERE
// NOTE: THIS DOES NOT WORK IF m_bLoaded is private...
// BUT IT THAT CASE YOU DO NOT GET ANY ERROR !!!!!
$oRetSet->m_bLoaded = true; // no DB load
return $oRetSet;
}
static public function FromArray($sClass, $aObjects)
{
$oFilter = new CMDBSearchFilter($sClass);
$oRetSet = new CMDBObjectSet($oFilter); // THE ONLY DIFF IS HERE
// NOTE: THIS DOES NOT WORK IF m_bLoaded is private...
// BUT IT THAT CASE YOU DO NOT GET ANY ERROR !!!!!
$oRetSet->m_bLoaded = true; // no DB load
$oRetSet->AddObjectArray($aObjects);
return $oRetSet;
}
}
/**
* TODO: investigate how to get rid of this class that was made to workaround some language limitation... or a poor design!
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class CMDBSearchFilter extends DBObjectSearch
{
// this is the public interface (?)
}
?>

View File

@@ -0,0 +1,386 @@
<?php
/**
* CMDBSource
* database access wrapper
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
require_once('MyHelpers.class.inc.php');
class MySQLException extends CoreException
{
public function __construct($sIssue, $aContext)
{
$aContext['mysql_error'] = mysql_error();
parent::__construct($sIssue, $aContext);
}
}
class CMDBSource
{
protected static $m_sDBHost;
protected static $m_sDBUser;
protected static $m_sDBPwd;
protected static $m_sDBName;
protected static $m_resDBLink;
public static function Init($sServer, $sUser, $sPwd, $sSource = '')
{
self::$m_sDBHost = $sServer;
self::$m_sDBUser = $sUser;
self::$m_sDBPwd = $sPwd;
self::$m_sDBName = $sSource;
if (!self::$m_resDBLink = mysql_pconnect($sServer, $sUser, $sPwd))
{
throw new MySQLException('Could not connect to the DB server', array('host'=>$sServer, 'user'=>$sUser));
}
if (!empty($sSource))
{
if (!mysql_select_db($sSource, self::$m_resDBLink))
{
throw new MySQLException('Could not select DB', array('db_name'=>$sSource));
}
}
}
public static function IsDB($sSource)
{
$aDBs = self::QueryToCol('SHOW DATABASES', 'Database');
// Show Database does return the DB names in lower case
$sSourceRef = strtolower($sSource);
return (in_array($sSourceRef, $aDBs));
}
public static function SelectDB($sSource)
{
if (!mysql_select_db($sSource, self::$m_resDBLink))
{
throw new MySQLException('Could not select DB', array('db_name'=>$sSource));
}
self::$m_sDBName = $sSource;
}
public static function CreateDB($sSource)
{
self::Query("CREATE DATABASE `$sSource`");
self::SelectDB($sSource);
}
public static function DropDB($sDBToDrop = '')
{
if (empty($sDBToDrop))
{
$sDBToDrop = self::$m_sDBName;
}
self::Query("DROP DATABASE `$sDBToDrop`");
if ($sDBToDrop == self::$m_sDBName)
{
self::$m_sDBName = '';
}
}
public static function CreateTable($sQuery)
{
$res = self::Query($sQuery);
self::_TablesInfoCacheReset(); // reset the table info cache!
return $res;
}
public static function DropTable($sTable)
{
$res = self::Query("DROP TABLE `$sTable`");
self::_TablesInfoCacheReset(true); // reset the table info cache!
return $res;
}
public static function DBHost() {return self::$m_sDBHost;}
public static function DBUser() {return self::$m_sDBUser;}
public static function DBPwd() {return self::$m_sDBPwd;}
public static function DBName() {return self::$m_sDBName;}
public static function Quote($value, $bAlways = false, $cQuoteStyle = "'")
{
// Quote variable and protect against SQL injection attacks
// Code found in the PHP documentation: quote_smart($value)
// bAlways should be set to true when the purpose is to create a IN clause,
// otherwise and if there is a mix of strings and numbers, the clause
// would always be false
if (is_array($value))
{
$aRes = array();
foreach ($value as $key => $itemvalue)
{
$aRes[$key] = self::Quote($itemvalue, $bAlways, $cQuoteStyle);
}
return $aRes;
}
// Stripslashes
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number or a numeric string
if ($bAlways || !is_numeric($value))
{
$value = $cQuoteStyle . mysql_real_escape_string($value, self::$m_resDBLink) . $cQuoteStyle;
}
return $value;
}
public static function Query($sSQLQuery)
{
// Add info into the query as a comment, for easier error tracking
//
//if ($user_contact) $aTraceInf['userID'] = $user_contact->get_key();
//$aTraceInf['file'] = __FILE__;
if ($_SERVER['REQUEST_URI']) $aTraceInf['requestURI'] = $_SERVER['REQUEST_URI'];
$i = 0;
foreach(debug_backtrace() as $aCallData)
{
$sClass = key_exists("class", $aCallData) ? $aCallData["class"]."::" : "";
//if ($aCallData['function'] !== 'mysql_simple_query' AND $sClass !== 'r2_set::')
//{
if ($i == 3) break;
$aTraceInf['function'.$i] = $sClass.$aCallData["function"]." on line ".$aCallData['line'];
$i++;
//}
}
// disabled until we need it really!
// $sSQLQuery = $sSQLQuery.MyHelpers::MakeSQLComment($aTraceInf);
$mu_t1 = MyHelpers::getmicrotime();
$result = mysql_query($sSQLQuery, self::$m_resDBLink);
if (!$result)
{
throw new MySQLException('Failed to issue SQL query', array('query' => $sSQLQuery));
}
$mu_t2 = MyHelpers::getmicrotime();
// #@# todo - query_trace($sSQLQuery, $mu_t2 - $mu_t1);
return $result;
}
public static function GetInsertId()
{
return mysql_insert_id(self::$m_resDBLink);
}
public static function InsertInto($sSQLQuery)
{
if (self::Query($sSQLQuery))
{
return self::GetInsertId();
}
return false;
}
public static function QueryToArray($sSql)
{
$aData = array();
$result = mysql_query($sSql, self::$m_resDBLink);
if (!$result)
{
throw new MySQLException('Failed to issue SQL query', array('query' => $sSql));
}
while ($aRow = mysql_fetch_array($result, MYSQL_BOTH))
{
$aData[] = $aRow;
}
mysql_free_result($result);
return $aData;
}
public static function QueryToCol($sSql, $col)
{
$aColumn = array();
$aData = self::QueryToArray($sSql);
foreach($aData as $aRow)
{
@$aColumn[] = $aRow[$col];
}
return $aColumn;
}
public static function ExplainQuery($sSql)
{
$aData = array();
$result = mysql_query("EXPLAIN $sSql", self::$m_resDBLink);
if (!$result)
{
throw new MySQLException('Failed to issue SQL query', array('query' => $sSql));
}
$aNames = array();
for ($i = 0; $i < mysql_num_fields($result) ; $i++)
{
$meta = mysql_fetch_field($result, $i);
if (!$meta)
{
throw new MySQLException('mysql_fetch_field: No information available', array('query'=>$sSql, 'i'=>$i));
}
else
{
$aNames[] = $meta->name;
}
}
$aData[] = $aNames;
while ($aRow = mysql_fetch_array($result, MYSQL_ASSOC))
{
$aData[] = $aRow;
}
mysql_free_result($result);
return $aData;
}
public static function TestQuery($sSql)
{
$result = mysql_query("EXPLAIN $sSql", self::$m_resDBLink);
if (!$result)
{
return mysql_error();
}
mysql_free_result($result);
return '';
}
public static function NbRows($result)
{
return mysql_num_rows($result);
}
public static function FetchArray($result)
{
return mysql_fetch_array($result, MYSQL_ASSOC);
}
public static function Seek($result, $iRow)
{
return mysql_data_seek($result, $iRow);
}
public static function FreeResult($result)
{
return mysql_free_result($result);
}
public static function IsTable($sTable)
{
$aTableInfo = self::GetTableInfo($sTable);
return (!empty($aTableInfo));
}
public static function IsKey($sTable, $iKey)
{
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return false;
if (!array_key_exists($iKey, $aTableInfo["Fields"])) return false;
$aFieldData = $aTableInfo["Fields"][$iKey];
if (!array_key_exists("Key", $aFieldData)) return false;
return ($aFieldData["Key"] == "PRI");
}
public static function IsAutoIncrement($sTable, $sField)
{
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return false;
if (!array_key_exists($sField, $aTableInfo["Fields"])) return false;
$aFieldData = $aTableInfo["Fields"][$sField];
if (!array_key_exists("Extra", $aFieldData)) return false;
//MyHelpers::debug_breakpoint($aFieldData);
return (strstr($aFieldData["Extra"], "auto_increment"));
}
public static function IsField($sTable, $sField)
{
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return false;
if (!array_key_exists($sField, $aTableInfo["Fields"])) return false;
return true;
}
public static function IsNullAllowed($sTable, $sField)
{
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return false;
if (!array_key_exists($sField, $aTableInfo["Fields"])) return false;
$aFieldData = $aTableInfo["Fields"][$sField];
return (strtolower($aFieldData["Null"]) == "yes");
}
// Returns an array of (fieldname => array of field info)
public static function GetTableFieldsList($sTable)
{
assert(!empty($sTable));
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return array(); // #@# or an error ?
return array_keys($aTableInfo["Fields"]);
}
// Cache the information about existing tables, and their fields
private static $m_aTablesInfo = array();
private static function _TablesInfoCacheReset()
{
self::$m_aTablesInfo = array();
}
private static function _TablesInfoCacheInit()
{
if (!empty(self::$m_aTablesInfo)) return;
$aTables = self::QueryToArray("SHOW TABLES FROM `".self::$m_sDBName."`", 0);
foreach ($aTables as $aTableData)
{
$sTableName = $aTableData[0];
$aFields = self::QueryToArray("SHOW COLUMNS FROM `$sTableName`");
// Note: without backticks, you get an error with some table names (e.g. "group")
foreach ($aFields as $aFieldData)
{
$sFieldName = $aFieldData["Field"];
self::$m_aTablesInfo[$sTableName]["Fields"][$sFieldName] =
array
(
"Name"=>$aFieldData["Field"],
"Type"=>$aFieldData["Type"],
"Null"=>$aFieldData["Null"],
"Key"=>$aFieldData["Key"],
"Default"=>$aFieldData["Default"],
"Extra"=>$aFieldData["Extra"]
);
}
}
}
public static function EnumTables()
{
self::_TablesInfoCacheInit();
return array_keys(self::$m_aTablesInfo);
}
public static function GetTableInfo($sTable)
{
self::_TablesInfoCacheInit();
// table names are transformed into lower case
// is that 100% specific to innodb and myISAM?
$sTableLC = strtolower($sTable);
if (array_key_exists($sTableLC, self::$m_aTablesInfo)) return self::$m_aTablesInfo[$sTableLC];
return null;
}
}
?>

170
core/config.class.inc.php Normal file
View File

@@ -0,0 +1,170 @@
<?php
/**
* Config
* configuration data
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class ConfigException extends CoreException
{
}
class Config
{
//protected $m_bIsLoaded = false;
protected $m_sFile = '';
protected $m_aAppModules;
protected $m_aDataModels;
protected $m_aAddons;
protected $m_sDBHost;
protected $m_sDBUser;
protected $m_sDBPwd;
protected $m_sDBName;
protected $m_sDBSubname;
public function __construct($sConfigFile)
{
$this->m_sFile = $sConfigFile;
$this->Load($sConfigFile);
$this->Verify();
}
protected function CheckFile($sPurpose, $sFileName)
{
if (!file_exists($sFileName))
{
throw new ConfigException("Could not find $sPurpose file", array('file' => $sFileName));
}
}
protected function Load($sConfigFile)
{
$this->CheckFile('configuration', $sConfigFile);
$sConfigCode = trim(file_get_contents($sConfigFile));
// This does not work on several lines
// preg_match('/^<\\?php(.*)\\?'.'>$/', $sConfigCode, $aMatches)...
// So, I've implemented a solution suggested in the PHP doc (search for phpWrapper)
try
{
ob_start();
$sCode = str_replace('<'.'?php','<'.'?', $sConfigCode);
eval('?'.'>'.trim($sCode).'<'.'?');
$sNoise = trim(ob_get_contents());
ob_end_clean();
}
catch (Exception $e)
{
// well, never reach in case of parsing error :-(
// will be improved in PHP 6 ?
throw new ConfigException('Error in configuration file', array('file' => $sConfigFile, 'error' => $e->getMessage()));
}
if (strlen($sNoise) > 0)
{
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
throw new ConfigException('Syntax error in configuration file', array('file' => $sConfigFile, 'error' => $sNoise));
}
if (!isset($MySettings) || !is_array($MySettings))
{
throw new ConfigException('Missing array in configuration file', array('file' => $sConfigFile, 'expected' => '$MySettings'));
}
if (!isset($MyModules) || !is_array($MyModules))
{
throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules'));
}
if (!array_key_exists('application', $MyModules))
{
throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules[\'application\']'));
}
if (!array_key_exists('business', $MyModules))
{
throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules[\'business\']'));
}
if (!array_key_exists('addons', $MyModules))
{
throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules[\'addons\']'));
}
if (!array_key_exists('user rights', $MyModules['addons']))
{
$MyModules['addons']['user rights'] = '../addons/userrights/userrightsnull.class.inc.php';
}
$this->m_aAppModules = $MyModules['application'];
$this->m_aDataModels = $MyModules['business'];
$this->m_aAddons = $MyModules['addons'];
$this->m_sDBHost = trim($MySettings['db_host']);
$this->m_sDBUser = trim($MySettings['db_user']);
$this->m_sDBPwd = trim($MySettings['db_pwd']);
$this->m_sDBName = trim($MySettings['db_name']);
$this->m_sDBSubname = trim($MySettings['db_subname']);
}
protected function Verify()
{
foreach ($this->m_aAppModules as $sModule => $sToInclude)
{
$this->CheckFile('application module', $sToInclude);
}
foreach ($this->m_aDataModels as $sModule => $sToInclude)
{
$this->CheckFile('business model', $sToInclude);
}
foreach ($this->m_aAddons as $sModule => $sToInclude)
{
$this->CheckFile('addon module', $sToInclude);
}
}
public function GetAppModules()
{
return $this->m_aAppModules;
}
public function GetDataModels()
{
return $this->m_aDataModels;
}
public function GetAddons()
{
return $this->m_aAddons;
}
public function GetDBHost()
{
return $this->m_sDBHost;
}
public function GetDBName()
{
return $this->m_sDBName;
}
public function GetDBSubname()
{
return $this->m_sDBSubname;
}
public function GetDBUser()
{
return $this->m_sDBUser;
}
public function GetDBPwd()
{
return $this->m_sDBPwd;
}
}
?>

View File

@@ -0,0 +1,52 @@
<?php
class CoreException extends Exception
{
public function __construct($sIssue, $aContextData = null, $sImpact = '')
{
$this->m_sIssue = $sIssue;
$this->m_sImpact = $sImpact;
$this->m_aContextData = $aContextData ? $aContextData : array();
$sMessage = $sIssue;
if (!empty($sImpact)) $sMessage .= "($sImpact)";
if (count($this->m_aContextData) > 0)
{
$sMessage .= ": ";
$aContextItems = array();
foreach($this->m_aContextData as $sKey => $value)
{
if (is_array($value))
{
$aPairs = array();
foreach($value as $key => $val)
{
if (is_array($val))
{
$aPairs[$key] = '('.implode(', ', $val).')';
}
else
{
$aPairs[$key] = $val;
}
}
$sValue = '{'.implode('; ', $aPairs).'}';
}
else
{
$sValue = $value;
}
$aContextItems[] = "$sKey = $sValue";
}
$sMessage .= implode(', ', $aContextItems);
}
parent::__construct($sMessage, 0);
}
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
{
return $this->getMessage();
}
}
?>

View File

@@ -0,0 +1,362 @@
<?php
/**
* data generator
* helps the consultants in creating dummy data sets, for various test purposes (validation, usability, scalability)
*
* @package tbd
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
/**
* Data Generator helper class
*
* This class is useful to generate a lot of sample data that look consistent
* for a given organization in order to simulate a real CMDB
*/
class cmdbDataGenerator
{
protected $m_sOrganizationKey;
protected $m_sOrganizationCode;
protected $m_sOrganizationName;
protected $m_OrganizationDomains;
/**
* Constructor
*/
public function __construct($sOrganizationId = "")
{
global $aCompanies, $aCompaniesCode;
if ($sOrganizationId == '')
{
// No organization provided, pick a random and unused one from our predefined list
$retries = 5*count($aCompanies);
while ( ($retries > 0) && !isset($this->m_sOrganizationCode)) // Stupid algorithm, but I'm too lazy to do something bulletproof tonight
{
$index = rand(0, count($aCompanies) - 1);
if (!$this->OrganizationExists($aCompanies[$index]['code']))
{
$this->m_sOrganizationCode = $aCompanies[$index]['code'];
$this->m_sOrganizationName = $aCompanies[$index]['name'];
$this->m_OrganizationDomains = $aCompanies[$index]['domain'];
}
$retries--;
}
}
else
{
// A code has been provided, let's take the information we need from the organization itself
$this->m_sOrganizationId = $sOrganizationId;
$oOrg = $this->GetOrganization($sOrganizationId);
if ($oOrg == null)
{
echo "Unable to find the organization '$sOrganisationCode' in the database... can not add objects into this organization.<br/>\n";
exit();
}
$this->m_sOrganizationCode = $oOrg->Get('code');
$this->m_sOrganizationName = $oOrg->Get('name');
if (!isset($aCompaniesCode[$this->m_sOrganizationCode]['domain']))
{
// Generate some probable domain names for this organization
$this->m_OrganizationDomains = array(strtolower($this->m_sOrganizationCode).".com", strtolower($this->m_sOrganizationCode).".org", strtolower($this->m_sOrganizationCode)."corp.net",);
}
else
{
// Pick the domain names for this organization from the predefined list
$this->m_OrganizationDomains = $aCompaniesCode[$this->m_sOrganizationCode]['domain'];
}
}
if (!isset($this->m_sOrganizationCode))
{
echo "Unable to find an organization code which is not already used... can not create a new organization. Enhance the list of fake organizations (\$aCompanies in data_sample.inc.php).<br/>\n";
exit();
}
}
/**
* Get the current organization id used by the generator
*
* @return string The organization id
*/
public function GetOrganizationId()
{
return $this->m_sOrganizationId;
}
/**
* Get the current organization id used by the generator
*
* @param string The organization id
* @return none
*/
public function SetOrganizationId($sId)
{
$this->m_sOrganizationId = $sId;
}
/**
* Get the current organization code used by the generator
*
* @return string The organization code
*/
public function GetOrganizationCode()
{
return $this->m_sOrganizationCode;
}
/**
* Get the current organization name used by the generator
*
* @return string The organization name
*/
function GetOrganizationName()
{
return $this->m_sOrganizationName;
}
/**
* Get a pseudo random first name taken from a (big) prefedined list
*
* @return string A random first name
*/
function GenerateFirstName()
{
global $aFirstNames;
return $aFirstNames[rand(0, count($aFirstNames) - 1)];
}
/**
* Get a pseudo random last name taken from a (big) prefedined list
*
* @return string A random last name
*/
function GenerateLastName()
{
global $aNames;
return $aNames[rand(0, count($aNames) - 1)];
}
/**
* Get a pseudo random country name taken from a prefedined list
*
* @return string A random city name
*/
function GenerateCountryName()
{
global $aCountries;
return $aCountries[rand(0, count($aCountries) - 1)];
}
/**
* Get a pseudo random city name taken from a (big) prefedined list
*
* @return string A random city name
*/
function GenerateCityName()
{
global $aCities;
return $aCities[rand(0, count($aCities) - 1)];
}
/**
* Get a pseudo random email address made of the first name, last name and organization's domain
*
* @return string A random email address
*/
function GenerateEmail($sFirstName, $sLastName)
{
if (rand(1, 20) > 18)
{
// some people (let's say 5~10%) have an irregular email address
$sEmail = strtolower($this->CleanForEmail($sLastName))."@".strtolower($this->GenerateDomain());
}
else
{
$sEmail = strtolower($this->CleanForEmail($sFirstName)).".".strtolower($this->CleanForEmail($sLastName))."@".strtolower($this->GenerateDomain());
}
return $sEmail;
}
/**
* Generate (pseudo) random strings that follow a given pattern
*
* The template is made of any number of 'parts' separated by pipes '|'
* Each part is either:
* - domain() => returns a domain name for the current organization
* - enum(aaa,bb,c,dddd) => returns randomly one of aaa,bb,c or dddd with the same
* probability of occurence. If you want to change the probability you can repeat some values
* i.e enum(most probable,most probable,most probable,most probable,most probable,rare)
* - number(xxx-yyy) => a random number between xxx and yyy (bounds included)
* note that if the first number (xxx) begins with a zero, then the result will zero padded
* to the same number of digits as xxx.
* All other 'part' that does not follow one of the above mentioned pattern is returned as is
*
* Example: GenerateString("enum(sw,rtr,gw)|number(00-99)|.|domain()")
* will produce strings like "sw01.netcmdb.com" or "rtr45.itop.org"
*
* @param string $sTemplate The template used for generating the string
* @return string The generated pseudo random the string
*/
function GenerateString($sTemplate)
{
$sResult = "";
$aParts = split("\|", $sTemplate);
foreach($aParts as $sPart)
{
if (preg_match("/domain\(\)/", $sPart, $aMatches))
{
$sResult .= strtolower($this->GenerateDomain());
}
elseif (preg_match("/enum\((.+)\)/", $sPart, $aMatches))
{
$sEnumValues = $aMatches[1];
$aEnumValues = split(",", $sEnumValues);
$sResult .= $aEnumValues[rand(0, count($aEnumValues) - 1)];
}
elseif (preg_match("/number\((\d+)-(\d+)\)/", $sPart, $aMatches))
{
$sStartNumber = $aMatches[1];
if ($sStartNumber[0] == '0')
{
// number must be zero padded
$sFormat = "%0".strlen($sStartNumber)."d";
}
else
{
$sFormat = "%d";
}
$sEndNumber = $aMatches[2];
$sResult .= sprintf($sFormat, rand($sStartNumber, $sEndNumber));
}
else
{
$sResult .= $sPart;
}
}
return $sResult;
}
/**
* Generate a foreign key by picking a random element of the given class in a set limited by the given search criteria
*
* Example: GenerateKey("bizLocation", array('org_id', $oGenerator->GetOrganizationId());
* will produce the foreign key of a Location object picked at random in the same organization
*
* @param string $sClass The name of the class to search for
* @param string $aFilterCriteria A hash array of filterCOde => FilterValue (the strict operator '=' is used )
* @return mixed The key to an object of the given class, or null if none are found
*/
function GenerateKey($sClass, $aFilterCriteria)
{
$retKey = null;
$oFilter = new CMDBSearchFilter($sClass);
foreach($aFilterCriteria as $sFilterCode => $filterValue)
{
$oFilter->AddCondition($sFilterCode, $filterValue, '=');
}
$oSet = new CMDBObjectSet($oFilter);
if ($oSet->Count() > 0)
{
$max_count = $index = rand(1, $oSet->Count());
do
{
$oObj = $oSet->Fetch();
$index--;
}
while($index > 0);
if (!is_object($oObj))
{
echo "<pre>";
echo "ERROR: non empty set, but invalid object picked! class='$sClass'\n";
echo "Index chosen: $max_count\n";
echo "The set is supposed to contain ".$oSet->Count()." object(s)\n";
echo "Filter criteria:\n";
print_r($aFilterCriteria);
echo "</pre>";
}
else
{
$retKey = $oObj->GetKey();
}
}
return $retKey;
}
///////////////////////////////////////////////////////////////////////////////
//
// Protected methods
//
///////////////////////////////////////////////////////////////////////////////
/**
* Generate a (random) domain name consistent with the organization name & code
*
* The values are pulled from a (limited) predefined list. Note that a given
* organization may have several domain names, so the result may be random
*
* @return string A domain name (like netcnmdb.com)
*/
protected function GenerateDomain()
{
if (is_array($this->m_OrganizationDomains))
{
$sDomain = $this->m_OrganizationDomains[rand(0, count($this->m_OrganizationDomains)-1)];
}
else
{
$sDomain = $this->m_OrganizationDomains;
}
return $sDomain;
}
/**
* Strips accented characters from a string in order to produce a suitable email address
*
* @param string The text string to clean
* @return string The cleanified text string
*/
protected function CleanForEmail($sText)
{
return str_replace(array("'", "é", "è", "ê", "ç", "à", "â", "ñ", "ö", "ä"), array("", "e", "e", "e", "c", "a", "a", "n", "oe", "ae"), $sText);
}
/**
* Check if an organization with the given code already exists in the database
*
* @param string $sCode The code to look for
* @return boolean true if the given organization exists, false otherwise
*/
protected function OrganizationExists($sCode)
{
$oFilter = new CMDBSearchFilter('bizOrganization');
$oFilter->AddCondition('code', $sCode, '=');
$oSet = new CMDBObjectSet($oFilter);
return ($oSet->Count() > 0);
}
/**
* Search for an organization with the given code in the database
*
* @param string $Id The organization Id to look for
* @return cmdbOrganization the organization if it exists, null otherwise
*/
protected function GetOrganization($sId)
{
$oOrg = null;
$oFilter = new CMDBSearchFilter('bizOrganization');
$oFilter->AddCondition('pkey', $sId, '=');
$oSet = new CMDBObjectSet($oFilter);
if ($oSet->Count() > 0)
{
$oOrg = $oSet->Fetch(); // Let's take the first one found
}
return $oOrg;
}
}
?>

791
core/dbobject.class.php Normal file
View File

@@ -0,0 +1,791 @@
<?php
/**
* ???
* the class a persistent object must be derived from
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
require_once('metamodel.class.php');
/**
* A persistent object, as defined by the metamodel
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class DBObject
{
private static $m_aMemoryObjectsByClass = array();
private $m_bIsInDB = false; // true IIF the object is mapped to a DB record
private $m_iKey = null;
private $m_aCurrValues = array();
private $m_aOrigValues = array();
private $m_bFullyLoaded = false; // Compound objects can be partially loaded
private $m_aLoadedAtt = array(); // Compound objects can be partially loaded, array of sAttCode
// Use the MetaModel::NewObject to build an object (do we have to force it?)
public function __construct($aRow = null)
{
if (!empty($aRow))
{
$this->FromRow($aRow);
$this->m_bFullyLoaded = $this->IsFullyLoaded();
return;
}
// Creation of brand new object
//
$this->m_iKey = self::GetNextTempId(get_class($this));
// set default values
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
$this->m_aOrigValues[$sAttCode] = null;
// ??? $this->m_aLoadedAtt[$sAttCode] = true;
}
}
// Returns an Id for memory objects
static protected function GetNextTempId($sClass)
{
if (!array_key_exists($sClass, self::$m_aMemoryObjectsByClass))
{
self::$m_aMemoryObjectsByClass[$sClass] = 0;
}
self::$m_aMemoryObjectsByClass[$sClass]++;
return (- self::$m_aMemoryObjectsByClass[$sClass]);
}
public function __toString()
{
$sRet = '';
$sClass = get_class($this);
$sRootClass = MetaModel::GetRootClass($sClass);
$iPKey = $this->GetKey();
$sRet .= "<b title=\"$sRootClass\">$sClass</b>::$iPKey<br/>\n";
$sRet .= "<ul class=\"treeview\">\n";
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
$sRet .= "<li>".$oAttDef->GetLabel()." = ".$this->GetAsHtml($sAttCode)."</li>\n";
}
$sRet .= "</ul>";
return $sRet;
}
// Restore initial values... mmmm, to be discussed
public function DBRevert()
{
$this->Reload();
}
protected function IsFullyLoaded()
{
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
@$bIsLoaded = $this->m_aLoadedAtt[$sAttCode];
if ($bIsLoaded !== true)
{
return false;
}
}
return true;
}
protected function Reload()
{
assert($this->m_bIsInDB);
$aRow = MetaModel::MakeSingleRow(get_class($this), $this->m_iKey);
if (empty($aRow))
{
trigger_error("Failed to reload object of class '".get_class($this)."', pkey = ".$this->m_iKey, E_USER_ERROR);
}
$this->FromRow($aRow);
// Process linked set attributes
//
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if (!$oAttDef->IsLinkSet()) continue;
// Load the link information
$sLinkClass = $oAttDef->GetLinkedClass();
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
// The class to target is not the current class, because if this is a derived class,
// it may differ from the target class, then things start to become confusing
$oRemoteExtKeyAtt = MetaModel::GetAttributeDef($sLinkClass, $sExtKeyToMe);
$sMyClass = $oRemoteExtKeyAtt->GetTargetClass();
$oMyselfSearch = new DBObjectSearch($sMyClass);
$oMyselfSearch->AddCondition('pkey', $this->m_iKey, '=');
$oLinkSearch = new DBObjectSearch($sLinkClass);
$oLinkSearch->AddCondition_PointingTo($oMyselfSearch, $sExtKeyToMe);
$oLinks = new DBObjectSet($oLinkSearch);
$this->m_aCurrValues[$sAttCode] = $oLinks;
$this->m_aOrigValues[$sAttCode] = clone $this->m_aCurrValues[$sAttCode];
$this->m_aLoadedAtt[$sAttCode] = true;
}
$this->m_bFullyLoaded = true;
}
protected function FromRow($aRow)
{
$this->m_iKey = null;
$this->m_bIsInDB = true;
$this->m_aCurrValues = array();
$this->m_aOrigValues = array();
$this->m_aLoadedAtt = array();
// Get the key
//
$sKeyField = "pkey";
if (!array_key_exists($sKeyField, $aRow))
{
// #@# Bug ?
trigger_error("Missing key for class '".get_class($this)."'", E_USER_ERROR);
}
else
{
$iPKey = $aRow[$sKeyField];
if (!self::IsValidPKey($iPKey))
{
trigger_error("An object PKey must be an integer value ($iPKey)", E_USER_NOTICE);
}
$this->m_iKey = $iPKey;
}
// Build the object from an array of "attCode"=>"value")
//
$bFullyLoaded = true; // ... set to false if any attribute is not found
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
// Say something, whatever the type of attribute
$this->m_aLoadedAtt[$sAttCode] = false;
// Skip links (could not be loaded by the mean of this query)
if ($oAttDef->IsLinkSet()) continue;
if (array_key_exists($sAttCode, $aRow))
{
$sValue = $oAttDef->SQLValueToRealValue($aRow[$sAttCode]);
$this->m_aCurrValues[$sAttCode] = $sValue;
$this->m_aOrigValues[$sAttCode] = $sValue;
$this->m_aLoadedAtt[$sAttCode] = true;
}
else
{
// This attribute was expected and not found in the query columns
$bFullyLoaded = false;
}
}
return $bFullyLoaded;
}
public function Set($sAttCode, $value)
{
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
{
trigger_error("Unknown attribute code '$sAttCode' for the class ".get_class($this), E_USER_ERROR);
}
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($this->m_bIsInDB && !$this->m_bFullyLoaded)
{
// First time Set is called... ensure that the object gets fully loaded
// Otherwise we would lose the values on a further Reload
// + consistency does not make sense !
$this->Reload();
}
if($oAttDef->IsScalar() && !$oAttDef->IsNullAllowed() && is_null($value))
{
trigger_error("null not allowed for attribute '$sAttCode', setting default value", E_USER_NOTICE);
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
if ($oAttDef->IsExternalKey() && is_object($value))
{
// Setting an external key with a whole object (instead of just an ID)
// let's initialize also the external fields that depend on it
// (useful when building objects in memory and not from a query)
if ( (get_class($value) != $oAttDef->GetTargetClass()) && (!is_subclass_of($value, $oAttDef->GetTargetClass())))
{
trigger_error("Trying to set the value of '$sAttCode', to an object of class '".get_class($value)."', whereas it's an ExtKey to '".$oAttDef->GetTargetClass()."'. Ignored", E_USER_NOTICE);
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
}
else
{
$this->m_aCurrValues[$sAttCode] = $value->GetKey();
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
{
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode))
{
$this->m_aCurrValues[$sCode] = $value->Get($oDef->GetExtAttCode());
}
}
}
return;
}
if(!$oAttDef->IsScalar() && !is_object($value))
{
trigger_error("scalar not allowed for attribute '$sAttCode', setting default value (empty list)", E_USER_NOTICE);
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
if($oAttDef->IsLinkSet())
{
if((get_class($value) != 'DBObjectSet') && !is_subclass_of($value, 'DBObjectSet'))
{
trigger_error("expecting a set of persistent objects (found a '".get_class($value)."'), setting default value (empty list)", E_USER_NOTICE);
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
$oObjectSet = $value;
$sSetClass = $oObjectSet->GetClass();
$sLinkClass = $oAttDef->GetLinkedClass();
// not working fine :-( if (!is_subclass_of($sSetClass, $sLinkClass))
if ($sSetClass != $sLinkClass)
{
trigger_error("expecting a set of '$sLinkClass' objects (found a set of '$sSetClass'), setting default value (empty list)", E_USER_NOTICE);
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
}
$this->m_aCurrValues[$sAttCode] = $oAttDef->MakeRealValue($value);
}
public function Get($sAttCode)
{
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
{
trigger_error("Unknown attribute code '$sAttCode' for the class ".get_class($this), E_USER_ERROR);
}
if ($this->m_bIsInDB && !$this->m_aLoadedAtt[$sAttCode])
{
// #@# non-scalar attributes.... handle that differentely
$this->Reload();
}
$this->ComputeFields();
return $this->m_aCurrValues[$sAttCode];
}
public function ComputeFields()
{
if (is_callable(array($this, 'ComputeValues')))
{
// First check that we are not currently computing the fields
// (yes, we need to do some things like Set/Get to compute the fields which will in turn trigger the update...)
foreach (debug_backtrace() as $aCallInfo)
{
if (!array_key_exists("class", $aCallInfo)) continue;
if ($aCallInfo["class"] != get_class($this)) continue;
if ($aCallInfo["function"] != "ComputeValues") continue;
return; //skip!
}
$this->ComputeValues();
}
}
public function GetHyperLink($sLabel = "")
{
if (empty($sLabel))
{
$sLabel = $this->GetName();
}
$aAvailableFields = array($sLabel);
return call_user_func(array(get_class($this), 'MakeHyperLink'), get_class($this), $this->GetKey(), $aAvailableFields);
}
public function GetAsHTML($sAttCode)
{
$sClass = get_class($this);
$oAtt = MetaModel::GetAttributeDef($sClass, $sAttCode);
$aExtKeyFriends = MetaModel::GetExtKeyFriends($sClass, $sAttCode);
if (count($aExtKeyFriends) > 0)
{
// This attribute is an ext key (in this class or in another class)
// The corresponding value is an id of the remote object
// Let's try to use the corresponding external fields for a sexy display
$aAvailableFields = array();
foreach ($aExtKeyFriends as $sDispAttCode => $oExtField)
{
$aAvailableFields[$oExtField->GetExtAttCode()] = $oExtField->GetAsHTML($this->Get($oExtField->GetCode()));
}
$sTargetClass = $oAtt->GetTargetClass(EXTKEY_ABSOLUTE);
return call_user_func(array(get_class($this), 'MakeHyperLink'), $sTargetClass, $this->Get($sAttCode), $aAvailableFields);
}
// That's a standard attribute (might be an ext field or a direct field, etc.)
return $oAtt->GetAsHTML($this->Get($sAttCode));
}
public function GetAsXML($sAttCode)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsXML($this->Get($sAttCode));
}
public function GetAsCSV($sAttCode, $sSeparator = ';', $sSepEscape = ',')
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsCSV($this->Get($sAttCode), $sSeparator, $sSepEscape);
}
// could be in the metamodel ?
public static function IsValidPKey($value)
{
return ((string)$value === (string)(int)$value);
}
public function GetKey()
{
return $this->m_iKey;
}
public function SetKey($iNewKey)
{
if (!self::IsValidPKey($iNewKey))
{
trigger_error("An object PKey must be an integer value ($iNewKey)", E_USER_ERROR);
}
if ($this->m_bIsInDB && !empty($this->m_iKey) && ($this->m_iKey != $iNewKey))
{
trigger_error("Changing the key ({$this->m_iKey} to $iNewKey) on an object (class {".get_class($this).") wich already exists in the Database", E_USER_NOTICE);
}
$this->m_iKey = $iNewKey;
}
public function GetName()
{
$sNameAttCode = MetaModel::GetNameAttributeCode(get_class($this));
if (empty($sNameAttCode))
{
return $this->m_iKey;
}
else
{
return $this->Get($sNameAttCode);
}
}
public function GetState()
{
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
if (empty($sStateAttCode))
{
return '';
}
else
{
$aStates = MetaModel::EnumStates(get_class($this));
return $aStates[$this->Get($sStateAttCode)]['label'];
}
}
/**
* Returns the set of flags (OPT_ATT_HIDDEN, OPT_ATT_READONLY, OPT_ATT_MANDATORY...)
* for the given attribute in the current state of the object
* @param string $sAttCode The code of the attribute
* @return integer Flags: the binary combination of the flags applicable to this attribute
*/
public function GetAttributeFlags($sAttCode)
{
$iFlags = 0; // By default (if no life cycle) no flag at all
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
if (!empty($sStateAttCode))
{
$iFlags = MetaModel::GetAttributeFlags(get_class($this), $this->Get($sStateAttCode), $sAttCode);
}
return $iFlags;
}
// check if the given (or current) value is suitable for the attribute
public function CheckValue($sAttCode, $value = null)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($oAtt->IsExternalKey())
{
if (!$oAtt->IsNullAllowed() || ($this->Get($sAttCode) != 0) )
{
$oTargetObj = MetaModel::GetObject($oAtt->GetTargetClass(), $this->Get($sAttCode));
if (!$oTargetObj)
{
echo "Invalid value (".$this->Get($sAttCode).") for ExtKey $sAttCode.";
return false;
}
}
}
return true;
}
// check attributes together
public function CheckConsistency()
{
return true;
}
// check if it is allowed to record the new object into the database
// a displayable error is returned
// Note: checks the values and consistency
public function CheckToInsert()
{
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if (!$this->CheckValue($sAttCode)) return false;
}
if (!$this->CheckConsistency()) return false;
return true;
}
// check if it is allowed to update the existing object into the database
// a displayable error is returned
// Note: checks the values and consistency
public function CheckToUpdate()
{
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if (!$this->CheckValue($sAttCode)) return false;
}
if (!$this->CheckConsistency()) return false;
return true;
}
// check if it is allowed to delete the existing object from the database
// a displayable error is returned
public function CheckToDelete()
{
return true;
}
protected function ListChangedValues(array $aProposal)
{
$aDelta = array();
foreach ($aProposal as $sAtt => $proposedValue)
{
if (!array_key_exists($sAtt, $this->m_aOrigValues) || ($this->m_aOrigValues[$sAtt] != $proposedValue))
{
$aDelta[$sAtt] = $proposedValue;
}
}
return $aDelta;
}
// List the attributes that have been changed
// Returns an array of attname => currentvalue
public function ListChanges()
{
return $this->ListChangedValues($this->m_aCurrValues);
}
// used both by insert/update
private function DBWriteLinks()
{
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if (!$oAttDef->IsLinkSet()) continue;
$oLinks = $this->Get($sAttCode);
$oLinks->Rewind();
while ($oLinkedObject = $oLinks->Fetch())
{
$oLinkedObject->Set($oAttDef->GetExtKeyToMe(), $this->m_iKey);
$oLinkedObject->DBWrite();
}
// Delete the objects that were initialy present and disappeared from the list
// (if any)
$oOriginalSet = $this->m_aOrigValues[$sAttCode];
if ($oOriginalSet != null)
{
$aOriginalList = $oOriginalSet->ToArray();
$aNewSet = $oLinks->ToArray();
$aToDelete = array_diff($aOriginalList, $aNewSet);
foreach ($aToDelete as $iKey => $oObject)
{
$oObject->DBDelete();
}
}
}
}
private function DBInsertSingleTable($sTableClass)
{
$sClass = get_class($this);
// fields in first array, values in the second
$aFieldsToWrite = array();
$aValuesToWrite = array();
if (!empty($this->m_iKey) && ($this->m_iKey >= 0))
{
// Add it to the list of fields to write
$aFieldsToWrite[] = MetaModel::DBGetKey($sTableClass);
$aValuesToWrite[] = CMDBSource::Quote($this->m_iKey);
}
foreach(MetaModel::ListAttributeDefs($sTableClass) as $sAttCode=>$oAttDef)
{
// Skip this attribute if not defined in this table
if (!MetaModel::IsAttributeOrigin($sTableClass, $sAttCode)) continue;
if ($oAttDef->IsDirectField())
{
$aFieldsToWrite[] = $oAttDef->GetSQLExpr();
$aValuesToWrite[] = CMDBSource::Quote($oAttDef->RealValueToSQLValue($this->m_aCurrValues[$sAttCode]));
}
}
if (count($aValuesToWrite) == 0) return false;
$sTable = MetaModel::DBGetTable($sTableClass);
$sInsertSQL = "INSERT INTO $sTable (".join(",", $aFieldsToWrite).") VALUES (".join(", ", $aValuesToWrite).")";
$iNewKey = CMDBSource::InsertInto($sInsertSQL);
// Note that it is possible to have a key defined here, and the autoincrement expected, this is acceptable in a non root class
if (empty($this->m_iKey))
{
// Take the autonumber
$this->m_iKey = $iNewKey;
}
return $this->m_iKey;
}
// Insert of record for the new object into the database
// Returns the key of the newly created object
public function DBInsert()
{
if ($this->m_bIsInDB)
{
trigger_error("The object already exists into the Database, you may want to use the clone function", E_USER_ERROR);
}
$sClass = get_class($this);
$sRootClass = MetaModel::GetRootClass($sClass);
// Ensure the update of the values (we are accessing the data directly)
$this->ComputeFields();
if ($this->m_iKey < 0)
{
// This was a temporary "memory" key: discard it so that DBInsertSingleTable will not try to use it!
$this->m_iKey = null;
}
// If not automatically computed, then check that the key is given by the caller
if (!MetaModel::IsAutoIncrementKey($sRootClass))
{
if (empty($this->m_iKey))
{
trigger_error("Missing key for the object to write - This class is supposed to have a user defined key, not an autonumber", E_USER_NOTICE);
}
}
// First query built upon on the root class, because the ID must be created first
$this->m_iKey = $this->DBInsertSingleTable($sRootClass);
// Then do the leaf class, if different from the root class
if ($sClass != $sRootClass)
{
$this->DBInsertSingleTable($sClass);
}
// Then do the other classes
foreach(MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
if ($sParentClass == $sRootClass) continue;
if (MetaModel::DBGetTable($sParentClass) == "") continue;
$this->DBInsertSingleTable($sParentClass);
}
$this->DBWriteLinks();
// Reload to update the external attributes
$this->m_bIsInDB = true;
$this->Reload();
return $this->m_iKey;
}
// Creates a copy of the current object into the database
// Returns the id of the newly created object
public function DBClone($iNewKey = null)
{
$this->m_bIsInDB = false;
$this->m_iKey = $iNewKey;
return $this->DBInsert();
}
// Update a record
public function DBUpdate()
{
if (!$this->m_bIsInDB)
{
trigger_error("DBUpdate: could not update a newly created object, please call DBInsert instead", E_USER_ERROR);
}
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
trigger_error("Attempting to update an unchanged object", E_USER_NOTICE);
return;
}
$bHasANewExternalKeyValue = false;
foreach($aChanges as $sAttCode => $valuecurr)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($oAttDef->IsExternalKey()) $bHasANewExternalKeyValue = true;
if (!$oAttDef->IsDirectField()) unset($aChanges[$sAttCode]);
}
// Update scalar attributes
if (count($aChanges) != 0)
{
$oFilter = new DBObjectSearch(get_class($this));
$oFilter->AddCondition('pkey', $this->m_iKey, '=');
$sSQL = MetaModel::MakeUpdateQuery($oFilter, $aChanges);
CMDBSource::Query($sSQL);
}
$this->DBWriteLinks();
// Reload to get the external attributes
if ($bHasANewExternalKeyValue) $this->Reload();
return $this->m_iKey;
}
// Make the current changes persistent - clever wrapper for Insert or Update
public function DBWrite()
{
if ($this->m_bIsInDB)
{
return $this->DBUpdate();
}
else
{
return $this->DBInsert();
}
}
// Delete a record
public function DBDelete()
{
$oFilter = new DBObjectSearch(get_class($this));
$oFilter->AddCondition('pkey', $this->m_iKey, '=');
$sSQL = MetaModel::MakeDeleteQuery($oFilter);
CMDBSource::Query($sSQL);
$this->m_bIsInDB = false;
$this->m_iKey = null;
}
public function EnumTransitions()
{
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
if (empty($sStateAttCode)) return array();
$sState = $this->Get(MetaModel::GetStateAttributeCode(get_class($this)));
return MetaModel::EnumTransitions(get_class($this), $sState);
}
public function ApplyStimulus($sStimulusCode)
{
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
if (empty($sStateAttCode)) return false;
MyHelpers::CheckKeyInArray('object lifecycle stimulus', $sStimulusCode, MetaModel::EnumStimuli(get_class($this)));
$aStateTransitions = $this->EnumTransitions();
$aTransitionDef = $aStateTransitions[$sStimulusCode];
// Change the state before proceeding to the actions, this is necessary because an action might
// trigger another stimuli (alternative: push the stimuli into a queue)
$this->Set($sStateAttCode, $aTransitionDef['target_state']);
// $aTransitionDef is an
// array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
$bSuccess = true;
foreach ($aTransitionDef['actions'] as $sActionHandler)
{
// std PHP spec
$aActionCallSpec = array($this, $sActionHandler);
if (!is_callable($aActionCallSpec))
{
trigger_error("Unable to call action: ".get_class($this)."::$sActionHandler", E_USER_ERROR);
return;
}
$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
// if one call fails, the whole is considered as failed
if (!$bRet) $bSuccess = false;
}
return $bSuccess;
}
// Return an empty set for the parent of all
public static function GetRelationQueries($sRelCode)
{
return array();
}
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array())
{
foreach (MetaModel::EnumRelationQueries(get_class($this), $sRelCode) as $sDummy => $aQueryInfo)
{
MetaModel::DbgTrace("object=".$this->GetKey().", depth=$iMaxDepth, rel=".$aQueryInfo["sQuery"]);
$sQuery = $aQueryInfo["sQuery"];
$bPropagate = $aQueryInfo["bPropagate"];
$iDistance = $aQueryInfo["iDistance"];
$iDepth = $bPropagate ? $iMaxDepth - 1 : 0;
$oFlt = DBObjectSearch::FromSibusQL($sQuery, array(), $this);
$oObjSet = new DBObjectSet($oFlt);
while ($oObj = $oObjSet->Fetch())
{
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
$sObjKey = $oObj->GetKey();
if (array_key_exists($sRootClass, $aResults))
{
if (array_key_exists($sObjKey, $aResults[$sRootClass]))
{
continue; // already visited, skip
}
}
$aResults[$sRootClass][$sObjKey] = $oObj;
if ($iDepth > 0)
{
$oObj->GetRelatedObjects($sRelCode, $iDepth, $aResults);
}
}
}
return $aResults;
}
}
?>

View File

@@ -0,0 +1,967 @@
<?php
/**
* Define filters for a given class of objects (formerly named "filter")
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
/**
* Sibusql - value set start
* @package iTopORM
* @info zis is private
*/
define('VS_START', '{');
/**
* Sibusql - value set end
* @package iTopORM
*/
define('VS_END', '}');
define('SIBUSQLPARAMREGEXP', "/\\$\\[(.*)\\:(.*)\\:(.*)\\]/U");
define('SIBUSQLTHISREGEXP', "/this\\.(.*)/U");
/**
* Define filters for a given class of objects (formerly named "filter")
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @mytagrom youpi
* @since 1.0
* @version 1.1.1.1 $
*/
class DBObjectSearch
{
private $m_sClass;
private $m_sClassAlias;
private $m_aClasses; // queried classes (alias => class name)
private $m_oSearchCondition;
private $m_aFullText;
private $m_aPointingTo;
private $m_aReferencedBy;
private $m_aRelatedTo;
public function __construct($sClass, $sClassAlias = '')
{
if (empty($sClassAlias)) $sClassAlias = $sClass;
assert('is_string($sClass)');
assert('MetaModel::IsValidClass($sClass)'); // #@# could do better than an assert, or at least give the caller's reference
// => idee d'un assert avec call stack (autre utilisation = echec sur query SQL)
if (empty($sClassAlias)) $sClassAlias = $sClass;
$this->m_sClass = $sClass;
$this->m_sClassAlias = $sClassAlias;
$this->m_aClasses = array($sClassAlias => $sClass);
$this->m_oSearchCondition = new TrueExpression;
$this->m_aFullText = array();
$this->m_aPointingTo = array();
$this->m_aReferencedBy = array();
$this->m_aRelatedTo = array();
}
public function IsAny()
{
// #@# todo - if (!$this->m_oSearchCondition->IsTrue()) return false;
if (count($this->m_aFullText) > 0) return false;
if (count($this->m_aPointingTo) > 0) return false;
if (count($this->m_aReferencedBy) > 0) return false;
if (count($this->m_aRelatedTo) > 0) return false;
return true;
}
public function Describe()
{
// To replace __Describe
}
public function DescribeConditionPointTo($sExtKeyAttCode)
{
if (!isset($this->m_aPointingTo[$sExtKeyAttCode])) return "";
$oFilter = $this->m_aPointingTo[$sExtKeyAttCode];
if ($oFilter->IsAny()) return "";
$oAtt = MetaModel::GetAttributeDef($this->GetClass(), $sExtKeyAttCode);
return $oAtt->GetLabel()." having ({$oFilter->DescribeConditions()})";
}
public function DescribeConditionRefBy($sForeignClass, $sForeignExtKeyAttCode)
{
if (!isset($this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode])) return "";
$oFilter = $this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode];
if ($oFilter->IsAny()) return "";
$oAtt = MetaModel::GetAttributeDef($sForeignClass, $sForeignExtKeyAttCode);
return "being ".$oAtt->GetLabel()." for ".$sForeignClass."s in ({$oFilter->DescribeConditions()})";
}
public function DescribeConditionRelTo($aRelInfo)
{
$oFilter = $aRelInfo['flt'];
$sRelCode = $aRelInfo['relcode'];
$iMaxDepth = $aRelInfo['maxdepth'];
return "related ($sRelCode... peut mieux faire !, $iMaxDepth dig depth) to a {$oFilter->GetClass()} ({$oFilter->DescribeConditions()})";
}
public function DescribeConditions()
{
$aConditions = array();
$aCondFT = array();
foreach($this->m_aFullText as $sFullText)
{
$aCondFT[] = " contain word(s) '$sFullText'";
}
if (count($aCondFT) > 0)
{
$aConditions[] = "which ".implode(" and ", $aCondFT);
}
// #@# todo - review textual description of the JOIN and search condition (is that still feasible?)
$aConditions[] = $this->RenderCondition();
$aCondPoint = array();
foreach($this->m_aPointingTo as $sExtKeyAttCode=>$oFilter)
{
if ($oFilter->IsAny()) continue;
$aCondPoint[] = $this->DescribeConditionPointTo($sExtKeyAttCode);
}
if (count($aCondPoint) > 0)
{
$aConditions[] = implode(" and ", $aCondPoint);
}
$aCondReferred= array();
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode=>$oForeignFilter)
{
if ($oForeignFilter->IsAny()) continue;
$aCondReferred[] = $this->DescribeConditionRefBy($sForeignClass, $sForeignExtKeyAttCode);
}
}
foreach ($this->m_aRelatedTo as $aRelInfo)
{
$aCondReferred[] = $this->DescribeConditionRelTo($aRelInfo);
}
if (count($aCondReferred) > 0)
{
$aConditions[] = implode(" and ", $aCondReferred);
}
return implode(" and ", $aConditions);
}
public function __DescribeHTML()
{
$sConditionDesc = $this->DescribeConditions();
if (!empty($sConditionDesc))
{
return "Objects of class '$this->m_sClass', $sConditionDesc";
}
return "Any object of class '$this->m_sClass'";
}
protected function TransferConditionExpression($oFilter, $aTranslation)
{
$oTranslated = $oFilter->GetCriteria()->Translate($aTranslation, false);
$this->AddConditionExpression($oTranslated);
}
public function ResetCondition()
{
$this->m_oSearchCondition = new TrueExpression();
// ? is that enough, do I need to rebuild the list after the subqueries ?
$this->m_aClasses = array($this->m_sClassAlias => $this->m_sClass);
}
public function AddConditionExpression($oExpression)
{
$this->m_oSearchCondition = $this->m_oSearchCondition->LogAnd($oExpression);
}
public function AddCondition($sFilterCode, $value, $sOpCode = null)
{
MyHelpers::CheckKeyInArray('filter code', $sFilterCode, MetaModel::GetClassFilterDefs($this->m_sClass));
$oFilterDef = MetaModel::GetClassFilterDef($this->m_sClass, $sFilterCode);
if (empty($sOpCode))
{
$sOpCode = $oFilterDef->GetLooseOperator();
}
MyHelpers::CheckKeyInArray('operator', $sOpCode, $oFilterDef->GetOperators());
// Preserve backward compatibility - quick n'dirty way to change that API semantic
//
$oField = new FieldExpression($sFilterCode, $this->m_sClassAlias);
switch($sOpCode)
{
case 'SameDay':
case 'SameMonth':
case 'SameYear':
case 'Today':
case '>|':
case '<|':
case '=|':
throw new CoreException('Deprecated operator, please consider using OQL (SQL) expressions like "(TO_DAYS(NOW()) - TO_DAYS(x)) AS AgeDays"', array('operator' => $sOpCode));
break;
case "IN":
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
break;
case "NOTIN":
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
$sOQLCondition = $oField->Render()." NOT IN $sListExpr";
break;
case 'Contains':
$oRightExpr = new ScalarExpression("%$value%");
$sOperator = 'LIKE';
break;
case 'Begins with':
$oRightExpr = new ScalarExpression("$value%");
$sOperator = 'LIKE';
break;
case 'Finishes with':
$oRightExpr = new ScalarExpression("%$value");
$sOperator = 'LIKE';
break;
default:
$oRightExpr = new ScalarExpression($value);
$sOperator = $sOpCode;
}
switch($sOpCode)
{
case "IN":
case "NOTIN":
$oNewCondition = Expression::FromOQL($sOQLCondition);
break;
case 'Contains':
case 'Begins with':
case 'Finishes with':
default:
$oNewCondition = new BinaryExpression($oField, $sOperator, $oRightExpr);
}
$this->AddConditionExpression($oNewCondition);
}
public function AddCondition_FullText($sFullText)
{
$this->m_aFullText[] = $sFullText;
}
protected function AddToNameSpace(&$aClassAliases, &$aAliasTranslation)
{
$sOrigAlias = $this->m_sClassAlias;
if (array_key_exists($sOrigAlias, $aClassAliases))
{
$this->m_sClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $oFilter->GetClass());
// Translate the condition expression with the new alias
$aAliasTranslation[$sOrigAlias]['*'] = $this->m_sClassAlias;
}
foreach($this->m_aPointingTo as $sExtKeyAttCode=>$oFilter)
{
$oFilter->AddToNameSpace($aClassAliases, $aAliasTranslation);
}
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode=>$oForeignFilter)
{
$oForeignFilter->AddToNameSpace($aClassAliases, $aAliasTranslation);
}
}
}
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode)
{
$aAliasTranslation = array();
$res = $this->AddCondition_PointingTo_InNameSpace($oFilter, $sExtKeyAttCode, $this->m_aClasses, $aAliasTranslation);
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
return $res;
}
protected function AddCondition_PointingTo_InNameSpace(DBObjectSearch $oFilter, $sExtKeyAttCode, &$aClassAliases, &$aAliasTranslation)
{
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
{
trigger_error("The attribute code '$sExtKeyAttCode' is not an external key of the class '{$this->GetClass()}' - the condition will be ignored", E_USER_WARNING);
}
$oAttExtKey = MetaModel::GetAttributeDef($this->GetClass(), $sExtKeyAttCode);
if(!MetaModel::IsSameFamilyBranch($oFilter->GetClass(), $oAttExtKey->GetTargetClass()))
{
trigger_error("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}", E_USER_ERROR);
}
if (array_key_exists($sExtKeyAttCode, $this->m_aPointingTo))
{
$this->m_aPointingTo[$sExtKeyAttCode]->MergeWith_InNamespace($oFilter, $aClassAliases, $aAliasTranslation);
}
else
{
$sOrigAlias = $oFilter->GetClassAlias();
$sKeyClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $oFilter->GetClass());
if ($sKeyClassAlias != $sOrigAlias)
{
// Translate the condition expression with the new alias
$aAliasTranslation[$sOrigAlias]['*'] = $sKeyClassAlias;
}
// #@# The condition expression found in that filter should not be used - could be another kind of structure like a join spec tree !!!!
$oNewFilter = clone $oFilter;
$oNewFilter->ResetCondition();
$this->m_aPointingTo[$sExtKeyAttCode] = $oNewFilter;
}
}
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode)
{
$aAliasTranslation = array();
$res = $this->AddCondition_ReferencedBy_InNameSpace($oFilter, $sForeignExtKeyAttCode, $this->m_aClasses, $aAliasTranslation);
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
return $res;
}
public function AddCondition_ReferencedBy_InNameSpace(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, &$aClassAliases, &$aAliasTranslation)
{
$sForeignClass = $oFilter->GetClass();
$sForeignClassAlias = $oFilter->GetClassAlias();
if (!MetaModel::IsValidKeyAttCode($sForeignClass, $sForeignExtKeyAttCode))
{
trigger_error("The attribute code '$sForeignExtKeyAttCode' is not an external key of the class '{$sForeignClass}' - the condition will be ignored", E_USER_WARNING);
}
$oAttExtKey = MetaModel::GetAttributeDef($sForeignClass, $sForeignExtKeyAttCode);
if(!MetaModel::IsSameFamilyBranch($this->GetClass(), $oAttExtKey->GetTargetClass()))
{
trigger_error("The specified filter (objects referencing an object of class {$this->GetClass()}) is not compatible with the key '{$sForeignClass}::$sForeignExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}", E_USER_ERROR);
}
if (array_key_exists($sForeignClass, $this->m_aReferencedBy) && array_key_exists($sForeignExtKeyAttCode, $this->m_aReferencedBy[$sForeignClass]))
{
$this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]->MergeWith_InNamespace($oFilter, $aClassAliases, $aAliasTranslation);
}
else
{
$sOrigAlias = $oFilter->GetClassAlias();
$sKeyClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $oFilter->GetClass());
if ($sKeyClassAlias != $sOrigAlias)
{
// Translate the condition expression with the new alias
$aAliasTranslation[$sOrigAlias]['*'] = $sKeyClassAlias;
}
// #@# The condition expression found in that filter should not be used - could be another kind of structure like a join spec tree !!!!
$oNewFilter = clone $oFilter;
$oNewFilter->ResetCondition();
$this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]= $oNewFilter;
}
}
public function AddCondition_LinkedTo(DBObjectSearch $oLinkFilter, $sExtKeyAttCodeToMe, $sExtKeyAttCodeTarget, DBObjectSearch $oFilterTarget)
{
$oLinkFilterFinal = clone $oLinkFilter;
$oLinkFilterFinal->AddCondition_PointingTo($sExtKeyAttCodeToMe);
$this->AddCondition_ReferencedBy($oLinkFilterFinal, $sExtKeyAttCodeToMe);
}
public function AddCondition_RelatedTo(DBObjectSearch $oFilter, $sRelCode, $iMaxDepth)
{
MyHelpers::CheckValueInArray('relation code', $sRelCode, MetaModel::EnumRelations());
$this->m_aRelatedTo[] = array('flt'=>$oFilter, 'relcode'=>$sRelCode, 'maxdepth'=>$iMaxDepth);
}
public function MergeWith($oFilter)
{
$aAliasTranslation = array();
$res = $this->MergeWith_InNamespace($oFilter, $this->m_aClasses, $aAliasTranslation);
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
return $res;
}
protected function MergeWith_InNamespace($oFilter, &$aClassAliases, &$aAliasTranslation)
{
if ($this->GetClass() != $oFilter->GetClass())
{
trigger_error("Attempting to merge a filter of class '{$this->GetClass()}' with a filter of class '{$oFilter->GetClass()}'", E_USER_ERROR);
}
// Translate search condition into our aliasing scheme
$aAliasTranslation[$oFilter->GetClassAlias()]['*'] = $this->GetClassAlias();
$this->m_aFullText = array_merge($this->m_aFullText, $oFilter->m_aFullText);
$this->m_aRelatedTo = array_merge($this->m_aRelatedTo, $oFilter->m_aRelatedTo);
foreach($oFilter->m_aPointingTo as $sExtKeyAttCode=>$oExtFilter)
{
$this->AddCondition_PointingTo_InNamespace($oExtFilter, $sExtKeyAttCode, $aClassAliases, $aAliasTranslation);
}
foreach($oFilter->m_aReferencedBy as $sForeignClass => $aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode => $oForeignFilter)
{
$this->AddCondition_ReferencedBy_InNamespace($oForeignFilter, $sForeignExtKeyAttCode, $aClassAliases, $aAliasTranslation);
}
}
}
public function GetClassName($sAlias) {return $this->m_aClasses[$sAlias];}
public function GetClasses() {return $this->m_aClasses;}
public function GetClass() {return $this->m_sClass;}
public function GetClassAlias() {return $this->m_sClassAlias;}
public function GetCriteria() {return $this->m_oSearchCondition;}
public function GetCriteria_FullText() {return $this->m_aFullText;}
public function GetCriteria_PointingTo($sKeyAttCode = "")
{
if (empty($sKeyAttCode))
{
return $this->m_aPointingTo;
}
if (!array_key_exists($sKeyAttCode, $this->m_aPointingTo)) return null;
return $this->m_aPointingTo[$sKeyAttCode];
}
public function GetCriteria_ReferencedBy($sRemoteClass = "", $sForeignExtKeyAttCode = "")
{
if (empty($sRemoteClass))
{
return $this->m_aReferencedBy;
}
if (!array_key_exists($sRemoteClass, $this->m_aReferencedBy)) return null;
if (empty($sForeignExtKeyAttCode))
{
return $this->m_aReferencedBy[$sRemoteClass];
}
if (!array_key_exists($sForeignExtKeyAttCode, $this->m_aReferencedBy[$sRemoteClass])) return null;
return $this->m_aReferencedBy[$sRemoteClass][$sForeignExtKeyAttCode];
}
public function GetCriteria_RelatedTo()
{
return $this->m_aRelatedTo;
}
public function RenderCondition()
{
return $this->m_oSearchCondition->Render();
}
public function serialize()
{
// Efficient but resulting in long strings:
// -> return (base64_encode(serialize($this)));
$sValue = $this->GetClass()."\n";
$sValue .= $this->GetClassAlias()."\n";
foreach($this->m_aClasses as $sClassAlias => $sClass)
{
// A stands for "Aliases"
$sValue .= "A:$sClassAlias:$sClass\n";
}
foreach($this->m_aFullText as $sFullText)
{
// F stands for "Full text"
$sValue .= "F:".$sFullText."\n";
}
$sValue .= "C:".$this->m_oSearchCondition->serialize()."\n";
foreach($this->m_aPointingTo as $sExtKey=>$oFilter)
{
// P stands for "Pointing to"
$sValue .= "P:".$sExtKey.":".$oFilter->serialize()."\n";
}
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode=>$oForeignFilter)
{
// R stands for "Referenced by"
$sValue .= "R:".$sForeignExtKeyAttCode.":".$oForeignFilter->serialize()."\n";
}
}
foreach($this->m_aRelatedTo as $aRelatedTo)
{
$oFilter = $aRelatedTo['flt'];
$sRelCode = $aRelatedTo['relcode'];
$iMaxDepth = $aRelatedTo['maxdepth'];
$sValue .= "T:".$oFilter->serialize().":$sRelCode:$iMaxDepth";
}
return base64_encode($sValue);
}
static public function unserialize($sValue)
{
// See comment above...
// -> return (unserialize(base64_decode($sValue)));
$sClearText = base64_decode($sValue);
$aValues = split("\n", $sClearText);
$i = 0;
$sClass = $aValues[$i++];
$sClassAlias = $aValues[$i++];
$oFilter = new DBObjectSearch($sClass, $sClassAlias);
while($i < count($aValues) && !empty($aValues[$i]))
{
$aCondition = split(":", $aValues[$i++]);
switch ($aCondition[0])
{
case "A":
$oFilter->m_aClasses[$aCondition[1]] = $aCondition[2];
break;
case "F":
$oFilter->AddCondition_FullText($aCondition[1]);
break;
case "C":
$oFilter->m_oSearchCondition = Expression::unserialize($aCondition[1]);
break;
case "P":
//$oAtt = DBObject::GetAttributeDef($sClass, $aCondition[1]);
//$sRemoteClass = $oAtt->GetTargetClass();
$oSubFilter = self::unserialize($aCondition[2]);
$sExtKeyAttCode = $aCondition[1];
$oFilter->AddCondition_PointingTo($oSubFilter, $sExtKeyAttCode);
break;
case "R":
$oRemoteFilter = self::unserialize($aCondition[2]);
$sExtKeyAttCodeToMe = $aCondition[1];
$oFilter->AddCondition_ReferencedBy($oRemoteFilter, $sExtKeyAttCodeToMe);
break;
case "T":
$oSubFilter = self::unserialize($aCondition[1]);
$sRelCode = $aCondition[2];
$iMaxDepth = $aCondition[3];
$oFilter->AddCondition_RelatedTo($oSubFilter, $sRelCode, $iMaxDepth);
default:
trigger_error("invalid filter definition (cannot unserialize the data, clear text = '$sClearText')", E_USER_ERROR);
}
}
return $oFilter;
}
// SImple BUt Structured Query Languag - SubuSQL
//
static private function Value2Expression($value)
{
$sRet = $value;
if (is_array($value))
{
$sRet = VS_START.implode(', ', $value).VS_END;
}
else if (!is_numeric($value))
{
$sRet = "'".addslashes($value)."'";
}
return $sRet;
}
static private function Expression2Value($sExpr)
{
$retValue = $sExpr;
if ((substr($sExpr, 0, 1) == "'") && (substr($sExpr, -1, 1) == "'"))
{
$sNoQuotes = substr($sExpr, 1, -1);
return stripslashes($sNoQuotes);
}
if ((substr($sExpr, 0, 1) == VS_START) && (substr($sExpr, -1, 1) == VS_END))
{
$sNoBracket = substr($sExpr, 1, -1);
$aRetValue = array();
foreach (explode(",", $sNoBracket) as $sItem)
{
$aRetValue[] = self::Expression2Value(trim($sItem));
}
return $aRetValue;
}
return $retValue;
}
public function ToSibusQL()
{
$aConds = array(); // string conditions, to be merged into a logical AND
foreach($this->m_aFullText as $sFullText)
{
$aConds[] = "* HAS ".self::Value2Expression($sFullText);
}
// #@# todo - changer ToSibusQL en ToOQL et l'implementer !
// $aConds[] = $this->m_oSearchCondition->ToSibusQL
/*
foreach($this->m_aCriteria as $aCritInfo)
{
$aConds[] = $aCritInfo["filtercode"]." ".$aCritInfo["opcode"]." ".self::Value2Expression($aCritInfo["value"]);
}
*/
foreach($this->m_aPointingTo as $sExtKey=>$oFilter)
{
$aConds[] = $sExtKey." IN (".$oFilter->ToSibusQL().")";
}
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode=>$oForeignFilter)
{
$aConds[] = "PKEY IS ".$sForeignExtKeyAttCode." IN (".$oForeignFilter->ToSibusQL().")";
}
}
foreach($this->m_aRelatedTo as $aRelatedTo)
{
$oFilter = $aRelatedTo['flt'];
$sRelCode = $aRelatedTo['relcode'];
$iMaxDepth = $aRelatedTo['maxdepth'];
$aConds[] = "RELATED ($sRelCode, $iMaxDepth) TO (".$oFilter->ToSibuSQL().")";
}
$sValue = $this->GetClass();
if (count($aConds) > 0)
{
$sValue .= ": ".implode(" AND ", $aConds);
}
return $sValue;
}
static private function privProcessParams($sQuery, array $aParams, $oDbObject)
{
$iPlaceHoldersCount = preg_match_all(SIBUSQLPARAMREGEXP, $sQuery, $aMatches, PREG_SET_ORDER);
if ($iPlaceHoldersCount > 0)
{
foreach($aMatches as $aMatch)
{
$sStringToSearch = $aMatch[0];
$sParameterName = $aMatch[1];
$sDefaultValue = $aMatch[2];
$sDescription = $aMatch[3];
$sValue = $sDefaultValue;
if (array_key_exists($sParameterName, $aParams))
{
$sValue = $aParams[$sParameterName];
unset($aParams[$sParameterName]);
}
else if (is_object($oDbObject))
{
if (strpos($sParameterName, "this.") === 0)
{
$sAttCode = substr($sParameterName, strlen("this."));
if ($sAttCode == 'pkey')
{
$sValue = $oDbObject->GetKey();
}
else if ($sAttCode == 'class')
{
$sValue = get_class($oDbObject);
}
else if (MetaModel::IsValidAttCode(get_class($oDbObject), $sAttCode))
{
$sValue = $oDbObject->Get($sAttCode);
}
}
}
$sQuery = str_replace($sStringToSearch, $sValue, $sQuery);
}
}
if (count($aParams) > 0)
{
trigger_error("Unused parameter(s) for this SibusQL expression: (".implode(', ', array_keys($aParams)).")");
}
return $sQuery;
}
static public function ListSibusQLParams($sQuery)
{
$aRet = array();
$iPlaceHoldersCount = preg_match_all(SIBUSQLPARAMREGEXP, $sQuery, $aMatches, PREG_SET_ORDER);
if ($iPlaceHoldersCount > 0)
{
foreach($aMatches as $aMatch)
{
$sStringToSearch = $aMatch[0];
$sParameterName = $aMatch[1];
$sDefaultValue = $aMatch[2];
$sDescription = $aMatch[3];
$aRet[$sParameterName]["description"] = $sDescription;
$aRet[$sParameterName]["default"] = $sDefaultValue;
}
}
return $aRet;
}
protected function OQLExpressionToCondition($sQuery, $oExpression, $aClassAliases)
{
if ($oExpression instanceof BinaryOqlExpression)
{
$sOperator = $oExpression->GetOperator();
$oLeft = $this->OQLExpressionToCondition($sQuery, $oExpression->GetLeftExpr(), $aClassAliases);
$oRight = $this->OQLExpressionToCondition($sQuery, $oExpression->GetRightExpr(), $aClassAliases);
return new BinaryExpression($oLeft, $sOperator, $oRight);
}
elseif ($oExpression instanceof FieldOqlExpression)
{
$sClassAlias = $oExpression->GetParent();
$sFltCode = $oExpression->GetName();
if (empty($sClassAlias))
{
$iPos = $oExpression->GetPosition();
throw new OqlNormalizeException('Missing class specification', $sQuery, 0, $iPos, '');
}
if (!array_key_exists($sClassAlias, $aClassAliases))
{
$iPos = $oExpression->GetPosition();
throw new OqlNormalizeException('Unknown class', $sQuery, 0, $iPos, $sClassAlias, array_keys($aClassAliases));
}
$sClass = $aClassAliases[$sClassAlias];
if (!MetaModel::IsValidFilterCode($sClass, $sFltCode))
{
$iPos = $oExpression->GetPosition();
throw new OqlNormalizeException('Unknown filter code', $sQuery, 0, $iPos, "$sFltCode in class $sClassAlias", MetaModel::GetFiltersList($sClass));
}
return new FieldExpression($sFltCode, $sClassAlias);
}
elseif ($oExpression instanceof TrueOqlExpression)
{
return new TrueExpression;
}
elseif ($oExpression instanceof ScalarOqlExpression)
{
return new ScalarExpression($oExpression->GetValue());
}
elseif ($oExpression instanceof ListOqlExpression)
{
return new ListExpression($oExpression->GetItems());
}
elseif ($oExpression instanceof FunctionOqlExpression)
{
return new FunctionExpression($oExpression->GetVerb(), $oExpression->GetArgs());
}
else
{
throw new CoreException('Unknown expression type', array('class'=>get_class($oExpression), 'query'=>$sQuery));
}
}
static public function FromOQL($sQuery, array $aParams = array(), $oObject = null)
{
if (empty($sQuery)) return null;
$oOql = new OqlInterpreter($sQuery);
$oOqlQuery = $oOql->ParseQuery();
$sClass = $oOqlQuery->GetClass();
$sClassAlias = $oOqlQuery->GetClassAlias();
if (!MetaModel::IsValidClass($sClass))
{
throw new OqlNormalizeException('Unknown class', $sQuery, 0, 0, $sClass, MetaModel::GetClasses());
}
$oResultFilter = new DBObjectSearch($sClass, $sClassAlias);
$oResultFilter->m_aClasses = array($sClassAlias => $sClass);
// Maintain an array of filters, because the flat list is in fact referring to a tree
// And this will be an easy way to dispatch the conditions
// $oResultFilter will be referenced by the other filters, or the other way around...
$aJoinItems = array($sClassAlias => $oResultFilter);
$aJoinSpecs = $oOqlQuery->GetJoins();
if (is_array($aJoinSpecs))
{
foreach ($aJoinSpecs as $oJoinSpec)
{
$sJoinClass = $oJoinSpec->GetClass();
$sJoinClassAlias = $oJoinSpec->GetClassAlias();
if (!MetaModel::IsValidClass($sJoinClass))
{
throw new OqlNormalizeException('Unknown class', $sQuery, 0, 0, $sJoinClass, MetaModel::GetClasses());
}
if (array_key_exists($sJoinClassAlias, $oResultFilter->m_aClasses))
{
if ($sJoinClassAlias != $sJoinClass)
{
throw new OqlNormalizeException('Duplicate class alias', $sQuery, 0, 0, $sJoinClassAlias);
}
else
{
throw new OqlNormalizeException('Duplicate class name', $sQuery, 0, 0, $sJoinClass);
}
}
// Assumption: ext key on the left only !!!
// normalization should take care of this
$oLeftField = $oJoinSpec->GetLeftField();
$sFromClass = $oLeftField->GetParent();
$sExtKeyAttCode = $oLeftField->GetName();
$oRightField = $oJoinSpec->GetRightField();
$sToClass = $oRightField->GetParent();
$sPKeyDescriptor = $oRightField->GetName();
if ($sPKeyDescriptor != 'id')
{
throw new OqlNormalizeException('Wrong format for Join clause (right hand), expecting an id', $sQuery, 0, $oRightField->GetPosition(), $sPKeyDescriptor, array('id'));
}
$oResultFilter->m_aClasses[$sJoinClassAlias] = $sJoinClass;
$aJoinItems[$sJoinClassAlias] = new DBObjectSearch($sJoinClass, $sJoinClassAlias);
if (!array_key_exists($sFromClass, $aJoinItems))
{
throw new OqlNormalizeException('Unknown class in join condition (left expression)', $sQuery, 0, $oLeftField->GetPosition(), $sFromClass, array_keys($aJoinItems));
}
if (!array_key_exists($sToClass, $aJoinItems))
{
throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sQuery, 0, $oRightField->GetPosition(), $sToClass, array_keys($aJoinItems));
}
$aExtKeys = array_keys(MetaModel::GetExternalKeys($oResultFilter->m_aClasses[$sFromClass]));
if (!in_array($sExtKeyAttCode, $aExtKeys))
{
throw new OqlNormalizeException('Unknown external key in join condition (left expression)', $sQuery, 0, $oLeftField->GetPosition(), $sExtKeyAttCode, $aExtKeys);
}
if ($sFromClass == $sJoinClassAlias)
{
$aJoinItems[$sToClass]->AddCondition_ReferencedBy($aJoinItems[$sFromClass], $sExtKeyAttCode);
}
else
{
$aJoinItems[$sFromClass]->AddCondition_PointingTo($aJoinItems[$sToClass], $sExtKeyAttCode);
}
}
}
$oConditionTree = $oOqlQuery->GetCondition();
if ($oConditionTree instanceof Expression)
{
$oResultFilter->m_oSearchCondition = $oResultFilter->OQLExpressionToCondition($sQuery, $oConditionTree, $oResultFilter->m_aClasses);
}
return $oResultFilter;
}
static public function FromSibusQL($sQuery, array $aParams = array(), $oObject = null)
{
if (empty($sQuery)) return null;
$sQuery = self::privProcessParams($sQuery, $aParams, $oObject);
$iSepPos = strpos($sQuery, ":");
if ($iSepPos === false)
{
if (preg_match('@^\\s*SELECT@', $sQuery))
{
return self::FromOQL($sQuery, $aParams, $oObject);
}
// Only the class was specified -> all rows are required
$sClass = trim($sQuery);
$oFilter = new DBObjectSearch($sClass);
}
else
{
$sClass = trim(substr($sQuery, 0, $iSepPos));
$sConds = trim(substr($sQuery, $iSepPos + 1));
$aValues = split(" AND ", $sConds);
$oFilter = new DBObjectSearch($sClass);
foreach ($aValues as $sCond)
{
$sCond = trim($sCond);
if (strpos($sCond, "* HAS ") === 0)
{
$sValue = self::Expression2Value(substr($sCond, strlen("* HAS ")));
$oFilter->AddCondition_FullText($sValue);
}
else if (preg_match("@^(\S+) IN \\((.+)\\)$@", $sCond, $aMatches))
{
$sExtKeyAttCode = $aMatches[1];
$sFilterExp = $aMatches[2];
$oSubFilter = self::FromSibuSQL($sFilterExp);
$oFilter->AddCondition_PointingTo($oSubFilter, $sExtKeyAttCode);
}
else if (strpos($sCond, "PKEY IS ") === 0)
{
if (preg_match("@^PKEY IS (\S+) IN \\((.+)\\)$@", $sCond, $aMatches))
{
$sExtKeyAttCodeToMe = $aMatches[1];
$sFilterExp = $aMatches[2];
$oRemoteFilter = self::FromSibuSQL($sFilterExp);
$oFilter->AddCondition_ReferencedBy($oRemoteFilter, $sExtKeyAttCodeToMe);
}
}
else if (strpos($sCond, "RELATED") === 0)
{
if (preg_match("@^RELATED\s*\\((.+)\\)\s*TO\s*\\((.+)\\)@", trim($sCond), $aMatches))
{
$aRelation = explode(',', trim($aMatches[1]));
$sRelCode = trim($aRelation[0]);
$iMaxDepth = intval(trim($aRelation[1]));
$sFilterExp = trim($aMatches[2]);
$oSubFilter = self::FromSibuSQL($sFilterExp);
$oFilter->AddCondition_RelatedTo($oSubFilter, $sRelCode, $iMaxDepth);
}
}
else
{
$sOperandExpr = "'.*'|\d+|-\d+|".VS_START.".+".VS_END;
if (preg_match("@^(\S+)\s+(.*)\s+($sOperandExpr)$@", $sCond, $aMatches))
{
$sFltCode = trim($aMatches[1]);
$sOpCode = trim($aMatches[2]);
$value = self::Expression2Value($aMatches[3]);
$oFilter->AddCondition($sFltCode, $value, $sOpCode);
}
else
{
trigger_error("Wrong format for filter definition: '$sQuery'");
}
}
}
}
return $oFilter;
}
// Sexy display of a SibuSQL expression
static public function SibuSQLAsHtml($sQuery)
{
$sQuery = htmlentities($sQuery);
$aParams = self::ListSibusQLParams($sQuery);
$aParamValues = array();
foreach ($aParams as $sParamName => $aParamInfo)
{
$sDescription = $aParamInfo["description"];
$sDefaultValue = $aParamInfo["default"];
$aParamValues[$sParamName] = "<span style=\"background-color:#aaa;\" title\"$sDescription (default to '$sDefaultValue')\">$sParamName</span>";
}
$sQuery = self::privProcessParams($sQuery, $aParamValues, null);
return $sQuery;
}
public function toxpath()
{
// #@# a voir...
}
static public function fromxpath()
{
// #@# a voir...
}
}
?>

255
core/dbobjectset.class.php Normal file
View File

@@ -0,0 +1,255 @@
<?php
/**
* A set of persistent objects, could be heterogeneous
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class DBObjectSet
{
private $m_oFilter;
private $m_aOrderBy;
public $m_bLoaded;
private $m_aData;
private $m_aId2Row;
private $m_iCurrRow;
public function __construct($oFilter, $aOrderBy = array())
{
$this->m_oFilter = $oFilter;
$this->m_aOrderBy = $aOrderBy;
$this->m_bLoaded = false;
$this->m_aData = array();
$this->m_aId2Row = array();
$this->m_iCurrRow = 0;
}
public function __destruct()
{
}
public function __toString()
{
$sRet = '';
$this->Rewind();
$sRet .= "Set (".$this->m_oFilter->ToSibuSQL().")<br/>\n";
$sRet .= "Query: <pre style=\"font-size: smaller; display:inline;\">".MetaModel::MakeSelectQuery($this->m_oFilter, array()).")</pre>\n";
$sRet .= $this->Count()." records<br/>\n";
if ($this->Count() > 0)
{
$sRet .= "<ul class=\"treeview\">\n";
while ($oObj = $this->Fetch())
{
$sRet .= "<li>".$oObj->__toString()."</li>\n";
}
$sRet .= "</ul>\n";
}
return $sRet;
}
static public function FromScratch($sClass)
{
$oFilter = new CMDBSearchFilter($sClass);
$oRetSet = new self($oFilter);
$oRetSet->m_bLoaded = true; // no DB load
return $oRetSet;
}
static public function FromArray($sClass, $aObjects)
{
$oFilter = new CMDBSearchFilter($sClass);
$oRetSet = new self($oFilter);
$oRetSet->m_bLoaded = true; // no DB load
$oRetSet->AddObjectArray($aObjects);
return $oRetSet;
}
public function ToArray($bWithId = true)
{
$aRet = array();
$this->Rewind();
while ($oObject = $this->Fetch())
{
if ($bWithId)
{
$aRet[$oObject->GetKey()] = $oObject;
}
else
{
$aRet[] = $oObject;
}
}
return $aRet;
}
public function GetFilter()
{
return $this->m_oFilter;
}
public function GetClass()
{
return $this->m_oFilter->GetClass();
}
public function GetRootClass()
{
return MetaModel::GetRootClass($this->GetClass());
}
public function Load()
{
if ($this->m_bLoaded) return;
// #@# debug - echo "Loading (".$this->m_oFilter->ToSibuSQL().")....</br>\n";
$sSQL = MetaModel::MakeSelectQuery($this->m_oFilter, $this->m_aOrderBy);
$resQuery = CMDBSource::Query($sSQL);
if (!$resQuery) return;
while ($aRow = CMDBSource::FetchArray($resQuery))
{
$sClass = $this->m_oFilter->GetClass();
$oObject = MetaModel::GetObjectByRow($sClass, $aRow);
$this->AddObject($oObject);
}
CMDBSource::FreeResult($resQuery);
$this->m_bLoaded = true;
}
public function Count()
{
if (!$this->m_bLoaded) $this->Load();
return count($this->m_aData);
}
public function Fetch()
{
if (!$this->m_bLoaded) $this->Load();
if ($this->m_iCurrRow >= count($this->m_aData))
{
return null;
}
$oRetObj = $this->m_aData[$this->m_iCurrRow];
$this->m_iCurrRow++;
return $oRetObj;
}
public function Rewind()
{
$this->Seek(0);
}
public function Seek($iRow)
{
if (!$this->m_bLoaded) $this->Load();
$this->m_iCurrRow = min($iRow, count($this->m_aData));
return $this->m_iCurrRow;
}
public function AddObject($oObject)
{
// ?usefull? if ($oObject->GetClass() != $this->GetClass()) return;
// it is mandatory to avoid duplicates
if (array_key_exists($oObject->GetKey(), $this->m_aId2Row)) return;
// Do not load here, because the load uses that method too
$iNextPos = count($this->m_aData);
$this->m_aData[$iNextPos] = $oObject;
$this->m_aId2Row[$oObject->GetKey()] = $iNextPos;
}
public function RemoveObject($iRow)
{
trigger_error("#@# not implemented! ca sert a quoi ?");
}
public function AddObjectArray($aObjects)
{
foreach ($aObjects as $oObj)
{
$this->AddObject($oObj);
}
}
public function Merge($oObjectSet)
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
{
trigger_error("Could not merge two objects sets if they don't have the same root class");
}
if (!$this->m_bLoaded) $this->Load();
$oObjectSet->Seek(0);
while ($oObject = $oObjectSet->Fetch())
{
$this->AddObject($oObject);
}
}
public function CreateIntersect($oObjectSet)
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
{
trigger_error("Could not 'intersect' two objects sets if they don't have the same root class");
}
if (!$this->m_bLoaded) $this->Load();
$oNewSet = DBObjectSet::FromScratch($this->GetClass());
$oObjectSet->Seek(0);
while ($oObject = $oObjectSet->Fetch())
{
if (array_key_exists($oObject->GetKey(), $this->m_aId2Row))
{
$oNewSet->AddObject($oObject);
}
}
return $oNewSet;
}
public function CreateDelta($oObjectSet)
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
{
trigger_error("Could not 'delta' two objects sets if they don't have the same root class");
}
if (!$this->m_bLoaded) $this->Load();
$oNewSet = DBObjectSet::FromScratch($this->GetClass());
$oObjectSet->Seek(0);
while ($oObject = $oObjectSet->Fetch())
{
if (!array_key_exists($oObject->GetKey(), $this->m_aId2Row))
{
$oNewSet->AddObject($oObject);
}
}
return $oNewSet;
}
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99)
{
$aVisited = array(); // optimization for consecutive calls of MetaModel::GetRelatedObjects
$this->Seek(0);
while ($oObject = $this->Fetch())
{
$aRelatedObjs = $oObject->GetRelatedObjects($sRelCode, $iMaxDepth, $aVisited);
}
return $aRelatedObjs;
}
}
?>

View File

@@ -0,0 +1,431 @@
<?php
/**
* General definition of an expression tree (could be OQL, SQL or whatever)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
abstract class Expression
{
// recursive translation of identifiers
abstract public function Translate($aTranslationData, $bMatchAll = true);
// recursive rendering
abstract public function Render();
// recursively builds an array of class => fieldname
abstract public function ListRequiredFields();
public function RequiresField($sClass, $sFieldName)
{
// #@# todo - optimize : this is called quite often when building a single query !
$aRequired = $this->ListRequiredFields();
if (!in_array($sClass.'.'.$sFieldName, $aRequired)) return false;
return true;
}
public function serialize()
{
return base64_encode($this->Render());
}
static public function unserialize($sValue)
{
return self::FromOQL(base64_decode($sValue));
}
static public function FromOQL($sConditionExpr)
{
$oOql = new OqlInterpreter($sConditionExpr);
$oExpression = $oOql->ParseExpression();
return $oExpression;
}
public function LogAnd($oExpr)
{
return new BinaryExpression($this, 'AND', $oExpr);
}
public function LogOr($oExpr)
{
return new BinaryExpression($this, 'OR', $oExpr);
}
}
class BinaryExpression extends Expression
{
protected $m_oLeftExpr; // filter code or an SQL expression (later?)
protected $m_oRightExpr;
protected $m_sOperator;
public function __construct($oLeftExpr, $sOperator, $oRightExpr)
{
if (!is_object($oLeftExpr))
{
throw new CoreException('Expecting an Expression object on the left hand', array('found_type' => gettype($oLeftExpr)));
}
if (!is_object($oRightExpr))
{
throw new CoreException('Expecting an Expression object on the right hand', array('found_type' => gettype($oRightExpr)));
}
if (!$oLeftExpr instanceof Expression)
{
throw new CoreException('Expecting an Expression object on the left hand', array('found_class' => get_class($oLeftExpr)));
}
if (!$oRightExpr instanceof Expression)
{
throw new CoreException('Expecting an Expression object on the right hand', array('found_class' => get_class($oRightExpr)));
}
$this->m_oLeftExpr = $oLeftExpr;
$this->m_oRightExpr = $oRightExpr;
$this->m_sOperator = $sOperator;
}
public function GetLeftExpr()
{
return $this->m_oLeftExpr;
}
public function GetRightExpr()
{
return $this->m_oRightExpr;
}
public function GetOperator()
{
return $this->m_sOperator;
}
// recursive rendering
public function Render()
{
$sOperator = $this->GetOperator();
$sLeft = $this->GetLeftExpr()->Render();
$sRight = $this->GetRightExpr()->Render();
return "($sLeft $sOperator $sRight)";
}
public function Translate($aTranslationData, $bMatchAll = true)
{
$oLeft = $this->GetLeftExpr()->Translate($aTranslationData, $bMatchAll);
$oRight = $this->GetRightExpr()->Translate($aTranslationData, $bMatchAll);
return new BinaryExpression($oLeft, $this->GetOperator(), $oRight);
}
public function ListRequiredFields()
{
$aLeft = $this->GetLeftExpr()->ListRequiredFields();
$aRight = $this->GetRightExpr()->ListRequiredFields();
return array_merge($aLeft, $aRight);
}
}
class UnaryExpression extends Expression
{
protected $m_value;
public function __construct($value)
{
$this->m_value = $value;
}
public function GetValue()
{
return $this->m_value;
}
// recursive rendering
public function Render()
{
return CMDBSource::Quote($this->m_value);
}
public function Translate($aTranslationData, $bMatchAll = true)
{
return clone $this;
}
public function ListRequiredFields()
{
return array();
}
}
class ScalarExpression extends UnaryExpression
{
public function __construct($value)
{
if (!is_scalar($value))
{
throw new CoreException('Attempt to create a scalar expression from a non scalar', array('var_type'=>gettype($value)));
}
parent::__construct($value);
}
}
class TrueExpression extends ScalarExpression
{
public function __construct()
{
parent::__construct(1);
}
}
class FieldExpression extends UnaryExpression
{
protected $m_sParent;
protected $m_sName;
public function __construct($sName, $sParent = '')
{
parent::__construct("$sParent.$sName");
$this->m_sParent = $sParent;
$this->m_sName = $sName;
}
public function GetParent() {return $this->m_sParent;}
public function GetName() {return $this->m_sName;}
// recursive rendering
public function Render()
{
if (empty($this->m_sParent))
{
return "`{$this->m_sName}`";
}
return "`{$this->m_sParent}`.`{$this->m_sName}`";
}
public function Translate($aTranslationData, $bMatchAll = true)
{
if (!array_key_exists($this->m_sParent, $aTranslationData))
{
if ($bMatchAll) throw new CoreException('Unknown parent id in translation table', array('parent_id' => $this->m_sParent, 'translation_table' => array_keys($aTranslationData)));
return clone $this;
}
if (!array_key_exists($this->m_sName, $aTranslationData[$this->m_sParent]))
{
if (!array_key_exists('*', $aTranslationData[$this->m_sParent]))
{
// #@# debug - if ($bMatchAll) MyHelpers::var_dump_html($aTranslationData, true);
if ($bMatchAll) throw new CoreException('Unknown name in translation table', array('name' => $this->m_sName, 'parent_id' => $this->m_sParent, 'translation_table' => array_keys($aTranslationData[$this->m_sParent])));
return clone $this;
}
$sNewParent = $aTranslationData[$this->m_sParent]['*'];
$sNewName = $this->m_sName;
}
else
{
$sNewParent = $aTranslationData[$this->m_sParent][$this->m_sName][0];
$sNewName = $aTranslationData[$this->m_sParent][$this->m_sName][1];
}
return new FieldExpression($sNewName, $sNewParent);
}
public function ListRequiredFields()
{
return array($this->m_sParent.'.'.$this->m_sName);
}
}
// Temporary, until we implement functions and expression casting!
// ... or until we implement a real full text search based in the MATCH() expression
class ListExpression extends Expression
{
protected $m_aExpressions;
public function __construct($aExpressions)
{
$this->m_aExpressions = $aExpressions;
}
public function GetItems()
{
return $this->m_aExpressions;
}
// recursive rendering
public function Render()
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes[] = $oExpr->Render();
}
return '('.implode(', ', $aRes).')';
}
public function Translate($aTranslationData, $bMatchAll = true)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes[] = $oExpr->Translate($aTranslationData, $bMatchAll);
}
return new ListExpression($aRes);
}
public function ListRequiredFields()
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes = array_merge($aRes, $oExpr->ListRequiredFields());
}
return $aRes;
}
}
class FunctionExpression extends Expression
{
protected $m_sVerb;
protected $m_aArgs; // array of expressions
public function __construct($sVerb, $aArgExpressions)
{
$this->m_sVerb = $sVerb;
$this->m_aArgs = $aArgExpressions;
}
public function GetVerb()
{
return $this->m_sVerb;
}
public function GetArgs()
{
return $this->m_aArgs;
}
// recursive rendering
public function Render()
{
$aRes = array();
foreach ($this->m_aArgs as $oExpr)
{
$aRes[] = $oExpr->Render();
}
return $this->m_sVerb.'('.implode(', ', $aRes).')';
}
public function Translate($aTranslationData, $bMatchAll = true)
{
$aRes = array();
foreach ($this->m_aArgs as $oExpr)
{
$aRes[] = $oExpr->Translate($aTranslationData, $bMatchAll);
}
return new FunctionExpression($this->m_sVerb, $aRes);
}
public function ListRequiredFields()
{
$aRes = array();
foreach ($this->m_aArgs as $oExpr)
{
$aRes = array_merge($aRes, $oExpr->ListRequiredFields());
}
return $aRes;
}
}
class IntervalExpression extends Expression
{
protected $m_oValue; // expression
protected $m_sUnit;
public function __construct($oValue, $sUnit)
{
$this->m_oValue = $oValue;
$this->m_sUnit = $sUnit;
}
public function GetValue()
{
return $this->m_oValue;
}
public function GetUnit()
{
return $this->m_sUnit;
}
// recursive rendering
public function Render()
{
return 'INTERVAL '.$this->m_oValue->Render().' '.$this->m_sUnit;
}
public function Translate($aTranslationData, $bMatchAll = true)
{
return new IntervalExpression($this->m_oValue->Translate($aTranslationData, $bMatchAll), $this->m_sUnit);
}
public function ListRequiredFields()
{
return array();
}
}
class CharConcatExpression extends Expression
{
protected $m_aExpressions;
public function __construct($aExpressions)
{
$this->m_aExpressions = $aExpressions;
}
public function GetItems()
{
return $this->m_aExpressions;
}
// recursive rendering
public function Render()
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$sCol = $oExpr->Render();
// Concat will be globally NULL if one single argument is null !
$aRes[] = "COALESCE($sCol, '')";
}
return "CAST(CONCAT(".implode(', ', $aRes).") AS CHAR)";
}
public function Translate($aTranslationData, $bMatchAll = true)
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes[] = $oExpr->Translate($aTranslationData, $bMatchAll);
}
return new CharConcatExpression($aRes);
}
public function ListRequiredFields()
{
$aRes = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aRes = array_merge($aRes, $oExpr->ListRequiredFields());
}
return $aRes;
}
}
?>

View File

@@ -0,0 +1,296 @@
<?php
require_once('MyHelpers.class.inc.php');
/**
* Definition of a filter (could be made out of an existing attribute, or from an expression)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
abstract class FilterDefinition
{
abstract public function GetType();
abstract public function GetTypeDesc();
protected $m_sCode;
private $m_aParams = array();
protected function Get($sParamName) {return $this->m_aParams[$sParamName];}
public function __construct($sCode, $aParams = array())
{
$this->m_sCode = $sCode;
$this->m_aParams = $aParams;
$this->ConsistencyCheck();
}
public function OverloadParams($aParams)
{
foreach ($aParams as $sParam => $value)
{
if (!array_key_exists($sParam, $this->m_aParams))
{
trigger_error("Unknown attribute definition parameter '$sParam', please select a value in {".implode(", ", $this->m_aParams)."}");
}
else
{
$this->m_aParams[$sParam] = $value;
}
}
}
// to be overloaded
static protected function ListExpectedParams()
{
return array();
}
private function ConsistencyCheck()
{
// Check that any mandatory param has been specified
//
$aExpectedParams = $this->ListExpectedParams();
foreach($aExpectedParams as $sParamName)
{
if (!array_key_exists($sParamName, $this->m_aParams))
{
$aBacktrace = debug_backtrace();
$sTargetClass = $aBacktrace[2]["class"];
$sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"];
trigger_error("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)</br>\n", E_USER_ERROR);
}
}
}
public function GetCode() {return $this->m_sCode;}
abstract public function GetLabel();
abstract public function GetValuesDef();
// returns an array of opcode=>oplabel (e.g. "differs from")
abstract public function GetOperators();
// returns an opcode
abstract public function GetLooseOperator();
abstract public function GetFilterSQLExpr($sOpCode, $value);
abstract public function TemporaryGetSQLCol();
// Wrapper - no need for overloading this one
public function GetOpDescription($sOpCode)
{
$aOperators = $this->GetOperators();
if (!array_key_exists($sOpCode, $aOperators))
{
trigger_error("Unknown operator '$sOpCode'", E_USER_ERROR);
}
return $aOperators[$sOpCode];
}
}
/**
* Match against the object unique identifier
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class FilterPrivateKey extends FilterDefinition
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("pkey_field"));
}
public function GetType() {return "PKey";}
public function GetTypeDesc() {return "Match against object identifier";}
public function GetLabel()
{
return "Object Private Key";
}
public function GetValuesDef()
{
return null;
}
public function GetOperators()
{
return array(
"="=>"equals",
"!="=>"differs from",
"IN"=>"in",
"NOTIN"=>"not in"
);
}
public function GetLooseOperator()
{
return "IN";
}
public function GetFilterSQLExpr($sOpCode, $value)
{
$sFieldName = $this->Get("pkey_field");
// #@# not obliged to quote... these are numbers !!!
$sQValue = CMDBSource::Quote($value);
switch($sOpCode)
{
case "IN":
if (!is_array($sQValue)) trigger_error("Expected an array for argument value (sOpCode='$sOpCode')");
return "$sFieldName IN (".implode(", ", $sQValue).")";
case "NOTIN":
if (!is_array($sQValue)) trigger_error("Expected an array for argument value (sOpCode='$sOpCode')");
return "$sFieldName NOT IN (".implode(", ", $sQValue).")";
case "!=":
return $sFieldName." != ".$sQValue;
case "=":
default:
return $sFieldName." = ".$sQValue;
}
}
public function TemporaryGetSQLCol()
{
return $this->Get("pkey_field");
}
}
/**
* Match against an existing attribute (the attribute type will determine the available operators)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class FilterFromAttribute extends FilterDefinition
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("refattribute"));
}
public function __construct($oRefAttribute, $aParam = array())
{
// In this very specific case, the code is the one of the attribute
// (this to get a very very simple syntax upon declaration)
$aParam["refattribute"] = $oRefAttribute;
parent::__construct($oRefAttribute->GetCode(), $aParam);
}
public function GetType() {return "Basic";}
public function GetTypeDesc() {return "Match against field contents";}
public function __GetRefAttribute() // for checking purposes only !!!
{
return $oAttDef = $this->Get("refattribute");
}
public function GetLabel()
{
$oAttDef = $this->Get("refattribute");
return $oAttDef->GetLabel();
}
public function GetValuesDef()
{
$oAttDef = $this->Get("refattribute");
return $oAttDef->GetValuesDef();
}
public function GetOperators()
{
$oAttDef = $this->Get("refattribute");
return $oAttDef->GetBasicFilterOperators();
}
public function GetLooseOperator()
{
$oAttDef = $this->Get("refattribute");
return $oAttDef->GetBasicFilterLooseOperator();
}
public function GetFilterSQLExpr($sOpCode, $value)
{
$oAttDef = $this->Get("refattribute");
return $oAttDef->GetBasicFilterSQLExpr($sOpCode, $value);
}
public function TemporaryGetSQLCol()
{
$oAttDef = $this->Get("refattribute");
return $oAttDef->GetSQLExpr();
}
}
/**
* Match against a given column (experimental -to be cleaned up later)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class FilterDBValues extends FilterDefinition
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("dbfield"));
}
public function GetType() {return "Values from DB";}
public function GetTypeDesc() {return "Match against the existing values in a field";}
public function GetLabel()
{
return "enum de valeurs DB";
}
public function GetValuesDef()
{
return null;
}
public function GetOperators()
{
return array(
"IN"=>"in",
);
}
public function GetLooseOperator()
{
return "IN";
}
public function GetFilterSQLExpr($sOpCode, $value)
{
$sFieldName = $this->Get("dbfield");
if (is_array($value) && !empty($value))
{
$sValueList = "'".implode("', '", $value)."'";
return "$sFieldName IN ($sValueList)";
}
return "1=1";
}
public function TemporaryGetSQLCol()
{
return $this->Get("dbfield");
}
}
?>

2675
core/metamodel.class.php Normal file

File diff suppressed because it is too large Load Diff

3
core/oql/build.cmd Normal file
View File

@@ -0,0 +1,3 @@
c:\itop\php-5.2.3\php.exe -q "C:\itop\PHP-5.2.3\PEAR\PHP\LexerGenerator\cli.php" oql-lexer.plex
c:\itop\php-5.2.3\php.exe -q "C:\itop\PHP-5.2.3\PEAR\PHP\ParserGenerator\cli.php" oql-parser.y
pause

522
core/oql/oql-lexer.php Normal file
View File

@@ -0,0 +1,522 @@
<?php
// Notes (from the source file: oql-lexer.plex) - Romain
//
// The strval rule is a little bit cryptic.
// This is due to both a bug in the lexer generator and the complexity of our need
// The rule means: either a quoted string with ", or a quoted string with '
// literal " (resp. ') must be escaped by a \
// \ must be escaped by an additional \
//
// Here are the issues and limitation found in the lexer generator:
// * Matching simple quotes is an issue, because regexp are not correctly escaped (and the ESC code is escaped itself)
// Workaround: insert '.chr(39).' which will be a real ' in the end
// * Matching an alternate regexp is an issue because you must specify "|^...."
// and the regexp parser will not accept that syntax
// Workaround: insert '.chr(94).' which will be a real ^
//
// Let's analyze an overview of the regexp, we have
// 1) The strval rule in the lexer definition
// /"([^\\"]|\\"|\\\\)*"|'.chr(94).chr(39).'([^\\'.chr(39).']|\\'.chr(39).'|\\\\)*'.chr(39).'/
// 2) Becomes the php expression in the lexer
// (note the escaped double quotes, hopefully having no effect, but showing where the issue is!)
// $myRegexp = '/^\"([^\\\\\"]|\\\\\"|\\\\\\\\)*\"|'.chr(94).chr(39).'([^\\\\'.chr(39).']|\\\\'.chr(39).'|\\\\\\\\)*'.chr(39).'/';
//
// To be fixed in LexerGenerator/Parser.y, in doLongestMatch (doFirstMatch is ok)
//
//
// Now, let's explain how the regexp has been designed.
// Here is a simplified version, dealing with simple quotes, and based on the assumption that the lexer generator has been fixed!
// The strval rule in the lexer definition
// /'([^\\']*(\\')*(\\\\)*)*'/
// This means anything containing \\ or \' or any other char but a standalone ' or \
// This means ' or \ could not be found without a preceding \
//
class OQLLexerRaw
{
protected $data; // input string
public $token; // token id
public $value; // token string representation
protected $line; // current line
protected $count; // current column
function __construct($data)
{
$this->data = $data;
$this->count = 0;
$this->line = 1;
}
private $_yy_state = 1;
private $_yy_stack = array();
function yylex()
{
return $this->{'yylex' . $this->_yy_state}();
}
function yypushstate($state)
{
array_push($this->_yy_stack, $this->_yy_state);
$this->_yy_state = $state;
}
function yypopstate()
{
$this->_yy_state = array_pop($this->_yy_stack);
}
function yybegin($state)
{
$this->_yy_state = $state;
}
function yylex1()
{
if ($this->count >= strlen($this->data)) {
return false; // end of input
}
do {
$rules = array(
'/^[ \t\n]+/',
'/^SELECT/',
'/^AS/',
'/^WHERE/',
'/^JOIN/',
'/^ON/',
'/^\//',
'/^\\*/',
'/^\\+/',
'/^-/',
'/^AND/',
'/^OR/',
'/^,/',
'/^\\(/',
'/^\\)/',
'/^=/',
'/^!=/',
'/^>/',
'/^</',
'/^>=/',
'/^<=/',
'/^LIKE/',
'/^NOT LIKE/',
'/^IN/',
'/^NOT IN/',
'/^INTERVAL/',
'/^IF/',
'/^ELT/',
'/^COALESCE/',
'/^CONCAT/',
'/^SUBSTR/',
'/^TRIM/',
'/^DATE/',
'/^DATE_FORMAT/',
'/^CURRENT_DATE/',
'/^NOW/',
'/^TIME/',
'/^TO_DAYS/',
'/^FROM_DAYS/',
'/^YEAR/',
'/^MONTH/',
'/^DAY/',
'/^DATE_ADD/',
'/^DATE_SUB/',
'/^ROUND/',
'/^FLOOR/',
'/^[0-9]+|0x[0-9a-fA-F]+/',
'/^\"([^\\\\\"]|\\\\\"|\\\\\\\\)*\"|'.chr(94).chr(39).'([^\\\\'.chr(39).']|\\\\'.chr(39).'|\\\\\\\\)*'.chr(39).'/',
'/^([_a-zA-Z][_a-zA-Z0-9]*|`[^`]+`)/',
'/^\\./',
);
$match = false;
foreach ($rules as $index => $rule) {
if (preg_match($rule, substr($this->data, $this->count), $yymatches)) {
if ($match) {
if (strlen($yymatches[0]) > strlen($match[0][0])) {
$match = array($yymatches, $index); // matches, token
}
} else {
$match = array($yymatches, $index);
}
}
}
if (!$match) {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->count]);
}
$this->token = $match[1];
$this->value = $match[0][0];
$yysubmatches = $match[0];
array_shift($yysubmatches);
if (!$yysubmatches) {
$yysubmatches = array();
}
$r = $this->{'yy_r1_' . $this->token}($yysubmatches);
if ($r === null) {
$this->count += strlen($this->value);
$this->line += substr_count($this->value, "\n");
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->count += strlen($this->value);
$this->line += substr_count($this->value, "\n");
if ($this->count >= strlen($this->data)) {
return false; // end of input
}
// skip this token
continue;
} else {
$yy_yymore_patterns = array_slice($rules, $this->token, true);
// yymore is needed
do {
if (!isset($yy_yymore_patterns[$this->token])) {
throw new Exception('cannot do yymore for the last token');
}
$match = false;
foreach ($yy_yymore_patterns[$this->token] as $index => $rule) {
if (preg_match('/' . $rule . '/',
substr($this->data, $this->count), $yymatches)) {
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if ($match) {
if (strlen($yymatches[0]) > strlen($match[0][0])) {
$match = array($yymatches, $index); // matches, token
}
} else {
$match = array($yymatches, $index);
}
}
}
if (!$match) {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->count]);
}
$this->token = $match[1];
$this->value = $match[0][0];
$yysubmatches = $match[0];
array_shift($yysubmatches);
if (!$yysubmatches) {
$yysubmatches = array();
}
$this->line = substr_count($this->value, "\n");
$r = $this->{'yy_r1_' . $this->token}();
} while ($r !== null || !$r);
if ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} else {
// accept
$this->count += strlen($this->value);
$this->line += substr_count($this->value, "\n");
return true;
}
}
} while (true);
} // end function
function yy_r1_0($yy_subpatterns)
{
return false;
}
function yy_r1_1($yy_subpatterns)
{
$this->token = OQLParser::SELECT;
}
function yy_r1_2($yy_subpatterns)
{
$this->token = OQLParser::AS_ALIAS;
}
function yy_r1_3($yy_subpatterns)
{
$this->token = OQLParser::WHERE;
}
function yy_r1_4($yy_subpatterns)
{
$this->token = OQLParser::JOIN;
}
function yy_r1_5($yy_subpatterns)
{
$this->token = OQLParser::ON;
}
function yy_r1_6($yy_subpatterns)
{
$this->token = OQLParser::MATH_DIV;
}
function yy_r1_7($yy_subpatterns)
{
$this->token = OQLParser::MATH_MULT;
}
function yy_r1_8($yy_subpatterns)
{
$this->token = OQLParser::MATH_PLUS;
}
function yy_r1_9($yy_subpatterns)
{
$this->token = OQLParser::MATH_MINUS;
}
function yy_r1_10($yy_subpatterns)
{
$this->token = OQLParser::LOG_AND;
}
function yy_r1_11($yy_subpatterns)
{
$this->token = OQLParser::LOG_OR;
}
function yy_r1_12($yy_subpatterns)
{
$this->token = OQLParser::COMA;
}
function yy_r1_13($yy_subpatterns)
{
$this->token = OQLParser::PAR_OPEN;
}
function yy_r1_14($yy_subpatterns)
{
$this->token = OQLParser::PAR_CLOSE;
}
function yy_r1_15($yy_subpatterns)
{
$this->token = OQLParser::EQ;
}
function yy_r1_16($yy_subpatterns)
{
$this->token = OQLParser::NOT_EQ;
}
function yy_r1_17($yy_subpatterns)
{
$this->token = OQLParser::GT;
}
function yy_r1_18($yy_subpatterns)
{
$this->token = OQLParser::LT;
}
function yy_r1_19($yy_subpatterns)
{
$this->token = OQLParser::GE;
}
function yy_r1_20($yy_subpatterns)
{
$this->token = OQLParser::LE;
}
function yy_r1_21($yy_subpatterns)
{
$this->token = OQLParser::LIKE;
}
function yy_r1_22($yy_subpatterns)
{
$this->token = OQLParser::NOT_LIKE;
}
function yy_r1_23($yy_subpatterns)
{
$this->token = OQLParser::IN;
}
function yy_r1_24($yy_subpatterns)
{
$this->token = OQLParser::NOT_IN;
}
function yy_r1_25($yy_subpatterns)
{
$this->token = OQLParser::INTERVAL;
}
function yy_r1_26($yy_subpatterns)
{
$this->token = OQLParser::F_IF;
}
function yy_r1_27($yy_subpatterns)
{
$this->token = OQLParser::F_ELT;
}
function yy_r1_28($yy_subpatterns)
{
$this->token = OQLParser::F_COALESCE;
}
function yy_r1_29($yy_subpatterns)
{
$this->token = OQLParser::F_CONCAT;
}
function yy_r1_30($yy_subpatterns)
{
$this->token = OQLParser::F_SUBSTR;
}
function yy_r1_31($yy_subpatterns)
{
$this->token = OQLParser::F_TRIM;
}
function yy_r1_32($yy_subpatterns)
{
$this->token = OQLParser::F_DATE;
}
function yy_r1_33($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_FORMAT;
}
function yy_r1_34($yy_subpatterns)
{
$this->token = OQLParser::F_CURRENT_DATE;
}
function yy_r1_35($yy_subpatterns)
{
$this->token = OQLParser::F_NOW;
}
function yy_r1_36($yy_subpatterns)
{
$this->token = OQLParser::F_TIME;
}
function yy_r1_37($yy_subpatterns)
{
$this->token = OQLParser::F_TO_DAYS;
}
function yy_r1_38($yy_subpatterns)
{
$this->token = OQLParser::F_FROM_DAYS;
}
function yy_r1_39($yy_subpatterns)
{
$this->token = OQLParser::F_YEAR;
}
function yy_r1_40($yy_subpatterns)
{
$this->token = OQLParser::F_MONTH;
}
function yy_r1_41($yy_subpatterns)
{
$this->token = OQLParser::F_DAY;
}
function yy_r1_42($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_ADD;
}
function yy_r1_43($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_SUB;
}
function yy_r1_44($yy_subpatterns)
{
$this->token = OQLParser::F_ROUND;
}
function yy_r1_45($yy_subpatterns)
{
$this->token = OQLParser::F_FLOOR;
}
function yy_r1_46($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
}
function yy_r1_47($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
}
function yy_r1_48($yy_subpatterns)
{
$this->token = OQLParser::NAME;
}
function yy_r1_49($yy_subpatterns)
{
$this->token = OQLParser::DOT;
}
}
define('UNEXPECTED_INPUT_AT_LINE', 'Unexpected input at line');
class OQLLexerException extends OQLException
{
public function __construct($sInput, $iLine, $iCol, $sUnexpected)
{
parent::__construct("Syntax error", $sInput, $iLine, $iCol, $sUnexpected);
}
}
class OQLLexer extends OQLLexerRaw
{
public function getTokenPos()
{
return max(0, $this->count - strlen($this->value));
}
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
}
}
}
?>

305
core/oql/oql-lexer.plex Normal file
View File

@@ -0,0 +1,305 @@
<?php
// Notes (from the source file: oql-lexer.plex) - Romain
//
// The strval rule is a little bit cryptic.
// This is due to both a bug in the lexer generator and the complexity of our need
// The rule means: either a quoted string with ", or a quoted string with '
// literal " (resp. ') must be escaped by a \
// \ must be escaped by an additional \
//
// Here are the issues and limitation found in the lexer generator:
// * Matching simple quotes is an issue, because regexp are not correctly escaped (and the ESC code is escaped itself)
// Workaround: insert '.chr(39).' which will be a real ' in the end
// * Matching an alternate regexp is an issue because you must specify "|^...."
// and the regexp parser will not accept that syntax
// Workaround: insert '.chr(94).' which will be a real ^
//
// Let's analyze an overview of the regexp, we have
// 1) The strval rule in the lexer definition
// /"([^\\"]|\\"|\\\\)*"|'.chr(94).chr(39).'([^\\'.chr(39).']|\\'.chr(39).'|\\\\)*'.chr(39).'/
// 2) Becomes the php expression in the lexer
// (note the escaped double quotes, hopefully having no effect, but showing where the issue is!)
// $myRegexp = '/^\"([^\\\\\"]|\\\\\"|\\\\\\\\)*\"|'.chr(94).chr(39).'([^\\\\'.chr(39).']|\\\\'.chr(39).'|\\\\\\\\)*'.chr(39).'/';
//
// To be fixed in LexerGenerator/Parser.y, in doLongestMatch (doFirstMatch is ok)
//
//
// Now, let's explain how the regexp has been designed.
// Here is a simplified version, dealing with simple quotes, and based on the assumption that the lexer generator has been fixed!
// The strval rule in the lexer definition
// /'([^\\']*(\\')*(\\\\)*)*'/
// This means anything containing \\ or \' or any other char but a standalone ' or \
// This means ' or \ could not be found without a preceding \
//
class OQLLexerRaw
{
protected $data; // input string
public $token; // token id
public $value; // token string representation
protected $line; // current line
protected $count; // current column
function __construct($data)
{
$this->data = $data;
$this->count = 0;
$this->line = 1;
}
/*!lex2php
%input $this->data
%counter $this->count
%token $this->token
%value $this->value
%line $this->line
%matchlongest 1
whitespace = /[ \t\n]+/
select = "SELECT"
as_alias = "AS"
where = "WHERE"
join = "JOIN"
on = "ON"
coma = ","
par_open = "("
par_close = ")"
math_div = "/"
math_mult = "*"
math_plus = "+"
math_minus = "-"
log_and = "AND"
log_or = "OR"
eq = "="
not_eq = "!="
gt = ">"
lt = "<"
ge = ">="
le = "<="
like = "LIKE"
not_like = "NOT LIKE"
in = "IN"
not_in = "NOT IN"
interval = "INTERVAL"
f_if = "IF"
f_elt = "ELT"
f_coalesce = "COALESCE"
f_concat = "CONCAT"
f_substr = "SUBSTR"
f_trim = "TRIM"
f_date = "DATE"
f_date_format = "DATE_FORMAT"
f_current_date = "CURRENT_DATE"
f_now = "NOW"
f_time = "TIME"
f_to_days = "TO_DAYS"
f_from_days = "FROM_DAYS"
f_year = "YEAR"
f_month = "MONTH"
f_day = "DAY"
f_date_add = "DATE_ADD"
f_date_sub = "DATE_SUB"
f_round = "ROUND"
f_floor = "FLOOR"
numval = /[0-9]+|0x[0-9a-fA-F]+/
strval = /"([^\\"]|\\"|\\\\)*"|'.chr(94).chr(39).'([^\\'.chr(39).']|\\'.chr(39).'|\\\\)*'.chr(39).'/
name = /([_a-zA-Z][_a-zA-Z0-9]*|`[^`]+`)/
dot = "."
*/
/*!lex2php
whitespace {
return false;
}
select {
$this->token = OQLParser::SELECT;
}
as_alias {
$this->token = OQLParser::AS_ALIAS;
}
where {
$this->token = OQLParser::WHERE;
}
join {
$this->token = OQLParser::JOIN;
}
on {
$this->token = OQLParser::ON;
}
math_div {
$this->token = OQLParser::MATH_DIV;
}
math_mult {
$this->token = OQLParser::MATH_MULT;
}
math_plus {
$this->token = OQLParser::MATH_PLUS;
}
math_minus {
$this->token = OQLParser::MATH_MINUS;
}
log_and {
$this->token = OQLParser::LOG_AND;
}
log_or {
$this->token = OQLParser::LOG_OR;
}
coma {
$this->token = OQLParser::COMA;
}
par_open {
$this->token = OQLParser::PAR_OPEN;
}
par_close {
$this->token = OQLParser::PAR_CLOSE;
}
eq {
$this->token = OQLParser::EQ;
}
not_eq {
$this->token = OQLParser::NOT_EQ;
}
gt {
$this->token = OQLParser::GT;
}
lt {
$this->token = OQLParser::LT;
}
ge {
$this->token = OQLParser::GE;
}
le {
$this->token = OQLParser::LE;
}
like {
$this->token = OQLParser::LIKE;
}
not_like {
$this->token = OQLParser::NOT_LIKE;
}
in {
$this->token = OQLParser::IN;
}
not_in {
$this->token = OQLParser::NOT_IN;
}
interval {
$this->token = OQLParser::INTERVAL;
}
f_if {
$this->token = OQLParser::F_IF;
}
f_elt {
$this->token = OQLParser::F_ELT;
}
f_coalesce {
$this->token = OQLParser::F_COALESCE;
}
f_concat {
$this->token = OQLParser::F_CONCAT;
}
f_substr {
$this->token = OQLParser::F_SUBSTR;
}
f_trim {
$this->token = OQLParser::F_TRIM;
}
f_date {
$this->token = OQLParser::F_DATE;
}
f_date_format {
$this->token = OQLParser::F_DATE_FORMAT;
}
f_current_date {
$this->token = OQLParser::F_CURRENT_DATE;
}
f_now {
$this->token = OQLParser::F_NOW;
}
f_time {
$this->token = OQLParser::F_TIME;
}
f_to_days {
$this->token = OQLParser::F_TO_DAYS;
}
f_from_days {
$this->token = OQLParser::F_FROM_DAYS;
}
f_year {
$this->token = OQLParser::F_YEAR;
}
f_month {
$this->token = OQLParser::F_MONTH;
}
f_day {
$this->token = OQLParser::F_DAY;
}
f_date_add {
$this->token = OQLParser::F_DATE_ADD;
}
f_date_sub {
$this->token = OQLParser::F_DATE_SUB;
}
f_round {
$this->token = OQLParser::F_ROUND;
}
f_floor {
$this->token = OQLParser::F_FLOOR;
}
numval {
$this->token = OQLParser::NUMVAL;
}
strval {
$this->token = OQLParser::STRVAL;
}
name {
$this->token = OQLParser::NAME;
}
dot {
$this->token = OQLParser::DOT;
}
*/
}
define('UNEXPECTED_INPUT_AT_LINE', 'Unexpected input at line');
class OQLLexerException extends OQLException
{
public function __construct($sInput, $iLine, $iCol, $sUnexpected)
{
parent::__construct("Syntax error", $sInput, $iLine, $iCol, $sUnexpected);
}
}
class OQLLexer extends OQLLexerRaw
{
public function getTokenPos()
{
return max(0, $this->count - strlen($this->value));
}
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{
$sMessage = $e->getMessage();
if (substr($sMessage, 0, strlen(UNEXPECTED_INPUT_AT_LINE)) == UNEXPECTED_INPUT_AT_LINE)
{
$sLineAndChar = substr($sMessage, strlen(UNEXPECTED_INPUT_AT_LINE));
if (preg_match('#^([0-9]+): (.+)$#', $sLineAndChar, $aMatches))
{
$iLine = $aMatches[1];
$sUnexpected = $aMatches[2];
throw new OQLLexerException($this->data, $iLine, $this->count, $sUnexpected);
}
}
// Default: forward the exception
throw $e;
}
}
}
?>

1613
core/oql/oql-parser.php Normal file

File diff suppressed because it is too large Load Diff

213
core/oql/oql-parser.y Normal file
View File

@@ -0,0 +1,213 @@
%name OQLParser_
%declare_class {class OQLParserRaw}
%syntax_error {
throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN);
}
result ::= query(X). { $this->my_result = X; }
result ::= condition(X). { $this->my_result = X; }
query(A) ::= SELECT class_name(X) join_statement(J) where_statement(W). {
A = new OqlQuery(X, X, W, J);
}
query(A) ::= SELECT class_name(X) AS_ALIAS class_name(Y) join_statement(J) where_statement(W). {
A = new OqlQuery(X, Y, W, J);
}
where_statement(A) ::= WHERE condition(C). { A = C;}
where_statement(A) ::= . { A = null;}
join_statement(A) ::= join_item(J) join_statement(S). {
// insert the join statement on top of the existing list
array_unshift(S, J);
// and return the updated array
A = S;
}
join_statement(A) ::= join_item(J). {
A = Array(J);
}
join_statement(A) ::= . { A = null;}
join_item(A) ::= JOIN class_name(X) AS_ALIAS class_name(Y) ON join_condition(C).
{
// create an array with one single item
A = new OqlJoinSpec(X, Y, C);
}
join_item(A) ::= JOIN class_name(X) ON join_condition(C).
{
// create an array with one single item
A = new OqlJoinSpec(X, X, C);
}
join_condition(A) ::= field_id(X) EQ field_id(Y). { A = new BinaryOqlExpression(X, '=', Y); }
condition(A) ::= expression(X). { A = X; }
expression(A) ::= PAR_OPEN expression(X) PAR_CLOSE. { A = X; }
expression(A) ::= expression(X) operator(Y) expression(Z). { A = new BinaryOqlExpression(X, Y, Z); }
expression(A) ::= scalar(X). { A=X; }
expression(A) ::= field_id(X). { A = X; }
expression(A) ::= expression(X) list_operator(Y) list(Z). { A = new BinaryOqlExpression(X, Y, Z); }
expression(A) ::= func_name(X) PAR_OPEN arg_list(Y) PAR_CLOSE. { A = new FunctionOqlExpression(X, Y); }
list(A) ::= PAR_OPEN scalar_list(X) PAR_CLOSE. {
A = new ListOqlExpression(X);
}
scalar_list(A) ::= scalar(X). {
A = array(X);
}
scalar_list(A) ::= scalar_list(L) COMA scalar(X). {
array_push(L, X);
A = L;
}
arg_list(A) ::= . {
A = array();
}
arg_list(A) ::= argument(X). {
A = array(X);
}
arg_list(A) ::= arg_list(L) COMA argument(X). {
array_push(L, X);
A = L;
}
argument(A) ::= expression(X). { A = X; }
argument(A) ::= INTERVAL expression(X) interval_unit(Y). { A = new IntervalOqlExpression(X, Y); }
interval_unit(A) ::= F_DAY(X). { A = X; }
interval_unit(A) ::= F_MONTH(X). { A = X; }
interval_unit(A) ::= F_YEAR(X). { A = X; }
scalar(A) ::= num_scalar(X). { A = X; }
scalar(A) ::= str_scalar(X). { A = X; }
num_scalar(A) ::= num_value(X). { A = new ScalarOqlExpression(X); }
str_scalar(A) ::= str_value(X). { A = new ScalarOqlExpression(X); }
field_id(A) ::= class_name(X) DOT name(Y). { A = new FieldOqlExpression($this->m_iCol, Y, X); }
class_name(A) ::= name(X). {A=X;}
name(A) ::= NAME(X). {
if (X[0] == '`')
{
A = substr(X, 1, strlen(X) - 2);
}
else
{
A = X;
}
}
num_value(A) ::= NUMVAL(X). {A=X;}
str_value(A) ::= STRVAL(X). {A=stripslashes(substr(X, 1, strlen(X) - 2));}
operator(A) ::= log_operator(X). {A=X;}
operator(A) ::= num_operator(X). {A=X;}
operator(A) ::= str_operator(X). {A=X;}
operator(A) ::= EQ(X). {A=X;}
operator(A) ::= NOT_EQ(X). {A=X;}
log_operator(A) ::= LOG_AND(X). {A=X;}
log_operator(A) ::= LOG_OR(X). {A=X;}
num_operator(A) ::= GT(X). {A=X;}
num_operator(A) ::= LT(X). {A=X;}
num_operator(A) ::= GE(X). {A=X;}
num_operator(A) ::= LE(X). {A=X;}
num_operator(A) ::= MATH_DIV(X). {A=X;}
num_operator(A) ::= MATH_MULT(X). {A=X;}
num_operator(A) ::= MATH_PLUS(X). {A=X;}
num_operator(A) ::= MATH_MINUS(X). {A=X;}
str_operator(A) ::= LIKE(X). {A=X;}
str_operator(A) ::= NOT_LIKE(X). {A=X;}
list_operator(A) ::= IN(X). {A=X;}
list_operator(A) ::= NOT_IN(X). {A=X;}
func_name(A) ::= F_IF(X). { A=X; }
func_name(A) ::= F_ELT(X). { A=X; }
func_name(A) ::= F_COALESCE(X). { A=X; }
func_name(A) ::= F_CONCAT(X). { A=X; }
func_name(A) ::= F_SUBSTR(X). { A=X; }
func_name(A) ::= F_TRIM(X). { A=X; }
func_name(A) ::= F_DATE(X). { A=X; }
func_name(A) ::= F_DATE_FORMAT(X). { A=X; }
func_name(A) ::= F_CURRENT_DATE(X). { A=X; }
func_name(A) ::= F_NOW(X). { A=X; }
func_name(A) ::= F_TIME(X). { A=X; }
func_name(A) ::= F_TO_DAYS(X). { A=X; }
func_name(A) ::= F_FROM_DAYS(X). { A=X; }
func_name(A) ::= F_YEAR(X). { A=X; }
func_name(A) ::= F_MONTH(X). { A=X; }
func_name(A) ::= F_DAY(X). { A=X; }
func_name(A) ::= F_DATE_ADD(X). { A=X; }
func_name(A) ::= F_DATE_SUB(X). { A=X; }
func_name(A) ::= F_ROUND(X). { A=X; }
func_name(A) ::= F_FLOOR(X). { A=X; }
%code {
class OQLParserException extends OQLException
{
public function __construct($sInput, $iLine, $iCol, $sTokenName, $sTokenValue)
{
$sIssue = "Unexpected token $sTokenName";
parent::__construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue);
}
}
class OQLParser extends OQLParserRaw
{
// dirty, but working for us (no other mean to get the final result :-(
protected $my_result;
public function GetResult()
{
return $this->my_result;
}
// More info on the source query and the current position while parsing it
// Data used when an exception is raised
protected $m_iLine; // still not used
protected $m_iCol;
protected $m_sSourceQuery;
public function __construct($sQuery)
{
$this->m_iLine = 0;
$this->m_iCol = 0;
$this->m_sSourceQuery = $sQuery;
// no constructor - parent::__construct();
}
public function doParse($token, $value, $iCurrPosition = 0)
{
$this->m_iCol = $iCurrPosition;
return parent::DoParse($token, $value);
}
public function doFinish()
{
$this->doParse(0, 0);
return $this->my_result;
}
public function __destruct()
{
// Bug in the original destructor, causing an infinite loop !
// This is a real issue when a fatal error occurs on the first token (the error could not be seen)
if (is_null($this->yyidx))
{
$this->yyidx = -1;
}
parent::__destruct();
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
class OQLException extends CoreException
{
public function __construct($sIssue, $sInput, $iLine, $iCol, $sUnexpected, $aExpecting = null)
{
$this->m_MyIssue = $sIssue;
$this->m_sInput = $sInput;
$this->m_iLine = $iLine;
$this->m_iCol = $iCol;
$this->m_sUnexpected = $sUnexpected;
$this->m_aExpecting = $aExpecting;
if (is_null($this->m_aExpecting))
{
$sMessage = "$sIssue - found '$sUnexpected' at $iCol in '$sInput'";
}
else
{
$sExpectations = '{'.implode(', ', $aExpecting).'}';
$sMessage = "$sIssue - found '$sUnexpected' at $iCol in '$sInput', expecting $sExpectations";
}
// make sure everything is assigned properly
parent::__construct($sMessage, 0);
}
public function getHtmlDesc($sHighlightHtmlBegin = '<b>', $sHighlightHtmlEnd = '</b>')
{
$sRet = htmlentities($this->m_MyIssue.", found '".$this->m_sUnexpected."' in: ");
$sRet .= htmlentities(substr($this->m_sInput, 0, $this->m_iCol));
$sRet .= $sHighlightHtmlBegin.htmlentities(substr($this->m_sInput, $this->m_iCol, strlen($this->m_sUnexpected))).$sHighlightHtmlEnd;
$sRet .= htmlentities(substr($this->m_sInput, $this->m_iCol + strlen($this->m_sUnexpected)));
return $sRet;
}
}
?>

View File

@@ -0,0 +1,55 @@
<?
class OqlNormalizeException extends OQLException
{
}
class OqlInterpreterException extends OQLException
{
}
class OqlInterpreter
{
public $m_sQuery;
public function __construct($sQuery)
{
$this->m_sQuery = $sQuery;
}
protected function Parse()
{
$oLexer = new OQLLexer($this->m_sQuery);
$oParser = new OQLParser($this->m_sQuery);
while($oLexer->yylex())
{
$oParser->doParse($oLexer->token, $oLexer->value, $oLexer->getTokenPos());
}
$res = $oParser->doFinish();
return $res;
}
public function ParseQuery()
{
$oRes = $this->Parse();
if (!$oRes instanceof OqlQuery)
{
throw new OqlException('Expecting an OQL query', $this->m_sQuery, 0, 0, get_class($oRes), array('OqlQuery'));
}
return $oRes;
}
public function ParseExpression()
{
$oRes = $this->Parse();
if (!$oRes instanceof Expression)
{
throw new OqlException('Expecting an OQL expression', $this->m_sQuery, 0, 0, get_class($oRes), array('Expression'));
}
return $oRes;
}
}
?>

View File

@@ -0,0 +1,106 @@
<?
class OqlJoinSpec
{
protected $m_sClass;
protected $m_sClassAlias;
protected $m_oLeftField;
protected $m_oRightField;
protected $m_oNextJoinspec;
public function __construct($sClass, $sClassAlias, BinaryExpression $oExpression)
{
$this->m_sClass = $sClass;
$this->m_sClassAlias = $sClassAlias;
$this->m_oLeftField = $oExpression->GetLeftExpr();
$this->m_oRightField = $oExpression->GetRightExpr();
}
public function GetClass()
{
return $this->m_sClass;
}
public function GetClassAlias()
{
return $this->m_sClassAlias;
}
public function GetLeftField()
{
return $this->m_oLeftField;
}
public function GetRightField()
{
return $this->m_oRightField;
}
}
class BinaryOqlExpression extends BinaryExpression
{
}
class ScalarOqlExpression extends ScalarExpression
{
}
class FieldOqlExpression extends FieldExpression
{
protected $m_iPosition; // position in the source string
public function __construct($iPosition, $sName, $sParent = '')
{
$this->m_iPosition = $iPosition;
parent::__construct($sName, $sParent);
}
public function GetPosition()
{
return $this->m_iPosition;
}
}
class ListOqlExpression extends ListExpression
{
}
class FunctionOqlExpression extends FunctionExpression
{
}
class IntervalOqlExpression extends IntervalExpression
{
}
class OqlQuery
{
protected $m_sClass;
protected $m_sClassAlias;
protected $m_aJoins; // array of OqlJoinSpec
protected $m_oCondition; // condition tree (expressions)
public function __construct($sClass, $sClassAlias = '', $oCondition = null, $aJoins = null)
{
$this->m_sClass = $sClass;
$this->m_sClassAlias = $sClassAlias;
$this->m_aJoins = $aJoins;
$this->m_oCondition = $oCondition;
}
public function GetClass()
{
return $this->m_sClass;
}
public function GetClassAlias()
{
return $this->m_sClassAlias;
}
public function GetJoins()
{
return $this->m_aJoins;
}
public function GetCondition()
{
return $this->m_oCondition;
}
}
?>

399
core/sqlquery.class.inc.php Normal file
View File

@@ -0,0 +1,399 @@
<?php
/**
* SQLQuery
* build an mySQL compatible SQL query
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
require_once('cmdbsource.class.inc.php');
class SQLExpression extends BinaryExpression
{
}
class ScalarSQLExpression extends ScalarExpression
{
}
class TrueSQLExpression extends TrueExpression
{
}
class FieldSQLExpression extends FieldExpression
{
}
class SQLQuery
{
private $m_sTable = '';
private $m_sTableAlias = '';
private $m_aFields = array();
private $m_oConditionExpr = null;
private $m_aFullTextNeedles = array();
private $m_bToDelete = true; // The current table must be listed for deletion ?
private $m_aValues = array(); // Values to set in case of an update query
private $m_aJoinSelects = array();
public function __construct($sTable, $sTableAlias, $aFields, $oConditionExpr, $aFullTextNeedles, $bToDelete = true, $aValues = array())
{
if (!CMDBSource::IsTable($sTable))
{
trigger_error("Unknown table '$sTable'", E_USER_ERROR);
}
// $aFields must be an array of "alias"=>"expr"
// $oConditionExpr must be a condition tree
// $aValues is an array of "alias"=>value
$this->m_sTable = $sTable;
$this->m_sTableAlias = $sTableAlias;
$this->m_aFields = $aFields;
$this->m_oConditionExpr = $oConditionExpr;
if (is_null($oConditionExpr))
{
$this->m_oConditionExpr = new TrueExpression;
}
else if (!$oConditionExpr instanceof Expression)
{
throw new CoreException('Invalid type for condition, expecting an Expression', array('class' => get_class($oConditionExpr)));
}
$this->m_aFullTextNeedles = $aFullTextNeedles;
$this->m_bToDelete = $bToDelete;
$this->m_aValues = $aValues;
}
public function DisplayHtml()
{
if (count($this->m_aFields) == 0) $sFields = "";
else
{
$aFieldDesc = array();
foreach ($this->m_aFields as $sAlias => $oExpression)
{
$aFieldDesc[] = $oExpression->Render()." as <em>$sAlias</em>";
}
$sFields = " =&gt; ".implode(', ', $aFieldDesc);
}
echo "<b>$this->m_sTable</b>$sFields<br/>\n";
// #@# todo - display html of an expression tree
//$this->m_oConditionExpr->DisplayHtml()
if (count($this->m_aFullTextNeedles) > 0)
{
echo "Full text criteria...<br/>\n";
echo "<ul class=\"treeview\">\n";
foreach ($this->m_aFullTextNeedles as $sFTNeedle)
{
echo "<li>$sFTNeedle</li>\n";
}
echo "</ul>";
}
if (count($this->m_aJoinSelects) > 0)
{
echo "Joined to...<br/>\n";
echo "<ul class=\"treeview\">\n";
foreach ($this->m_aJoinSelects as $aJoinInfo)
{
$sJoinType = $aJoinInfo["jointype"];
$oSQLQuery = $aJoinInfo["select"];
$sLeftField = $aJoinInfo["leftfield"];
$sRightField = $aJoinInfo["rightfield"];
echo "<li>Join '$sJoinType', $sLeftField, $sRightField".$oSQLQuery->DisplayHtml()."</li>\n";
}
echo "</ul>";
}
$aFrom = array();
$aFields = array();
$oCondition = null;
$aDelTables = array();
$aSetValues = array();
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues);
echo "From ...<br/>\n";
echo "<pre style=\"font-size: smaller;\">\n";
print_r($aFrom);
echo "</pre>";
}
public function SetCondition($oConditionExpr)
{
$this->m_oConditionExpr = $oConditionExpr;
}
public function AddCondition($oConditionExpr)
{
$this->m_oConditionExpr->LogAnd($oConditionExpr);
}
private function AddJoin($sJoinType, $oSQLQuery, $sLeftField, $sRightField)
{
assert((get_class($oSQLQuery) == __CLASS__) || is_subclass_of($oSQLQuery, __CLASS__));
if (!CMDBSource::IsField($this->m_sTable, $sLeftField))
{
trigger_error("Unknown field '$sLeftField' in table '".$this->m_sTable, E_USER_ERROR);
}
if (!CMDBSource::IsField($oSQLQuery->m_sTable, $sRightField))
{
trigger_error("Unknown field '$sRightField' in table '".$oSQLQuery->m_sTable."'", E_USER_ERROR);
}
$this->m_aJoinSelects[] = array(
"jointype" => $sJoinType,
"select" => $oSQLQuery,
"leftfield" => $sLeftField,
"rightfield" => $sRightField
);
}
public function AddInnerJoin($oSQLQuery, $sLeftField, $sRightField)
{
$this->AddJoin("inner", $oSQLQuery, $sLeftField, $sRightField);
}
public function AddLeftJoin($oSQLQuery, $sLeftField, $sRightField)
{
return $this->AddJoin("left", $oSQLQuery, $sLeftField, $sRightField);
}
// Interface, build the SQL query
public function RenderDelete()
{
// The goal will be to complete the list as we build the Joins
$aFrom = array();
$aFields = array();
$oCondition = null;
$aDelTables = array();
$aSetValues = array();
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues);
// Target: DELETE myAlias1, myAlias2 FROM t1 as myAlias1, t2 as myAlias2, t3 as topreserve WHERE ...
$sDelete = self::ClauseDelete($aDelTables);
$sFrom = self::ClauseFrom($aFrom);
// #@# safety net to redo ?
/*
if ($this->m_oConditionExpr->IsAny())
-- if (count($aConditions) == 0) --
{
trigger_error("Building a request wich will delete every object of a given table -looks suspicious- please use truncate instead...", E_USER_ERROR);
}
*/
$sWhere = self::ClauseWhere($oCondition);
return "DELETE $sDelete FROM $sFrom WHERE $sWhere";
}
// Interface, build the SQL query
public function RenderUpdate()
{
// The goal will be to complete the list as we build the Joins
$aFrom = array();
$aFields = array();
$oCondition = null;
$aDelTables = array();
$aSetValues = array();
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues);
$sFrom = self::ClauseFrom($aFrom);
$sValues = self::ClauseValues($aSetValues);
$sWhere = self::ClauseWhere($oCondition);
return "UPDATE $sFrom SET $sValues WHERE $sWhere";
}
// Interface, build the SQL query
public function RenderSelect($aOrderBy = array())
{
// The goal will be to complete the lists as we build the Joins
$aFrom = array();
$aFields = array();
$oCondition = null;
$aDelTables = array();
$aSetValues = array();
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues);
$sSelect = self::ClauseSelect($aFields);
$sFrom = self::ClauseFrom($aFrom);
$sWhere = self::ClauseWhere($oCondition);
$sOrderBy = self::ClauseOrderBy($aOrderBy);
if (!empty($sOrderBy))
{
$sOrderBy = "ORDER BY $sOrderBy";
}
return "SELECT DISTINCT $sSelect FROM $sFrom WHERE $sWhere $sOrderBy";
}
private static function ClauseSelect($aFields)
{
$aSelect = array();
foreach ($aFields as $sFieldAlias => $sSQLExpr)
{
$aSelect[] = "$sSQLExpr AS $sFieldAlias";
}
$sSelect = implode(', ', $aSelect);
return $sSelect;
}
private static function ClauseDelete($aDelTableAliases)
{
$aDelTables = array();
foreach ($aDelTableAliases as $sTableAlias)
{
$aDelTables[] = "$sTableAlias";
}
$sDelTables = implode(', ', $aDelTables);
return $sDelTables;
}
private static function ClauseFrom($aFrom)
{
$sFrom = "";
foreach ($aFrom as $sTableAlias => $aJoinInfo)
{
switch ($aJoinInfo["jointype"])
{
case "first":
$sFrom .= "`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
break;
case "inner":
$sFrom .= " INNER JOIN `".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ON ".$aJoinInfo["joincondition"];
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
break;
case "left":
$sFrom .= " LEFT JOIN (`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
$sFrom .= ") ON ".$aJoinInfo["joincondition"];
break;
default:
trigger_error("Unknown jointype: '".$aJoinInfo["jointype"]."'");
}
}
return $sFrom;
}
private static function ClauseValues($aValues)
{
$aSetValues = array();
foreach ($aValues as $sFieldSpec => $value)
{
$aSetValues[] = "$sFieldSpec = ".CMDBSource::Quote($value);
}
$sSetValues = implode(', ', $aSetValues);
return $sSetValues;
}
private static function ClauseWhere($oConditionExpr)
{
return $oConditionExpr->Render();
}
private static function ClauseOrderBy($aOrderBy)
{
$aOrderBySpec = array();
foreach($aOrderBy as $sFieldAlias => $bAscending)
{
$aOrderBySpec[] = '`'.$sFieldAlias.'`'.($bAscending ? " ASC" : " DESC");
}
$sOrderBy = implode(", ", $aOrderBySpec);
return $sOrderBy;
}
// Purpose: prepare the query data, once for all
private function privRender(&$aFrom, &$aFields, &$oCondition, &$aDelTables, &$aSetValues)
{
$sTableAlias = $this->privRenderSingleTable($aFrom, $aFields, $aDelTables, $aSetValues);
// Add the full text search condition, based on each and every requested field
//
// To be updated with a real full text search based on the mySQL settings
// (then it might move somewhere else !)
//
$oCondition = $this->m_oConditionExpr;
if ((count($aFields) > 0) && (count($this->m_aFullTextNeedles) > 0))
{
$aFieldExp = array();
foreach ($aFields as $sField)
{
// This is TEMPORARY (that's why it is weird, actually)
// Full text match will be done as an expression in the filter condition
// $sField is already a string `table`.`column`
// Let's make an expression out of it (again !)
$aFieldExp[] = Expression::FromOQL($sField);
}
$oFullTextExpr = new CharConcatExpression($aFieldExp);
// The cast is necessary because the CONCAT result in a binary string:
// if any of the field is a binary string => case sensitive comparison
//
foreach($this->m_aFullTextNeedles as $sFTNeedle)
{
$oNewCond = new BinaryExpression($oFullTextExpr, 'LIKE', new ScalarExpression("%$sFTNeedle%"));
$oCondition = $oCondition->LogAnd($oNewCond);
}
}
return $sTableAlias;
}
private function privRenderSingleTable(&$aFrom, &$aFields, &$aDelTables, &$aSetValues, $sJoinType = "first", $sCallerAlias = "", $sLeftField = "", $sRightField = "")
{
$aActualTableFields = CMDBSource::GetTableFieldsList($this->m_sTable);
$aTranslationTable[$this->m_sTable]['*'] = $this->m_sTableAlias;
// Handle the various kinds of join (or first table in the list)
//
$sJoinCond = "`$sCallerAlias`.`$sLeftField` = `{$this->m_sTableAlias}`.`$sRightField`";
switch ($sJoinType)
{
case "first":
$aFrom[$this->m_sTableAlias] = array("jointype"=>"first", "tablename"=>$this->m_sTable, "joincondition"=>"");
break;
case "inner":
case "left":
$aFrom[$this->m_sTableAlias] = array("jointype"=>$sJoinType, "tablename"=>$this->m_sTable, "joincondition"=>"$sJoinCond");
break;
}
// Given the alias, modify the fields and conditions
// before adding them into the current lists
//
foreach($this->m_aFields as $sAlias => $oExpression)
{
$sTable = $oExpression->GetParent();
$sColumn = $oExpression->GetName();
$aFields["`$sAlias`"] = $oExpression->Render();
}
if ($this->m_bToDelete)
{
$aDelTables[] = "`{$this->m_sTableAlias}`";
}
foreach($this->m_aValues as $sFieldName=>$value)
{
$aSetValues["`{$this->m_sTableAlias}`.`$sFieldName`"] = $value; // quoted further!
}
// loop on joins, to complete the list of tables/fields/conditions
//
$aTempFrom = array(); // temporary subset of 'from' specs, to be grouped in the final query
foreach ($this->m_aJoinSelects as $aJoinData)
{
$sJoinType = $aJoinData["jointype"];
$oRightSelect = $aJoinData["select"];
$sLeftField = $aJoinData["leftfield"];
$sRightField = $aJoinData["rightfield"];
$sJoinTableAlias = $oRightSelect->privRenderSingleTable($aTempFrom, $aFields, $aDelTables, $aSetValues, $sJoinType, $this->m_sTableAlias, $sLeftField, $sRightField);
}
$aFrom[$this->m_sTableAlias]['subfrom'] = $aTempFrom;
return $this->m_sTableAlias;
}
}
?>

View File

@@ -0,0 +1,59 @@
<?php
/**
* A stimulus is the trigger that makes the lifecycle go ahead (state machine)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class ObjectStimulus
{
private $m_aParams = array();
public function __construct($aParams)
{
$this->m_aParams = $aParams;
$this->ConsistencyCheck();
}
public function Get($sParamName) {return $this->m_aParams[$sParamName];}
// Note: I could factorize this code with the parameter management made for the AttributeDef class
// to be overloaded
static protected function ListExpectedParams()
{
return array("label", "description");
}
private function ConsistencyCheck()
{
// Check that any mandatory param has been specified
//
$aExpectedParams = $this->ListExpectedParams();
foreach($aExpectedParams as $sParamName)
{
if (!array_key_exists($sParamName, $this->m_aParams))
{
$aBacktrace = debug_backtrace();
$sTargetClass = $aBacktrace[2]["class"];
$sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"];
trigger_error("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)</br>\n", E_USER_ERROR);
}
}
}
}
class StimulusUserAction extends ObjectStimulus
{
}
?>

430
core/test.class.inc.php Normal file
View File

@@ -0,0 +1,430 @@
<?php
require_once('coreexception.class.inc.php');
require_once('attributedef.class.inc.php');
require_once('filterdef.class.inc.php');
require_once('stimulus.class.inc.php');
require_once('MyHelpers.class.inc.php');
require_once('expression.class.inc.php');
require_once('cmdbsource.class.inc.php');
require_once('sqlquery.class.inc.php');
require_once('dbobject.class.php');
require_once('dbobjectsearch.class.php');
require_once('dbobjectset.class.php');
require_once('userrights.class.inc.php');
// Just to differentiate programmatically triggered exceptions and other kind of errors (usefull?)
class UnitTestException extends Exception
{}
/**
* Improved display of the backtrace
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class ExceptionFromError extends Exception
{
public function getTraceAsHtml()
{
$aBackTrace = $this->getTrace();
return MyHelpers::get_callstack_html(0, $this->getTrace());
// return "<pre>\n".$this->getTraceAsString()."</pre>\n";
}
}
/**
* Test handler API and basic helpers
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
abstract class TestHandler
{
protected $m_aSuccesses;
protected $m_aWarnings;
protected $m_aErrors;
protected $m_sOutput;
public function __construct()
{
$this->m_aSuccesses = array();
$this->m_aWarnings = array();
$this->m_aErrors = array();
}
abstract static public function GetName();
abstract static public function GetDescription();
protected function DoPrepare() {return true;}
abstract protected function DoExecute();
protected function DoCleanup() {return true;}
protected function ReportSuccess($sMessage, $sSubtestId = '')
{
$this->m_aSuccesses[] = $sMessage;
}
protected function ReportWarning($sMessage, $sSubtestId = '')
{
$this->m_aWarnings[] = $sMessage;
}
protected function ReportError($sMessage, $sSubtestId = '')
{
$this->m_aErrors[] = $sMessage;
}
public function GetResults()
{
return $this->m_aSuccesses;
}
public function GetWarnings()
{
return $this->m_aWarnings;
}
public function GetErrors()
{
return $this->m_aErrors;
}
public function GetOutput()
{
return $this->m_sOutput;
}
public function error_handler($errno, $errstr, $errfile, $errline)
{
// Note: return false to call the default handler (stop the program if an error)
switch ($errno)
{
case E_USER_ERROR:
$this->ReportError($errstr);
//throw new ExceptionFromError("Fatal error in line $errline of file $errfile: $errstr");
break;
case E_USER_WARNING:
$this->ReportWarning($errstr);
break;
case E_USER_NOTICE:
$this->ReportWarning($errstr);
break;
default:
throw new ExceptionFromError("Fatal warning in line $errline of file $errfile: $errstr");
$this->ReportWarning("Unknown error type: [$errno] $errstr");
echo "Unknown error type: [$errno] $errstr<br />\n";
break;
}
return true; // do not call the default handler
}
public function Execute()
{
ob_start();
set_error_handler(array($this, 'error_handler'));
try
{
$this->DoPrepare();
$this->DoExecute();
}
catch (ExceptionFromError $e)
{
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
}
catch (Exception $e)
{
//$this->ReportError($e->getMessage());
//$this->ReportError($e->__tostring());
$this->ReportError($e->getMessage().' - '.$e->getTraceAsString());
}
restore_error_handler();
$this->m_sOutput = ob_get_clean();
return (count($this->GetErrors()) == 0);
}
}
/**
* Test to execute a piece of code (checks if an error occurs)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestFunction extends TestHandler
{
// simply overload DoExecute (temporary)
}
/**
* Test to check that a function outputs some values depending on its input
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestFunctionInOut extends TestFunction
{
abstract static public function GetCallSpec(); // parameters to call_user_func
abstract static public function GetInOut(); // array of input => output
protected function DoExecute()
{
$aTests = $this->GetInOut();
if (is_array($aTests))
{
foreach ($aTests as $iTestId => $aTest)
{
$ret = call_user_func_array($this->GetCallSpec(), $aTest['args']);
if ($ret != $aTest['output'])
{
// Note: to be improved to cope with non string parameters
$this->ReportError("Found '$ret' while expecting '".$aTest['output']."'", $iTestId);
}
else
{
$this->ReportSuccess("Found the expected output '$ret'", $iTestId);
}
}
}
else
{
$ret = call_user_func($this->GetCallSpec());
$this->ReportSuccess('Finished successfully');
}
}
}
/**
* Test to check an URL (Searches for Error/Warning/Etc keywords)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestUrl extends TestHandler
{
abstract static public function GetUrl();
abstract static public function GetErrorKeywords();
abstract static public function GetWarningKeywords();
protected function DoExecute()
{
return true;
}
}
/**
* Test to check a user management module
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestUserRights extends TestHandler
{
protected function DoExecute()
{
return true;
}
}
/**
* Test to execute a scenario on a given DB
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestScenarioOnDB extends TestHandler
{
abstract static public function GetDBHost();
abstract static public function GetDBUser();
abstract static public function GetDBPwd();
abstract static public function GetDBName();
protected function DoPrepare()
{
$sDBHost = $this->GetDBHost();
$sDBUser = $this->GetDBUser();
$sDBPwd = $this->GetDBPwd();
$sDBName = $this->GetDBName();
CMDBSource::Init($sDBHost, $sDBUser, $sDBPwd);
if (CMDBSource::IsDB($sDBName))
{
CMDBSource::DropDB($sDBName);
}
CMDBSource::CreateDB($sDBName);
}
protected function DoCleanup()
{
// CMDBSource::DropDB($this->GetDBName());
}
}
/**
* Test to use a business model on a given DB
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestBizModel extends TestHandler
{
// abstract static public function GetDBSubName();
// abstract static public function GetBusinessModelFile();
abstract static public function GetConfigFile();
protected function DoPrepare()
{
MetaModel::Startup($this->GetConfigFile(), true); // allow missing DB
MetaModel::CheckDefinitions();
// something here to create records... but that's another story
}
protected function ResetDB()
{
if (MetaModel::DBExists())
{
MetaModel::DBDrop();
}
MetaModel::DBCreate();
}
static protected function show_list($oObjectSet)
{
$oObjectSet->Rewind();
while ($oItem = $oObjectSet->Fetch())
{
$aValues = array();
foreach(MetaModel::GetAttributesList(get_class($oItem)) as $sAttCode)
{
$aValues[] = $oItem->GetAsHTML($sAttCode);
}
echo $oItem->GetKey()." => ".implode(", ", $aValues)."</br>\n";
}
}
static protected function search_and_show_list(DBObjectSearch $oMyFilter)
{
$oObjSet = new CMDBObjectSet($oMyFilter);
echo $oMyFilter->__DescribeHTML()."' - Found ".$oObjSet->Count()." items.</br>\n";
self::show_list($oObjSet);
}
static protected function search_and_show_list_from_sibusql($sSibuSQL)
{
echo $sSibuSQL."...<br/>\n";
$oNewFilter = DBObjectSearch::FromSibuSQL($sSibuSQL);
self::search_and_show_list($oNewFilter);
}
}
/**
* Test to execute a scenario common to any business model (tries to build all the possible queries, etc.)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class TestBizModelGeneric extends TestBizModel
{
static public function GetName()
{
return 'Full test on a given business model';
}
static public function GetDescription()
{
return 'Systematic tests: gets each and every existing class and tries every attribute, search filters, etc.';
}
protected function DoPrepare()
{
parent::DoPrepare();
if (!MetaModel::DBExists())
{
MetaModel::DBCreate();
}
// something here to create records... but that's another story
}
protected function DoExecute()
{
foreach(MetaModel::GetClasses() as $sClassName)
{
if (MetaModel::IsAbstract($sClassName)) continue;
$oNobody = MetaModel::GetObject($sClassName, 123);
$oBaby = new $sClassName;
$oFilter = new DBObjectSearch($sClassName);
// Challenge reversibility of SibusQL / filter object
//
$sExpr1 = $oFilter->ToSibuSQL();
$oNewFilter = DBObjectSearch::FromSibuSQL($sExpr1);
$sExpr2 = $oNewFilter->ToSibuSQL();
if ($sExpr1 != $sExpr2)
{
$this->ReportError("Found two different SibuSQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
}
// Use the filter (perform the query)
//
$oSet = new CMDBObjectSet($oFilter);
$this->ReportSuccess('Found '.$oSet->Count()." objects of class $sClassName");
}
return true;
}
}
?>

View File

@@ -0,0 +1,205 @@
<?php
/**
* UserRights
* User management API
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
class UserRightException extends CoreException
{
}
define('UR_ALLOWED_NO', 0);
define('UR_ALLOWED_YES', 1);
define('UR_ALLOWED_DEPENDS', 2);
define('UR_ACTION_READ', 1); // View an object
define('UR_ACTION_MODIFY', 2); // Create/modify an object/attribute
define('UR_ACTION_DELETE', 3); // Delete an object
define('UR_ACTION_BULK_READ', 4); // Export multiple objects
define('UR_ACTION_BULK_MODIFY', 5); // Create/modify multiple objects
define('UR_ACTION_BULK_DELETE', 6); // Delete multiple objects
define('UR_ACTION_APPLICATION_DEFINED', 10000); // Application specific actions (CSV import, View schema...)
/**
* User management module API
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
abstract class UserRightsAddOnAPI
{
abstract public function Setup(); // initial installation
abstract public function Init(); // loads data (possible optimizations)
abstract public function CheckCredentials($iUserId, $sPassword); // returns the id of the user or false
abstract public function GetFilter($iUserId, $sClass); // returns a filter object
abstract public function IsActionAllowed($iUserId, $sClass, $iActionCode, dbObjectSet $aInstances);
abstract public function IsStimulusAllowed($iUserId, $sClass, $sStimulusCode, dbObjectSet $aInstances);
abstract public function IsActionAllowedOnAttribute($iUserId, $sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances);
}
/**
* User management core API
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class UserRights
{
protected static $m_oAddOn;
protected static $m_sUser;
protected static $m_sRealUser;
protected static $m_iUserId;
protected static $m_iRealUserId;
public static function SelectModule($sModuleName)
{
if (!class_exists($sModuleName))
{
trigger_error("Could not select this module, '$sModuleName' in not a valid class name", E_USER_ERROR);
return;
}
if (!is_subclass_of($sModuleName, 'UserRightsAddOnAPI'))
{
trigger_error("Could not select this module, the class '$sModuleName' is not derived from UserRightsAddOnAPI", E_USER_ERROR);
return;
}
self::$m_oAddOn = new $sModuleName;
self::$m_oAddOn->Init();
self::$m_sUser = '';
self::$m_sRealUser = '';
self::$m_iUserId = 0;
self::$m_iRealUserId = 0;
}
// Installation (e.g: give default values for users)
public static function Setup()
{
// to be discussed...
return self::$m_oAddOn->Setup();
}
protected static function IsLoggedIn()
{
return (!empty(self::$m_sUser));
}
public static function Login($sName, $sPassword)
{
self::$m_iUserId = self::$m_oAddOn->CheckCredentials($sName, $sPassword);
if ( self::$m_iUserId !== false )
{
self::$m_sUser = $sName;
self::$m_iRealUserId = self::$m_iUserId;
self::$m_sRealUser = $sName;
return true;
}
else
{
return false;
}
}
public static function Impersonate($sName, $sPassword)
{
if (!self::CheckLogin()) return false;
self::$m_iRealUserId = self::$m_oAddOn->CheckCredentials($sName, $sPassword);
if ( self::$m_iRealUserId !== false)
{
self::$m_sUser = $sName;
return true;
}
else
{
return false;
}
}
public static function GetUser()
{
return self::$m_sUser;
}
public static function GetUserId()
{
return self::$m_iUserId;
}
public static function GetRealUser()
{
return self::$m_sRealUser;
}
public static function GetRealUserId()
{
return self::$m_iRealUserId;
}
protected static function CheckLogin()
{
if (!self::IsLoggedIn())
{
//throw new UserRightException('No user logged in', array());
return false;
}
return true;
}
public static function GetFilter($sClass)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return new DBObjectSearch($sClass);
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->GetFilter(self::$m_iUserId, $sClass);
}
public static function IsActionAllowed($sClass, $iActionCode, dbObjectSet $aInstances)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return true;
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->IsActionAllowed(self::$m_iUserId, $sClass, $iActionCode, $aInstances);
}
public static function IsStimulusAllowed($sClass, $sStimulusCode, dbObjectSet $aInstances)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return true;
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->IsStimulusAllowed(self::$m_iUserId, $sClass, $sStimulusCode, $aInstances);
}
public static function IsActionAllowedOnAttribute($sClass, $sAttCode, $iActionCode, dbObjectSet $aInstances)
{
if (!MetaModel::HasCategory($sClass, 'bizModel')) return true;
if (!self::CheckLogin()) return false;
return self::$m_oAddOn->IsActionAllowedOnAttribute(self::$m_iUserId, $sClass, $sAttCode, $iActionCode, $aInstances);
}
}
?>

View File

@@ -0,0 +1,238 @@
<?php
/**
* ValueSetDefinition
* value sets API and implementations
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @author Denis Flaven <denisflave@free.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version 1.1.1.1 $
*/
require_once('MyHelpers.class.inc.php');
abstract class ValueSetDefinition
{
protected $m_bIsLoaded = false;
protected $m_aValues = array();
protected $m_aArgsObj = array();
protected $m_aArgsApp = array();
// Displayable description that could be computed out of the std usage context
public function GetValuesDescription()
{
$aValues = $this->GetValues(array(), '');
$aDisplayedValues = array();
foreach($aValues as $key => $value)
{
$aDisplayedValues[] = "$key => $value";
}
$sAllowedValues = implode(', ', $aDisplayedValues);
return $sAllowedValues;
}
public function GetValues($aArgs, $sBeginsWith)
{
if (!$this->m_bIsLoaded)
{
$this->LoadValues($aArgs);
$this->m_bIsLoaded = true;
}
if (strlen($sBeginsWith) == 0)
{
$aRet = $this->m_aValues;
}
else
{
$iCheckedLen = strlen($sBeginsWith);
$sBeginsWith = strtolower($sBeginsWith);
$aRet = array();
foreach ($this->m_aValues as $sKey=>$sValue)
{
if (strtolower(substr($sValue, 0, $iCheckedLen)) == $sBeginsWith)
{
$aRet[$sKey] = $sValue;
}
}
}
return $aRet;
}
public function ListArgsFromContextApp()
{
return $this->m_aArgsObj;
}
public function ListArgsFromContextObj()
{
return $this->m_aArgsApp;
}
abstract protected function LoadValues($aArgs);
}
/**
* Set of existing values for an attribute, given a search filter
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class ValueSetObjects extends ValueSetDefinition
{
protected $m_sFilterExpr; // in SibuSQL
protected $m_sValueAttCode;
protected $m_aOrderBy;
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array())
{
$this->m_sFilterExpr = $sFilterExp;
$this->m_sValueAttCode = $sValueAttCode;
$this->m_aOrderBy = $aOrderBy;
}
protected function LoadValues($aArgs)
{
$this->m_aValues = array();
$oFilter = DBObjectSearch::FromSibuSQL($this->m_sFilterExpr, $aArgs);
if (!$oFilter) return false;
if (empty($this->m_sValueAttCode))
{
$this->m_sValueAttCode = MetaModel::GetNameAttributeCode($oFilter->GetClass());
}
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy);
while ($oObject = $oObjects->Fetch())
{
$this->m_aValues[$oObject->GetKey()] = $oObject->GetAsHTML($this->m_sValueAttCode);
}
return true;
}
public function GetValuesDescription()
{
return 'Filter: '.$this->m_sFilterExpr;
}
}
/**
* Set of existing values for an attribute, given a search filter and a relation id
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class ValueSetRelatedObjects extends ValueSetObjects
{
public function __construct($sFilterExp, $sRelCode, $sClass, $sValueAttCode = '', $aOrderBy = array())
{
$sFullFilterExp = "$sClass: RELATED ($sRelCode, 1) TO ($sFilterExp)";
parent::__construct($sFullFilterExp, $sValueAttCode, $aOrderBy);
}
}
/**
* Set oof existing values for an attribute, given a set of objects (AttributeLinkedSet)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class ValueSetRelatedObjectsFromLinkedSet extends ValueSetDefinition
{
protected $m_sLinkedSetAttCode;
protected $m_sRelCode;
protected $m_sValueAttCode;
protected $m_aOrderBy;
public function __construct($sLinkedSetAttCode, $sRelCode, $sValueAttCode = '', $aOrderBy = array())
{
$this->m_sLinkedSetAttCode = $sLinkedSetAttCode;
$this->m_sRelCode = $sRelCode;
$this->m_sValueAttCode = $sValueAttCode;
$this->m_aOrderBy = $aOrderBy;
}
protected function LoadValues($aArgs)
{
$this->m_aValues = array();
if (empty($this->m_sValueAttCode))
{
$this->m_sValueAttCode = MetaModel::GetNameAttributeCode($oFilter->GetClass());
}
$oCurrentObject = @$aArgs['*this*'];
if (!is_object($oCurrentObject)) return false;
$oObjects = $oCurrentObject->Get($this->m_sLinkedSetAttCode);
while ($oObject = $oObjects->Fetch())
{
$this->m_aValues[$oObject->GetKey()] = $oObject->Get($this->m_sValueAttCode);
}
return true;
}
public function GetValuesDescription()
{
return 'Objects related ('.$this->m_sRelCode.') to objects linked through '.$this->m_sLinkedSetAttCode;
}
}
/**
* Fixed set values (could be hardcoded in the business model)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class ValueSetEnum extends ValueSetDefinition
{
public function __construct($Values)
{
if (is_array($Values))
{
$aValues = $Values;
}
else
{
$aValues = array();
foreach (explode(",", $Values) as $sVal)
{
$sVal = trim($sVal);
$sKey = $sVal;
$aValues[$sKey] = $sVal;
}
}
$this->m_aValues = $aValues;
}
protected function LoadValues($aArgs)
{
return true;
}
}
?>

222
css/blue_green.css Normal file
View File

@@ -0,0 +1,222 @@
/* CSS Document */
body {
font-family: Verdana, Arial, Helevtica;
font-size: smaller;
background-color: #68a;
color:#000000;
margin: 0; /* Remove body margin/padding */
padding: 0;
overflow: hidden; /* Remove scroll bars on browser window */
}
table {
border: 1px solid #000000;
}
.raw_output {
font-family: Courier-New, Courier, Arial, Helevtica;
font-size: smaller;
background-color: #eeeeee;
color: #000000;
border: 1px dashed #000000;
padding: 0.25em;
margin-top: 1em;
}
th {
font-family: Verdana, Arial, Helvetica;
font-size: smaller;
color: #000000;
background-color:#ace27d;
}
td {
font-family: Verdana, Arial, Helvetica;
font-size: smaller;
background-color: #b7cfe8;
}
tr.clicked td {
font-family: Verdana, Arial, Helvetica;
font-size: smaller;
background-color: #ffcfe8;
}
td.label {
font-family: Verdana, Arial, Helvetica;
font-size: smaller;
color: #000000;
background-color:#ace27d;
padding: 0.2em;
}
td a, td a:visited {
text-decoration:none;
color:#000000;
}
td a:hover {
text-decoration:underline;
color:#FFFFFF;
}
a.small_action {
font-family: Verdana, Arial, Helvetica;
font-size: smaller;
color: #000000;
text-decoration:none;
}
.display_block {
noborder: 1px dashed #CCC;
background: #79b;
padding:0.25em;
}
div#TopPane .display_block {
background: #f0eee0;
padding:0.25em;
text-align:center;
}
div#TopPane label {
color:#000;
background: #f0eee0;
}
div#TopPane td {
color:#000;
background: #f0eee0;
}
.loading {
noborder: 1px dashed #CCC;
background: #b9c1c8;
padding:0.25em;
}
label {
font-family:Georgia, "Times New Roman", Times, serif;
color:#FFFFFF;
text-align:right;
}
input.textSearch {
border:1px solid #333;
noheight:1.2em;
font-size:0.8em;
font-family:Verdana, Arial, Helvetica, sans-serif;
color:#000000;
}
/* By Rom */
.csvimport_createobj {
color: #AA0000;
background-color:#EEEEEE;
}
.csvimport_error {
font-weight: bold;
color: #FF0000;
background-color:#EEEEEE;
}
.csvimport_warning {
color: #CC8888;
background-color:#EEEEEE;
}
.csvimport_ok {
color: #00000;
background-color:#BBFFBB;
}
.csvimport_reconkey {
font-style: italic;
color: #888888;
background-color:#FFFFF;
}
.csvimport_extreconkey {
color: #888888;
background-color:#FFFFFF;
}
.treeview, .treeview ul {
padding: 0;
margin: 0;
list-style: none;
}
.treeview li {
margin: 0;
padding: 3px 0pt 3px 16px;
font-size:0.9em;
}
ul.dir li {
padding: 2px 0 0 16px;
}
.treeview li { background: url(../images/tv-item.gif) 0 0 no-repeat; }
.treeview .collapsable { background-image: url(/images/tv-collapsable.gif); }
.treeview .expandable { background-image: url(/images/tv-expandable.gif); }
.treeview .last { background-image: url(/images/tv-item-last.gif); }
.treeview .lastCollapsable { background-image: url(/images/tv-collapsable-last.gif); }
.treeview .lastExpandable { background-image: url(/images/tv-expandable-last.gif); }
#Header { padding: 0; background:#ccc url(/images/bandeau2.gif) repeat-x center;}
div.iTopLogo {
background:url(/images/iTop.gif) no-repeat center;
width:100px;
height:56px;
}
div.iTopLogo span {
display:none;
}
#MySplitter {
/* Height is set to match window size in $().ready() below */
border:0px;
margin:4px;
padding:0px;
min-width: 100px; /* Splitter can't be too thin ... */
min-height: 100px; /* ... or too flat */
}
#LeftPane {
background: #f0eee0;
padding: 4px;
overflow: auto; /* Scroll bars appear as needed */
color:#666;
}
#TopPane { /* Top nested in right pane */
background: #f0eee0;
padding: 4px;
height: 150px; /* Initial height */
min-height: 75px; /* Minimum height */
overflow: auto;
color:#666;
}
#RightPane { /* Bottom nested in right pane */
background: #79b;
height:150px; /* Initial height */
min-height:130px;
no.padding:15px;
no.margin:10px;
overflow:auto;
color:#fff;
}
#BottomPane { /* Bottom nested in right pane */
background: #79b;
padding: 4px;
overflow: auto;
color:#fff;
}
#MySplitter .vsplitbar {
width: 7px;
height: 50px;
background: #68a url(/images/vgrabber2.gif) no-repeat center;
}
#MySplitter .vsplitbar.active, #MySplitter .vsplitbar:hover {
background: #68a url(/images/vgrabber2_active.gif) no-repeat center;
}
#MySplitter .hsplitbar {
height: 8px;
background: #68a url(/images/hgrabber2.gif) no-repeat center;
}
#MySplitter .hsplitbar.active, #MySplitter .hsplitbar:hover {
background: #68a url(/images/hgrabber2_active.gif) no-repeat center;
}

117
css/date.picker.css Normal file
View File

@@ -0,0 +1,117 @@
table.jCalendar {
border: 1px solid #000;
background: #aaa;
border-collapse: separate;
border-spacing: 2px;
}
table.jCalendar th {
background: #333;
color: #fff;
font-weight: bold;
padding: 3px 5px;
}
table.jCalendar td {
background: #ccc;
color: #000;
padding: 3px 5px;
text-align: center;
}
table.jCalendar td.other-month {
background: #ddd;
color: #aaa;
}
table.jCalendar td.today {
background: #666;
color: #fff;
}
table.jCalendar td.selected {
background: #f66;
color: #fff;
}
table.jCalendar td.selected:hover {
background: #f33;
color: #fff;
}
table.jCalendar td:hover, table.jCalendar td.dp-hover {
background: #fff;
color: #000;
}
table.jCalendar td.disabled, table.jCalendar td.disabled:hover {
background: #bbb;
color: #888;
}
/* For the popup */
/* NOTE - you will probably want to style a.dp-choose-date - see how I did it in demo.css */
div.dp-popup {
position: relative;
background: #ccc;
font-size: 10px;
font-family: arial, sans-serif;
padding: 2px;
width: 171px;
line-height: 1.2em;
}
div#dp-popup {
position: absolute;
z-index: 199;
}
div.dp-popup h2 {
font-size: 12px;
text-align: center;
margin: 2px 0;
padding: 0;
}
a#dp-close {
font-size: 11px;
padding: 4px 0;
text-align: center;
display: block;
}
a#dp-close:hover {
text-decoration: underline;
}
div.dp-popup a {
color: #000;
text-decoration: none;
padding: 3px 2px 0;
}
div.dp-popup div.dp-nav-prev {
position: absolute;
top: 2px;
left: 4px;
width: 100px;
}
div.dp-popup div.dp-nav-prev a {
float: left;
}
/* Opera needs the rules to be this specific otherwise it doesn't change the cursor back to pointer after you have disabled and re-enabled a link */
div.dp-popup div.dp-nav-prev a, div.dp-popup div.dp-nav-next a {
cursor: pointer;
}
div.dp-popup div.dp-nav-prev a.disabled, div.dp-popup div.dp-nav-next a.disabled {
cursor: default;
}
div.dp-popup div.dp-nav-next {
position: absolute;
top: 2px;
right: 4px;
width: 100px;
}
div.dp-popup div.dp-nav-next a {
float: right;
}
div.dp-popup a.disabled {
cursor: default;
color: #aaa;
}
div.dp-popup td {
cursor: pointer;
}
div.dp-popup td.disabled {
cursor: default;
}

165
css/default.css Normal file
View File

@@ -0,0 +1,165 @@
/* CSS Document */
body {
font-family: Verdana, Arial, Helevtica;
font-size: smaller;
background-color: #ffffff;
color:#000000;
margin: 0; /* Remove body margin/padding */
padding: 0;
overflow: hidden; /* Remove scroll bars on browser window */
}
table {
border: 1px solid #000000;
}
.raw_output {
font-family: Courier-New, Courier, Arial, Helevtica;
font-size: smaller;
background-color: #eeeeee;
color: #000000;
border: 1px dashed #000000;
padding: 0.25em;
margin-top: 1em;
}
th {
font-family: Verdana, Arial, Helevtica;
font-size: smaller;
color: #000000;
background-color:#E1DEB5;
}
td {
font-family: Verdana, Arial, Helevtica;
font-size: smaller;
}
td.label {
font-family: Verdana, Arial, Helevtica;
font-size: smaller;
color: #000000;
background-color:#E1DEB5;
padding: 0.2em;
}
a.small_action {
font-family: Verdana, Arial, Helvetica;
font-size: smaller;
color: #000000;
text-decoration:none;
}
.display_block {
border: 1px dashed #CCC;
background: #CFC;
padding:0.25em;
}
.loading {
border: 1px dashed #CCC;
background: #FCC;
padding:0.25em;
}
/* By Rom */
.csvimport_createobj {
color: #AA0000;
background-color:#EEEEEE;
}
.csvimport_error {
font-weight: bold;
color: #FF0000;
background-color:#EEEEEE;
}
.csvimport_warning {
color: #CC8888;
background-color:#EEEEEE;
}
.csvimport_ok {
color: #00000;
background-color:#BBFFBB;
}
.csvimport_reconkey {
font-style: italic;
color: #888888;
background-color:#FFFFF;
}
.csvimport_extreconkey {
color: #888888;
background-color:#FFFFFF;
}
.treeview, .treeview ul {
padding: 0;
margin: 0;
list-style: none;
}
.treeview li {
margin: 0;
padding: 3px 0pt 3px 16px;
}
ul.dir li { padding: 2px 0 0 16px; }
.treeview li { background: url(../images/tv-item.gif) 0 0 no-repeat; }
.treeview .collapsable { background-image: url(../images/tv-collapsable.gif); }
.treeview .expandable { background-image: url(../images/tv-expandable.gif); }
.treeview .last { background-image: url(../images/tv-item-last.gif); }
.treeview .lastCollapsable { background-image: url(../images/tv-collapsable-last.gif); }
.treeview .lastExpandable { background-image: url(../images/tv-expandable-last.gif); }
#MySplitter {
/* Height is set to match window size in $().ready() below */
border:0px;
margin:4px;
padding:0px;
min-width: 100px; /* Splitter can't be too thin ... */
min-height: 100px; /* ... or too flat */
}
#LeftPane {
background: #f0eee0;
padding: 4px;
overflow: auto; /* Scroll bars appear as needed */
color:#666;
}
#TopPane { /* Top nested in right pane */
background: #f0eee0;
padding: 4px;
height: 150px; /* Initial height */
min-height: 75px; /* Minimum height */
overflow: auto;
color:#666;
}
#RightPane { /* Bottom nested in right pane */
background: #79b;
height:150px; /* Initial height */
min-height:130px;
no.padding:15px;
no.margin:10px;
overflow:auto;
color:#fff;
}
#BottomPane { /* Bottom nested in right pane */
background: #79b;
padding: 4px;
overflow: auto;
color:#fff;
}
#MySplitter .vsplitbar {
width: 7px;
height: 50px;
background: #68a url(../images/vgrabber2.gif) no-repeat center;
}
#MySplitter .vsplitbar.active, #MySplitter .vsplitbar:hover {
background: #68a url(../images/vgrabber2_active.gif) no-repeat center;
}
#MySplitter .hsplitbar {
height: 8px;
background: #68a url(../images/hgrabber2.gif) no-repeat center;
}
#MySplitter .hsplitbar.active, #MySplitter .hsplitbar:hover {
background: #68a url(../images/hgrabber2_active.gif) no-repeat center;
}

40
css/jqModal.css Normal file
View File

@@ -0,0 +1,40 @@
/* jqModal base Styling courtesy of;
Brice Burgess <bhb@iceburg.net> */
/* The Window's CSS z-index value is respected (takes priority). If none is supplied,
the Window's z-index value will be set to 3000 by default (in jqModal.js). You
can change this value by either;
a) supplying one via CSS
b) passing the "zIndex" parameter. E.g. (window).jqm({zIndex: 500}); */
.jqmWindow {
display: none;
position: fixed;
top: 10%;
left: 20%;
margin-left: -100px;
width: 800px;
background-color: #FFF;
color: #333;
border: 1px solid black;
padding: 12px;
}
.jqmOverlay { background-color: #333; }
/* Background iframe styling for IE6. Prevents ActiveX bleed-through (<select> form elements, etc.) */
* removed.iframe.jqm {position:absolute;top:0;left:0;z-index:-1;
width: expression(this.parentNode.offsetWidth+'px');
height: expression(this.parentNode.offsetHeight+'px');
}
/* Fixed posistioning emulation for IE6
Star selector used to hide definition from browsers other than IE6
For valid CSS, use a conditional include instead */
* removed.html .jqmWindow {
position: absolute;
top: expression((document.documentElement.scrollTop || document.body.scrollTop) + Math.round(17 * (document.documentElement.offsetHeight || document.body.clientHeight) / 100) + 'px');
}

View File

@@ -0,0 +1,46 @@
.ac_results {
padding: 0px;
border: 1px solid WindowFrame;
background-color: Window;
overflow: hidden;
}
.ac_results ul {
width: 100%;
list-style-position: outside;
list-style: none;
padding: 0;
margin: 0;
}
.ac_results iframe {
display:none;/*sorry for IE5*/
display/**/:block;/*sorry for IE5*/
position:absolute;
top:0;
left:0;
z-index:-1;
filter:mask();
width:3000px;
height:3000px;
}
.ac_results li {
margin: 0px;
padding: 2px 5px;
cursor: pointer;
display: block;
width: 100%;
font: menu;
font-size: 12px;
overflow: hidden;
}
.ac_loading {
background : Window url('../images/indicator.gif') right center no-repeat;
}
.ac_over {
background-color: Highlight;
color: HighlightText;
}

15
css/jquery.tabs-ie.css Normal file
View File

@@ -0,0 +1,15 @@
/*
Tabs - additional IE specific bug fixes
Recommended usage (Conditional Comments):
<!--[if lte IE 7]>
<link rel="stylesheet" href="tabs_ie.css" type="text/css" media="projection, screen" />
<![endif]-->
*/
.tabs-nav { /* auto clear */
display: inline-block;
}
.tabs-nav .tabs-disabled a {
filter: alpha(opacity=40);
}

76
css/jquery.tabs.css Normal file
View File

@@ -0,0 +1,76 @@
/* Caution! Ensure accessibility in print and other media types... */
@media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
.tabs-hide {
display: none;
}
}
/* Hide useless elements in print layouts... */
@media print {
.tabs-nav {
display: none;
}
}
/* Skin */
.tabs-nav {
list-style: none;
margin: 0;
padding: 0 0 0 4px;
}
.tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */
display: block;
clear: both;
content: " ";
}
.tabs-nav li {
float: left;
margin: 0 0 0 1px;
}
.tabs-nav a {
display: block;
position: relative;
top: 1px;
z-index: 2;
padding: 6px 10px 0;
width: 64px;
height: 18px;
color: #27537a;
font-size: 12px;
font-weight: bold;
line-height: 1.2;
text-align: center;
text-decoration: none;
background: url(../images/tab.png) no-repeat;
}
.tabs-nav .tabs-selected a {
padding-top: 7px;
color: #000;
}
.tabs-nav .tabs-selected a, .tabs-nav a:hover, .tabs-nav a:focus, .tabs-nav a:active {
background-position: 0 -50px;
outline: 0; /* @ Firefox, switch off dotted border */
}
.tabs-nav .tabs-disabled a:hover, .tabs-nav .tabs-disabled a:focus, .tabs-nav .tabs-disabled a:active {
background-position: 0 0;
}
.tabs-nav .tabs-selected a:link, .tabs-nav .tabs-selected a:visited,
.tabs-nav .tabs-disabled a:link, .tabs-nav .tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */
cursor: text;
}
.tabs-nav a:hover, .tabs-nav a:focus, .tabs-nav a:active { /* @ Opera, we need to be explicit again here now... */
cursor: pointer;
}
.tabs-nav .tabs-disabled {
opacity: .4;
}
.tabs-container {
border-top: 1px solid #97a5b0;
padding: 1em 8px;
background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */
}
/* Uncomment this if you want a little spinner to be shown next to the tab title while an Ajax tab gets loaded
.tabs-loading span {
padding: 0 0 0 20px;
background: url(loading.gif) no-repeat 0 50%;
}*/

47
css/jquery.treeview.css Normal file
View File

@@ -0,0 +1,47 @@
.treeview ul { background-color: white; }
.treeview, .treeview ul {
padding: 0;
margin: 0;
list-style: none;
}
.treeview div.hitarea {
height: 15px;
width: 15px;
margin-left: -15px;
float: left;
cursor: pointer;
}
/* fix for IE6 */
* html div.hitarea {
background: #fff;
filter: alpha(opacity=0);
display: inline;
float:none;
}
.treeview li {
margin: 0;
padding: 3px 0pt 3px 16px;
}
.treeview a.selected {
background-color: #eee;
}
#treecontrol { margin: 1em 0; }
.treeview .hover { color: red; cursor: pointer; }
.treeview li { background: url(/images/tv-item.gif) 0 0 no-repeat; }
.treeview .collapsable { background-image: url(/images/tv-collapsable.gif); }
.treeview .expandable { background-image: url(/images/tv-expandable.gif); }
.treeview .last { background-image: url(/images/tv-item-last.gif); }
.treeview .lastCollapsable { background-image: url(/images/tv-collapsable-last.gif); }
.treeview .lastExpandable { background-image: url(/images/tv-expandable-last.gif); }
.filetree li { padding: 3px 0 1px 16px; }
.filetree span.folder, .filetree span.file { padding-left: 16px; display: block; height: 15px; }
.filetree span.folder { background: url(/images/folder.gif) 0 0 no-repeat; }
.filetree span.file { background: url(/images/file.gif) 0 0 no-repeat; }

633
css/light-grey.css Normal file
View File

@@ -0,0 +1,633 @@
/* CSS Document */
body {
font-family: Tahoma, Verdana, Arial, Helevtica;
font-size: 8pt;
background-color: #fff;
color:#000000;
margin: 0; /* Remove body margin/padding */
padding: 0;
overflow: hidden; /* Remove scroll bars on browser window */
}
.raw_output {
font-family: Courier-New, Courier, Arial, Helevtica;
font-size: 8pt;
background-color: #eeeeee;
color: #000000;
border: 1px dashed #000000;
padding: 0.25em;
margin-top: 1em;
}
h1 {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 10pt;
color: #000;
font-weight:10px;
}
.hilite {
color: #d81515;
}
table.listResults {
padding: 0px;
border-top: 3px solid #f6f6f1;
border-left: 3px solid #f6f6f1;
border-bottom: 3px solid #e6e6e1;
border-right: 3px solid #e6e6e1;
width: 100%;
}
table.listResults td {
padding: 2px;
}
table.listContainer {
border: 0;
padding: 0;
margin:0;
width: 97%;
}
tr.containerHeader, tr.containerHeader td {
background: transparent;
}
tr.even td {
background-color: #f9f9f1;
}
tr td.hover, tr.even td.hover, .hover a, .hover a:visited, .hover a:hover {
background-color: #E8FFD3;
}
th {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 8pt;
color: #d81515;
height:20px;
background: #f6f6f1 url(../images/grey-header.gif) bottom repeat-x;
}
th.header {
cursor: pointer;
}
th.headerSortUp, th.headerSortDown {
text-decoration: underline;
cursor: pointer;
}
td {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 8pt;
color:#696969;
background-color: #ffffff;
padding: 0px;
}
tr.clicked td {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: smaller;
background-color: #ffcfe8;
}
td.label {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 8pt;
color: #000000;
background-color:#f6f6f6;
padding: 0.25em;
font-weight:bold;
}
td a, td a:visited {
text-decoration:none;
color:#000000;
padding-left:14px;
background: url(../images/red-arrow.gif) no-repeat left;
}
td a:hover {
text-decoration:underline;
color:#d81515;
padding-left:14px;
background: url(../images/red-arrow.gif) no-repeat left;
}
td a.no-arrow, td a.no-arrow:visited {
text-decoration:none;
color:#000000;
padding-left:0px;
background: inherit;
}
td a.no-arrow:hover {
text-decoration:underline;
color:#d81515;
padding-left:0px;
background: inherit;
}
a.small_action {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 8pt;
color: #000000;
text-decoration:none;
}
.display_block {
noborder: 1px dashed #CCC;
padding:0.25em;
}
div#TopPane .display_block {
background: #fff;
padding:0.25em;
text-align:center;
}
div#TopPane label {
color:#000;
background: #fff;
}
div#TopPane td {
color:#000;
background: #fff;
}
.actions_details {
float:right;
margin-top:10px;
margin-right:10px;
padding-left: 5px;
padding-top: 2px;
padding-bottom: 2px;
background: url(../images/actions_left.png) no-repeat left;
}
.actions_details span{
background: url(../images/actions_right.png) no-repeat right;
color: #fff;
font-weight: bold;
padding-top: 2px;
padding-bottom: 2px;
padding-right: 12px;
}
.actions_details a {
text-decoration:none;
}
.loading {
noborder: 1px dashed #CCC;
background: #b9c1c8;
padding:0.25em;
}
input.textSearch {
border:1px solid #000;
noheight:1.2em;
font-size:8pt;
font-family:Tahoma,Verdana, Arial, Helvetica, sans-serif;
color:#000000;
}
/* By Rom */
.csvimport_createobj {
color: #AA0000;
background-color:#EEEEEE;
}
.csvimport_error {
font-weight: bold;
color: #FF0000;
background-color:#EEEEEE;
}
.csvimport_warning {
color: #CC8888;
background-color:#EEEEEE;
}
.csvimport_ok {
color: #00000;
background-color:#BBFFBB;
}
.csvimport_reconkey {
font-style: italic;
color: #888888;
background-color:#FFFFF;
}
.csvimport_extreconkey {
color: #888888;
background-color:#FFFFFF;
}
ul.dir {
list-style:none;
}
ul.dir ul {
padding: 8px 0px 8px 16px;
margin:0;
list-style:none;
border: 0;
}
ul.dir li a, ul.dir li a:visited, ul.dir li a:hover{
noborder-top: 1px solid #8b8b8b;
padding: 4px 0px 0px 16px;
font-size:8pt;
background: url(../images/green-square.gif) no-repeat bottom left;
color:#83b217;
font-weight:bold;
text-decoration:none;
}
ul.dir li li a, ul.dir li li a:visited, ul.dir li li a:hover {
color:#8b8b8b;
text-decoration:none;
margin: 0;
padding: 0px 0pt 0px 16px;
font-size:8pt;
background: url(../images/mini-arrow-green.gif) no-repeat left;
font-weight:normal;
border: 0;
}
a.CollapsibleLabel, td a.CollapsibleLabel {
margin: 0;
padding: 0px 0pt 0px 16px;
font-size:8pt;
text-decoration:none;
color:#8b8b8b;
background: url(../images/mini-arrow-green.gif) no-repeat left;
}
a.CollapsibleLabel.open, td a.CollapsibleLabel.open {
margin: 0;
padding: 0px 0pt 0px 16px;
font-size:8pt;
text-decoration:none;
color:red;
background: url(../images/mini-arrow-green-open.gif) no-repeat left;
}
.page_header {
background-color:#f6f6f1;
padding:5px;
}
.notreeview li { background: url(../images/tv-item.gif) 0 0 no-repeat; }
.notreeview .collapsable { background-image: url(../images/tv-collapsable.gif); }
.notreeview .expandable { background-image: url(../images/tv-expandable.gif); }
.notreeview .last { background-image: url(../images/tv-item-last.gif); }
.notreeview .lastCollapsable { background-image: url(../images/tv-collapsable-last.gif); }
.notreeview .lastExpandable { background-image: url(../images/tv-expandable-last.gif); }
#Header { padding: 0; background:#ccc url(../images/bandeau3.gif) repeat-x center;}
div.iTopLogo {
background:url(../images/iTop2.gif) no-repeat center;
width:150px;
height:56px;
}
div.iTopLogo span {
display:none;
}
#MySplitter {
/* Height is set to match window size in $().ready() below */
border:0px;
margin:4px;
padding:0px;
min-width: 100px; /* Splitter can't be too thin ... */
min-height: 100px; /* ... or too flat */
}
#LeftPane {
background: #f6f6f1 url(../images/left-border.gif) repeat-y top left;
padding: 16px;
overflow: auto; /* Scroll bars appear as needed */
color:#000;
}
#TopPane { /* Top nested in right pane */
background: #fff;
padding: 4px;
height: 150px; /* Initial height */
min-height: 75px; /* Minimum height */
overflow: auto;
color:#000;
}
#RightPane { /* Bottom nested in right pane */
background: #fff;
height:150px; /* Initial height */
min-height:130px;
no.padding:15px;
no.margin:10px;
overflow:auto;
color:#000000;
padding-left:10px;
}
#BottomPane { /* Bottom nested in right pane */
background: #fff;
padding: 4px;
overflow: auto;
color:#000;
}
#MySplitter .vsplitbar {
width: 9px;
height: 50px;
background: url(../images/vsplitter-grey.gif) repeat top;
}
#MySplitter .vsplitbar.active, #MySplitter .vsplitbar:hover {
background-color: #fff;
}
#MySplitter .hsplitbar {
height: 8px;
background-color: #fff;
}
#MySplitter .hsplitbar.active, #MySplitter .hsplitbar:hover {
background-color: #fff;
}
#OrganizationSelection {
padding:5px 0px 16px 40px;
}
/* jdMenu popup menus */
ul.jd_menu,
ul.jd_menu_vertical {
margin: 0px;
padding: 0px;
list-style-type: none;
}
ul.jd_menu ul,
ul.jd_menu_vertical ul {
display: none;
}
ul.jd_menu li {
float: left;
}
/* -- Sub-Menus -- */
ul.jd_menu ul,
ul.jd_menu_vertical ul {
position: absolute;
display: none;
list-style-type: none;
margin: 0px;
padding: 0px;
z-index: 10000;
}
ul.jd_menu ul li,
ul.jd_menu_vertical ul li {
float: none;
margin: 0px;
}
/* jdMenu popup menus styling */
div.jd_menu_itop {
height:19px;
float:right;
display:inline;
width:70px; /* Nasty work-around for IE... en attendant mieux */
padding-left: 5px;
background: url(../images/actions_left.png) no-repeat left;
}
ul.jd_menu_itop {
height: 19px;
padding-right:16px;
background: url(../images/actions_right.png) no-repeat right;
font-weight: bold;
}
ul.jd_menu_vertical {
width: 200px;
height: auto;
clear: both;
background: url(gradient-vertical.png) repeat-x;
background-color: #A5AFB8;
}
ul.jd_menu_itop a,
ul.jd_menu_itop a:active,
ul.jd_menu_itop a:link,
ul.jd_menu_itop a:visited {
text-decoration: none;
color: #FFF;
}
ul.jd_menu_itop ul li a,
ul.jd_menu_itop ul li a:active,
ul.jd_menu_itop ul li a:link,
ul.jd_menu_itop ul li a:visited {
color: #000;
}
ul.jd_menu_itop li {
font-family: Tahoma, sans-serif;
font-size: 11px;
padding: 2px 6px 4px 6px;
cursor: pointer;
white-space: nowrap;
color: #FFF;
}
ul.jd_menu_itop li.jd_menu_active_menubar,
ul.jd_menu_itop li.jd_menu_hover_menubar {
color: #FFF;
}
ul.jd_menu_vertical li.jd_menu_active_menubar,
ul.jd_menu_vertical li.jd_menu_hover_menubar {
padding-left: 6px;
padding-top: 1px;
border-top: 1px solid #70777D;
border-left: 0px;
border-right: 0px;
}
ul.jd_menu_itop ul {
background: #d81515;
border: 1px solid #70777D;
}
ul.jd_menu_itop ul li {
padding: 3px 10px 3px 4px;
background: #FFF;
border: none;
color: #000;
}
ul.jd_menu_itop ul li.jd_menu_active,
ul.jd_menu_itop ul li.jd_menu_hover {
background: #d81515;
padding-top: 2px;
border-top: 1px solid #ABB5BC;
padding-bottom: 2px;
border-bottom: 1px solid #929AA1;
color: #FFF;
}
ul.jd_menu_itop li ul li a {
padding: 0;
background: #fff;
padding-left:0;
}
ul.jd_menu_itop ul li.jd_menu_active a.jd_menu_active,
ul.jd_menu_itop ul li.jd_menu_hover a.jd_menu_hover {
color: #FFF;
background: #d81515;
padding-left:0;
}
.wizHeader {
background: #83b217;
padding: 15px;
}
.wizSeparator {
float:left;
background: #83b217;
height: 29px;
margin-top: 5px;
}
div.wizActiveStep {
height: 29px;
background: url(/images/wizActiveStepLeft.gif) no-repeat left;
color: #d81515;
padding-left: 8px;
margin-top: 5px;
vertical-align: middle;
float: left;
}
div.wizActiveStep span {
height: 29px;
background: url(/images/wizActiveStepRight.gif) no-repeat top right;
padding-right: 8px;
padding-top: 8px;
float:left;
}
div.wizStep {
height: 29px;
background: url(/images/wizStepLeft.gif) no-repeat left;
padding-left: 8px;
vertical-align: middle;
margin-top: 5px;
float:left;
}
div.wizStep span {
height: 29px;
background: url(/images/wizStepRight.gif) no-repeat top right;
padding-right: 8px;
padding-top: 8px;
float:left;
}
.wizContainer {
border: 5px solid #83b217;
background: #e8f3cf;
padding: 5px;
}
.alignRight {
text-align: right;
padding: 3px;
}
.alignLeft {
text-align: left;
padding: 3px;
}
.red {
background-color: #ff6000;
color: #000;
}
th.red {
background: url(../images/red-header.gif) bottom left repeat-x;
color: #000;
}
.green {
background-color: #00cc00;
color: #000;
}
th.green {
background: url(../images/green-header.gif) bottom left repeat-x;
color: #000;
}
.orange {
background-color: #ffde00;
color: #000;
}
th.orange {
background: url(../images/orange-header.gif) bottom left repeat-x;
color: #000;
}
/* For Date Picker: Creates a little calendar icon
* instead of a text link for "Choose date"
*/
a.dp-choose-date, a.dp-choose-date:hover {
float: left;
width: 16px;
height: 16px;
padding: 0;
margin: 5px 3px 0;
display: block;
text-indent: -2000px;
overflow: hidden;
background: url(../images/calendar.png) no-repeat;
}
a.dp-choose-date.dp-disabled {
background-position: 0 -20px;
cursor: default;
}
/* For Date Picker: makes the input field shorter once the date picker code
* has run (to allow space for the calendar icon)
*/
input.dp-applied {
width: 140px;
float: left;
}
/* For search forms */
.SearchDrawer {
background: #83b217 url(../images/green-corner.png) top left no-repeat;
color: #fff;
padding: 10px;
margin: 0;
}
.SearchDrawer form table tbody tr td {
background: #83b217;
color: #fff;
}
.SearchDrawer label {
background: #83b217;
color: #fff;
padding-left: 10px;
}
.SearchDrawer h1 {
color: #fff;
}
.DrawerClosed {
display: none;
}
.DrawerHandle {
margin: 0;
padding: 5px;
background: #fff url(../images/drawer-handle.gif) bottom no-repeat;
color: #fff;
cursor: pointer;
text-align: center;
/* center the block */
width: 100px;
margin-left: auto;
margin-right: auto;
margin-top: 0;
margin-bottom: 0;
display: block;
}
div.HRDrawer {
height: 5px;
width: 100%;
margin: 0;
background-color: #83b217;
margin: 0;
padding: 0;
border: 0;
display: block;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

BIN
images/Thumbs.db Normal file

Binary file not shown.

BIN
images/WanLinks.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
images/actions_left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

BIN
images/actions_right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

BIN
images/bandeau2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/bandeau3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

BIN
images/blue-corner.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

BIN
images/bomb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
images/bomb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
images/calendar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
images/charts.swf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More