summaryrefslogtreecommitdiffstats
path: root/codebase/Dhtmlx/Connector/Data
diff options
context:
space:
mode:
authorEgor <egor.26.93@gmail.com>2015-06-11 16:01:20 +0300
committerEgor <egor.26.93@gmail.com>2015-06-11 16:01:20 +0300
commit5992398183bf84c87dd4315d1532d10022718e9b (patch)
treec192dec5f76a7875265659d42dc2a5be22fc319b /codebase/Dhtmlx/Connector/Data
parent388e84730286a153c12a77d9f19215f2b74c5c4f (diff)
downloadconnector-php-5992398183bf84c87dd4315d1532d10022718e9b.zip
connector-php-5992398183bf84c87dd4315d1532d10022718e9b.tar.gz
connector-php-5992398183bf84c87dd4315d1532d10022718e9b.tar.bz2
Changed psr-4 structure to psr-0. Added connectors for phpcake, codeigniter frameworks.
Diffstat (limited to 'codebase/Dhtmlx/Connector/Data')
-rw-r--r--codebase/Dhtmlx/Connector/Data/CommonDataItem.php27
-rw-r--r--codebase/Dhtmlx/Connector/Data/CommonDataProcessor.php55
-rw-r--r--codebase/Dhtmlx/Connector/Data/DataAction.php276
-rw-r--r--codebase/Dhtmlx/Connector/Data/DataItem.php128
-rw-r--r--codebase/Dhtmlx/Connector/Data/DataItemUpdate.php105
-rw-r--r--codebase/Dhtmlx/Connector/Data/DataProcessor.php253
-rw-r--r--codebase/Dhtmlx/Connector/Data/DataUpdate.php163
-rw-r--r--codebase/Dhtmlx/Connector/Data/GridDataProcessor.php23
-rw-r--r--codebase/Dhtmlx/Connector/Data/JSONCommonDataItem.php29
-rw-r--r--codebase/Dhtmlx/Connector/Data/TreeDataItem.php157
-rw-r--r--codebase/Dhtmlx/Connector/Data/TreeDataProcessor.php25
11 files changed, 1241 insertions, 0 deletions
diff --git a/codebase/Dhtmlx/Connector/Data/CommonDataItem.php b/codebase/Dhtmlx/Connector/Data/CommonDataItem.php
new file mode 100644
index 0000000..523cd08
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/CommonDataItem.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace DHTMLX\Connector\Data;
+/*! DataItem class for DataView component
+**/
+class CommonDataItem extends DataItem{
+ /*! return self as XML string
+ */
+ function to_xml(){
+ if ($this->skip) return "";
+ return $this->to_xml_start().$this->to_xml_end();
+ }
+
+ function to_xml_start(){
+ $str="<item id='".$this->get_id()."' ";
+ for ($i=0; $i < sizeof($this->config->text); $i++){
+ $name=$this->config->text[$i]["name"];
+ $str.=" ".$name."='".$this->xmlentities($this->data[$name])."'";
+ }
+
+ if ($this->userdata !== false)
+ foreach ($this->userdata as $key => $value)
+ $str.=" ".$key."='".$this->xmlentities($value)."'";
+
+ return $str.">";
+ }
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/CommonDataProcessor.php b/codebase/Dhtmlx/Connector/Data/CommonDataProcessor.php
new file mode 100644
index 0000000..8f00b94
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/CommonDataProcessor.php
@@ -0,0 +1,55 @@
+<?php
+namespace DHTMLX\Connector\Data;
+
+use DHTMLX\Connector\XSSFilter\ConnectorSecurity;
+use DHTMLX\Connector\Tools\LogMaster;
+
+class CommonDataProcessor extends DataProcessor{
+ protected function get_post_values($ids){
+ if (isset($_GET['action'])){
+ $data = array();
+ if (isset($_POST["id"])){
+ $dataset = array();
+ foreach($_POST as $key=>$value)
+ $dataset[$key] = ConnectorSecurity::filter($value);
+
+ $data[$_POST["id"]] = $dataset;
+ }
+ else
+ $data["dummy_id"] = $_POST;
+ return $data;
+ }
+ return parent::get_post_values($ids);
+ }
+
+ protected function get_ids(){
+ if (isset($_GET['action'])){
+ if (isset($_POST["id"]))
+ return array($_POST['id']);
+ else
+ return array("dummy_id");
+ }
+ return parent::get_ids();
+ }
+
+ protected function get_operation($rid){
+ if (isset($_GET['action']))
+ return $_GET['action'];
+ return parent::get_operation($rid);
+ }
+
+ public function output_as_xml($results){
+ if (isset($_GET['action'])){
+ LogMaster::log("Edit operation finished",$results);
+ ob_clean();
+ $type = $results[0]->get_status();
+ if ($type == "error" || $type == "invalid"){
+ echo "false";
+ } else if ($type=="insert"){
+ echo "true\n".$results[0]->get_new_id();
+ } else
+ echo "true";
+ } else
+ return parent::output_as_xml($results);
+ }
+}; \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/DataAction.php b/codebase/Dhtmlx/Connector/Data/DataAction.php
new file mode 100644
index 0000000..8e4b5dd
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/DataAction.php
@@ -0,0 +1,276 @@
+<?php
+namespace DHTMLX\Connector\Data;
+
+use DHTMLX\Connector\Tools\LogMaster;
+/*! 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){
+ //die(var_dump($this->data["c0"]));
+ 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."='".$this->xmlentities($v)."' ";
+ }
+ $str.=">{$this->output}</action>";
+ return $str;
+ }
+
+ /*! replace xml unsafe characters
+
+ @param string
+ string to be escaped
+ @return
+ escaped string
+ */
+ public function xmlentities($string) {
+ return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string);
+ }
+
+ /*! 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
diff --git a/codebase/Dhtmlx/Connector/Data/DataItem.php b/codebase/Dhtmlx/Connector/Data/DataItem.php
new file mode 100644
index 0000000..b980d9c
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/DataItem.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace DHTMLX\Connector\Data;
+/*! base class for component item representation
+**/
+class DataItem{
+ protected $data; //!< hash of data
+ protected $config;//!< DataConfig instance
+ protected $index;//!< index of element
+ protected $skip;//!< flag , which set if element need to be skiped during rendering
+ protected $userdata;
+
+ /*! constructor
+
+ @param data
+ hash of data
+ @param config
+ DataConfig object
+ @param index
+ index of element
+ */
+ function __construct($data,$config,$index){
+ $this->config=$config;
+ $this->data=$data;
+ $this->index=$index;
+ $this->skip=false;
+ $this->userdata=false;
+ }
+
+ //set userdata for the item
+ function set_userdata($name, $value){
+ if ($this->userdata === false)
+ $this->userdata = array();
+
+ $this->userdata[$name]=$value;
+ }
+ /*! get named value
+
+ @param name
+ name or alias of field
+ @return
+ value from field with provided name or alias
+ */
+ public function get_value($name){
+ return $this->data[$name];
+ }
+ /*! set named value
+
+ @param name
+ name or alias of field
+ @param value
+ value for field with provided name or alias
+ */
+ public function set_value($name,$value){
+ return $this->data[$name]=$value;
+ }
+ /*! get id of element
+ @return
+ id of element
+ */
+ public function get_id(){
+ $id = $this->config->id["name"];
+ if (array_key_exists($id,$this->data))
+ return $this->data[$id];
+ return false;
+ }
+ /*! change id of element
+
+ @param value
+ new id value
+ */
+ public function set_id($value){
+ $this->data[$this->config->id["name"]]=$value;
+ }
+ /*! get index of element
+
+ @return
+ index of element
+ */
+ public function get_index(){
+ return $this->index;
+ }
+ /*! mark element for skiping ( such element will not be rendered )
+ */
+ public function skip(){
+ $this->skip=true;
+ }
+
+ /*! return self as XML string
+ */
+ public function to_xml(){
+ return $this->to_xml_start().$this->to_xml_end();
+ }
+
+ /*! replace xml unsafe characters
+
+ @param string
+ string to be escaped
+ @return
+ escaped string
+ */
+ public function xmlentities($string) {
+ return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string);
+ }
+
+ /*! return starting tag for self as XML string
+ */
+ public function to_xml_start(){
+ $str="<item";
+ for ($i=0; $i < sizeof($this->config->data); $i++){
+ $name=$this->config->data[$i]["name"];
+ $db_name=$this->config->data[$i]["db_name"];
+ $str.=" ".$name."='".$this->xmlentities($this->data[$name])."'";
+ }
+ //output custom data
+ if ($this->userdata !== false)
+ foreach ($this->userdata as $key => $value){
+ $str.=" ".$key."='".$this->xmlentities($value)."'";
+ }
+
+ return $str.">";
+ }
+ /*! return ending tag for XML string
+ */
+ public function to_xml_end(){
+ return "</item>";
+ }
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/DataItemUpdate.php b/codebase/Dhtmlx/Connector/Data/DataItemUpdate.php
new file mode 100644
index 0000000..ad97be2
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/DataItemUpdate.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ @author dhtmlx.com
+ @license GPL, see license.txt
+*/
+
+/*! DataItemUpdate class for realization Optimistic concurrency control
+ Wrapper for DataItem object
+ It's used during outputing updates instead of DataItem object
+ Create wrapper for every data item with update information.
+*/
+
+namespace DHTMLX\Connector\Data;
+
+class DataItemUpdate extends DataItem {
+
+
+ /*! constructor
+ @param data
+ hash of data
+ @param config
+ DataConfig object
+ @param index
+ index of element
+ */
+ public function __construct($data,$config,$index,$type){
+ $this->config=$config;
+ $this->data=$data;
+ $this->index=$index;
+ $this->skip=false;
+ $this->child = new $type($data, $config, $index);
+ }
+
+ /*! returns parent_id (for Tree and TreeGrid components)
+ */
+ public function get_parent_id(){
+ if (method_exists($this->child, 'get_parent_id')) {
+ return $this->child->get_parent_id();
+ } else {
+ return '';
+ }
+ }
+
+
+ /*! generate XML on the data hash base
+ */
+ public function to_xml(){
+ $str= "<update ";
+ $str .= 'status="'.$this->data['type'].'" ';
+ $str .= 'id="'.$this->data['dataId'].'" ';
+ $str .= 'parent="'.$this->get_parent_id().'"';
+ $str .= '>';
+ $str .= $this->child->to_xml();
+ $str .= '</update>';
+ return $str;
+ }
+
+ /*! return starting tag for XML string
+ */
+ public function to_xml_start(){
+ $str="<update ";
+ $str .= 'status="'.$this->data['type'].'" ';
+ $str .= 'id="'.$this->data['dataId'].'" ';
+ $str .= 'parent="'.$this->get_parent_id().'"';
+ $str .= '>';
+ $str .= $this->child->to_xml_start();
+ return $str;
+ }
+
+ /*! return ending tag for XML string
+ */
+ public function to_xml_end(){
+ $str = $this->child->to_xml_end();
+ $str .= '</update>';
+ return $str;
+ }
+
+ /*! returns false for outputing only current item without child items
+ */
+ public function has_kids(){
+ return false;
+ }
+
+ /*! sets count of child items
+ @param value
+ count of child items
+ */
+ public function set_kids($value){
+ if (method_exists($this->child, 'set_kids')) {
+ $this->child->set_kids($value);
+ }
+ }
+
+ /*! sets attribute for item
+ */
+ public function set_attribute($name, $value){
+ if (method_exists($this->child, 'set_attribute')) {
+ LogMaster::log("setting attribute: \nname = {$name}\nvalue = {$value}");
+ $this->child->set_attribute($name, $value);
+ } else {
+ LogMaster::log("set_attribute method doesn't exists");
+ }
+ }
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/DataProcessor.php b/codebase/Dhtmlx/Connector/Data/DataProcessor.php
new file mode 100644
index 0000000..973753a
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/DataProcessor.php
@@ -0,0 +1,253 @@
+<?php
+/*! Base DataProcessor handling
+**/
+namespace DHTMLX\Connector\Data;
+use DHTMLX\Connector\Tools\LogMaster;
+use DHTMLX\Connector\XSSFilter\ConnectorSecurity;
+use DHTMLX\Connector\DataStorage\DataConfig;
+
+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: {$mode} operation blocked");
+ $action->error();
+ } else {
+ $check = $this->connector->event->trigger("beforeProcessing",$action);
+
+
+ if (!$action->is_ready())
+ $this->check_exts($action,$mode);
+ if ($mode == "insert" && $action->get_status() != "error" && $action->get_status() != "invalid")
+ $this->connector->sql->new_record_order($action, $this->request);
+
+ $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>";
+ }
+
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/DataUpdate.php b/codebase/Dhtmlx/Connector/Data/DataUpdate.php
new file mode 100644
index 0000000..8fc1c46
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/DataUpdate.php
@@ -0,0 +1,163 @@
+<?php
+
+class DataUpdate{
+
+ protected $table; //!< table , where actions are stored
+ protected $url; //!< url for notification service, optional
+ protected $sql; //!< DB wrapper object
+ protected $config; //!< DBConfig object
+ protected $request; //!< DBRequestConfig object
+ protected $event;
+ protected $item_class;
+ protected $demu;
+
+ //protected $config;//!< DataConfig instance
+ //protected $request;//!< DataRequestConfig instance
+
+ /*! constructor
+
+ @param connector
+ Connector object
+ @param config
+ DataConfig object
+ @param request
+ DataRequestConfig object
+ */
+ function __construct($sql, $config, $request, $table, $url){
+ $this->config= $config;
+ $this->request= $request;
+ $this->sql = $sql;
+ $this->table=$table;
+ $this->url=$url;
+ $this->demu = false;
+ }
+
+ public function set_demultiplexor($path){
+ $this->demu = $path;
+ }
+
+ public function set_event($master, $name){
+ $this->event = $master;
+ $this->item_class = $name;
+ }
+
+ private function select_update($actions_table, $join_table, $id_field_name, $version, $user) {
+ $sql = "SELECT * FROM {$actions_table}";
+ $sql .= " LEFT OUTER JOIN {$join_table} ON ";
+ $sql .= "{$actions_table}.DATAID = {$join_table}.{$id_field_name} ";
+ $sql .= "WHERE {$actions_table}.ID > '{$version}' AND {$actions_table}.USER <> '{$user}'";
+ return $sql;
+ }
+
+ private function get_update_max_version() {
+ $sql = "SELECT MAX(id) as VERSION FROM {$this->table}";
+ $res = $this->sql->query($sql);
+ $data = $this->sql->get_next($res);
+
+ if ($data == false || $data['VERSION'] == false)
+ return 1;
+ else
+ return $data['VERSION'];
+ }
+
+ private function log_update_action($actions_table, $dataId, $status, $user) {
+ $sql = "INSERT INTO {$actions_table} (DATAID, TYPE, USER) VALUES ('{$dataId}', '{$status}', '{$user}')";
+ $this->sql->query($sql);
+ if ($this->demu)
+ file_get_contents($this->demu);
+ }
+
+
+
+
+ /*! records operations in actions_table
+ @param action
+ DataAction object
+ */
+ public function log_operations($action) {
+ $type = $this->sql->escape($action->get_status());
+ $dataId = $this->sql->escape($action->get_new_id());
+ $user = $this->sql->escape($this->request->get_user());
+ if ($type!="error" && $type!="invalid" && $type !="collision") {
+ $this->log_update_action($this->table, $dataId, $type, $user);
+ }
+ }
+
+
+ /*! return action version in XMl format
+ */
+ public function get_version() {
+ $version = $this->get_update_max_version();
+ return "<userdata name='version'>".$version."</userdata>";
+ }
+
+
+ /*! adds action version in output XML as userdata
+ */
+ public function version_output($conn, $out) {
+ $out->add($this->get_version());
+ }
+
+
+ /*! create update actions in XML-format and sends it to output
+ */
+ public function get_updates() {
+ $sub_request = new DataRequestConfig($this->request);
+ $version = $this->request->get_version();
+ $user = $this->request->get_user();
+
+ $sub_request->parse_sql($this->select_update($this->table, $this->request->get_source(), $this->config->id['db_name'], $version, $user));
+ $sub_request->set_relation(false);
+
+ $output = $this->render_set($this->sql->select($sub_request), $this->item_class);
+
+ ob_clean();
+ header("Content-type:text/xml");
+
+ echo $this->updates_start();
+ echo $this->get_version();
+ echo $output;
+ echo $this->updates_end();
+ }
+
+
+ protected function render_set($res, $name){
+ $output="";
+ $index=0;
+ while ($data=$this->sql->get_next($res)){
+ $data = new DataItemUpdate($data,$this->config,$index, $name);
+ $this->event->trigger("beforeRender",$data);
+ $output.=$data->to_xml();
+ $index++;
+ }
+ return $output;
+ }
+
+ /*! returns update start string
+ */
+ protected function updates_start() {
+ $start = '<updates>';
+ return $start;
+ }
+
+ /*! returns update end string
+ */
+ protected function updates_end() {
+ $start = '</updates>';
+ return $start;
+ }
+
+ /*! checks if action version given by client is deprecated
+ @param action
+ DataAction object
+ */
+ public function check_collision($action) {
+ $version = $this->sql->escape($this->request->get_version());
+ //$user = $this->sql->escape($this->request->get_user());
+ $last_version = $this->get_update_max_version();
+ if (($last_version > $version)&&($action->get_status() == 'update')) {
+ $action->error();
+ $action->set_status('collision');
+ }
+ }
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/GridDataProcessor.php b/codebase/Dhtmlx/Connector/Data/GridDataProcessor.php
new file mode 100644
index 0000000..9b487eb
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/GridDataProcessor.php
@@ -0,0 +1,23 @@
+<?php
+namespace DHTMLX\Connector\Data;
+
+/*! DataProcessor class for Grid component
+**/
+class GridDataProcessor extends DataProcessor{
+
+ /*! convert incoming data name to valid db name
+ converts c0..cN to valid field names
+ @param data
+ data name from incoming request
+ @return
+ related db_name
+ */
+ function name_data($data){
+ if ($data == "gr_id") return $this->config->id["name"];
+ $parts=explode("c",$data);
+ if ($parts[0]=="" && ((string)intval($parts[1]))==$parts[1])
+ if (sizeof($this->config->text)>intval($parts[1]))
+ return $this->config->text[intval($parts[1])]["name"];
+ return $data;
+ }
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/JSONCommonDataItem.php b/codebase/Dhtmlx/Connector/Data/JSONCommonDataItem.php
new file mode 100644
index 0000000..4a69068
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/JSONCommonDataItem.php
@@ -0,0 +1,29 @@
+<?php
+namespace DHTMLX\Connector\Data;
+
+class JSONCommonDataItem extends DataItem{
+ /*! return self as XML string
+ */
+ function to_xml(){
+ if ($this->skip) return false;
+
+ $data = array(
+ 'id' => $this->get_id()
+ );
+ for ($i=0; $i<sizeof($this->config->text); $i++){
+ $extra = $this->config->text[$i]["name"];
+ $data[$extra]=$this->data[$extra];
+ if (is_null($data[$extra]))
+ $data[$extra] = "";
+ }
+
+ if ($this->userdata !== false)
+ foreach ($this->userdata as $key => $value){
+ if ($value === null)
+ $data[$key]="";
+ $data[$key]=$value;
+ }
+
+ return $data;
+ }
+}
diff --git a/codebase/Dhtmlx/Connector/Data/TreeDataItem.php b/codebase/Dhtmlx/Connector/Data/TreeDataItem.php
new file mode 100644
index 0000000..561d495
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/TreeDataItem.php
@@ -0,0 +1,157 @@
+<?php
+
+namespace DHTMLX\Connector\Data;
+
+class TreeDataItem extends DataItem
+{
+ private $im0;//!< image of closed folder
+ private $im1;//!< image of opened folder
+ private $im2;//!< image of leaf item
+ private $check;//!< checked state
+ private $kids = -1;//!< checked state
+ private $attrs;//!< collection of custom attributes
+
+ function __construct($data, $config, $index)
+ {
+ parent::__construct($data, $config, $index);
+
+ $this->im0 = false;
+ $this->im1 = false;
+ $this->im2 = false;
+ $this->check = false;
+ $this->attrs = array();
+ }
+
+ /*! get id of parent record
+
+ @return
+ id of parent record
+ */
+ function get_parent_id()
+ {
+ return $this->data[$this->config->relation_id["name"]];
+ }
+
+ /*! get state of items checkbox
+
+ @return
+ state of item's checkbox as int value, false if state was not defined
+ */
+ function get_check_state()
+ {
+ return $this->check;
+ }
+
+ /*! set state of item's checkbox
+
+ @param value
+ int value, 1 - checked, 0 - unchecked, -1 - third state
+ */
+ function set_check_state($value)
+ {
+ $this->check = $value;
+ }
+
+ /*! return count of child items
+ -1 if there is no info about childs
+ @return
+ count of child items
+ */
+ function has_kids()
+ {
+ return $this->kids;
+ }
+
+ /*! sets count of child items
+ @param value
+ count of child items
+ */
+ function set_kids($value)
+ {
+ $this->kids = $value;
+ }
+
+ /*! set custom attribute
+
+ @param name
+ name of the attribute
+ @param value
+ new value of the attribute
+ */
+ function set_attribute($name, $value)
+ {
+ switch ($name) {
+ case "id":
+ $this->set_id($value);
+ break;
+ case "text":
+ $this->data[$this->config->text[0]["name"]] = $value;
+ break;
+ case "checked":
+ $this->set_check_state($value);
+ break;
+ case "im0":
+ $this->im0 = $value;
+ break;
+ case "im1":
+ $this->im1 = $value;
+ break;
+ case "im2":
+ $this->im2 = $value;
+ break;
+ case "child":
+ $this->set_kids($value);
+ break;
+ default:
+ $this->attrs[$name] = $value;
+ }
+ }
+
+
+ /*! assign image for tree's item
+
+ @param img_folder_closed
+ image for item, which represents folder in closed state
+ @param img_folder_open
+ image for item, which represents folder in opened state, optional
+ @param img_leaf
+ image for item, which represents leaf item, optional
+ */
+ function set_image($img_folder_closed, $img_folder_open = false, $img_leaf = false)
+ {
+ $this->im0 = $img_folder_closed;
+ $this->im1 = $img_folder_open ? $img_folder_open : $img_folder_closed;
+ $this->im2 = $img_leaf ? $img_leaf : $img_folder_closed;
+ }
+
+ /*! return self as XML string, starting part
+ */
+ function to_xml_start()
+ {
+ if ($this->skip) return "";
+
+ $str1 = "<item id='" . $this->get_id() . "' text='" . $this->xmlentities($this->data[$this->config->text[0]["name"]]) . "' ";
+ if ($this->has_kids() == true) $str1 .= "child='" . $this->has_kids() . "' ";
+ if ($this->im0) $str1 .= "im0='" . $this->im0 . "' ";
+ if ($this->im1) $str1 .= "im1='" . $this->im1 . "' ";
+ if ($this->im2) $str1 .= "im2='" . $this->im2 . "' ";
+ if ($this->check) $str1 .= "checked='" . $this->check . "' ";
+ foreach ($this->attrs as $key => $value)
+ $str1 .= $key . "='" . $this->xmlentities($value) . "' ";
+ $str1 .= ">";
+ if ($this->userdata !== false)
+ foreach ($this->userdata as $key => $value)
+ $str1 .= "<userdata name='" . $key . "'><![CDATA[" . $value . "]]></userdata>";
+
+ return $str1;
+ }
+
+ /*! return self as XML string, ending part
+ */
+ function to_xml_end()
+ {
+ if ($this->skip) return "";
+ return "</item>";
+ }
+
+} \ No newline at end of file
diff --git a/codebase/Dhtmlx/Connector/Data/TreeDataProcessor.php b/codebase/Dhtmlx/Connector/Data/TreeDataProcessor.php
new file mode 100644
index 0000000..dca6a8f
--- /dev/null
+++ b/codebase/Dhtmlx/Connector/Data/TreeDataProcessor.php
@@ -0,0 +1,25 @@
+<?php
+namespace DHTMLX\Connector\Data;
+
+class TreeDataProcessor extends DataProcessor{
+
+ function __construct($connector,$config,$request){
+ parent::__construct($connector,$config,$request);
+ $request->set_relation(false);
+ }
+
+ /*! convert incoming data name to valid db name
+ converts c0..cN to valid field names
+ @param data
+ data name from incoming request
+ @return
+ related db_name
+ */
+ function name_data($data){
+ if ($data=="tr_pid")
+ return $this->config->relation_id["db_name"];
+ if ($data=="tr_text")
+ return $this->config->text[0]["db_name"];
+ return $data;
+ }
+} \ No newline at end of file