summaryrefslogtreecommitdiffstats
path: root/codebase/connector/dataprocessor.php
diff options
context:
space:
mode:
Diffstat (limited to 'codebase/connector/dataprocessor.php')
-rw-r--r--codebase/connector/dataprocessor.php505
1 files changed, 505 insertions, 0 deletions
diff --git a/codebase/connector/dataprocessor.php b/codebase/connector/dataprocessor.php
new file mode 100644
index 0000000..e75fc85
--- /dev/null
+++ b/codebase/connector/dataprocessor.php
@@ -0,0 +1,505 @@
+<?php
+/*
+ @author dhtmlx.com
+ @license GPL, see license.txt
+*/
+/*! Base DataProcessor handling
+**/
+
+require_once("xss_filter.php");
+
+class DataProcessor{
+ protected $connector;//!< Connector instance
+ protected $config;//!< DataConfig instance
+ protected $request;//!< DataRequestConfig instance
+ static public $action_param ="!nativeeditor_status";
+
+ /*! constructor
+
+ @param connector
+ Connector object
+ @param config
+ DataConfig object
+ @param request
+ DataRequestConfig object
+ */
+ function __construct($connector,$config,$request){
+ $this->connector= $connector;
+ $this->config=$config;
+ $this->request=$request;
+ }
+
+ /*! convert incoming data name to valid db name
+ redirect to Connector->name_data by default
+ @param data
+ data name from incoming request
+ @return
+ related db_name
+ */
+ function name_data($data){
+ return $data;
+ }
+ /*! retrieve data from incoming request and normalize it
+
+ @param ids
+ array of extected IDs
+ @return
+ hash of data
+ */
+ protected function get_post_values($ids){
+ $data=array();
+ for ($i=0; $i < sizeof($ids); $i++)
+ $data[$ids[$i]]=array();
+
+ foreach ($_POST as $key => $value) {
+ $details=explode("_",$key,2);
+ if (sizeof($details)==1) continue;
+
+ $name=$this->name_data($details[1]);
+ $data[$details[0]][$name]=ConnectorSecurity::filter($value);
+ }
+
+ return $data;
+ }
+ protected function get_ids(){
+ if (!isset($_POST["ids"]))
+ throw new Exception("Incorrect incoming data, ID of incoming records not recognized");
+ return explode(",",$_POST["ids"]);
+ }
+
+ protected function get_operation($rid){
+ if (!isset($_POST[$rid."_".DataProcessor::$action_param]))
+ throw new Exception("Status of record [{$rid}] not found in incoming request");
+ return $_POST[$rid."_".DataProcessor::$action_param];
+ }
+ /*! process incoming request ( save|update|delete )
+ */
+ function process(){
+ LogMaster::log("DataProcessor object initialized",$_POST);
+
+ $results=array();
+
+ $ids=$this->get_ids();
+ $rows_data=$this->get_post_values($ids);
+ $failed=false;
+
+ try{
+ if ($this->connector->sql->is_global_transaction())
+ $this->connector->sql->begin_transaction();
+
+ for ($i=0; $i < sizeof($ids); $i++) {
+ $rid = $ids[$i];
+ LogMaster::log("Row data [{$rid}]",$rows_data[$rid]);
+ $status = $this->get_operation($rid);
+
+ $action=new DataAction($status,$rid,$rows_data[$rid]);
+ $results[]=$action;
+ $this->inner_process($action);
+ }
+
+ } catch(Exception $e){
+ LogMaster::log($e);
+ $failed=true;
+ }
+
+ if ($this->connector->sql->is_global_transaction()){
+ if (!$failed)
+ for ($i=0; $i < sizeof($results); $i++)
+ if ($results[$i]->get_status()=="error" || $results[$i]->get_status()=="invalid"){
+ $failed=true;
+ break;
+ }
+ if ($failed){
+ for ($i=0; $i < sizeof($results); $i++)
+ $results[$i]->error();
+ $this->connector->sql->rollback_transaction();
+ }
+ else
+ $this->connector->sql->commit_transaction();
+ }
+
+ $this->output_as_xml($results);
+ }
+
+ /*! converts status string to the inner mode name
+
+ @param status
+ external status string
+ @return
+ inner mode name
+ */
+ protected function status_to_mode($status){
+ switch($status){
+ case "updated":
+ return "update";
+ break;
+ case "inserted":
+ return "insert";
+ break;
+ case "deleted":
+ return "delete";
+ break;
+ default:
+ return $status;
+ break;
+ }
+ }
+ /*! process data updated request received
+
+ @param action
+ DataAction object
+ @return
+ DataAction object with details of processing
+ */
+ protected function inner_process($action){
+
+ if ($this->connector->sql->is_record_transaction())
+ $this->connector->sql->begin_transaction();
+
+ try{
+
+ $mode = $this->status_to_mode($action->get_status());
+ if (!$this->connector->access->check($mode)){
+ LogMaster::log("Access control: {$operation} operation blocked");
+ $action->error();
+ } else {
+ $check = $this->connector->event->trigger("beforeProcessing",$action);
+ if (!$action->is_ready())
+ $this->check_exts($action,$mode);
+ $check = $this->connector->event->trigger("afterProcessing",$action);
+ }
+
+ } catch (Exception $e){
+ LogMaster::log($e);
+ $action->set_status("error");
+ if ($action)
+ $this->connector->event->trigger("onDBError", $action, $e);
+ }
+
+ if ($this->connector->sql->is_record_transaction()){
+ if ($action->get_status()=="error" || $action->get_status()=="invalid")
+ $this->connector->sql->rollback_transaction();
+ else
+ $this->connector->sql->commit_transaction();
+ }
+
+ return $action;
+ }
+ /*! check if some event intercepts processing, send data to DataWrapper in other case
+
+ @param action
+ DataAction object
+ @param mode
+ name of inner mode ( will be used to generate event names )
+ */
+ function check_exts($action,$mode){
+ $old_config = new DataConfig($this->config);
+
+ $this->connector->event->trigger("before".$mode,$action);
+ if ($action->is_ready())
+ LogMaster::log("Event code for ".$mode." processed");
+ else {
+ //check if custom sql defined
+ $sql = $this->connector->sql->get_sql($mode,$action);
+ if ($sql){
+ $this->connector->sql->query($sql);
+ }
+ else{
+ $action->sync_config($this->config);
+ if ($this->connector->model && method_exists($this->connector->model, $mode)){
+ call_user_func(array($this->connector->model, $mode), $action);
+ LogMaster::log("Model object process action: ".$mode);
+ }
+ if (!$action->is_ready()){
+ $method=array($this->connector->sql,$mode);
+ if (!is_callable($method))
+ throw new Exception("Unknown dataprocessing action: ".$mode);
+ call_user_func($method,$action,$this->request);
+ }
+ }
+ }
+ $this->connector->event->trigger("after".$mode,$action);
+
+ $this->config->copy($old_config);
+ }
+
+ /*! output xml response for dataprocessor
+
+ @param results
+ array of DataAction objects
+ */
+ function output_as_xml($results){
+ LogMaster::log("Edit operation finished",$results);
+ ob_clean();
+ header("Content-type:text/xml");
+ echo "<?xml version='1.0' ?>";
+ echo "<data>";
+ for ($i=0; $i < sizeof($results); $i++)
+ echo $results[$i]->to_xml();
+ echo "</data>";
+ }
+
+}
+
+/*! contain all info related to action and controls customizaton
+**/
+class DataAction{
+ private $status; //!< cuurent status of record
+ private $id;//!< id of record
+ private $data;//!< data hash of record
+ private $userdata;//!< hash of extra data , attached to record
+ private $nid;//!< new id value , after operation executed
+ private $output;//!< custom output to client side code
+ private $attrs;//!< hash of custtom attributes
+ private $ready;//!< flag of operation's execution
+ private $addf;//!< array of added fields
+ private $delf;//!< array of deleted fields
+
+
+ /*! constructor
+
+ @param status
+ current operation status
+ @param id
+ record id
+ @param data
+ hash of data
+ */
+ function __construct($status,$id,$data){
+ $this->status=$status;
+ $this->id=$id;
+ $this->data=$data;
+ $this->nid=$id;
+
+ $this->output="";
+ $this->attrs=array();
+ $this->ready=false;
+
+ $this->addf=array();
+ $this->delf=array();
+ }
+
+
+ /*! add custom field and value to DB operation
+
+ @param name
+ name of field which will be added to DB operation
+ @param value
+ value which will be used for related field in DB operation
+ */
+ function add_field($name,$value){
+ LogMaster::log("adding field: ".$name.", with value: ".$value);
+ $this->data[$name]=$value;
+ $this->addf[]=$name;
+ }
+ /*! remove field from DB operation
+
+ @param name
+ name of field which will be removed from DB operation
+ */
+ function remove_field($name){
+ LogMaster::log("removing field: ".$name);
+ $this->delf[]=$name;
+ }
+
+ /*! sync field configuration with external object
+
+ @param slave
+ SQLMaster object
+ @todo
+ check , if all fields removed then cancel action
+ */
+ function sync_config($slave){
+ foreach ($this->addf as $k => $v)
+ $slave->add_field($v);
+ foreach ($this->delf as $k => $v)
+ $slave->remove_field($v);
+ }
+ /*! get value of some record's propery
+
+ @param name
+ name of record's property ( name of db field or alias )
+ @return
+ value of related property
+ */
+ function get_value($name){
+ if (!array_key_exists($name,$this->data)){
+ LogMaster::log("Incorrect field name used: ".$name);
+ LogMaster::log("data",$this->data);
+ return "";
+ }
+ return $this->data[$name];
+ }
+ /*! set value of some record's propery
+
+ @param name
+ name of record's property ( name of db field or alias )
+ @param value
+ value of related property
+ */
+ function set_value($name,$value){
+ LogMaster::log("change value of: ".$name." as: ".$value);
+ $this->data[$name]=$value;
+ }
+ /*! get hash of data properties
+
+ @return
+ hash of data properties
+ */
+ function get_data(){
+ return $this->data;
+ }
+ /*! get some extra info attached to record
+ deprecated, exists just for backward compatibility, you can use set_value instead of it
+ @param name
+ name of userdata property
+ @return
+ value of related userdata property
+ */
+ function get_userdata_value($name){
+ return $this->get_value($name);
+ }
+ /*! set some extra info attached to record
+ deprecated, exists just for backward compatibility, you can use get_value instead of it
+ @param name
+ name of userdata property
+ @param value
+ value of userdata property
+ */
+ function set_userdata_value($name,$value){
+ return $this->set_value($name,$value);
+ }
+ /*! get current status of record
+
+ @return
+ string with status value
+ */
+ function get_status(){
+ return $this->status;
+ }
+ /*! assign new status to the record
+
+ @param status
+ new status value
+ */
+ function set_status($status){
+ $this->status=$status;
+ }
+ /*! set id
+ @param id
+ id value
+ */
+ function set_id($id) {
+ $this->id = $id;
+ LogMaster::log("Change id: ".$id);
+ }
+ /*! set id
+ @param id
+ id value
+ */
+ function set_new_id($id) {
+ $this->nid = $id;
+ LogMaster::log("Change new id: ".$id);
+ }
+ /*! get id of current record
+
+ @return
+ id of record
+ */
+ function get_id(){
+ return $this->id;
+ }
+ /*! sets custom response text
+
+ can be accessed through defineAction on client side. Text wrapped in CDATA, so no extra escaping necessary
+ @param text
+ custom response text
+ */
+ function set_response_text($text){
+ $this->set_response_xml("<![CDATA[".$text."]]>");
+ }
+ /*! sets custom response xml
+
+ can be accessed through defineAction on client side
+ @param text
+ string with XML data
+ */
+ function set_response_xml($text){
+ $this->output=$text;
+ }
+ /*! sets custom response attributes
+
+ can be accessed through defineAction on client side
+ @param name
+ name of custom attribute
+ @param value
+ value of custom attribute
+ */
+ function set_response_attribute($name,$value){
+ $this->attrs[$name]=$value;
+ }
+ /*! check if action finished
+
+ @return
+ true if action finished, false otherwise
+ */
+ function is_ready(){
+ return $this->ready;
+ }
+ /*! return new id value
+
+ equal to original ID normally, after insert operation - value assigned for new DB record
+ @return
+ new id value
+ */
+ function get_new_id(){
+ return $this->nid;
+ }
+
+ /*! set result of operation as error
+ */
+ function error(){
+ $this->status="error";
+ $this->ready=true;
+ }
+ /*! set result of operation as invalid
+ */
+ function invalid(){
+ $this->status="invalid";
+ $this->ready=true;
+ }
+ /*! confirm successful opeation execution
+ @param id
+ new id value, optional
+ */
+ function success($id=false){
+ if ($id!==false)
+ $this->nid = $id;
+ $this->ready=true;
+ }
+ /*! convert DataAction to xml format compatible with client side dataProcessor
+ @return
+ DataAction operation report as XML string
+ */
+ function to_xml(){
+ $str="<action type='{$this->status}' sid='{$this->id}' tid='{$this->nid}' ";
+ foreach ($this->attrs as $k => $v) {
+ $str.=$k."='".$v."' ";
+ }
+ $str.=">{$this->output}</action>";
+ return $str;
+ }
+ /*! convert self to string ( for logs )
+
+ @return
+ DataAction operation report as plain string
+ */
+ function __toString(){
+ return "action:{$this->status}; sid:{$this->id}; tid:{$this->nid};";
+ }
+
+
+}
+
+
+?> \ No newline at end of file