summaryrefslogtreecommitdiffstats
path: root/codebase
diff options
context:
space:
mode:
authorKirylka <kirylanoshko@gmail.com>2015-03-31 17:56:47 +0300
committerKirylka <kirylanoshko@gmail.com>2015-03-31 17:56:47 +0300
commitf5f99c335707d9b11d40f1eb0f6ddb5a993fd31a (patch)
treed9c0d3532ec9f0f2fb68e31d2611282ae0642181 /codebase
parent458f0aead573842f1df00ce2ae00334c27f66585 (diff)
downloadconnector-php-f5f99c335707d9b11d40f1eb0f6ddb5a993fd31a.zip
connector-php-f5f99c335707d9b11d40f1eb0f6ddb5a993fd31a.tar.gz
connector-php-f5f99c335707d9b11d40f1eb0f6ddb5a993fd31a.tar.bz2
Creating a new connector for yii2.
Diffstat (limited to 'codebase')
-rw-r--r--codebase/Connector.php645
-rw-r--r--codebase/ConvertService.php (renamed from codebase/convert.php)28
-rw-r--r--codebase/Data/DataAction.php276
-rw-r--r--codebase/Data/DataItem.php128
-rw-r--r--codebase/Data/DataItemUpdate.php105
-rw-r--r--codebase/Data/DataProcessor.php253
-rw-r--r--codebase/Data/DataUpdate.php163
-rw-r--r--codebase/Data/GridDataProcessor.php23
-rw-r--r--codebase/Data/TreeDataItem.php157
-rw-r--r--codebase/Data/TreeDataProcessor.php25
-rw-r--r--codebase/DataStorage/ArrayDBDataWrapper.php50
-rw-r--r--codebase/DataStorage/ArrayQueryWrapper.php9
-rw-r--r--codebase/DataStorage/DBDataWrapper.php456
-rw-r--r--codebase/DataStorage/DataConfig.php227
-rw-r--r--codebase/DataStorage/DataRequestConfig.php284
-rw-r--r--codebase/DataStorage/DataWrapper.php100
-rw-r--r--codebase/DataStorage/MsSQLDBDataWrapper.php78
-rw-r--r--codebase/DataStorage/MySQLDBDataWrapper.php69
-rw-r--r--codebase/DataStorage/PDODBDataWrapper.php (renamed from codebase/db_pdo.php)50
-rw-r--r--codebase/DataStorage/PDOResultSet.php18
-rw-r--r--codebase/DataStorage/PHPYii2DBDataWrapper.php (renamed from codebase/db_phpyii.php)32
-rw-r--r--codebase/DataStorage/PostgreDBDataWrapper.php70
-rw-r--r--codebase/DistinctOptionsConnector.php18
-rw-r--r--codebase/Event/EventInterface.php37
-rw-r--r--codebase/Event/FilterInterface.php32
-rw-r--r--codebase/Event/SortInterface.php31
-rw-r--r--codebase/GridConfiguration.php445
-rw-r--r--codebase/GridConnector.php125
-rw-r--r--codebase/GridDataItem.php120
-rw-r--r--codebase/MixedConnector.php24
-rw-r--r--codebase/OptionsConnector.php27
-rw-r--r--codebase/Output/JSONRenderStrategy.php30
-rw-r--r--codebase/Output/JSONTreeRenderStrategy.php39
-rw-r--r--codebase/Output/OutputWriter.php40
-rw-r--r--codebase/Output/RenderStrategy.php115
-rw-r--r--codebase/Output/TreeRenderStrategy.php64
-rw-r--r--codebase/Tools/AccessMaster.php57
-rw-r--r--codebase/Tools/EventMaster.php107
-rw-r--r--codebase/Tools/LogMaster.php101
-rw-r--r--codebase/TreeConnector.php63
-rw-r--r--codebase/XSSFilter/ConnectorSecurity.php67
-rw-r--r--codebase/XSSFilter/dhxExternalInputClean.php120
-rw-r--r--codebase/base_connector.php948
-rw-r--r--codebase/chart_connector.php18
-rw-r--r--codebase/combo_connector.php94
-rw-r--r--codebase/connector.js155
-rw-r--r--codebase/crosslink_connector.php141
-rw-r--r--codebase/data_connector.php528
-rw-r--r--codebase/dataprocessor.php521
-rw-r--r--codebase/dataview_connector.php73
-rw-r--r--codebase/db_adodb.php72
-rw-r--r--codebase/db_common.php1157
-rw-r--r--codebase/db_excel.php190
-rw-r--r--codebase/db_filesystem.php345
-rw-r--r--codebase/db_mssql.php73
-rw-r--r--codebase/db_mysqli.php56
-rw-r--r--codebase/db_oracle.php88
-rw-r--r--codebase/db_phpcake.php85
-rw-r--r--codebase/db_phpci.php65
-rw-r--r--codebase/db_postgre.php73
-rw-r--r--codebase/db_sasql.php54
-rw-r--r--codebase/db_sqlite.php34
-rw-r--r--codebase/db_sqlite3.php33
-rw-r--r--codebase/db_sqlsrv.php102
-rw-r--r--codebase/filesystem_item.php19
-rw-r--r--codebase/form_connector.php62
-rw-r--r--codebase/gantt_connector.php364
-rw-r--r--codebase/grid_config.php423
-rw-r--r--codebase/grid_connector.php269
-rw-r--r--codebase/keygrid_connector.php48
-rw-r--r--codebase/mixed_connector.php28
-rw-r--r--codebase/options_connector.php45
-rw-r--r--codebase/scheduler_connector.php230
-rw-r--r--codebase/strategy.php508
-rw-r--r--codebase/tools.php267
-rw-r--r--codebase/tree_connector.php231
-rw-r--r--codebase/treedatagroup_connector.php89
-rw-r--r--codebase/treedatamultitable_connector.php91
-rw-r--r--codebase/treegrid_connector.php121
-rw-r--r--codebase/treegridgroup_connector.php46
-rw-r--r--codebase/treegridmultitable_connector.php69
-rw-r--r--codebase/treegroup_connector.php46
-rw-r--r--codebase/treemultitable_connector.php51
-rw-r--r--codebase/update.php266
-rw-r--r--codebase/xss_filter.php199
85 files changed, 4845 insertions, 8440 deletions
diff --git a/codebase/Connector.php b/codebase/Connector.php
new file mode 100644
index 0000000..9c28872
--- /dev/null
+++ b/codebase/Connector.php
@@ -0,0 +1,645 @@
+<?php
+
+namespace DHTMLX\Connector;
+
+use DHTMLX\Connector\Tools\EventMaster;
+use DHTMLX\Connector\Tools\AccessMaster;
+use DHTMLX\Connector\Tools\LogMaster;
+use DHTMLX\Connector\Output\RenderStrategy;
+use DHTMLX\Connector\Output\OutputWriter;
+use DHTMLX\Connector\DataStorage\DataConfig;
+use DHTMLX\Connector\DataStorage\DataAction;
+use DHTMLX\Connector\DataStorage\DataRequestConfig;
+use DHTMLX\Connector\DataStorage\MySQLDBDataWrapper;
+use DHTMLX\Connector\DataStorage\ArrayDBDataWrapper;
+use DHTMLX\Connector\DataStorage\PHPYii2DBDataWrapper;
+use DHTMLX\Connector\XSSFilter\ConnectorSecurity;
+use DHTMLX\Connector\Event\SortInterface;
+use DHTMLX\Connector\Event\FilterInterface;
+
+class Connector {
+ protected $config;//DataConfig instance
+ protected $request;//DataRequestConfig instance
+ protected $names;//!< hash of names for used classes
+ protected $encoding="utf-8";//!< assigned encoding (UTF-8 by default)
+ protected $editing=false;//!< flag of edit mode ( response for dataprocessor )
+
+ public static $filter_var="dhx_filter";
+ public static $sort_var="dhx_sort";
+ public static $kids_var="dhx_kids";
+
+ public $model=false;
+
+ private $updating=false;//!< flag of update mode ( response for data-update )
+ private $db; //!< db connection resource
+ protected $dload;//!< flag of dyn. loading mode
+ public $access; //!< AccessMaster instance
+ protected $data_separator = "\n";
+
+ public $sql; //DataWrapper instance
+ public $event; //EventMaster instance
+ public $limit=false;
+
+ private $id_seed=0; //!< default value, used to generate auto-IDs
+ protected $live_update = false; // actions table name for autoupdating
+ protected $extra_output="";//!< extra info which need to be sent to client side
+ protected $options=array();//!< hash of OptionsConnector
+ protected $as_string = false; // render() returns string, don't send result in response
+ protected $simple = false; // render only data without any other info
+ protected $filters;
+ protected $sorts;
+ protected $mix;
+ protected $order = false;
+
+ /*! constructor
+
+ Here initilization of all Masters occurs, execution timer initialized
+ @param db
+ db connection resource
+ @param type
+ string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
+ @param item_type
+ name of class, which will be used for item rendering, optional, DataItem will be used by default
+ @param data_type
+ name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
+ */
+ public function __construct($db,$type=false, $item_type=false, $data_type=false, $render_type = false){
+ $this->exec_time=microtime(true);
+ $dsnamespace = "DHTMLX\\Connector\\DataStorage\\";
+ if (!$type) $type=$dsnamespace."MySQLDBDataWrapper";
+
+ //die(var_dump(class_exists("DataConfig",true), new MySQLDBDataWrapper));
+ if (class_exists($dsnamespace.$type."DBDataWrapper",true))
+ $type.="DBDataWrapper";
+ if (!$item_type) $item_type="DHTMLX\\Connector\\Data\\DataItem";
+ if (!$data_type) $data_type="DHTMLX\\Connector\\Data\\DataProcessor";
+ if (!$render_type) $render_type="DHTMLX\\Connector\\Output\\RenderStrategy";
+
+ $this->names=array(
+ "db_class"=>$type,
+ "item_class"=>$item_type,
+ "data_class"=>$data_type,
+ "render_class"=>$render_type
+ );
+ $this->attributes = array();
+ $this->filters = array();
+ $this->sorts = array();
+ $this->mix = array();
+
+ $this->config = new DataConfig();
+ $this->request = new DataRequestConfig();
+ $this->event = new EventMaster();
+ $this->access = new AccessMaster();
+
+// if (!class_exists($this->names["db_class"],false))
+// throw new \Exception("DB class not found: ".$this->names["db_class"]);
+ $dbClass = $dsnamespace.$this->names["db_class"];
+ $this->sql = new $dbClass($db,$this->config);
+ $this->render = new $this->names["render_class"]($this);
+
+ $this->db=$db;//saved for options connectors, if any
+
+ EventMaster::trigger_static("connectorCreate",$this);
+ }
+
+ /*! return db connection resource
+ nested class may neeed to access live connection object
+ @return
+ DB connection resource
+ */
+ protected function get_connection(){
+ return $this->db;
+ }
+
+ public function get_config(){
+ return new DataConfig($this->config);
+ }
+
+ public function get_request(){
+ return new DataRequestConfig($this->request);
+ }
+
+
+ protected $attributes;
+ public function add_top_attribute($name, $string){
+ $this->attributes[$name] = $string;
+ }
+
+ //model is a class, which will be used for all data operations
+ //we expect that it has next methods get, update, insert, delete
+ //if method was not defined - we will use default logic
+ public function useModel($model){
+ $this->model = $model;
+ }
+
+
+ /*! config connector based on table
+
+ @param table
+ name of table in DB
+ @param id
+ name of id field
+ @param fields
+ list of fields names
+ @param extra
+ list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
+ @param relation_id
+ name of field used to define relations for hierarchical data organization, optional
+ */
+ public function render_table($table,$id="",$fields=false,$extra=false,$relation_id=false){
+ $this->configure($table,$id,$fields,$extra,$relation_id);
+ return $this->render();
+ }
+ public function configure($table,$id="",$fields=false,$extra=false,$relation_id=false){
+ if ($fields === false){
+ //auto-config
+ $info = $this->sql->fields_list($table);
+ $fields = implode(",",$info["fields"]);
+ if ($info["key"])
+ $id = $info["key"];
+ }
+ $this->config->init($id,$fields,$extra,$relation_id);
+ if (strpos(trim($table), " ")!==false)
+ $this->request->parse_sql($table);
+ else
+ $this->request->set_source($table);
+ }
+
+ public function uuid(){
+ return time()."x".$this->id_seed++;
+ }
+
+ /*! config connector based on sql
+
+ @param sql
+ sql query used as base of configuration
+ @param id
+ name of id field
+ @param fields
+ list of fields names
+ @param extra
+ list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
+ @param relation_id
+ name of field used to define relations for hierarchical data organization, optional
+ */
+ public function render_sql($sql,$id,$fields,$extra=false,$relation_id=false){
+ $this->config->init($id,$fields,$extra,$relation_id);
+ $this->request->parse_sql($sql);
+ return $this->render();
+ }
+
+ public function render_array($data, $id, $fields, $extra=false, $relation_id=false){
+ $this->configure("-",$id,$fields,$extra,$relation_id);
+ $this->sql = new ArrayDBDataWrapper($data, $this->config);
+ return $this->render();
+ }
+
+ public function render_complex_sql($sql,$id,$fields,$extra=false,$relation_id=false){
+ $this->config->init($id,$fields,$extra,$relation_id);
+ $this->request->parse_sql($sql, true);
+ return $this->render();
+ }
+
+ /*! render already configured connector
+
+ @param config
+ configuration of data
+ @param request
+ configuraton of request
+ */
+ public function render_connector($config,$request){
+ $this->config->copy($config);
+ $this->request->copy($request);
+ return $this->render();
+ }
+
+ /*! render self
+ process commands, output requested data as XML
+ */
+ public function render(){
+ $this->event->trigger("onInit", $this);
+ EventMaster::trigger_static("connectorInit",$this);
+
+ if (!$this->as_string)
+ $this->parse_request();
+ $this->set_relation();
+
+ if ($this->live_update !== false && $this->updating!==false) {
+ $this->live_update->get_updates();
+ } else {
+ if ($this->editing){
+ //die($this->names["data_class"]);
+ $dp = new $this->names["data_class"]($this,$this->config,$this->request);
+ $dp->process($this->config,$this->request);
+ } else {
+ if (!$this->access->check("read")){
+ LogMaster::log("Access control: read operation blocked");
+ echo "Access denied";
+ die();
+ }
+ $wrap = new SortInterface($this->request);
+ $this->apply_sorts($wrap);
+ $this->event->trigger("beforeSort",$wrap);
+ $wrap->store();
+
+ $wrap = new FilterInterface($this->request);
+ $this->apply_filters($wrap);
+ $this->event->trigger("beforeFilter",$wrap);
+ $wrap->store();
+
+ if ($this->model && method_exists($this->model, "get")){
+ $this->sql = new ArrayDBDataWrapper();
+ $result = new ArrayQueryWrapper(call_user_func(array($this->model, "get"), $this->request));
+ $out = $this->output_as_xml($result);
+ } else {
+ $out = $this->output_as_xml($this->get_resource());
+
+ if ($out !== null) return $out;
+ }
+
+ }
+ }
+ $this->end_run();
+ }
+
+
+ /*! empty call which used for tree-logic
+ * to prevent code duplicating
+ */
+ protected function set_relation() {}
+
+ /*! gets resource for rendering
+ */
+ protected function get_resource() {
+ //die(var_dump($this->sql->select($this->request)));
+ return $this->sql->select($this->request);
+ }
+
+
+ /*! prevent SQL injection through column names
+ replace dangerous chars in field names
+ @param str
+ incoming field name
+ @return
+ safe field name
+ */
+ protected function safe_field_name($str){
+ return strtok($str, " \n\t;',");
+ }
+
+ /*! limit max count of records
+ connector will ignore any records after outputing max count
+ @param limit
+ max count of records
+ @return
+ none
+ */
+ public function set_limit($limit){
+ $this->limit = $limit;
+ }
+
+
+ public function limit($start, $count, $sort_field=false, $sort_dir=false){
+ $this->request->set_limit($start, $count);
+ if ($sort_field)
+ $this->request->set_sort($sort_field, $sort_dir);
+ }
+
+ protected function parse_request_mode(){
+ //detect edit mode
+ if (isset($_GET["editing"])){
+ $this->editing=true;
+ } else if (isset($_POST["ids"])){
+ $this->editing=true;
+ LogMaster::log('While there is no edit mode mark, POST parameters similar to edit mode detected. \n Switching to edit mode ( to disable behavior remove POST[ids]');
+ } else if (isset($_GET['dhx_version'])){
+ $this->updating = true;
+ }
+ }
+
+ /*! parse incoming request, detects commands and modes
+ */
+ protected function parse_request(){
+ //set default dyn. loading params, can be reset in child classes
+ if ($this->dload)
+ $this->request->set_limit(0,$this->dload);
+ else if ($this->limit)
+ $this->request->set_limit(0,$this->limit);
+
+ if (isset($_GET["posStart"]) && isset($_GET["count"])) {
+ $this->request->set_limit($_GET["posStart"],$_GET["count"]);
+ }
+
+ $this->parse_request_mode();
+
+ if ($this->live_update && ($this->updating || $this->editing)){
+ $this->request->set_version($_GET["dhx_version"]);
+ $this->request->set_user($_GET["dhx_user"]);
+ }
+
+ if (isset($_GET[Connector::$sort_var]))
+ foreach($_GET[Connector::$sort_var] as $k => $v){
+ $k = $this->safe_field_name($k);
+ $this->request->set_sort($this->resolve_parameter($k),$v);
+ }
+
+ if (isset($_GET[Connector::$filter_var]))
+ foreach($_GET[Connector::$filter_var] as $k => $v){
+ $k = $this->safe_field_name($k);
+ if ($v !== "")
+ $this->request->set_filter($this->resolve_parameter($k),$v);
+ }
+
+ $this->check_csrf();
+ }
+
+ protected function check_csrf(){
+ $key = ConnectorSecurity::checkCSRF($this->editing);
+ if ($key !== "")
+ $this->add_top_attribute(ConnectorSecurity::$security_var, $key);
+ }
+
+ /*! convert incoming request name to the actual DB name
+ @param name
+ incoming parameter name
+ @return
+ name of related DB field
+ */
+ protected function resolve_parameter($name){
+ return $name;
+ }
+
+
+ /*! replace xml unsafe characters
+
+ @param string
+ string to be escaped
+ @return
+ escaped string
+ */
+ protected function xmlentities($string) {
+ return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string);
+ }
+
+ public function getRecord($id){
+ LogMaster::log("Retreiving data for record: ".$id);
+ $source = new DataRequestConfig($this->request);
+ $source->set_filter($this->config->id["name"],$id, "=");
+
+ $res = $this->sql->select($source);
+
+ $temp = $this->data_separator;
+ $this->data_separator="";
+ $output = $this->render_set($res);
+ $this->data_separato=$temp;
+
+ return $output;
+ }
+
+ /*! render from DB resultset
+ @param res
+ DB resultset
+ process commands, output requested data as XML
+ */
+ protected function render_set($res){
+ return $this->render->render_set($res, $this->names["item_class"], $this->dload, $this->data_separator, $this->config, $this->mix);
+ }
+
+ /*! output fetched data as XML
+ @param res
+ DB resultset
+ */
+ protected function output_as_xml($res){
+ $result = $this->render_set($res);
+ if ($this->simple) return $result;
+
+ $start="<?xml version='1.0' encoding='".$this->encoding."' ?>".$this->xml_start();
+ $end=$result.$this->xml_end();
+
+ if ($this->as_string) return $start.$end;
+
+ $out = new OutputWriter($start, $end);
+ $this->event->trigger("beforeOutput", $this, $out);
+ $out->output("", true, $this->encoding);
+ }
+
+
+ /*! end processing
+ stop execution timer, kill the process
+ */
+ protected function end_run(){
+ $time=microtime(true)-$this->exec_time;
+ LogMaster::log("Done in {$time}s");
+ flush();
+ die();
+ }
+
+ /*! set xml encoding
+
+ methods sets only attribute in XML, no real encoding conversion occurs
+ @param encoding
+ value which will be used as XML encoding
+ */
+ public function set_encoding($encoding){
+ $this->encoding=$encoding;
+ }
+
+ /*! enable or disable dynamic loading mode
+
+ @param count
+ count of rows loaded from server, actual only for grid-connector, can be skiped in other cases.
+ If value is a false or 0 - dyn. loading will be disabled
+ */
+ public function dynamic_loading($count){
+ $this->dload=$count;
+ }
+
+ /*! enable or disable data reordering
+
+ @param name
+ name of field, which will be used for order storing, optional
+ by default 'sortorder' field will be used
+ */
+ public function enable_order($name = true){
+ if ($name === true)
+ $name = "sortorder";
+
+ $this->sort($name);
+ $this->access->allow("order");
+ $this->request->set_order($name);
+ $this->order = $name;
+ }
+
+ /*! enable logging
+
+ @param path
+ path to the log file. If set as false or empty strig - logging will be disabled
+ @param client_log
+ enable output of log data to the client side
+ */
+ public function enable_log($path=true,$client_log=false){
+ LogMaster::enable_log($path,$client_log);
+ }
+
+ /*! provides infor about current processing mode
+ @return
+ true if processing dataprocessor command, false otherwise
+ */
+ public function is_select_mode(){
+ $this->parse_request_mode();
+ return !$this->editing;
+ }
+
+ public function is_first_call(){
+ $this->parse_request_mode();
+ return !($this->editing || $this->updating || $this->request->get_start() || isset($_GET['dhx_no_header']));
+
+ }
+
+ /*! renders self as xml, starting part
+ */
+ protected function xml_start(){
+ $attributes = "";
+
+ if ($this->dload){
+ //info for dyn. loadin
+ if ($pos=$this->request->get_start())
+ $attributes .= " pos='".$pos."'";
+ else
+ $attributes .= " total_count='".$this->sql->get_size($this->request)."'";
+ }
+ foreach($this->attributes as $k=>$v)
+ $attributes .= " ".$k."='".$v."'";
+
+ return "<data".$attributes.">";
+ }
+ /*! renders self as xml, ending part
+ */
+ protected function xml_end(){
+ $this->fill_collections();
+ if (isset($this->extra_output))
+ return $this->extra_output."</data>";
+ else
+ return "</data>";
+ }
+
+ protected function fill_collections($list=""){
+ foreach ($this->options as $k=>$v) {
+ $name = $k;
+ $this->extra_output.="<coll_options for='{$name}'>";
+ if (!is_string($this->options[$name]))
+ $this->extra_output.=$this->options[$name]->render();
+ else
+ $this->extra_output.=$this->options[$name];
+ $this->extra_output.="</coll_options>";
+ }
+ }
+
+ /*! assign options collection to the column
+
+ @param name
+ name of the column
+ @param options
+ array or connector object
+ */
+ public function set_options($name,$options){
+ if (is_array($options)){
+ $str="";
+ foreach($options as $k => $v)
+ $str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
+ $options=$str;
+ }
+ $this->options[$name]=$options;
+ }
+
+
+ public function insert($data) {
+ $action = new DataAction('inserted', false, $data);
+ $request = new DataRequestConfig();
+ $request->set_source($this->request->get_source());
+
+ $this->config->limit_fields($data);
+ $this->sql->insert($action,$request);
+ $this->config->restore_fields($data);
+
+ return $action->get_new_id();
+ }
+
+ public function delete($id) {
+ $action = new DataAction('deleted', $id, array());
+ $request = new DataRequestConfig();
+ $request->set_source($this->request->get_source());
+
+ $this->sql->delete($action,$request);
+ return $action->get_status();
+ }
+
+ public function update($data) {
+ $action = new DataAction('updated', $data[$this->config->id["name"]], $data);
+ $request = new DataRequestConfig();
+ $request->set_source($this->request->get_source());
+
+ $this->config->limit_fields($data);
+ $this->sql->update($action,$request);
+ $this->config->restore_fields($data);
+
+ return $action->get_status();
+ }
+
+ /*! sets actions_table for Optimistic concurrency control mode and start it
+ @param table_name
+ name of database table which will used for saving actions
+ @param url
+ url used for update notifications
+ */
+ public function enable_live_update($table, $url=false){
+ $this->live_update = new DataUpdate($this->sql, $this->config, $this->request, $table,$url);
+ $this->live_update->set_event($this->event,$this->names["item_class"]);
+ $this->event->attach("beforeOutput", Array($this->live_update, "version_output"));
+ $this->event->attach("beforeFiltering", Array($this->live_update, "get_updates"));
+ $this->event->attach("beforeProcessing", Array($this->live_update, "check_collision"));
+ $this->event->attach("afterProcessing", Array($this->live_update, "log_operations"));
+ }
+
+ /*! render() returns result as string or send to response
+ */
+ public function asString($as_string) {
+ $this->as_string = $as_string;
+ }
+
+ public function simple_render() {
+ $this->simple = true;
+ return $this->render();
+ }
+
+ public function filter($name, $value = false, $operation = '=') {
+ $this->filters[] = array('name' => $name, 'value' => $value, 'operation' => $operation);
+ }
+
+ public function clear_filter() {
+ $this->filters = array();
+ $this->request->set_filters(array());
+ }
+
+ protected function apply_filters($wrap) {
+ for ($i = 0; $i < count($this->filters); $i++) {
+ $f = $this->filters[$i];
+ $wrap->add($f['name'], $f['value'], $f['operation']);
+ }
+ }
+
+ public function sort($name, $direction = false) {
+ $this->sorts[] = array('name' => $name, 'direction' => $direction);
+ }
+
+ protected function apply_sorts($wrap) {
+ for ($i = 0; $i < count($this->sorts); $i++) {
+ $s = $this->sorts[$i];
+ $wrap->add($s['name'], $s['direction']);
+ }
+ }
+
+ public function mix($name, $value, $filter=false) {
+ $this->mix[] = Array('name'=>$name, 'value'=>$value, 'filter'=>$filter);
+ }
+} \ No newline at end of file
diff --git a/codebase/convert.php b/codebase/ConvertService.php
index f24922c..9fa3261 100644
--- a/codebase/convert.php
+++ b/codebase/ConvertService.php
@@ -1,4 +1,8 @@
<?php
+
+namespace DHTMLX\Connector;
+
+use DHTMLX\Connector\Tools\EventMaster;
/*
@author dhtmlx.com
@license GPL, see license.txt
@@ -8,9 +12,9 @@ class ConvertService{
private $type;
private $name;
private $inline;
-
+
public function __construct($url){
- $this->url = $url;
+ $this->url = $url;
$this->pdf();
EventMaster::attach_static("connectorInit",array($this, "handle"));
}
@@ -31,16 +35,16 @@ class ConvertService{
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
- header('Content-Transfer-Encoding: binary');
-
+ header('Content-Transfer-Encoding: binary');
+
header('Content-Length: '.$size);
if ($inline)
- header('Content-Disposition: inline; filename="'.$name.'";');
+ header('Content-Disposition: inline; filename="'.$name.'";');
else
header('Content-Disposition: attachment; filename="'.basename($name).'";');
- }
+ }
public function convert($conn, $out){
-
+
$str_out = str_replace("<rows>","<rows profile='color'>", $out);
$str_out = str_replace("<head>","<head><columns>", $str_out);
$str_out = str_replace("</head>","</columns></head>", $str_out);
@@ -55,15 +59,13 @@ class ConvertService{
curl_setopt($handle, CURLOPT_HEADER, false);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_POSTFIELDS, "grid_xml=".urlencode($str_out));
-
-
+
+
$out->reset();
$out->set_type("pdf");
$out->add(curl_exec($handle));
$this->as_file(strlen((string)$out), $this->name, $this->inline);
-
+
curl_close($handle);
}
-}
-
-?> \ No newline at end of file
+} \ No newline at end of file
diff --git a/codebase/Data/DataAction.php b/codebase/Data/DataAction.php
new file mode 100644
index 0000000..8e4b5dd
--- /dev/null
+++ b/codebase/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/Data/DataItem.php b/codebase/Data/DataItem.php
new file mode 100644
index 0000000..b980d9c
--- /dev/null
+++ b/codebase/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/Data/DataItemUpdate.php b/codebase/Data/DataItemUpdate.php
new file mode 100644
index 0000000..ad97be2
--- /dev/null
+++ b/codebase/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/Data/DataProcessor.php b/codebase/Data/DataProcessor.php
new file mode 100644
index 0000000..973753a
--- /dev/null
+++ b/codebase/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/Data/DataUpdate.php b/codebase/Data/DataUpdate.php
new file mode 100644
index 0000000..8fc1c46
--- /dev/null
+++ b/codebase/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/Data/GridDataProcessor.php b/codebase/Data/GridDataProcessor.php
new file mode 100644
index 0000000..9b487eb
--- /dev/null
+++ b/codebase/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/Data/TreeDataItem.php b/codebase/Data/TreeDataItem.php
new file mode 100644
index 0000000..561d495
--- /dev/null
+++ b/codebase/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/Data/TreeDataProcessor.php b/codebase/Data/TreeDataProcessor.php
new file mode 100644
index 0000000..dca6a8f
--- /dev/null
+++ b/codebase/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
diff --git a/codebase/DataStorage/ArrayDBDataWrapper.php b/codebase/DataStorage/ArrayDBDataWrapper.php
new file mode 100644
index 0000000..a806161
--- /dev/null
+++ b/codebase/DataStorage/ArrayDBDataWrapper.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+
+class ArrayDBDataWrapper extends DBDataWrapper
+{
+ public function get_next($res)
+ {
+ if ($res->index < sizeof($res->data))
+ return $res->data[$res->index++];
+ }
+
+ public function select($sql)
+ {
+ if ($this->config->relation_id["db_name"] == "") {
+ if ($sql->get_relation() == "0" || $sql->get_relation() == "") {
+ return new ArrayQueryWrapper($this->connection);
+ } else {
+ return new ArrayQueryWrapper(array());
+ }
+ }
+
+ $relation_id = $this->config->relation_id["db_name"];
+
+ for ($i = 0; $i < count($this->connection); $i++) {
+ $item = $this->connection[$i];
+ if (!isset($item[$relation_id])) continue;
+ if ($item[$relation_id] == $sql->get_relation())
+ $result[] = $item;
+
+ }
+
+ return new ArrayQueryWrapper($result);
+ }
+
+ public function query($sql)
+ {
+ throw new Exception("Not implemented");
+ }
+
+ public function escape($value)
+ {
+ throw new Exception("Not implemented");
+ }
+
+ public function get_new_id()
+ {
+ throw new Exception("Not implemented");
+ }
+} \ No newline at end of file
diff --git a/codebase/DataStorage/ArrayQueryWrapper.php b/codebase/DataStorage/ArrayQueryWrapper.php
new file mode 100644
index 0000000..c922bd8
--- /dev/null
+++ b/codebase/DataStorage/ArrayQueryWrapper.php
@@ -0,0 +1,9 @@
+<?php
+namespace DHTMLX\Connector\DataStorage;
+
+class ArrayQueryWrapper{
+ public function __construct($data){
+ $this->data = $data;
+ $this->index = 0;
+ }
+} \ No newline at end of file
diff --git a/codebase/DataStorage/DBDataWrapper.php b/codebase/DataStorage/DBDataWrapper.php
new file mode 100644
index 0000000..1311866
--- /dev/null
+++ b/codebase/DataStorage/DBDataWrapper.php
@@ -0,0 +1,456 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: user
+ * Date: 26.3.15
+ * Time: 15.50
+ */
+
+namespace DHTMLX\Connector\DataStorage;
+
+abstract class DBDataWrapper extends DataWrapper
+{
+ private $transaction = false; //!< type of transaction
+ private $sequence = false;//!< sequence name
+ private $sqls = array();//!< predefined sql actions
+
+
+ /*! assign named sql query
+ @param name
+ name of sql query
+ @param data
+ sql query text
+ */
+ public function attach($name, $data)
+ {
+ $name = strtolower($name);
+ $this->sqls[$name] = $data;
+ }
+
+ /*! replace vars in sql string with actual values
+
+ @param matches
+ array of field name matches
+ @return
+ value for the var name
+ */
+ public function get_sql_callback($matches)
+ {
+ return $this->escape($this->temp->get_value($matches[1]));
+ }
+
+ public function get_sql($name, $data)
+ {
+ $name = strtolower($name);
+ if (!array_key_exists($name, $this->sqls)) return "";
+
+
+ $str = $this->sqls[$name];
+ $this->temp = $data; //dirty
+ $str = preg_replace_callback('|\{([^}]+)\}|', array($this, "get_sql_callback"), $str);
+ unset ($this->temp); //dirty
+ return $str;
+ }
+
+ public function new_record_order($action, $source)
+ {
+ $order = $source->get_order();
+ if ($order) {
+ $table = $source->get_source();
+ $id = $this->config->id["db_name"];
+ $idvalue = $action->get_new_id();
+
+ $max = $this->queryOne("SELECT MAX($order) as dhx_maxvalue FROM $table");
+ $dhx_maxvalue = $max["dhx_maxvalue"] + 1;
+
+ $this->query("UPDATE $table SET $order = $dhx_maxvalue WHERE $id = $idvalue");
+ }
+ }
+
+ public function order($data, $source)
+ {
+ //id of moved item
+ $id1 = $this->escape($data->get_value("id"));
+ //id of target item
+ $target = $data->get_value("target");
+ if (strpos($target, "next:") !== false) {
+ $dropnext = true;
+ $id2 = str_replace("next:", "", $target);
+ } else {
+ $id2 = $target;
+ }
+ $id2 = $this->escape($id2);
+
+
+ //for tree like components we need to limit out queries to the affected branch only
+ $relation_select = $relation_update = $relation_sql_out = $relation_sql = "";
+ if ($this->config->relation_id["name"]) {
+ $relation = $data->get_value($this->config->relation_id["name"]);
+ if ($relation !== false && $relation !== "") {
+ $relation_sql = " " . $this->config->relation_id["db_name"] . " = '" . $this->escape($relation) . "' AND ";
+ $relation_select = $this->config->relation_id["db_name"] . " as dhx_parent, ";
+ $relation_update = " " . $this->config->relation_id["db_name"] . " = '" . $this->escape($relation) . "', ";
+ }
+ }
+
+
+ $name = $source->get_order();
+ $table = $source->get_source();
+ $idkey = $this->config->id["db_name"];
+
+ $source = $this->queryOne("select $relation_select $name as dhx_index from $table where $idkey = '$id1'");
+ $source_index = $source["dhx_index"] ? $source["dhx_index"] : 0;
+ if ($relation_sql)
+ $relation_sql_out = " " . $this->config->relation_id["db_name"] . " = '" . $this->escape($source["dhx_parent"]) . "' AND ";
+
+ $this->query("update $table set $name = $name - 1 where $relation_sql_out $name >= $source_index");
+
+ if ($id2 !== "") {
+ $target = $this->queryOne("select $name as dhx_index from $table where $idkey = '$id2'");
+ $target_index = $target["dhx_index"];
+ if (!$target_index)
+ $target_index = 0;
+ if ($dropnext)
+ $target_index += 1;
+ $this->query("update $table set $name = $name + 1 where $relation_sql $name >= $target_index");
+ } else {
+ $target = $this->queryOne("select max($name) as dhx_index from $table");
+ $target_index = ($target["dhx_index"] ? $target["dhx_index"] : 0) + 1;
+ }
+
+ $this->query("update $table set $relation_update $name = $target_index where $idkey = '$id1'");
+ }
+
+ public function insert($data, $source)
+ {
+ $sql = $this->insert_query($data, $source);
+ $this->query($sql);
+ $data->success($this->get_new_id());
+ }
+
+ public function delete($data, $source)
+ {
+ $sql = $this->delete_query($data, $source);
+ $this->query($sql);
+ $data->success();
+ }
+
+ public function update($data, $source)
+ {
+ $sql = $this->update_query($data, $source);
+ $this->query($sql);
+ $data->success();
+ }
+
+ public function select($source)
+ {
+ $select = $source->get_fieldset();
+ if (!$select) {
+ $select = $this->config->db_names_list($this);
+ $select = implode(",", $select);
+ }
+
+ $where = $this->build_where($source->get_filters(), $source->get_relation());
+ $sort = $this->build_order($source->get_sort_by());
+
+ return $this->query($this->select_query($select, $source->get_source(), $where, $sort, $source->get_start(), $source->get_count()));
+ }
+
+ public function queryOne($sql)
+ {
+ $res = $this->query($sql);
+ if ($res)
+ return $this->get_next($res);
+ return false;
+ }
+
+ public function get_size($source)
+ {
+ $count = new DataRequestConfig($source);
+
+ $count->set_fieldset("COUNT(*) as DHX_COUNT ");
+ $count->set_sort(null);
+ $count->set_limit(0, 0);
+
+ $res = $this->select($count);
+ $data = $this->get_next($res);
+ if (array_key_exists("DHX_COUNT", $data)) return $data["DHX_COUNT"];
+ else return $data["dhx_count"]; //postgresql
+ }
+
+ public function get_variants($name, $source)
+ {
+ $count = new DataRequestConfig($source);
+ $count->set_fieldset("DISTINCT " . $this->escape_name($name) . " as value");
+ $sort = new SortInterface($source);
+ $count->set_sort(null);
+ for ($i = 0; $i < count($sort->rules); $i++) {
+ if ($sort->rules[$i]['name'] == $name)
+ $count->set_sort($sort->rules[$i]['name'], $sort->rules[$i]['direction']);
+ }
+ $count->set_limit(0, 0);
+ return $this->select($count);
+ }
+
+ public function sequence($sec)
+ {
+ $this->sequence = $sec;
+ }
+
+ /*! create an sql string for filtering rules
+
+ @param rules
+ set of filtering rules
+ @param relation
+ name of relation id field
+ @return
+ sql string with filtering rules
+ */
+ protected function build_where($rules,$relation=false){
+ $sql=array();
+ for ($i=0; $i < sizeof($rules); $i++)
+ if (is_string($rules[$i]))
+ array_push($sql,"(".$rules[$i].")");
+ else
+ if ($rules[$i]["value"]!=""){
+ if (!$rules[$i]["operation"])
+ array_push($sql,$this->escape_name($rules[$i]["name"])." LIKE '%".$this->escape($rules[$i]["value"])."%'");
+ else
+ array_push($sql,$this->escape_name($rules[$i]["name"])." ".$rules[$i]["operation"]." '".$this->escape($rules[$i]["value"])."'");
+ }
+
+ if ($relation !== false && $relation !== ""){
+ $relsql = $this->escape_name($this->config->relation_id["db_name"])." = '".$this->escape($relation)."'";
+ if ($relation == "0")
+ $relsql = "( ".$relsql." OR ".$this->escape_name($this->config->relation_id["db_name"])." IS NULL )";
+
+ array_push($sql,$relsql);
+ }
+ return implode(" AND ",$sql);
+ }
+ /*! convert sorting rules to sql string
+
+ @param by
+ set of sorting rules
+ @return
+ sql string for set of sorting rules
+ */
+ protected function build_order($by){
+ if (!sizeof($by)) return "";
+ $out = array();
+ for ($i=0; $i < sizeof($by); $i++)
+ if (is_string($by[$i]))
+ $out[] = $by[$i];
+ else if ($by[$i]["name"])
+ $out[]=$this->escape_name($by[$i]["name"])." ".$by[$i]["direction"];
+ return implode(",",$out);
+ }
+
+ /*! generates sql code for select operation
+
+ @param select
+ list of fields in select
+ @param from
+ table name
+ @param where
+ list of filtering rules
+ @param sort
+ list of sorting rules
+ @param start
+ start index of fetching
+ @param count
+ count of records to fetch
+ @return
+ sql string for select operation
+ */
+ protected function select_query($select,$from,$where,$sort,$start,$count){
+ if (!$from)
+ return $select;
+
+ $sql="SELECT ".$select." FROM ".$from;
+ if ($where) $sql.=" WHERE ".$where;
+ if ($sort) $sql.=" ORDER BY ".$sort;
+ if ($start || $count) $sql.=" LIMIT ".$start.",".$count;
+ return $sql;
+ }
+ /*! generates update sql
+
+ @param data
+ DataAction object
+ @param request
+ DataRequestConfig object
+ @return
+ sql string, which updates record with provided data
+ */
+ protected function update_query($data,$request){
+ $sql="UPDATE ".$request->get_source()." SET ";
+ $temp=array();
+ for ($i=0; $i < sizeof($this->config->text); $i++) {
+ $step=$this->config->text[$i];
+
+ if ($data->get_value($step["name"])===Null)
+ $step_value ="Null";
+ else
+ $step_value = "'".$this->escape($data->get_value($step["name"]))."'";
+ $temp[$i]= $this->escape_name($step["db_name"])."=". $step_value;
+ }
+ if ($relation = $this->config->relation_id["db_name"]){
+ $temp[]= $this->escape_name($relation)."='".$this->escape($data->get_value($relation))."'";
+ }
+ $sql.=implode(",",$temp)." WHERE ".$this->escape_name($this->config->id["db_name"])."='".$this->escape($data->get_id())."'";
+
+ //if we have limited set - set constraints
+ $where=$this->build_where($request->get_filters());
+ if ($where) $sql.=" AND (".$where.")";
+
+ return $sql;
+ }
+
+ /*! generates delete sql
+
+ @param data
+ DataAction object
+ @param request
+ DataRequestConfig object
+ @return
+ sql string, which delete record
+ */
+ protected function delete_query($data,$request){
+ $sql="DELETE FROM ".$request->get_source();
+ $sql.=" WHERE ".$this->escape_name($this->config->id["db_name"])."='".$this->escape($data->get_id())."'";
+
+ //if we have limited set - set constraints
+ $where=$this->build_where($request->get_filters());
+ if ($where) $sql.=" AND (".$where.")";
+
+ return $sql;
+ }
+
+ /*! generates insert sql
+
+ @param data
+ DataAction object
+ @param request
+ DataRequestConfig object
+ @return
+ sql string, which inserts new record with provided data
+ */
+ protected function insert_query($data,$request){
+ $temp_n=array();
+ $temp_v=array();
+ foreach($this->config->text as $k => $v){
+ $temp_n[$k]=$this->escape_name($v["db_name"]);
+ if ($data->get_value($v["name"])===Null)
+ $temp_v[$k]="Null";
+ else
+ $temp_v[$k]="'".$this->escape($data->get_value($v["name"]))."'";
+ }
+ if ($relation = $this->config->relation_id["db_name"]){
+ $temp_n[]=$this->escape_name($relation);
+ $temp_v[]="'".$this->escape($data->get_value($relation))."'";
+ }
+ if ($this->sequence){
+ $temp_n[]=$this->escape_name($this->config->id["db_name"]);
+ $temp_v[]=$this->sequence;
+ }
+
+ $sql="INSERT INTO ".$request->get_source()."(".implode(",",$temp_n).") VALUES (".implode(",",$temp_v).")";
+
+ return $sql;
+ }
+
+ /*! sets the transaction mode, used by dataprocessor
+
+ @param mode
+ mode name
+ */
+ public function set_transaction_mode($mode){
+ if ($mode!="none" && $mode!="global" && $mode!="record")
+ throw new Exception("Unknown transaction mode");
+ $this->transaction=$mode;
+ }
+ /*! returns true if global transaction mode was specified
+ @return
+ true if global transaction mode was specified
+ */
+ public function is_global_transaction(){
+ return $this->transaction == "global";
+ }
+ /*! returns true if record transaction mode was specified
+ @return
+ true if record transaction mode was specified
+ */
+ public function is_record_transaction(){
+ return $this->transaction == "record";
+ }
+
+
+ public function begin_transaction(){
+ $this->query("BEGIN");
+ }
+ public function commit_transaction(){
+ $this->query("COMMIT");
+ }
+ public function rollback_transaction(){
+ $this->query("ROLLBACK");
+ }
+
+ /*! exec sql string
+
+ @param sql
+ sql string
+ @return
+ sql result set
+ */
+ abstract public function query($sql);
+ /*! returns next record from result set
+
+ @param res
+ sql result set
+ @return
+ hash of data
+ */
+ abstract public function get_next($res);
+ /*! returns new id value, for newly inserted row
+ @return
+ new id value, for newly inserted row
+ */
+ abstract public function get_new_id();
+ /*! escape data to prevent sql injections
+ @param data
+ unescaped data
+ @return
+ escaped data
+ */
+ abstract public function escape($data);
+
+ /*! escape field name to prevent sql reserved words conflict
+ @param data
+ unescaped data
+ @return
+ escaped data
+ */
+ public function escape_name($data){
+ return $data;
+ }
+
+ /*! get list of tables in the database
+
+ @return
+ array of table names
+ */
+ public function tables_list() {
+ throw new Exception("Not implemented");
+ }
+
+ /*! returns list of fields for the table in question
+
+ @param table
+ name of table in question
+ @return
+ array of field names
+ */
+ public function fields_list($table) {
+ throw new Exception("Not implemented");
+ }
+} \ No newline at end of file
diff --git a/codebase/DataStorage/DataConfig.php b/codebase/DataStorage/DataConfig.php
new file mode 100644
index 0000000..c10fd2d
--- /dev/null
+++ b/codebase/DataStorage/DataConfig.php
@@ -0,0 +1,227 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+/*! manager of data configuration
+**/
+class DataConfig{
+ public $id;////!< name of ID field
+ public $relation_id;//!< name or relation ID field
+ public $text;//!< array of text fields
+ public $data;//!< array of all known fields , fields which exists only in this collection will not be included in dataprocessor's operations
+
+
+ /*! converts self to the string, for logging purposes
+ **/
+ public function __toString(){
+ $str="ID:{$this->id['db_name']}(ID:{$this->id['name']})\n";
+ $str.="Relation ID:{$this->relation_id['db_name']}({$this->relation_id['name']})\n";
+ $str.="Data:";
+ for ($i=0; $i<sizeof($this->text); $i++)
+ $str.="{$this->text[$i]['db_name']}({$this->text[$i]['name']}),";
+
+ $str.="\nExtra:";
+ for ($i=0; $i<sizeof($this->data); $i++)
+ $str.="{$this->data[$i]['db_name']}({$this->data[$i]['name']}),";
+
+ return $str;
+ }
+
+ /*! removes un-used fields from configuration
+ @param name
+ name of field , which need to be preserved
+ */
+ public function minimize($name){
+ for ($i=0; $i < sizeof($this->text); $i++){
+ if ($this->text[$i]["db_name"]==$name || $this->text[$i]["name"]==$name){
+ $this->text[$i]["name"]="value";
+ $this->data=array($this->text[$i]);
+ $this->text=array($this->text[$i]);
+ return;
+ }
+ }
+ throw new Exception("Incorrect dataset minimization, master field not found.");
+ }
+
+ public function limit_fields($data){
+ if (isset($this->full_field_list))
+ $this->restore_fields();
+ $this->full_field_list = $this->text;
+ $this->text = array();
+
+ for ($i=0; $i < sizeof($this->full_field_list); $i++) {
+ if (array_key_exists($this->full_field_list[$i]["name"],$data))
+ $this->text[] = $this->full_field_list[$i];
+ }
+ }
+
+ public function restore_fields(){
+ if (isset($this->full_field_list))
+ $this->text = $this->full_field_list;
+ }
+
+ /*! initialize inner state by parsing configuration parameters
+
+ @param id
+ name of id field
+ @param fields
+ name of data field(s)
+ @param extra
+ name of extra field(s)
+ @param relation
+ name of relation field
+
+ */
+ public function init($id,$fields,$extra,$relation){
+ $this->id = $this->parse($id,false);
+ $this->text = $this->parse($fields,true);
+ $this->data = array_merge($this->text,$this->parse($extra,true));
+ $this->relation_id = $this->parse($relation,false);
+ }
+
+ /*! parse configuration string
+
+ @param key
+ key string from configuration
+ @param mode
+ multi names flag
+ @return
+ parsed field name object
+ */
+ private function parse($key,$mode){
+ if ($mode){
+ if (!$key) return array();
+ $key=explode(",",$key);
+ for ($i=0; $i < sizeof($key); $i++)
+ $key[$i]=$this->parse($key[$i],false);
+ return $key;
+ }
+ $key=explode("(",$key);
+ $data=array("db_name"=>trim($key[0]), "name"=>trim($key[0]));
+ if (sizeof($key)>1)
+ $data["name"]=substr(trim($key[1]),0,-1);
+ return $data;
+ }
+
+ /*! constructor
+ init public collectons
+ @param proto
+ DataConfig object used as prototype for new one, optional
+ */
+ public function __construct($proto=false){
+ if ($proto!==false)
+ $this->copy($proto);
+ else {
+ $this->text=array();
+ $this->data=array();
+ $this->id=array("name"=>"dhx_auto_id", "db_name"=>"dhx_auto_id");
+ $this->relation_id=array("name"=>"", "db_name"=>"");
+ }
+ }
+
+ /*! copy properties from source object
+
+ @param proto
+ source object
+ */
+ public function copy($proto){
+ $this->id = $proto->id;
+ $this->relation_id = $proto->relation_id;
+ $this->text = $proto->text;
+ $this->data = $proto->data;
+ }
+
+ /*! returns list of data fields (db_names)
+ @return
+ list of data fields ( ready to be used in SQL query )
+ */
+ public function db_names_list($db){
+ $out=array();
+ if ($this->id["db_name"])
+ array_push($out,$db->escape_name($this->id["db_name"]));
+ if ($this->relation_id["db_name"])
+ array_push($out,$db->escape_name($this->relation_id["db_name"]));
+
+ for ($i=0; $i < sizeof($this->data); $i++){
+ if ($this->data[$i]["db_name"]!=$this->data[$i]["name"])
+ $out[]=$db->escape_name($this->data[$i]["db_name"])." as ".$this->data[$i]["name"];
+ else
+ $out[]=$db->escape_name($this->data[$i]["db_name"]);
+ }
+
+ return $out;
+ }
+
+ /*! add field to dataset config ($text collection)
+
+ added field will be used in all auto-generated queries
+ @param name
+ name of field
+ @param aliase
+ aliase of field, optional
+ */
+ public function add_field($name,$aliase=false){
+ if ($aliase===false) $aliase=$name;
+
+ //adding to list of data-active fields
+ if ($this->id["db_name"]==$name || $this->relation_id["db_name"] == $name){
+ LogMaster::log("Field name already used as ID, be sure that it is really necessary.");
+ }
+ if ($this->is_field($name,$this->text)!=-1)
+ throw new Exception('Data field already registered: '.$name);
+ array_push($this->text,array("db_name"=>$name,"name"=>$aliase));
+
+ //adding to list of all fields as well
+ if ($this->is_field($name,$this->data)==-1)
+ array_push($this->data,array("db_name"=>$name,"name"=>$aliase));
+
+ }
+
+ /*! remove field from dataset config ($text collection)
+
+ removed field will be excluded from all auto-generated queries
+ @param name
+ name of field, or aliase of field
+ */
+ public function remove_field($name){
+ $ind = $this->is_field($name);
+ if ($ind==-1) throw new Exception('There was no such data field registered as: '.$name);
+ array_splice($this->text,$ind,1);
+ //we not deleting field from $data collection, so it will not be included in data operation, but its data still available
+ }
+
+ /*! remove field from dataset config ($text and $data collections)
+
+ removed field will be excluded from all auto-generated queries
+ @param name
+ name of field, or aliase of field
+ */
+ public function remove_field_full($name){
+ $ind = $this->is_field($name);
+ if ($ind==-1) throw new Exception('There was no such data field registered as: '.$name);
+ array_splice($this->text,$ind,1);
+
+ $ind = $this->is_field($name, $this->data);
+ if ($ind==-1) throw new Exception('There was no such data field registered as: '.$name);
+ array_splice($this->data,$ind,1);
+ }
+
+ /*! check if field is a part of dataset
+
+ @param name
+ name of field
+ @param collection
+ collection, against which check will be done, $text collection by default
+ @return
+ returns true if field already a part of dataset, otherwise returns true
+ */
+ public function is_field($name,$collection = false){
+ if (!$collection)
+ $collection=$this->text;
+
+ for ($i=0; $i<sizeof($collection); $i++)
+ if ($collection[$i]["name"] == $name || $collection[$i]["db_name"] == $name) return $i;
+ return -1;
+ }
+
+
+} \ No newline at end of file
diff --git a/codebase/DataStorage/DataRequestConfig.php b/codebase/DataStorage/DataRequestConfig.php
new file mode 100644
index 0000000..bb2c750
--- /dev/null
+++ b/codebase/DataStorage/DataRequestConfig.php
@@ -0,0 +1,284 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+
+/*! manager of data request
+**/
+class DataRequestConfig{
+ private $filters; //!< array of filtering rules
+ private $relation=false; //!< ID or other element used for linking hierarchy
+ private $sort_by; //!< sorting field
+ private $start; //!< start of requested data
+ private $count; //!< length of requested data
+
+ private $order = false;
+ private $user;
+ private $version;
+
+ //for render_sql
+ private $source; //!< souce table or another source destination
+ private $fieldset; //!< set of data, which need to be retrieved from source
+
+ /*! constructor
+
+ @param proto
+ DataRequestConfig object, optional, if provided then new request object will copy all properties from provided one
+ */
+ public function __construct($proto=false){
+ if ($proto)
+ $this->copy($proto);
+ else{
+ $start=0;
+ $this->filters=array();
+ $this->sort_by=array();
+ }
+ }
+
+ /*! copy parameters of source object into self
+
+ @param proto
+ source object
+ */
+ public function copy($proto){
+ $this->filters =$proto->get_filters();
+ $this->sort_by =$proto->get_sort_by();
+ $this->count =$proto->get_count();
+ $this->start =$proto->get_start();
+ $this->source =$proto->get_source();
+ $this->fieldset =$proto->get_fieldset();
+ $this->relation =$proto->get_relation();
+ $this->user = $proto->user;
+ $this->version = $proto->version;
+ }
+
+ /*! convert self to string ( for logs )
+ @return
+ self as plain string,
+ */
+ public function __toString(){
+ $str="Source:{$this->source}\nFieldset:{$this->fieldset}\nWhere:";
+ for ($i=0; $i < sizeof($this->filters); $i++)
+ $str.=$this->filters[$i]["name"]." ".$this->filters[$i]["operation"]." ".$this->filters[$i]["value"].";";
+ $str.="\nStart:{$this->start}\nCount:{$this->count}\n";
+ for ($i=0; $i < sizeof($this->sort_by); $i++)
+ $str.=$this->sort_by[$i]["name"]."=".$this->sort_by[$i]["direction"].";";
+ $str.="\nRelation:{$this->relation}";
+ return $str;
+ }
+
+ /*! returns set of filtering rules
+ @return
+ set of filtering rules
+ */
+ public function get_filters(){
+ return $this->filters;
+ }
+ public function &get_filters_ref(){
+ return $this->filters;
+ }
+ public function set_filters($data){
+ $this->filters=$data;
+ }
+
+
+ public function get_order(){
+ return $this->order;
+ }
+ public function set_order($order){
+ $this->order = $order;
+ }
+ public function get_user(){
+ return $this->user;
+ }
+ public function set_user($user){
+ $this->user = $user;
+ }
+ public function get_version(){
+ return $this->version;
+ }
+ public function set_version($version){
+ $this->version = $version;
+ }
+
+ /*! returns list of used fields
+ @return
+ list of used fields
+ */
+ public function get_fieldset(){
+ return $this->fieldset;
+ }
+ /*! returns name of source table
+ @return
+ name of source table
+ */
+ public function get_source(){
+ return $this->source;
+ }
+ /*! returns set of sorting rules
+ @return
+ set of sorting rules
+ */
+ public function get_sort_by(){
+ return $this->sort_by;
+ }
+ public function &get_sort_by_ref(){
+ return $this->sort_by;
+ }
+ public function set_sort_by($data){
+ $this->sort_by=$data;
+ }
+
+ /*! returns start index
+ @return
+ start index
+ */
+ public function get_start(){
+ return $this->start;
+ }
+ /*! returns count of requested records
+ @return
+ count of requested records
+ */
+ public function get_count(){
+ return $this->count;
+ }
+ /*! returns name of relation id
+ @return
+ relation id name
+ */
+ public function get_relation(){
+ return $this->relation;
+ }
+
+ /*! sets sorting rule
+
+ @param field
+ name of column
+ @param order
+ direction of sorting
+ */
+ public function set_sort($field,$order=false){
+ if (!$field && !$order)
+ $this->sort_by=array();
+ else{
+ if ($order===false)
+ $this->sort_by[] = $field;
+ else {
+ $order=strtolower($order)=="asc"?"ASC":"DESC";
+ $this->sort_by[]=array("name"=>$field,"direction" => $order);
+ }
+ }
+ }
+ /*! sets filtering rule
+
+ @param field
+ name of column
+ @param value
+ value for filtering
+ @param operation
+ operation for filtering, optional , LIKE by default
+ */
+ public function set_filter($field,$value=false,$operation=false){
+ if ($value === false)
+ array_push($this->filters,$field);
+ else
+ array_push($this->filters,array("name"=>$field,"value"=>$value,"operation"=>$operation));
+ }
+
+ /*! sets list of used fields
+
+ @param value
+ list of used fields
+ */
+ public function set_fieldset($value){
+ $this->fieldset=$value;
+ }
+ /*! sets name of source table
+
+ @param value
+ name of source table
+ */
+ public function set_source($value){
+ if (is_string($value))
+ $value = trim($value);
+ $this->source = $value;
+ if (!$this->source) throw new Exception("Source of data can't be empty");
+ }
+ /*! sets data limits
+
+ @param start
+ start index
+ @param count
+ requested count of data
+ */
+ public function set_limit($start,$count){
+ $this->start=$start;
+ $this->count=$count;
+ }
+ /*! sets name of relation id
+
+ @param value
+ name of relation id field
+ */
+ public function set_relation($value){
+ $this->relation=$value;
+ }
+ /*! parse incoming sql, to fill other properties
+
+ @param sql
+ incoming sql string
+ */
+ public function parse_sql($sql, $as_is = false){
+ if ($as_is){
+ $this->fieldset = $sql;
+ return;
+ }
+
+ $sql= preg_replace("/[ \n\t]+limit[\n\t ,0-9]*$/i","",$sql);
+
+ $data = preg_split("/[ \n\t]+\\_from\\_/i",$sql,2);
+ if (count($data)!=2)
+ $data = preg_split("/[ \n\t]+from/i",$sql,2);
+ $this->fieldset = preg_replace("/^[\s]*select/i","",$data[0],1);
+
+ //Ignore next type of calls
+ //direct call to stored procedure without FROM
+ if ((count($data) == 1) ||
+ //UNION select
+ preg_match("#[ \n\r\t]union[ \n\t\r]#i", $sql)){
+ $this->fieldset = $sql;
+ return;
+ }
+
+ $table_data = preg_split("/[ \n\t]+where/i",$data[1],2);
+ /*
+ if sql code contains group_by we will place all sql query in the FROM
+ it will not allow to use any filtering against the query
+ still it is better than just generate incorrect sql commands for any group by query
+ */
+ if (sizeof($table_data)>1 && !preg_match("#.*group by.*#i",$table_data[1])){ //where construction exists
+ $this->set_source($table_data[0]);
+ $where_data = preg_split("/[ \n\t]+order[ ]+by/i",$table_data[1],2);
+ $this->filters[]=$where_data[0];
+ if (sizeof($where_data)==1) return; //end of line detected
+ $data=$where_data[1];
+ } else {
+ $table_data = preg_split("/[ \n\t]+order[ ]+by/i",$data[1],2);
+ $this->set_source($table_data[0]);
+ if (sizeof($table_data)==1) return; //end of line detected
+ $data=$table_data[1];
+ }
+
+ if (trim($data)){ //order by construction exists
+ $s_data = preg_split("/\\,/",trim($data));
+ for ($i=0; $i < count($s_data); $i++) {
+ $data=preg_split("/[ ]+/",trim($s_data[$i]),2);
+ if (sizeof($data)>1)
+ $this->set_sort($data[0],$data[1]);
+ else
+ $this->set_sort($data[0]);
+ }
+
+ }
+ }
+} \ No newline at end of file
diff --git a/codebase/DataStorage/DataWrapper.php b/codebase/DataStorage/DataWrapper.php
new file mode 100644
index 0000000..19158cc
--- /dev/null
+++ b/codebase/DataStorage/DataWrapper.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+/*! Base abstraction class, used for data operations
+ Class abstract access to data, it is a base class to all DB wrappers
+**/
+abstract class DataWrapper{
+ protected $connection;
+ protected $config;//!< DataConfig instance
+ /*! constructor
+ @param connection
+ DB connection
+ @param config
+ DataConfig instance
+ */
+ public function __construct($connection = false,$config = false){
+ $this->config=$config;
+ $this->connection=$connection;
+ }
+
+ /*! insert record in storage
+
+ @param data
+ DataAction object
+ @param source
+ DataRequestConfig object
+ */
+ abstract function insert($data,$source);
+
+ /*! delete record from storage
+
+ @param data
+ DataAction object
+ @param source
+ DataRequestConfig object
+ */
+ abstract function delete($data,$source);
+
+ /*! update record in storage
+
+ @param data
+ DataAction object
+ @param source
+ DataRequestConfig object
+ */
+ abstract function update($data,$source);
+
+ /*! select record from storage
+
+ @param source
+ DataRequestConfig object
+ */
+ abstract function select($source);
+
+ /*! get size of storage
+
+ @param source
+ DataRequestConfig object
+ */
+ abstract function get_size($source);
+
+ /*! get all variations of field in storage
+
+ @param name
+ name of field
+ @param source
+ DataRequestConfig object
+ */
+ abstract function get_variants($name,$source);
+
+ /*! checks if there is a custom sql string for specified db operation
+
+ @param name
+ name of DB operation
+ @param data
+ hash of data
+ @return
+ sql string
+ */
+ public function get_sql($name,$data){
+ return ""; //custom sql not supported by default
+ }
+
+ /*! begins DB transaction
+ */
+ public function begin_transaction(){
+ throw new Exception("Data wrapper not supports transactions.");
+ }
+ /*! commits DB transaction
+ */
+ public function commit_transaction(){
+ throw new Exception("Data wrapper not supports transactions.");
+ }
+ /*! rollbacks DB transaction
+ */
+ public function rollback_transaction(){
+ throw new Exception("Data wrapper not supports transactions.");
+ }
+}
+
diff --git a/codebase/DataStorage/MsSQLDBDataWrapper.php b/codebase/DataStorage/MsSQLDBDataWrapper.php
new file mode 100644
index 0000000..1d245b2
--- /dev/null
+++ b/codebase/DataStorage/MsSQLDBDataWrapper.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+
+use DHTMLX\Connector\Tools\LogMaster;
+
+class MsSQLDBDataWrapper extends DBDataWrapper
+{
+ private $last_id = ""; //!< ID of previously inserted record
+ private $insert_operation = false; //!< flag of insert operation
+ private $start_from = false; //!< index of start position
+
+ public function query($sql)
+ {
+ LogMaster::log($sql);
+ $res = mssql_query($sql, $this->connection);
+ if ($this->insert_operation) {
+ $last = mssql_fetch_assoc($res);
+ $this->last_id = $last["dhx_id"];
+ mssql_free_result($res);
+ }
+ if ($this->start_from)
+ mssql_data_seek($res, $this->start_from);
+ return $res;
+ }
+
+ public function get_next($res)
+ {
+ return mssql_fetch_assoc($res);
+ }
+
+ public function get_new_id()
+ {
+ /*
+ MSSQL doesn't support identity or auto-increment fields
+ Insert SQL returns new ID value, which stored in last_id field
+ */
+ return $this->last_id;
+ }
+
+ protected function insert_query($data, $request)
+ {
+ $sql = parent::insert_query($data, $request);
+ $this->insert_operation = true;
+ return $sql . ";SELECT @@IDENTITY AS dhx_id";
+ }
+
+ protected function select_query($select, $from, $where, $sort, $start, $count)
+ {
+ if (!$from)
+ return $select;
+
+ $sql = "SELECT ";
+ if ($count)
+ $sql .= " TOP " . ($count + $start);
+ $sql .= " " . $select . " FROM " . $from;
+ if ($where) $sql .= " WHERE " . $where;
+ if ($sort) $sql .= " ORDER BY " . $sort;
+ if ($start && $count)
+ $this->start_from = $start;
+ else
+ $this->start_from = false;
+ return $sql;
+ }
+
+ public function escape($data)
+ {
+ /*
+ there is no special escaping method for mssql - use common logic
+ */
+ return str_replace("'", "''", $data);
+ }
+
+ public function begin_transaction()
+ {
+ $this->query("BEGIN TRAN");
+ }
+} \ No newline at end of file
diff --git a/codebase/DataStorage/MySQLDBDataWrapper.php b/codebase/DataStorage/MySQLDBDataWrapper.php
new file mode 100644
index 0000000..3f13492
--- /dev/null
+++ b/codebase/DataStorage/MySQLDBDataWrapper.php
@@ -0,0 +1,69 @@
+<?php
+namespace DHTMLX\Connector\DataStorage;
+
+
+/*! Implementation of DataWrapper for MySQL
+**/
+class MySQLDBDataWrapper extends DBDataWrapper{
+ protected $last_result;
+ public function query($sql){
+ LogMaster::log($sql);
+ $res=mysql_query($sql,$this->connection);
+ if ($res===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
+ $this->last_result = $res;
+ return $res;
+ }
+
+ public function get_next($res){
+ if (!$res)
+ $res = $this->last_result;
+
+ return mysql_fetch_assoc($res);
+ }
+
+ public function get_new_id(){
+ return mysql_insert_id($this->connection);
+ }
+
+ public function escape($data){
+ return mysql_real_escape_string($data, $this->connection);
+ }
+
+ public function tables_list() {
+ $result = mysql_query("SHOW TABLES");
+ if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
+
+ $tables = array();
+ while ($table = mysql_fetch_array($result)) {
+ $tables[] = $table[0];
+ }
+ return $tables;
+ }
+
+ public function fields_list($table) {
+ $result = mysql_query("SHOW COLUMNS FROM `".$table."`");
+ if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
+
+ $fields = array();
+ $id = "";
+ while ($field = mysql_fetch_assoc($result)) {
+ if ($field['Key'] == "PRI")
+ $id = $field["Field"];
+ else
+ $fields[] = $field["Field"];
+ }
+ return array("fields" => $fields, "key" => $id );
+ }
+
+ /*! escape field name to prevent sql reserved words conflict
+ @param data
+ unescaped data
+ @return
+ escaped data
+ */
+ public function escape_name($data){
+ if ((strpos($data,"`")!==false || is_int($data)) || (strpos($data,".")!==false))
+ return $data;
+ return '`'.$data.'`';
+ }
+} \ No newline at end of file
diff --git a/codebase/db_pdo.php b/codebase/DataStorage/PDODBDataWrapper.php
index 1417462..5a08e57 100644
--- a/codebase/db_pdo.php
+++ b/codebase/DataStorage/PDODBDataWrapper.php
@@ -1,32 +1,30 @@
<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
+
+namespace DHTMLX\Connector\DataStorage;
+
/*! Implementation of DataWrapper for PDO
if you plan to use it for Oracle - use Oracle connection type instead
**/
class PDODBDataWrapper extends DBDataWrapper{
private $last_result;//!< store result or last operation
-
+
public function query($sql){
LogMaster::log($sql);
-
+
$res=$this->connection->query($sql);
if ($res===false) {
$message = $this->connection->errorInfo();
throw new Exception("PDO - sql execution failed\n".$message[2]);
}
-
+
return new PDOResultSet($res);
}
protected function select_query($select,$from,$where,$sort,$start,$count){
if (!$from)
return $select;
-
+
$sql="SELECT ".$select." FROM ".$from;
if ($where) $sql.=" WHERE ".$where;
if ($sort) $sql.=" ORDER BY ".$sort;
@@ -38,7 +36,7 @@ class PDODBDataWrapper extends DBDataWrapper{
}
return $sql;
}
-
+
public function tables_list() {
$result = $this->query("SHOW TABLES");
if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
@@ -55,46 +53,30 @@ class PDODBDataWrapper extends DBDataWrapper{
if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
$fields = array();
- $id = "";
+ $id = "";
while ($field = $result->next()) {
if ($field['Key'] == "PRI")
$id = $field["Field"];
- else
- $fields[] = $field["Field"];
+ else
+ $fields[] = $field["Field"];
}
return array("fields" => $fields, "key" => $id );
}
-
+
public function get_next($res){
$data = $res->next();
return $data;
}
-
+
public function get_new_id(){
return $this->connection->lastInsertId();
}
-
+
public function escape($str){
$res=$this->connection->quote($str);
if ($res===false) //not supported by pdo driver
- return str_replace("'","''",$str);
+ return str_replace("'","''",$str);
return substr($res,1,-1);
}
-
-}
-class PDOResultSet{
- private $res;
- public function __construct($res){
- $this->res = $res;
- }
- public function next(){
- $data = $this->res->fetch(PDO::FETCH_ASSOC);
- if (!$data){
- $this->res->closeCursor();
- return null;
- }
- return $data;
- }
-}
-?> \ No newline at end of file
+} \ No newline at end of file
diff --git a/codebase/DataStorage/PDOResultSet.php b/codebase/DataStorage/PDOResultSet.php
new file mode 100644
index 0000000..536f75c
--- /dev/null
+++ b/codebase/DataStorage/PDOResultSet.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+
+class PDOResultSet{
+ private $res;
+ public function __construct($res){
+ $this->res = $res;
+ }
+ public function next(){
+ $data = $this->res->fetch(PDO::FETCH_ASSOC);
+ if (!$data){
+ $this->res->closeCursor();
+ return null;
+ }
+ return $data;
+ }
+} \ No newline at end of file
diff --git a/codebase/db_phpyii.php b/codebase/DataStorage/PHPYii2DBDataWrapper.php
index 616d7f3..95af1b7 100644
--- a/codebase/db_phpyii.php
+++ b/codebase/DataStorage/PHPYii2DBDataWrapper.php
@@ -1,28 +1,25 @@
<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
+namespace DHTMLX\Connector\DataStorage;
-require_once("db_common.php");
+class PHPYii2DBDataWrapper extends ArrayDBDataWrapper {
-class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
public function select($sql){
if (is_array($this->connection)) //result of findAll
$res = $this->connection;
else
- $res = $this->connection->findAll();
+ $res = $this->connection->find()->all();
$temp = array();
if (sizeof($res)){
foreach ($res as $obj)
$temp[]=$obj->getAttributes();
}
+ //die(var_dump($temp));
return new ArrayQueryWrapper($temp);
}
protected function getErrorMessage(){
- $errors = $this->connection->invalidFields();
+ $errors = $this->connection->getErrors();
$text = array();
foreach ($errors as $key => $value){
$text[] = $key." - ".$value[0];
@@ -32,11 +29,11 @@ class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
public function insert($data,$source){
$name = get_class($this->connection);
$obj = new $name();
-
+ //die(var_dump($data));
$this->fill_model_and_save($obj, $data);
}
public function delete($data,$source){
- $obj = $this->connection->findByPk($data->get_id());
+ $obj = $this->connection->findOne($data->get_id());
if ($obj->delete()){
$data->success();
$data->set_new_id($obj->getPrimaryKey());
@@ -46,18 +43,22 @@ class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
}
}
public function update($data,$source){
- $obj = $this->connection->findByPk($data->get_id());
+ //$obj = get_class($this->connection);
+ //$obj->setAttribute($obj->getPrimaryKey);
+
+ $obj = $this->connection->findOne($data->get_id());
+;
$this->fill_model_and_save($obj, $data);
- }
+ }
protected function fill_model_and_save($obj, $data){
- $values = $data->get_data();
//map data to model object
for ($i=0; $i < sizeof($this->config->text); $i++){
$step=$this->config->text[$i];
- $obj->setAttribute($step["name"], $data->get_value($step["name"]));
+ $obj->setAttribute($step["name"], $data->get_value("c".$i)); //TODO make array with corresponding names
}
+
if ($relation = $this->config->relation_id["db_name"])
$obj->setAttribute($relation, $data->get_value($relation));
@@ -86,6 +87,5 @@ class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
public function get_new_id(){
throw new Exception("Not implemented");
}
-}
-?> \ No newline at end of file
+} \ No newline at end of file
diff --git a/codebase/DataStorage/PostgreDBDataWrapper.php b/codebase/DataStorage/PostgreDBDataWrapper.php
new file mode 100644
index 0000000..56eaa48
--- /dev/null
+++ b/codebase/DataStorage/PostgreDBDataWrapper.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace DHTMLX\Connector\DataStorage;
+
+use DHTMLX\Connector\Tools\LogMaster;
+
+class PostgreDBDataWrapper extends DBDataWrapper{
+ public function query($sql){
+ LogMaster::log($sql);
+
+ $res=pg_query($this->connection,$sql);
+ if ($res===false) throw new \Exception("Postgre - sql execution failed\n".pg_last_error($this->connection));
+
+ return $res;
+ }
+
+ protected function select_query($select,$from,$where,$sort,$start,$count){
+ if (!$from)
+ return $select;
+
+ $sql="SELECT ".$select." FROM ".$from;
+ if ($where) $sql.=" WHERE ".$where;
+ if ($sort) $sql.=" ORDER BY ".$sort;
+ if ($start || $count)
+ $sql.=" OFFSET ".$start." LIMIT ".$count;
+ return $sql;
+ }
+
+ public function get_next($res){
+ return pg_fetch_assoc($res);
+ }
+
+ public function get_new_id(){
+ $res = pg_query( $this->connection, "SELECT LASTVAL() AS seq");
+ $data = pg_fetch_assoc($res);
+ pg_free_result($res);
+ return $data['seq'];
+ }
+
+ public function escape($data){
+ //need to use oci_bind_by_name
+ return pg_escape_string($this->connection,$data);
+ }
+
+ public function tables_list() {
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
+ $res = pg_query($this->connection, $sql);
+ $tables = array();
+ while ($table = pg_fetch_assoc($res)) {
+ $tables[] = $table['table_name'];
+ }
+ return $tables;
+ }
+
+ public function fields_list($table) {
+ $sql = "SELECT * FROM information_schema.constraint_column_usage";
+ $result = pg_query($this->connection, $sql);
+ $field = pg_fetch_assoc($result);
+ $id = $field['column_name'];
+
+ $sql = "SELECT * FROM information_schema.columns WHERE table_name ='".$table."';";
+ $result = pg_query($this->connection, $sql);
+ $fields = array();
+ $id = "";
+ while ($field = pg_fetch_assoc($result)) {
+ $fields[] = $field["column_name"];
+ }
+ return array('fields' => $fields, 'key' => $id );
+ }
+} \ No newline at end of file
diff --git a/codebase/DistinctOptionsConnector.php b/codebase/DistinctOptionsConnector.php
new file mode 100644
index 0000000..273ec6b
--- /dev/null
+++ b/codebase/DistinctOptionsConnector.php
@@ -0,0 +1,18 @@
+<?php
+namespace DHTMLX\Connector;
+
+class DistinctOptionsConnector extends OptionsConnector{
+ /*! render self
+ process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
+ @return
+ data as XML string
+ */
+ public function render(){
+ if (!$this->init_flag){
+ $this->init_flag=true;
+ return "";
+ }
+ $res = $this->sql->get_variants($this->config->text[0]["db_name"],$this->request);
+ return $this->render_set($res);
+ }
+} \ No newline at end of file
diff --git a/codebase/Event/EventInterface.php b/codebase/Event/EventInterface.php
new file mode 100644
index 0000000..645d89b
--- /dev/null
+++ b/codebase/Event/EventInterface.php
@@ -0,0 +1,37 @@
+<?php
+namespace DHTMLX\Connector\Event;
+
+class EventInterface{
+ protected $request; ////!< DataRequestConfig instance
+ public $rules=array(); //!< array of sorting rules
+
+ /*! constructor
+ creates a new interface based on existing request
+ @param request
+ DataRequestConfig object
+ */
+ public function __construct($request){
+ $this->request = $request;
+ }
+
+ /*! remove all elements from collection
+ */
+ public function clear(){
+ array_splice($rules,0);
+ }
+ /*! get index by name
+
+ @param name
+ name of field
+ @return
+ index of named field
+ */
+ public function index($name){
+ $len = sizeof($this->rules);
+ for ($i=0; $i < $len; $i++) {
+ if ($this->rules[$i]["name"]==$name)
+ return $i;
+ }
+ return false;
+ }
+}
diff --git a/codebase/Event/FilterInterface.php b/codebase/Event/FilterInterface.php
new file mode 100644
index 0000000..e37489d
--- /dev/null
+++ b/codebase/Event/FilterInterface.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace DHTMLX\Connector\Event;
+
+/*! Wrapper for collection of filtering rules
+**/
+class FilterInterface extends EventInterface{
+ /*! constructor
+ creates a new interface based on existing request
+ @param request
+ DataRequestConfig object
+ */
+ public function __construct($request){
+ $this->request = $request;
+ $this->rules = &$request->get_filters_ref();
+ }
+ /*! add new filatering rule
+
+ @param name
+ name of field
+ @param value
+ value to filter by
+ @param rule
+ filtering rule
+ */
+ public function add($name,$value,$rule){
+ $this->request->set_filter($name,$value,$rule);
+ }
+ public function store(){
+ $this->request->set_filters($this->rules);
+ }
+} \ No newline at end of file
diff --git a/codebase/Event/SortInterface.php b/codebase/Event/SortInterface.php
new file mode 100644
index 0000000..5e6aef4
--- /dev/null
+++ b/codebase/Event/SortInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace DHTMLX\Connector\Event;
+
+class SortInterface extends EventInterface{
+ /*! constructor
+ creates a new interface based on existing request
+ @param request
+ DataRequestConfig object
+ */
+ public function __construct($request){
+ parent::__construct($request);
+ $this->rules = &$request->get_sort_by_ref();
+ }
+ /*! add new sorting rule
+
+ @param name
+ name of field
+ @param dir
+ direction of sorting
+ */
+ public function add($name,$dir){
+ if ($dir === false)
+ $this->request->set_sort($name);
+ else
+ $this->request->set_sort($name,$dir);
+ }
+ public function store(){
+ $this->request->set_sort_by($this->rules);
+ }
+} \ No newline at end of file
diff --git a/codebase/GridConfiguration.php b/codebase/GridConfiguration.php
new file mode 100644
index 0000000..d67a0b6
--- /dev/null
+++ b/codebase/GridConfiguration.php
@@ -0,0 +1,445 @@
+<?php
+namespace DHTMLX\Connector;
+
+class GridConfiguration
+{
+
+ /*! attaching header functionality
+ */
+ protected $headerDelimiter = ',';
+ protected $headerNames = false;
+ protected $headerAttaches = array();
+ protected $footerAttaches = array();
+ protected $headerWidthsUnits = 'px';
+
+ protected $headerIds = false;
+ protected $headerWidths = false;
+ protected $headerTypes = false;
+ protected $headerAlign = false;
+ protected $headerVAlign = false;
+ protected $headerSorts = false;
+ protected $headerColors = false;
+ protected $headerHidden = false;
+ protected $headerFormat = false;
+
+ protected $convert_mode = false;
+
+ function __construct($headers = false)
+ {
+ if ($headers === false || $headers === true)
+ $this->headerNames = $headers;
+ else
+ $this->setHeader($headers);
+ }
+
+ /*! brief convert list of parameters to an array
+ @param param
+ list of values or array of values
+ @return array of parameters
+ */
+ private function parse_param_array($param, $check = false, $default = "")
+ {
+ if (gettype($param) == 'string')
+ $param = explode($this->headerDelimiter, $param);
+
+ if ($check) {
+ for ($i = 0; $i < sizeof($param); $i++) {
+ if (!array_key_exists($param[$i], $check))
+ $param[$i] = $default;
+ }
+ }
+ return $param;
+ }
+
+ /*! sets delimiter for string arguments in attach header functions (default is ,)
+ @param headerDelimiter
+ string delimiter
+ */
+ public function setHeaderDelimiter($headerDelimiter)
+ {
+ $this->headerDelimiter = $headerDelimiter;
+ }
+
+ /*! sets header
+ @param names
+ array of names or string of names, delimited by headerDelimiter (default is ,)
+ */
+ public function setHeader($names)
+ {
+ if ($names instanceof DataConfig) {
+ $out = array();
+ for ($i = 0; $i < sizeof($names->text); $i++)
+ $out[] = $names->text[$i]["name"];
+ $names = $out;
+ }
+
+ $this->headerNames = $this->parse_param_array($names);
+ }
+
+ /*! sets init columns width in pixels
+ @param wp
+ array of widths or string of widths, delimited by headerDelimiter (default is ,)
+ */
+ public function setInitWidths($wp)
+ {
+ $this->headerWidths = $this->parse_param_array($wp);
+ $this->headerWidthsUnits = 'px';
+ }
+
+ /*! sets init columns width in persents
+ @param wp
+ array of widths or string of widths, delimited by headerDelimiter (default is ,)
+ */
+ public function setInitWidthsP($wp)
+ {
+ $this->setInitWidths($wp);
+ $this->headerWidthsUnits = '%';
+ }
+
+ /*! sets columns align
+ @param alStr
+ array of aligns or string of aligns, delimited by headerDelimiter (default is ,)
+ */
+ public function setColAlign($alStr)
+ {
+ $this->headerAlign = $this->parse_param_array($alStr,
+ array("right" => 1, "left" => 1, "center" => 1, "justify" => 1),
+ "left");
+ }
+
+ /*! sets columns vertical align
+ @param alStr
+ array of vertical aligns or string of vertical aligns, delimited by headerDelimiter (default is ,)
+ */
+ public function setColVAlign($alStr)
+ {
+ $this->headerVAlign = $this->parse_param_array($alStr,
+ array("baseline" => 1, "sub" => 1, "super" => 1, "top" => 1, "text-top" => 1, "middle" => 1, "bottom" => 1, "text-bottom" => 1),
+ "top");
+ }
+
+ /*! sets column types
+ @param typeStr
+ array of types or string of types, delimited by headerDelimiter (default is ,)
+ */
+ public function setColTypes($typeStr)
+ {
+ $this->headerTypes = $this->parse_param_array($typeStr);
+ }
+
+ /*! sets columns sorting
+ @param sortStr
+ array if sortings or string of sortings, delimited by headerDelimiter (default is ,)
+ */
+ public function setColSorting($sortStr)
+ {
+ $this->headerSorts = $this->parse_param_array($sortStr);
+ }
+
+ /*! sets columns colors
+ @param colorStr
+ array of colors or string of colors, delimited by headerDelimiter (default is ,)
+ if (color should not be applied it's value should be null)
+ */
+ public function setColColor($colorStr)
+ {
+ $this->headerColors = $this->parse_param_array($colorStr);
+ }
+
+ /*! sets hidden columns
+ @param hidStr
+ array of bool values or string of bool values, delimited by headerDelimiter (default is ,)
+ */
+ public function setColHidden($hidStr)
+ {
+ $this->headerHidden = $this->parse_param_array($hidStr);
+ }
+
+ /*! sets columns id
+ @param idsStr
+ array of ids or string of ids, delimited by headerDelimiter (default is ,)
+ */
+ public function setColIds($idsStr)
+ {
+ $this->headerIds = $this->parse_param_array($idsStr);
+ }
+
+ /*! sets number/date format
+ @param formatArr
+ array of mask formats for number/dates , delimited by headerDelimiter (default is ,)
+ */
+ public function setColFormat($formatArr)
+ {
+ $this->headerFormat = $this->parse_param_array($formatArr);
+ }
+
+ /*! attaches header
+ @param values
+ array of header names or string of header names, delimited by headerDelimiter (default is ,)
+ @param styles
+ array of header styles or string of header styles, delimited by headerDelimiter (default is ,)
+ */
+ public function attachHeader($values, $styles = null, $footer = false)
+ {
+ $header = array();
+ $header['values'] = $this->parse_param_array($values);
+ if ($styles != null) {
+ $header['styles'] = $this->parse_param_array($styles);
+ } else {
+ $header['styles'] = null;
+ }
+ if ($footer)
+ $this->footerAttaches[] = $header;
+ else
+ $this->headerAttaches[] = $header;
+ }
+
+ /*! attaches footer
+ @param values
+ array of footer names or string of footer names, delimited by headerDelimiter (default is ,)
+ @param styles
+ array of footer styles or string of footer styles, delimited by headerDelimiter (default is ,)
+ */
+ public function attachFooter($values, $styles = null)
+ {
+ $this->attachHeader($values, $styles, true);
+ }
+
+ private function auto_fill($mode)
+ {
+ $headerWidths = array();
+ $headerTypes = array();
+ $headerSorts = array();
+ $headerAttaches = array();
+
+ for ($i = 0; $i < sizeof($this->headerNames); $i++) {
+ $headerWidths[] = 100;
+ $headerTypes[] = "ro";
+ $headerSorts[] = "connector";
+ $headerAttaches[] = "#connector_text_filter";
+ }
+ if ($this->headerWidths == false)
+ $this->setInitWidths($headerWidths);
+ if ($this->headerTypes == false)
+ $this->setColTypes($headerTypes);
+
+ if ($mode) {
+ if ($this->headerSorts == false)
+ $this->setColSorting($headerSorts);
+ $this->attachHeader($headerAttaches);
+ }
+ }
+
+ public function defineOptions($conn)
+ {
+ if (!$conn->is_first_call()) return; //render head only for first call
+
+ $config = $conn->get_config();
+ $full_header = ($this->headerNames === true);
+
+ if (gettype($this->headerNames) == 'boolean') //auto-config
+ $this->setHeader($config);
+ $this->auto_fill($full_header);
+
+ if (isset($_GET["dhx_colls"])) return;
+
+ $fillList = array();
+ for ($i = 0; $i < count($this->headerNames); $i++)
+ if ($this->headerTypes[$i] == "co" || $this->headerTypes[$i] == "coro")
+ $fillList[$i] = true;
+
+ for ($i = 0; $i < count($this->headerAttaches); $i++) {
+ for ($j = 0; $j < count($this->headerAttaches[$i]['values']); $j++) {
+ if ($this->headerAttaches[$i]['values'][$j] == "#connector_select_filter"
+ || $this->headerAttaches[$i]['values'][$j] == "#select_filter"
+ ) {
+ $fillList[$j] = true;;
+ }
+ }
+ }
+
+ $temp = array();
+ foreach ($fillList as $k => $v)
+ $temp[] = $k;
+ if (count($temp))
+ $_GET["dhx_colls"] = implode(",", $temp);
+ }
+
+
+ /*! gets header as array
+ */
+ private function getHeaderArray()
+ {
+ $head = Array();
+ $head[0] = $this->headerNames;
+ $head = $this->getAttaches($head, $this->headerAttaches);
+ return $head;
+ }
+
+
+ /*! get footer as array
+ */
+ private function getFooterArray()
+ {
+ $foot = Array();
+ $foot = $this->getAttaches($foot, $this->footerAttaches);
+ return $foot;
+ }
+
+
+ /*! gets array of data with attaches
+ */
+ private function getAttaches($to, $from)
+ {
+ for ($i = 0; $i < count($from); $i++) {
+ $line = $from[$i]['values'];
+ $to[] = $line;
+ }
+ return $to;
+ }
+
+
+ /*! calculates rowspan array according #cspan markers
+ */
+ private function processCspan($data)
+ {
+ $rspan = Array();
+ for ($i = 0; $i < count($data); $i++) {
+ $last = 0;
+ $rspan[$i] = Array();
+ for ($j = 0; $j < count($data[$i]); $j++) {
+ $rspan[$i][$j] = 0;
+ if ($data[$i][$j] === '#cspan') {
+ $rspan[$i][$last]++;
+ } else {
+ $last = $j;
+ }
+ }
+ }
+ return $rspan;
+ }
+
+
+ /*! calculates colspan array according #rspan markers
+ */
+ private function processRspan($data)
+ {
+ $last = Array();
+ $cspan = Array();
+ for ($i = 0; $i < count($data); $i++) {
+ $cspan[$i] = Array();
+ for ($j = 0; $j < count($data[$i]); $j++) {
+ $cspan[$i][$j] = 0;
+ if (!isset($last[$j])) $last[$j] = 0;
+ if ($data[$i][$j] === '#rspan') {
+ $cspan[$last[$j]][$j]++;
+ } else {
+ $last[$j] = $i;
+ }
+ }
+ }
+ return $cspan;
+ }
+
+
+ /*! sets mode of output format: usual mode or convert mode.
+ * @param mode
+ * true - convert mode, false - otherwise
+ */
+ public function set_convert_mode($mode)
+ {
+ $this->convert_mode = $mode;
+ }
+
+
+ /*! adds header configuration in output XML
+ */
+ public function attachHeaderToXML($conn, $out)
+ {
+ if (!$conn->is_first_call()) return; //render head only for first call
+
+ $head = $this->getHeaderArray();
+ $foot = $this->getFooterArray();
+ $rspan = $this->processRspan($head);
+ $cspan = $this->processCspan($head);
+
+ $str = '<head>';
+
+ if ($this->convert_mode) $str .= "<columns>";
+
+ for ($i = 0; $i < count($this->headerNames); $i++) {
+ $str .= '<column';
+ $str .= ' type="' . $this->headerTypes[$i] . '"';
+ $str .= ' width="' . $this->headerWidths[$i] . '"';
+ $str .= $this->headerIds ? ' id="' . $this->headerIds[$i] . '"' : '';
+ $str .= $this->headerAlign[$i] ? ' align="' . $this->headerAlign[$i] . '"' : '';
+ $str .= $this->headerVAlign[$i] ? ' valign="' . $this->headerVAlign[$i] . '"' : '';
+ $str .= $this->headerSorts[$i] ? ' sort="' . $this->headerSorts[$i] . '"' : '';
+ $str .= $this->headerColors[$i] ? ' color="' . $this->headerColors[$i] . '"' : '';
+ $str .= $this->headerHidden[$i] ? ' hidden="' . $this->headerHidden[$i] . '"' : '';
+ $str .= $this->headerFormat[$i] ? ' format="' . $this->headerFormat[$i] . '"' : '';
+ $str .= $cspan[0][$i] ? ' colspan="' . ($cspan[0][$i] + 1) . '"' : '';
+ $str .= $rspan[0][$i] ? ' rowspan="' . ($rspan[0][$i] + 1) . '"' : '';
+ $str .= '>' . $this->headerNames[$i] . '</column>';
+ }
+
+ if (!$this->convert_mode) {
+ $str .= '<settings><colwidth>' . $this->headerWidthsUnits . '</colwidth></settings>';
+ if ((count($this->headerAttaches) > 0) || (count($this->footerAttaches) > 0)) {
+ $str .= '<afterInit>';
+ }
+ for ($i = 0; $i < count($this->headerAttaches); $i++) {
+ $str .= '<call command="attachHeader">';
+ $str .= '<param>' . implode(",", $this->headerAttaches[$i]['values']) . '</param>';
+ if ($this->headerAttaches[$i]['styles'] != null) {
+ $str .= '<param>' . implode(",", $this->headerAttaches[$i]['styles']) . '</param>';
+ }
+ $str .= '</call>';
+ }
+ for ($i = 0; $i < count($this->footerAttaches); $i++) {
+ $str .= '<call command="attachFooter">';
+ $str .= '<param>' . implode(",", $this->footerAttaches[$i]['values']) . '</param>';
+ if ($this->footerAttaches[$i]['styles'] != null) {
+ $str .= '<param>' . implode(",", $this->footerAttaches[$i]['styles']) . '</param>';
+ }
+ $str .= '</call>';
+ }
+ if ((count($this->headerAttaches) > 0) || (count($this->footerAttaches) > 0)) {
+ $str .= '</afterInit>';
+ }
+ } else {
+ $str .= "</columns>";
+ for ($i = 1; $i < count($head); $i++) {
+ $str .= "<columns>";
+ for ($j = 0; $j < count($head[$i]); $j++) {
+ $str .= '<column';
+ $str .= $cspan[$i][$j] ? ' colspan="' . ($cspan[$i][$j] + 1) . '"' : '';
+ $str .= $rspan[$i][$j] ? ' rowspan="' . ($rspan[$i][$j] + 1) . '"' : '';
+ $str .= '>' . $head[$i][$j] . '</column>';
+ }
+ $str .= "</columns>\n";
+ }
+ }
+ $str .= '</head>';
+
+
+ if ($this->convert_mode && count($foot) > 0) {
+ $rspan = $this->processRspan($foot);
+ $cspan = $this->processCspan($foot);
+ $str .= "<foot>";
+ for ($i = 0; $i < count($foot); $i++) {
+ $str .= "<columns>";
+ for ($j = 0; $j < count($foot[$i]); $j++) {
+ $str .= '<column';
+ $str .= $cspan[$i][$j] ? ' colspan="' . ($cspan[$i][$j] + 1) . '"' : '';
+ $str .= $rspan[$i][$j] ? ' rowspan="' . ($rspan[$i][$j] + 1) . '"' : '';
+ $str .= '>' . $foot[$i][$j] . '</column>';
+ }
+ $str .= "</columns>\n";
+ }
+ $str .= "</foot>";
+ }
+
+ $out->add($str);
+ }
+} \ No newline at end of file
diff --git a/codebase/GridConnector.php b/codebase/GridConnector.php
new file mode 100644
index 0000000..1a0e216
--- /dev/null
+++ b/codebase/GridConnector.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace DHTMLX\Connector;
+/*! Connector for the dhtmlxgrid
+**/
+class GridConnector extends Connector{
+
+ /*! constructor
+
+ Here initilization of all Masters occurs, execution timer initialized
+ @param res
+ db connection resource
+ @param type
+ string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
+ @param item_type
+ name of class, which will be used for item rendering, optional, DataItem will be used by default
+ @param data_type
+ name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
+ */
+ public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
+ if (!$item_type) $item_type="DHTMLX\\Connector\\GridDataItem";
+ if (!$data_type) $data_type="DHTMLX\\Connector\\Data\\DataProcessor";
+ if (!$render_type) $render_type="DHTMLX\\Connector\\Output\\RenderStrategy";
+ parent::__construct($res,$type,$item_type,$data_type,$render_type);
+ }
+
+
+ protected function parse_request(){
+ parent::parse_request();
+
+ if (isset($_GET["dhx_colls"]))
+ $this->fill_collections($_GET["dhx_colls"]);
+ }
+ protected function resolve_parameter($name){
+ if (intval($name).""==$name)
+ return $this->config->text[intval($name)]["db_name"];
+ return $name;
+ }
+
+ /*! replace xml unsafe characters
+
+ @param string
+ string to be escaped
+ @return
+ escaped string
+ */
+ protected function xmlentities($string) {
+ return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string);
+ }
+
+ /*! assign options collection to the column
+
+ @param name
+ name of the column
+ @param options
+ array or connector object
+ */
+ public function set_options($name,$options){
+ if (is_array($options)){
+ $str="";
+ foreach($options as $k => $v)
+ $str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
+ $options=$str;
+ }
+ $this->options[$name]=$options;
+ }
+ /*! generates xml description for options collections
+
+ @param list
+ comma separated list of column names, for which options need to be generated
+ */
+ protected function fill_collections($list=""){
+ $names=explode(",",$list);
+ for ($i=0; $i < sizeof($names); $i++) {
+ $name = $this->resolve_parameter($names[$i]);
+ if (!array_key_exists($name,$this->options)){
+ $this->options[$name] = new DistinctOptionsConnector($this->get_connection(),$this->names["db_class"]);
+ $c = new DataConfig($this->config);
+ $r = new DataRequestConfig($this->request);
+ $c->minimize($name);
+
+ $this->options[$name]->render_connector($c,$r);
+ }
+
+ $this->extra_output.="<coll_options for='{$names[$i]}'>";
+ if (!is_string($this->options[$name]))
+ $this->extra_output.=$this->options[$name]->render();
+ else
+ $this->extra_output.=$this->options[$name];
+ $this->extra_output.="</coll_options>";
+ }
+ }
+
+ /*! renders self as xml, starting part
+ */
+ protected function xml_start(){
+ $attributes = "";
+ foreach($this->attributes as $k=>$v)
+ $attributes .= " ".$k."='".$v."'";
+
+ if ($this->dload){
+ if ($pos=$this->request->get_start())
+ return "<rows pos='".$pos."'".$attributes.">";
+ else
+ return "<rows total_count='".$this->sql->get_size($this->request)."'".$attributes.">";
+ }
+ else
+ return "<rows".$attributes.">";
+ }
+
+
+ /*! renders self as xml, ending part
+ */
+ protected function xml_end(){
+ return $this->extra_output."</rows>";
+ }
+
+ public function set_config($config = false){
+ if (gettype($config) == 'boolean')
+ $config = new GridConfiguration($config);
+
+ $this->event->attach("beforeOutput", Array($config, "attachHeaderToXML"));
+ $this->event->attach("onInit", Array($config, "defineOptions"));
+ }
+} \ No newline at end of file
diff --git a/codebase/GridDataItem.php b/codebase/GridDataItem.php
new file mode 100644
index 0000000..a405f8b
--- /dev/null
+++ b/codebase/GridDataItem.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace DHTMLX\Connector;
+
+use DHTMLX\Connector\Data\DataItem;
+/*! DataItem class for Grid component
+**/
+
+class GridDataItem extends DataItem{
+ protected $row_attrs;//!< hash of row attributes
+ protected $cell_attrs;//!< hash of cell attributes
+
+ function __construct($data,$name,$index=0){
+ parent::__construct($data,$name,$index);
+
+ $this->row_attrs=array();
+ $this->cell_attrs=array();
+ }
+ /*! set color of row
+
+ @param color
+ color of row
+ */
+ function set_row_color($color){
+ $this->row_attrs["bgColor"]=$color;
+ }
+ /*! set style of row
+
+ @param color
+ color of row
+ */
+ function set_row_style($color){
+ $this->row_attrs["style"]=$color;
+ }
+ /*! assign custom style to the cell
+
+ @param name
+ name of column
+ @param value
+ css style string
+ */
+ function set_cell_style($name,$value){
+ $this->set_cell_attribute($name,"style",$value);
+ }
+ /*! assign custom class to specific cell
+
+ @param name
+ name of column
+ @param value
+ css class name
+ */
+ function set_cell_class($name,$value){
+ $this->set_cell_attribute($name,"class",$value);
+ }
+ /*! set custom cell attribute
+
+ @param name
+ name of column
+ @param attr
+ name of attribute
+ @param value
+ value of attribute
+ */
+ function set_cell_attribute($name,$attr,$value){
+ if (!array_key_exists($name, $this->cell_attrs)) $this->cell_attrs[$name]=array();
+ $this->cell_attrs[$name][$attr]=$value;
+ }
+
+ /*! set custom row attribute
+
+ @param attr
+ name of attribute
+ @param value
+ value of attribute
+ */
+ function set_row_attribute($attr,$value){
+ $this->row_attrs[$attr]=$value;
+ }
+
+ /*! return self as XML string, starting part
+ */
+ public function to_xml_start(){
+ if ($this->skip) return "";
+
+ $str="<row id='".$this->xmlentities($this->get_id())."'";
+ foreach ($this->row_attrs as $k=>$v)
+ $str.=" ".$k."='".$v."'";
+ $str.=">";
+ for ($i=0; $i < sizeof($this->config->text); $i++){
+ $str.="<cell";
+ $name=$this->config->text[$i]["name"];
+ $xmlcontent = false;
+ if (isset($this->cell_attrs[$name])){
+ $cattrs=$this->cell_attrs[$name];
+ foreach ($cattrs as $k => $v){
+ $str.=" ".$k."='".$this->xmlentities($v)."'";
+ if ($k == "xmlcontent")
+ $xmlcontent = true;
+ }
+ }
+ $value = isset($this->data[$name]) ? $this->data[$name] : '';
+ if (!$xmlcontent)
+ $str.="><![CDATA[".$value."]]></cell>";
+ else
+ $str.=">".$value."</cell>";
+ }
+ if ($this->userdata !== false)
+ foreach ($this->userdata as $key => $value)
+ $str.="<userdata name='".$key."'><![CDATA[".$value."]]></userdata>";
+
+ return $str;
+ }
+ /*! return self as XML string, ending part
+ */
+ public function to_xml_end(){
+ if ($this->skip) return "";
+
+ return "</row>";
+ }
+} \ No newline at end of file
diff --git a/codebase/MixedConnector.php b/codebase/MixedConnector.php
new file mode 100644
index 0000000..898bfa9
--- /dev/null
+++ b/codebase/MixedConnector.php
@@ -0,0 +1,24 @@
+<?php
+namespace DHTMLX\Connector;
+
+use DHTMLX\Connector\Connector;
+
+class MixedConnector extends Connector {
+
+ protected $connectors = array();
+
+ public function add($name, $conn) {
+ $this->connectors[$name] = $conn;
+ }
+
+ public function render() {
+ $result = "{";
+ $parts = array();
+ foreach($this->connectors as $name => $conn) {
+ $conn->asString(true);
+ $parts[] = "\"".$name."\":".($conn->render())."\n";
+ }
+ $result .= implode(",\n", $parts)."}";
+ echo $result;
+ }
+} \ No newline at end of file
diff --git a/codebase/OptionsConnector.php b/codebase/OptionsConnector.php
new file mode 100644
index 0000000..4c0ab16
--- /dev/null
+++ b/codebase/OptionsConnector.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace DHTMLX\Connector;
+
+/*! wrapper around options collection, used for comboboxes and filters
+**/
+class OptionsConnector extends Connector{
+ protected $init_flag=false;//!< used to prevent rendering while initialization
+ public function __construct($res,$type=false,$item_type=false,$data_type=false){
+ if (!$item_type) $item_type="DataItem";
+ if (!$data_type) $data_type=""; //has not sense, options not editable
+ parent::__construct($res,$type,$item_type,$data_type);
+ }
+ /*! render self
+ process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
+ @return
+ data as XML string
+ */
+ public function render(){
+ if (!$this->init_flag){
+ $this->init_flag=true;
+ return "";
+ }
+ $res = $this->sql->select($this->request);
+ return $this->render_set($res);
+ }
+} \ No newline at end of file
diff --git a/codebase/Output/JSONRenderStrategy.php b/codebase/Output/JSONRenderStrategy.php
new file mode 100644
index 0000000..ea196e0
--- /dev/null
+++ b/codebase/Output/JSONRenderStrategy.php
@@ -0,0 +1,30 @@
+<?php
+class JSONRenderStrategy extends RenderStrategy {
+
+ /*! render from DB resultset
+ @param res
+ DB resultset
+ process commands, output requested data as json
+ */
+ public function render_set($res, $name, $dload, $sep, $config, $mix){
+ $output=array();
+ $index=0;
+ $conn = $this->conn;
+ $this->mix($config, $mix);
+ $conn->event->trigger("beforeRenderSet",$conn,$res,$config);
+ while ($data=$conn->sql->get_next($res)){
+ $data = $this->complex_mix($mix, $data);
+ $data = new $name($data,$config,$index);
+ if ($data->get_id()===false)
+ $data->set_id($conn->uuid());
+ $conn->event->trigger("beforeRender",$data);
+ $item = $data->to_xml();
+ if ($item !== false)
+ $output[]=$item;
+ $index++;
+ }
+ $this->unmix($config, $mix);
+ return $output;
+ }
+
+}
diff --git a/codebase/Output/JSONTreeRenderStrategy.php b/codebase/Output/JSONTreeRenderStrategy.php
new file mode 100644
index 0000000..04a8672
--- /dev/null
+++ b/codebase/Output/JSONTreeRenderStrategy.php
@@ -0,0 +1,39 @@
+<?php
+namespace DHTMLX\Connector\Output;
+
+class JSONTreeRenderStrategy extends TreeRenderStrategy {
+
+ public function render_set($res, $name, $dload, $sep, $config,$mix){
+ $output=array();
+ $index=0;
+ $conn = $this->conn;
+ $config_copy = new DataConfig($config);
+ $this->mix($config, $mix);
+ while ($data=$conn->sql->get_next($res)){
+ $data = $this->complex_mix($mix, $data);
+ $data = new $name($data,$config,$index);
+ $conn->event->trigger("beforeRender",$data);
+ //there is no info about child elements,
+ //if we are using dyn. loading - assume that it has,
+ //in normal mode just exec sub-render routine
+ if ($data->has_kids()===-1 && $dload)
+ $data->set_kids(true);
+ $record = $data->to_xml_start();
+ if ($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload)){
+ $sub_request = new DataRequestConfig($conn->get_request());
+ //$sub_request->set_fieldset(implode(",",$config_copy->db_names_list($conn->sql)));
+ $sub_request->set_relation($data->get_id());
+ //$sub_request->set_filters(array());
+ $temp = $this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config_copy, $mix);
+ if (sizeof($temp))
+ $record["data"] = $temp;
+ }
+ if ($record !== false)
+ $output[] = $record;
+ $index++;
+ }
+ $this->unmix($config, $mix);
+ return $output;
+ }
+
+} \ No newline at end of file
diff --git a/codebase/Output/OutputWriter.php b/codebase/Output/OutputWriter.php
new file mode 100644
index 0000000..96bb49a
--- /dev/null
+++ b/codebase/Output/OutputWriter.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace DHTMLX\Connector\Output;
+
+class OutputWriter{
+ private $start;
+ private $end;
+ private $type;
+
+ public function __construct($start, $end = ""){
+ $this->start = $start;
+ $this->end = $end;
+ $this->type = "xml";
+ }
+ public function add($add){
+ $this->start.=$add;
+ }
+ public function reset(){
+ $this->start="";
+ $this->end="";
+ }
+ public function set_type($add){
+ $this->type=$add;
+ }
+ public function output($name="", $inline=true, $encoding=""){
+ ob_clean();
+
+ if ($this->type == "xml"){
+ $header = "Content-type: text/xml";
+ if ("" != $encoding)
+ $header.="; charset=".$encoding;
+ header($header);
+ }
+
+ echo $this->__toString();
+ }
+ public function __toString(){
+ return $this->start.$this->end;
+ }
+} \ No newline at end of file
diff --git a/codebase/Output/RenderStrategy.php b/codebase/Output/RenderStrategy.php
new file mode 100644
index 0000000..9431d0d
--- /dev/null
+++ b/codebase/Output/RenderStrategy.php
@@ -0,0 +1,115 @@
+<?php
+namespace DHTMLX\Connector\Output;
+
+use DHTMLX\Connector\Data\DataItem;
+use DHTMLX\Connector\GridDataItem;
+class RenderStrategy {
+
+ protected $conn = null;
+
+ public function __construct($conn) {
+ $this->conn = $conn;
+ }
+
+ /*! adds mix fields into DataConfig
+ * @param config
+ * DataConfig object
+ * @param mix
+ * mix structure
+ */
+ protected function mix($config, $mix) {
+ for ($i = 0; $i < count($mix); $i++) {
+ if ($config->is_field($mix[$i]['name'])===-1) {
+ $config->add_field($mix[$i]['name']);
+ }
+ }
+ }
+
+ /*! remove mix fields from DataConfig
+ * @param config
+ * DataConfig object
+ * @param mix
+ * mix structure
+ */
+ protected function unmix($config, $mix) {
+ for ($i = 0; $i < count($mix); $i++) {
+ if ($config->is_field($mix[$i]['name'])!==-1) {
+ $config->remove_field_full($mix[$i]['name']);
+ }
+ }
+ }
+
+ /*! adds mix fields in item
+ * simple mix adds only strings specified by user
+ * @param mix
+ * mix structure
+ * @param data
+ * array of selected data
+ */
+ protected function simple_mix($mix, $data) {
+ // get mix details
+ for ($i = 0; $i < count($mix); $i++)
+ $data[$mix[$i]["name"]] = is_object($mix[$i]["value"]) ? "" : $mix[$i]["value"];
+ return $data;
+ }
+
+ /*! adds mix fields in item
+ * complex mix adds strings specified by user and results of subrequests
+ * @param mix
+ * mix structure
+ * @param data
+ * array of selected data
+ */
+ protected function complex_mix($mix, $data) {
+ // get mix details
+ for ($i = 0; $i < count($mix); $i++) {
+ $mixname = $mix[$i]["name"];
+ if ($mix[$i]['filter'] !== false) {
+ $subconn = $mix[$i]["value"];
+ $filter = $mix[$i]["filter"];
+
+ // setting relationships
+ $subconn->clear_filter();
+ foreach ($filter as $k => $v)
+ if (isset($data[$v]))
+ $subconn->filter($k, $data[$v], "=");
+ else
+ throw new Exception('There was no such data field registered as: '.$k);
+
+ $subconn->asString(true);
+ $data[$mixname]=$subconn->simple_render();
+ if (is_array($data[$mixname]) && count($data[$mixname]) == 1)
+ $data[$mixname] = $data[$mixname][0];
+ } else {
+ $data[$mixname] = $mix[$i]["value"];
+ }
+ }
+ return $data;
+ }
+
+ /*! render from DB resultset
+ @param res
+ DB resultset
+ process commands, output requested data as XML
+ */
+ public function render_set($res, $name, $dload, $sep, $config, $mix){
+ $output="";
+ $index=0;
+ $conn = $this->conn;
+ $this->mix($config, $mix);
+ $conn->event->trigger("beforeRenderSet",$conn,$res,$config);
+ while ($data=$conn->sql->get_next($res)){
+ $data = $this->simple_mix($mix, $data);
+
+ $data = new $name($data,$config,$index);
+ if ($data->get_id()===false)
+ $data->set_id($conn->uuid());
+ $conn->event->trigger("beforeRender",$data);
+ $output.=$data->to_xml().$sep;
+ $index++;
+ }
+ $this->unmix($config, $mix);
+ return $output;
+ }
+
+} \ No newline at end of file
diff --git a/codebase/Output/TreeRenderStrategy.php b/codebase/Output/TreeRenderStrategy.php
new file mode 100644
index 0000000..d66e58e
--- /dev/null
+++ b/codebase/Output/TreeRenderStrategy.php
@@ -0,0 +1,64 @@
+<?php
+namespace DHTMLX\Connector\Output;
+
+use DHTMLX\Connector\DataStorage\DataConfig;
+
+class TreeRenderStrategy extends RenderStrategy {
+
+ protected $id_swap = array();
+
+ public function __construct($conn) {
+ parent::__construct($conn);
+ $conn->event->attach("afterInsert",array($this,"parent_id_correction_a"));
+ $conn->event->attach("beforeProcessing",array($this,"parent_id_correction_b"));
+ }
+
+ public function render_set($res, $name, $dload, $sep, $config, $mix){
+ $output="";
+ $index=0;
+ $conn = $this->conn;
+ $config_copy = new DataConfig($config);
+ $this->mix($config, $mix);
+ while ($data=$conn->sql->get_next($res)){
+ $data = $this->simple_mix($mix, $data);
+ $data = new $name($data,$config,$index);
+ $conn->event->trigger("beforeRender",$data);
+ //there is no info about child elements,
+ //if we are using dyn. loading - assume that it has,
+ //in normal mode juse exec sub-render routine
+ if ($data->has_kids()===-1 && $dload)
+ $data->set_kids(true);
+ $output.=$data->to_xml_start();
+ if ($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload)){
+ $sub_request = new DataRequestConfig($conn->get_request());
+ //$sub_request->set_fieldset(implode(",",$config_copy->db_names_list($conn->sql)));
+ $sub_request->set_relation($data->get_id());
+ $output.=$this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config_copy, $mix);
+ }
+ $output.=$data->to_xml_end();
+ $index++;
+ }
+ $this->unmix($config, $mix);
+ return $output;
+ }
+
+ /*! store info about ID changes during insert operation
+ @param dataAction
+ data action object during insert operation
+ */
+ public function parent_id_correction_a($dataAction){
+ $this->id_swap[$dataAction->get_id()]=$dataAction->get_new_id();
+ }
+
+ /*! update ID if it was affected by previous operation
+ @param dataAction
+ data action object, before any processing operation
+ */
+ public function parent_id_correction_b($dataAction){
+ $relation = $this->conn->get_config()->relation_id["db_name"];
+ $value = $dataAction->get_value($relation);
+
+ if (array_key_exists($value,$this->id_swap))
+ $dataAction->set_value($relation,$this->id_swap[$value]);
+ }
+} \ No newline at end of file
diff --git a/codebase/Tools/AccessMaster.php b/codebase/Tools/AccessMaster.php
new file mode 100644
index 0000000..6c84e20
--- /dev/null
+++ b/codebase/Tools/AccessMaster.php
@@ -0,0 +1,57 @@
+<?php
+namespace DHTMLX\Connector\Tools;
+/*! Class which handles access rules.
+**/
+class AccessMaster{
+ private $rules,$local;
+ /*! constructor
+
+ Set next access right to "allowed" by default : read, insert, update, delete
+ Basically - all common data operations allowed by default
+ */
+ function __construct(){
+ $this->rules=array("read" => true, "insert" => true, "update" => true, "delete" => true);
+ $this->local=true;
+ }
+ /*! change access rule to "allow"
+ @param name
+ name of access right
+ */
+ public function allow($name){
+ $this->rules[$name]=true;
+ }
+ /*! change access rule to "deny"
+
+ @param name
+ name of access right
+ */
+ public function deny($name){
+ $this->rules[$name]=false;
+ }
+
+ /*! change all access rules to "deny"
+ */
+ public function deny_all(){
+ $this->rules=array();
+ }
+
+ /*! check access rule
+
+ @param name
+ name of access right
+ @return
+ true if access rule allowed, false otherwise
+ */
+ public function check($name){
+ if ($this->local){
+ /*!
+ todo
+ add referrer check, to prevent access from remote points
+ */
+ }
+ if (!isset($this->rules[$name]) || !$this->rules[$name]){
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/codebase/Tools/EventMaster.php b/codebase/Tools/EventMaster.php
new file mode 100644
index 0000000..ec849d8
--- /dev/null
+++ b/codebase/Tools/EventMaster.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace DHTMLX\Connector\Tools;
+/*! Class which allows to assign|fire events.
+*/
+class EventMaster{
+ private $events;//!< hash of event handlers
+ private $master;
+ private static $eventsStatic=array();
+
+ /*! constructor
+ */
+ function __construct(){
+ $this->events=array();
+ $this->master = false;
+ }
+ /*! Method check if event with such name already exists.
+ @param name
+ name of event, case non-sensitive
+ @return
+ true if event with such name registered, false otherwise
+ */
+ public function exist($name){
+ $name=strtolower($name);
+ return (isset($this->events[$name]) && sizeof($this->events[$name]));
+ }
+ /*! Attach custom code to event.
+
+ Only on event handler can be attached in the same time. If new event handler attached - old will be detached.
+
+ @param name
+ name of event, case non-sensitive
+ @param method
+ function which will be attached. You can use array(class, method) if you want to attach the method of the class.
+ */
+ public function attach($name,$method=false){
+ //use class for event handling
+ if ($method === false){
+ $this->master = $name;
+ return;
+ }
+ //use separate functions
+ $name=strtolower($name);
+ if (!array_key_exists($name,$this->events))
+ $this->events[$name]=array();
+ $this->events[$name][]=$method;
+ }
+
+ public static function attach_static($name, $method){
+ $name=strtolower($name);
+ if (!array_key_exists($name,EventMaster::$eventsStatic))
+ EventMaster::$eventsStatic[$name]=array();
+ EventMaster::$eventsStatic[$name][]=$method;
+ }
+
+ public static function trigger_static($name, $method){
+ $arg_list = func_get_args();
+ $name=strtolower(array_shift($arg_list));
+
+ if (isset(EventMaster::$eventsStatic[$name]))
+ foreach(EventMaster::$eventsStatic[$name] as $method){
+ if (is_array($method) && !method_exists($method[0],$method[1]))
+ throw new Exception("Incorrect method assigned to event: ".$method[0].":".$method[1]);
+ if (!is_array($method) && !function_exists($method))
+ throw new Exception("Incorrect function assigned to event: ".$method);
+ call_user_func_array($method, $arg_list);
+ }
+ return true;
+ }
+
+ /*! Detach code from event
+ @param name
+ name of event, case non-sensitive
+ */
+ public function detach($name){
+ $name=strtolower($name);
+ unset($this->events[$name]);
+ }
+ /*! Trigger event.
+ @param name
+ name of event, case non-sensitive
+ @param data
+ value which will be provided as argument for event function,
+ you can provide multiple data arguments, method accepts variable number of parameters
+ @return
+ true if event handler was not assigned , result of event hangler otherwise
+ */
+ public function trigger($name,$data){
+ $arg_list = func_get_args();
+ $name=strtolower(array_shift($arg_list));
+
+ if (isset($this->events[$name]))
+ foreach($this->events[$name] as $method){
+ if (is_array($method) && !method_exists($method[0],$method[1]))
+ throw new Exception("Incorrect method assigned to event: ".$method[0].":".$method[1]);
+ if (!is_array($method) && !function_exists($method))
+ throw new Exception("Incorrect function assigned to event: ".$method);
+ call_user_func_array($method, $arg_list);
+ }
+
+ if ($this->master !== false)
+ if (method_exists($this->master, $name))
+ call_user_func_array(array($this->master, $name), $arg_list);
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/codebase/Tools/LogMaster.php b/codebase/Tools/LogMaster.php
new file mode 100644
index 0000000..c9459cc
--- /dev/null
+++ b/codebase/Tools/LogMaster.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace DHTMLX\Connector\Tools;
+/*! Controls error and debug logging.
+ Class designed to be used as static object.
+**/
+class LogMaster{
+ private static $_log=false;//!< logging mode flag
+ private static $_output=false;//!< output error infor to client flag
+ private static $session="";//!< all messages generated for current request
+
+ /*! convert array to string representation ( it is a bit more readable than var_dump )
+
+ @param data
+ data object
+ @param pref
+ prefix string, used for formating, optional
+ @return
+ string with array description
+ */
+ private static function log_details($data,$pref=""){
+ if (is_array($data)){
+ $str=array("");
+ foreach($data as $k=>$v)
+ array_push($str,$pref.$k." => ".LogMaster::log_details($v,$pref."\t"));
+ return implode("\n",$str);
+ }
+ return $data;
+ }
+ /*! put record in log
+
+ @param str
+ string with log info, optional
+ @param data
+ data object, which will be added to log, optional
+ */
+ public static function log($str="",$data=""){
+ if (LogMaster::$_log){
+ $message = $str.LogMaster::log_details($data)."\n\n";
+ LogMaster::$session.=$message;
+ error_log($message,3,LogMaster::$_log);
+ }
+ }
+
+ /*! get logs for current request
+ @return
+ string, which contains all log messages generated for current request
+ */
+ public static function get_session_log(){
+ return LogMaster::$session;
+ }
+
+ /*! error handler, put normal php errors in log file
+
+ @param errn
+ error number
+ @param errstr
+ error description
+ @param file
+ error file
+ @param line
+ error line
+ @param context
+ error cntext
+ */
+ public static function error_log($errn,$errstr,$file,$line,$context){
+ LogMaster::log($errstr." at ".$file." line ".$line);
+ }
+
+ /*! exception handler, used as default reaction on any error - show execution log and stop processing
+
+ @param exception
+ instance of Exception
+ */
+ public static function exception_log($exception){
+ LogMaster::log("!!!Uncaught Exception\nCode: " . $exception->getCode() . "\nMessage: " . $exception->getMessage());
+ if (LogMaster::$_output){
+ echo "<pre><xmp>\n";
+ echo LogMaster::get_session_log();
+ echo "\n</xmp></pre>";
+ }
+ die();
+ }
+
+ /*! enable logging
+
+ @param name
+ path to the log file, if boolean false provided as value - logging will be disabled
+ @param output
+ flag of client side output, if enabled - session log will be sent to client side in case of an error.
+ */
+ public static function enable_log($name,$output=false){
+ LogMaster::$_log=$name;
+ LogMaster::$_output=$output;
+ if ($name){
+ set_error_handler(array("LogMaster","error_log"),E_ALL);
+ set_exception_handler(array("LogMaster","exception_log"));
+ LogMaster::log("\n\n====================================\nLog started, ".date("d/m/Y h:i:s")."\n====================================");
+ }
+ }
+} \ No newline at end of file
diff --git a/codebase/TreeConnector.php b/codebase/TreeConnector.php
new file mode 100644
index 0000000..b01e399
--- /dev/null
+++ b/codebase/TreeConnector.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace DHTMLX\Connector;
+
+class TreeConnector extends Connector
+{
+ protected $parent_name = 'id';
+ public $rootId = "0";
+
+ /*! constructor
+
+ Here initilization of all Masters occurs, execution timer initialized
+ @param res
+ db connection resource
+ @param type
+ string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
+ @param item_type
+ name of class, which will be used for item rendering, optional, DataItem will be used by default
+ @param data_type
+ name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
+ * @param render_type
+ * name of class which will provides data rendering
+ */
+ public function __construct($res, $type = false, $item_type = false, $data_type = false, $render_type = false)
+ {
+ if (!$item_type) $item_type = "TreeDataItem";
+ if (!$data_type) $data_type = "TreeDataProcessor";
+ if (!$render_type) $render_type = "TreeRenderStrategy";
+ parent::__construct($res, $type, $item_type, $data_type, $render_type);
+ }
+
+ //parse GET scoope, all operations with incoming request must be done here
+ public function parse_request()
+ {
+ parent::parse_request();
+
+ if (isset($_GET[$this->parent_name]))
+ $this->request->set_relation($_GET[$this->parent_name]);
+ else
+ $this->request->set_relation($this->rootId);
+
+ $this->request->set_limit(0, 0); //netralize default reaction on dyn. loading mode
+ }
+
+ /*! renders self as xml, starting part
+ */
+ public function xml_start()
+ {
+ $attributes = "";
+ foreach ($this->attributes as $k => $v)
+ $attributes .= " " . $k . "='" . $v . "'";
+
+ return "<tree id='" . $this->request->get_relation() . "'" . $attributes . ">";
+ }
+
+ /*! renders self as xml, ending part
+ */
+ public function xml_end()
+ {
+ $this->fill_collections();
+ return $this->extra_output . "</tree>";
+ }
+}
diff --git a/codebase/XSSFilter/ConnectorSecurity.php b/codebase/XSSFilter/ConnectorSecurity.php
new file mode 100644
index 0000000..195e962
--- /dev/null
+++ b/codebase/XSSFilter/ConnectorSecurity.php
@@ -0,0 +1,67 @@
+<?php
+namespace DHTMLX\Connector\XSSFilter;
+
+
+use DHTMLX\Connector\Tools\LogMaster;
+
+define("DHX_SECURITY_SAFETEXT", 1);
+define("DHX_SECURITY_SAFEHTML", 2);
+define("DHX_SECURITY_TRUSTED", 3);
+
+class ConnectorSecurity{
+ static public $xss = DHX_SECURITY_SAFETEXT;
+ static public $security_key = false;
+ static public $security_var = "dhx_security";
+
+ static private $filterClass = null;
+ static function filter($value, $mode = false){
+ if ($mode === false)
+ $mode = ConnectorSecurity::$xss;
+
+ if ($mode == DHX_SECURITY_TRUSTED)
+ return $value;
+ if ($mode == DHX_SECURITY_SAFETEXT)
+ return filter_var($value, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
+ if ($mode == DHX_SECURITY_SAFEHTML){
+ if (ConnectorSecurity::$filterClass == null)
+ ConnectorSecurity::$filterClass = new dhxExternalInputClean();
+ return ConnectorSecurity::$filterClass->basic($value);
+ }
+ throw new Error("Invalid security mode:"+$mode);
+ }
+
+ static function CSRF_detected(){
+ LogMaster::log("[SECURITY] Possible CSRF attack detected", array(
+ "referer" => $_SERVER["HTTP_REFERER"],
+ "remote" => $_SERVER["REMOTE_ADDR"]
+ ));
+ LogMaster::log("Request data", $_POST);
+ die();
+ }
+ static function checkCSRF($edit){
+ if (ConnectorSecurity::$security_key){
+ if (!isset($_SESSION))
+ @session_start();
+
+ if ($edit=== true){
+ if (!isset($_POST[ConnectorSecurity::$security_var]))
+ return ConnectorSecurity::CSRF_detected();
+ $master_key = $_SESSION[ConnectorSecurity::$security_var];
+ $update_key = $_POST[ConnectorSecurity::$security_var];
+ if ($master_key != $update_key)
+ return ConnectorSecurity::CSRF_detected();
+
+ return "";
+ }
+ //data loading
+ if (!array_key_exists(ConnectorSecurity::$security_var,$_SESSION)){
+ $_SESSION[ConnectorSecurity::$security_var] = md5(uniqid());
+ }
+
+ return $_SESSION[ConnectorSecurity::$security_var];
+ }
+
+ return "";
+ }
+
+} \ No newline at end of file
diff --git a/codebase/XSSFilter/dhxExternalInputClean.php b/codebase/XSSFilter/dhxExternalInputClean.php
new file mode 100644
index 0000000..4f3b526
--- /dev/null
+++ b/codebase/XSSFilter/dhxExternalInputClean.php
@@ -0,0 +1,120 @@
+<?php
+namespace DHTMLX\Connector\XSSFilter;
+//original name was lx_externalinput_clean
+//renamed to prevent possible conflicts
+class dhxExternalInputClean {
+ // this basic clean should clean html code from
+ // lot of possible malicious code for Cross Site Scripting
+ // use it whereever you get external input
+
+ // you can also set $filterOut to some use html cleaning, but I don't know of any code, which could
+ // exploit that. But if you want to be sure, set it to eg. array("Tidy","Dom");
+ static function basic($string, $filterIn = array("Tidy","Dom","Striptags"), $filterOut = "none") {
+ $string = self::tidyUp($string, $filterIn);
+ $string = str_replace(array("&amp;", "&lt;", "&gt;"), array("&amp;amp;", "&amp;lt;", "&amp;gt;"), $string);
+
+ // fix &entitiy\n;
+ $string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u', "$1;", $string);
+ $string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $string);
+
+ $string = html_entity_decode($string, ENT_COMPAT, "UTF-8");
+
+ // remove any attribute starting with "on" or xmlns
+ $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])(on|xmlns)[^>]*>#iUu', "$1>", $string);
+
+ // remove javascript: and vbscript: protocol
+ $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2nojavascript...', $string);
+ $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2novbscript...', $string);
+ $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*-moz-binding[\x00-\x20]*:#Uu', '$1=$2nomozbinding...', $string);
+ $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*data[\x00-\x20]*:#Uu', '$1=$2nodata...', $string);
+
+ //remove any style attributes, IE allows too much stupid things in them, eg.
+ //<span style="width: expression(alert('Ping!'));"></span>
+ // and in general you really don't want style declarations in your UGC
+
+ $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])style[^>]*>#iUu', "$1>", $string);
+
+ //remove namespaced elements (we do not need them...)
+ $string = preg_replace('#</*\w+:\w[^>]*>#i', "", $string);
+
+ //remove really unwanted tags
+ do {
+ $oldstring = $string;
+ $string = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $string);
+ } while ($oldstring != $string);
+
+ return self::tidyUp($string, $filterOut);
+ }
+
+ static function tidyUp($string, $filters) {
+ if (is_array($filters)) {
+ foreach ($filters as $filter) {
+ $return = self::tidyUpWithFilter($string, $filter);
+ if ($return !== false) {
+ return $return;
+ }
+ }
+ } else {
+ $return = self::tidyUpWithFilter($string, $filters);
+ }
+ // if no filter matched, use the Striptags filter to be sure.
+ if ($return === false) {
+ return self::tidyUpModuleStriptags($string);
+ } else {
+ return $return;
+ }
+ }
+
+ static private function tidyUpWithFilter($string, $filter) {
+ if (is_callable(array("self", "tidyUpModule" . $filter))) {
+ return call_user_func(array("self", "tidyUpModule" . $filter), $string);
+ }
+ return false;
+ }
+
+ static private function tidyUpModuleStriptags($string) {
+
+ return strip_tags($string);
+ }
+
+ static private function tidyUpModuleNone($string) {
+ return $string;
+ }
+
+ static private function tidyUpModuleDom($string) {
+ $dom = new domdocument();
+ @$dom->loadHTML("<html><body>" . $string . "</body></html>");
+ $string = '';
+ foreach ($dom->documentElement->firstChild->childNodes as $child) {
+ $string .= $dom->saveXML($child);
+ }
+ return $string;
+ }
+
+ static private function tidyUpModuleTidy($string) {
+ if (class_exists("tidy")) {
+ $tidy = new tidy();
+ $tidyOptions = array("output-xhtml" => true,
+ "show-body-only" => true,
+ "clean" => true,
+ "wrap" => "350",
+ "indent" => true,
+ "indent-spaces" => 1,
+ "ascii-chars" => false,
+ "wrap-attributes" => false,
+ "alt-text" => "",
+ "doctype" => "loose",
+ "numeric-entities" => true,
+ "drop-proprietary-attributes" => true,
+ "enclose-text" => false,
+ "enclose-block-text" => false
+
+ );
+ $tidy->parseString($string, $tidyOptions, "utf8");
+ $tidy->cleanRepair();
+ return (string) $tidy;
+ } else {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/codebase/base_connector.php b/codebase/base_connector.php
deleted file mode 100644
index 26f1f8b..0000000
--- a/codebase/base_connector.php
+++ /dev/null
@@ -1,948 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("tools.php");
-require_once("db_common.php");
-require_once("dataprocessor.php");
-require_once("strategy.php");
-require_once("update.php");
-
-//enable buffering to catch and ignore any custom output before XML generation
-//because of this command, it strongly recommended to include connector's file before any other libs
-//in such case it will handle any extra output from not well formed code of other libs
-ini_set("output_buffering","On");
-ob_start();
-
-class OutputWriter{
- private $start;
- private $end;
- private $type;
-
- public function __construct($start, $end = ""){
- $this->start = $start;
- $this->end = $end;
- $this->type = "xml";
- }
- public function add($add){
- $this->start.=$add;
- }
- public function reset(){
- $this->start="";
- $this->end="";
- }
- public function set_type($add){
- $this->type=$add;
- }
- public function output($name="", $inline=true, $encoding=""){
- ob_clean();
-
- if ($this->type == "xml"){
- $header = "Content-type: text/xml";
- if ("" != $encoding)
- $header.="; charset=".$encoding;
- header($header);
- }
-
- echo $this->__toString();
- }
- public function __toString(){
- return $this->start.$this->end;
- }
-}
-
-/*! EventInterface
- Base class , for iterable collections, which are used in event
-**/
-class EventInterface{
- protected $request; ////!< DataRequestConfig instance
- public $rules=array(); //!< array of sorting rules
-
- /*! constructor
- creates a new interface based on existing request
- @param request
- DataRequestConfig object
- */
- public function __construct($request){
- $this->request = $request;
- }
-
- /*! remove all elements from collection
- */
- public function clear(){
- array_splice($rules,0);
- }
- /*! get index by name
-
- @param name
- name of field
- @return
- index of named field
- */
- public function index($name){
- $len = sizeof($this->rules);
- for ($i=0; $i < $len; $i++) {
- if ($this->rules[$i]["name"]==$name)
- return $i;
- }
- return false;
- }
-}
-/*! Wrapper for collection of sorting rules
-**/
-class SortInterface extends EventInterface{
- /*! constructor
- creates a new interface based on existing request
- @param request
- DataRequestConfig object
- */
- public function __construct($request){
- parent::__construct($request);
- $this->rules = &$request->get_sort_by_ref();
- }
- /*! add new sorting rule
-
- @param name
- name of field
- @param dir
- direction of sorting
- */
- public function add($name,$dir){
- if ($dir === false)
- $this->request->set_sort($name);
- else
- $this->request->set_sort($name,$dir);
- }
- public function store(){
- $this->request->set_sort_by($this->rules);
- }
-}
-/*! Wrapper for collection of filtering rules
-**/
-class FilterInterface extends EventInterface{
- /*! constructor
- creates a new interface based on existing request
- @param request
- DataRequestConfig object
- */
- public function __construct($request){
- $this->request = $request;
- $this->rules = &$request->get_filters_ref();
- }
- /*! add new filatering rule
-
- @param name
- name of field
- @param value
- value to filter by
- @param rule
- filtering rule
- */
- public function add($name,$value,$rule){
- $this->request->set_filter($name,$value,$rule);
- }
- public function store(){
- $this->request->set_filters($this->rules);
- }
-}
-
-/*! 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>";
- }
-}
-
-
-
-
-
-/*! Base connector class
- This class used as a base for all component specific connectors.
- Can be used on its own to provide raw data.
-**/
-class Connector {
- protected $config;//DataConfig instance
- protected $request;//DataRequestConfig instance
- protected $names;//!< hash of names for used classes
- protected $encoding="utf-8";//!< assigned encoding (UTF-8 by default)
- protected $editing=false;//!< flag of edit mode ( response for dataprocessor )
-
- public static $filter_var="dhx_filter";
- public static $sort_var="dhx_sort";
- public static $kids_var="dhx_kids";
-
- public $model=false;
-
- private $updating=false;//!< flag of update mode ( response for data-update )
- private $db; //!< db connection resource
- protected $dload;//!< flag of dyn. loading mode
- public $access; //!< AccessMaster instance
- protected $data_separator = "\n";
-
- public $sql; //DataWrapper instance
- public $event; //EventMaster instance
- public $limit=false;
-
- private $id_seed=0; //!< default value, used to generate auto-IDs
- protected $live_update = false; // actions table name for autoupdating
- protected $extra_output="";//!< extra info which need to be sent to client side
- protected $options=array();//!< hash of OptionsConnector
- protected $as_string = false; // render() returns string, don't send result in response
- protected $simple = false; // render only data without any other info
- protected $filters;
- protected $sorts;
- protected $mix;
- protected $order = false;
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param db
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($db,$type=false, $item_type=false, $data_type=false, $render_type = false){
- $this->exec_time=microtime(true);
-
- if (!$type) $type="MySQL";
- if (class_exists($type."DBDataWrapper",false)) $type.="DBDataWrapper";
- if (!$item_type) $item_type="DataItem";
- if (!$data_type) $data_type="DataProcessor";
- if (!$render_type) $render_type="RenderStrategy";
-
- $this->names=array(
- "db_class"=>$type,
- "item_class"=>$item_type,
- "data_class"=>$data_type,
- "render_class"=>$render_type
- );
- $this->attributes = array();
- $this->filters = array();
- $this->sorts = array();
- $this->mix = array();
-
- $this->config = new DataConfig();
- $this->request = new DataRequestConfig();
- $this->event = new EventMaster();
- $this->access = new AccessMaster();
-
- if (!class_exists($this->names["db_class"],false))
- throw new Exception("DB class not found: ".$this->names["db_class"]);
- $this->sql = new $this->names["db_class"]($db,$this->config);
- $this->render = new $this->names["render_class"]($this);
-
- $this->db=$db;//saved for options connectors, if any
-
- EventMaster::trigger_static("connectorCreate",$this);
- }
-
- /*! return db connection resource
- nested class may neeed to access live connection object
- @return
- DB connection resource
- */
- protected function get_connection(){
- return $this->db;
- }
-
- public function get_config(){
- return new DataConfig($this->config);
- }
-
- public function get_request(){
- return new DataRequestConfig($this->request);
- }
-
-
- protected $attributes;
- public function add_top_attribute($name, $string){
- $this->attributes[$name] = $string;
- }
-
- //model is a class, which will be used for all data operations
- //we expect that it has next methods get, update, insert, delete
- //if method was not defined - we will use default logic
- public function useModel($model){
- $this->model = $model;
- }
-
-
- /*! config connector based on table
-
- @param table
- name of table in DB
- @param id
- name of id field
- @param fields
- list of fields names
- @param extra
- list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
- @param relation_id
- name of field used to define relations for hierarchical data organization, optional
- */
- public function render_table($table,$id="",$fields=false,$extra=false,$relation_id=false){
- $this->configure($table,$id,$fields,$extra,$relation_id);
- return $this->render();
- }
- public function configure($table,$id="",$fields=false,$extra=false,$relation_id=false){
- if ($fields === false){
- //auto-config
- $info = $this->sql->fields_list($table);
- $fields = implode(",",$info["fields"]);
- if ($info["key"])
- $id = $info["key"];
- }
- $this->config->init($id,$fields,$extra,$relation_id);
- if (strpos(trim($table), " ")!==false)
- $this->request->parse_sql($table);
- else
- $this->request->set_source($table);
- }
-
- public function uuid(){
- return time()."x".$this->id_seed++;
- }
-
- /*! config connector based on sql
-
- @param sql
- sql query used as base of configuration
- @param id
- name of id field
- @param fields
- list of fields names
- @param extra
- list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
- @param relation_id
- name of field used to define relations for hierarchical data organization, optional
- */
- public function render_sql($sql,$id,$fields,$extra=false,$relation_id=false){
- $this->config->init($id,$fields,$extra,$relation_id);
- $this->request->parse_sql($sql);
- return $this->render();
- }
-
- public function render_array($data, $id, $fields, $extra=false, $relation_id=false){
- $this->configure("-",$id,$fields,$extra,$relation_id);
- $this->sql = new ArrayDBDataWrapper($data, $this->config);
- return $this->render();
- }
-
- public function render_complex_sql($sql,$id,$fields,$extra=false,$relation_id=false){
- $this->config->init($id,$fields,$extra,$relation_id);
- $this->request->parse_sql($sql, true);
- return $this->render();
- }
-
- /*! render already configured connector
-
- @param config
- configuration of data
- @param request
- configuraton of request
- */
- public function render_connector($config,$request){
- $this->config->copy($config);
- $this->request->copy($request);
- return $this->render();
- }
-
- /*! render self
- process commands, output requested data as XML
- */
- public function render(){
- $this->event->trigger("onInit", $this);
- EventMaster::trigger_static("connectorInit",$this);
-
- if (!$this->as_string)
- $this->parse_request();
- $this->set_relation();
-
- if ($this->live_update !== false && $this->updating!==false) {
- $this->live_update->get_updates();
- } else {
- if ($this->editing){
- $dp = new $this->names["data_class"]($this,$this->config,$this->request);
- $dp->process($this->config,$this->request);
- } else {
- if (!$this->access->check("read")){
- LogMaster::log("Access control: read operation blocked");
- echo "Access denied";
- die();
- }
- $wrap = new SortInterface($this->request);
- $this->apply_sorts($wrap);
- $this->event->trigger("beforeSort",$wrap);
- $wrap->store();
-
- $wrap = new FilterInterface($this->request);
- $this->apply_filters($wrap);
- $this->event->trigger("beforeFilter",$wrap);
- $wrap->store();
-
- if ($this->model && method_exists($this->model, "get")){
- $this->sql = new ArrayDBDataWrapper();
- $result = new ArrayQueryWrapper(call_user_func(array($this->model, "get"), $this->request));
- $out = $this->output_as_xml($result);
- } else {
- $out = $this->output_as_xml($this->get_resource());
-
- if ($out !== null) return $out;
- }
-
- }
- }
- $this->end_run();
- }
-
-
- /*! empty call which used for tree-logic
- * to prevent code duplicating
- */
- protected function set_relation() {}
-
- /*! gets resource for rendering
- */
- protected function get_resource() {
- return $this->sql->select($this->request);
- }
-
-
- /*! prevent SQL injection through column names
- replace dangerous chars in field names
- @param str
- incoming field name
- @return
- safe field name
- */
- protected function safe_field_name($str){
- return strtok($str, " \n\t;',");
- }
-
- /*! limit max count of records
- connector will ignore any records after outputing max count
- @param limit
- max count of records
- @return
- none
- */
- public function set_limit($limit){
- $this->limit = $limit;
- }
-
-
- public function limit($start, $count, $sort_field=false, $sort_dir=false){
- $this->request->set_limit($start, $count);
- if ($sort_field)
- $this->request->set_sort($sort_field, $sort_dir);
- }
-
- protected function parse_request_mode(){
- //detect edit mode
- if (isset($_GET["editing"])){
- $this->editing=true;
- } else if (isset($_POST["ids"])){
- $this->editing=true;
- LogMaster::log('While there is no edit mode mark, POST parameters similar to edit mode detected. \n Switching to edit mode ( to disable behavior remove POST[ids]');
- } else if (isset($_GET['dhx_version'])){
- $this->updating = true;
- }
- }
-
- /*! parse incoming request, detects commands and modes
- */
- protected function parse_request(){
- //set default dyn. loading params, can be reset in child classes
- if ($this->dload)
- $this->request->set_limit(0,$this->dload);
- else if ($this->limit)
- $this->request->set_limit(0,$this->limit);
-
- if (isset($_GET["posStart"]) && isset($_GET["count"])) {
- $this->request->set_limit($_GET["posStart"],$_GET["count"]);
- }
-
- $this->parse_request_mode();
-
- if ($this->live_update && ($this->updating || $this->editing)){
- $this->request->set_version($_GET["dhx_version"]);
- $this->request->set_user($_GET["dhx_user"]);
- }
-
- if (isset($_GET[Connector::$sort_var]))
- foreach($_GET[Connector::$sort_var] as $k => $v){
- $k = $this->safe_field_name($k);
- $this->request->set_sort($this->resolve_parameter($k),$v);
- }
-
- if (isset($_GET[Connector::$filter_var]))
- foreach($_GET[Connector::$filter_var] as $k => $v){
- $k = $this->safe_field_name($k);
- if ($v !== "")
- $this->request->set_filter($this->resolve_parameter($k),$v);
- }
-
- $this->check_csrf();
- }
-
- protected function check_csrf(){
- $key = ConnectorSecurity::checkCSRF($this->editing);
- if ($key !== "")
- $this->add_top_attribute(ConnectorSecurity::$security_var, $key);
- }
-
- /*! convert incoming request name to the actual DB name
- @param name
- incoming parameter name
- @return
- name of related DB field
- */
- protected function resolve_parameter($name){
- return $name;
- }
-
-
- /*! replace xml unsafe characters
-
- @param string
- string to be escaped
- @return
- escaped string
- */
- protected function xmlentities($string) {
- return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string);
- }
-
- public function getRecord($id){
- LogMaster::log("Retreiving data for record: ".$id);
- $source = new DataRequestConfig($this->request);
- $source->set_filter($this->config->id["name"],$id, "=");
-
- $res = $this->sql->select($source);
-
- $temp = $this->data_separator;
- $this->data_separator="";
- $output = $this->render_set($res);
- $this->data_separato=$temp;
-
- return $output;
- }
-
- /*! render from DB resultset
- @param res
- DB resultset
- process commands, output requested data as XML
- */
- protected function render_set($res){
- return $this->render->render_set($res, $this->names["item_class"], $this->dload, $this->data_separator, $this->config, $this->mix);
- }
-
- /*! output fetched data as XML
- @param res
- DB resultset
- */
- protected function output_as_xml($res){
- $result = $this->render_set($res);
- if ($this->simple) return $result;
-
- $start="<?xml version='1.0' encoding='".$this->encoding."' ?>".$this->xml_start();
- $end=$result.$this->xml_end();
-
- if ($this->as_string) return $start.$end;
-
- $out = new OutputWriter($start, $end);
- $this->event->trigger("beforeOutput", $this, $out);
- $out->output("", true, $this->encoding);
- }
-
-
- /*! end processing
- stop execution timer, kill the process
- */
- protected function end_run(){
- $time=microtime(true)-$this->exec_time;
- LogMaster::log("Done in {$time}s");
- flush();
- die();
- }
-
- /*! set xml encoding
-
- methods sets only attribute in XML, no real encoding conversion occurs
- @param encoding
- value which will be used as XML encoding
- */
- public function set_encoding($encoding){
- $this->encoding=$encoding;
- }
-
- /*! enable or disable dynamic loading mode
-
- @param count
- count of rows loaded from server, actual only for grid-connector, can be skiped in other cases.
- If value is a false or 0 - dyn. loading will be disabled
- */
- public function dynamic_loading($count){
- $this->dload=$count;
- }
-
- /*! enable or disable data reordering
-
- @param name
- name of field, which will be used for order storing, optional
- by default 'sortorder' field will be used
- */
- public function enable_order($name = true){
- if ($name === true)
- $name = "sortorder";
-
- $this->sort($name);
- $this->access->allow("order");
- $this->request->set_order($name);
- $this->order = $name;
- }
-
- /*! enable logging
-
- @param path
- path to the log file. If set as false or empty strig - logging will be disabled
- @param client_log
- enable output of log data to the client side
- */
- public function enable_log($path=true,$client_log=false){
- LogMaster::enable_log($path,$client_log);
- }
-
- /*! provides infor about current processing mode
- @return
- true if processing dataprocessor command, false otherwise
- */
- public function is_select_mode(){
- $this->parse_request_mode();
- return !$this->editing;
- }
-
- public function is_first_call(){
- $this->parse_request_mode();
- return !($this->editing || $this->updating || $this->request->get_start() || isset($_GET['dhx_no_header']));
-
- }
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- $attributes = "";
-
- if ($this->dload){
- //info for dyn. loadin
- if ($pos=$this->request->get_start())
- $attributes .= " pos='".$pos."'";
- else
- $attributes .= " total_count='".$this->sql->get_size($this->request)."'";
- }
- foreach($this->attributes as $k=>$v)
- $attributes .= " ".$k."='".$v."'";
-
- return "<data".$attributes.">";
- }
- /*! renders self as xml, ending part
- */
- protected function xml_end(){
- $this->fill_collections();
- if (isset($this->extra_output))
- return $this->extra_output."</data>";
- else
- return "</data>";
- }
-
- protected function fill_collections($list=""){
- foreach ($this->options as $k=>$v) {
- $name = $k;
- $this->extra_output.="<coll_options for='{$name}'>";
- if (!is_string($this->options[$name]))
- $this->extra_output.=$this->options[$name]->render();
- else
- $this->extra_output.=$this->options[$name];
- $this->extra_output.="</coll_options>";
- }
- }
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str="";
- foreach($options as $k => $v)
- $str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
- $options=$str;
- }
- $this->options[$name]=$options;
- }
-
-
- public function insert($data) {
- $action = new DataAction('inserted', false, $data);
- $request = new DataRequestConfig();
- $request->set_source($this->request->get_source());
-
- $this->config->limit_fields($data);
- $this->sql->insert($action,$request);
- $this->config->restore_fields($data);
-
- return $action->get_new_id();
- }
-
- public function delete($id) {
- $action = new DataAction('deleted', $id, array());
- $request = new DataRequestConfig();
- $request->set_source($this->request->get_source());
-
- $this->sql->delete($action,$request);
- return $action->get_status();
-}
-
- public function update($data) {
- $action = new DataAction('updated', $data[$this->config->id["name"]], $data);
- $request = new DataRequestConfig();
- $request->set_source($this->request->get_source());
-
- $this->config->limit_fields($data);
- $this->sql->update($action,$request);
- $this->config->restore_fields($data);
-
- return $action->get_status();
- }
-
- /*! sets actions_table for Optimistic concurrency control mode and start it
- @param table_name
- name of database table which will used for saving actions
- @param url
- url used for update notifications
- */
- public function enable_live_update($table, $url=false){
- $this->live_update = new DataUpdate($this->sql, $this->config, $this->request, $table,$url);
- $this->live_update->set_event($this->event,$this->names["item_class"]);
- $this->event->attach("beforeOutput", Array($this->live_update, "version_output"));
- $this->event->attach("beforeFiltering", Array($this->live_update, "get_updates"));
- $this->event->attach("beforeProcessing", Array($this->live_update, "check_collision"));
- $this->event->attach("afterProcessing", Array($this->live_update, "log_operations"));
- }
-
- /*! render() returns result as string or send to response
- */
- public function asString($as_string) {
- $this->as_string = $as_string;
- }
-
- public function simple_render() {
- $this->simple = true;
- return $this->render();
- }
-
- public function filter($name, $value = false, $operation = '=') {
- $this->filters[] = array('name' => $name, 'value' => $value, 'operation' => $operation);
- }
-
- public function clear_filter() {
- $this->filters = array();
- $this->request->set_filters(array());
- }
-
- protected function apply_filters($wrap) {
- for ($i = 0; $i < count($this->filters); $i++) {
- $f = $this->filters[$i];
- $wrap->add($f['name'], $f['value'], $f['operation']);
- }
- }
-
- public function sort($name, $direction = false) {
- $this->sorts[] = array('name' => $name, 'direction' => $direction);
- }
-
- protected function apply_sorts($wrap) {
- for ($i = 0; $i < count($this->sorts); $i++) {
- $s = $this->sorts[$i];
- $wrap->add($s['name'], $s['direction']);
- }
- }
-
- public function mix($name, $value, $filter=false) {
- $this->mix[] = Array('name'=>$name, 'value'=>$value, 'filter'=>$filter);
- }
-}
-
-
-/*! wrapper around options collection, used for comboboxes and filters
-**/
-class OptionsConnector extends Connector{
- protected $init_flag=false;//!< used to prevent rendering while initialization
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="DataItem";
- if (!$data_type) $data_type=""; //has not sense, options not editable
- parent::__construct($res,$type,$item_type,$data_type);
- }
- /*! render self
- process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
- @return
- data as XML string
- */
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
- $res = $this->sql->select($this->request);
- return $this->render_set($res);
- }
-}
-
-
-
-class DistinctOptionsConnector extends OptionsConnector{
- /*! render self
- process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
- @return
- data as XML string
- */
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
- $res = $this->sql->get_variants($this->config->text[0]["db_name"],$this->request);
- return $this->render_set($res);
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/chart_connector.php b/codebase/chart_connector.php
deleted file mode 100644
index 247d1e6..0000000
--- a/codebase/chart_connector.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-
- require_once("dataview_connector.php");
-
-
-/*! Connector class for DataView
-**/
-class ChartConnector extends DataViewConnector{
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- parent::__construct($res,$type,$item_type,$data_type);
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/combo_connector.php b/codebase/combo_connector.php
deleted file mode 100644
index 8fb5416..0000000
--- a/codebase/combo_connector.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-
-require_once("base_connector.php");
-/*! DataItem class for Combo component
-**/
-class ComboDataItem extends DataItem{
- private $selected;//!< flag of selected option
-
- function __construct($data,$config,$index){
- parent::__construct($data,$config,$index);
-
- $this->selected=false;
- }
- /*! mark option as selected
- */
- function select(){
- $this->selected=true;
- }
- /*! return self as XML string, starting part
- */
- function to_xml_start(){
- if ($this->skip) return "";
-
- return "<option ".($this->selected?"selected='true'":"")."value='".$this->xmlentities($this->get_id())."'><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]>";
- }
- /*! return self as XML string, ending part
- */
- function to_xml_end(){
- if ($this->skip) return "";
- return "</option>";
- }
-}
-
-/*! Connector for the dhtmlxCombo
-**/
-class ComboConnector extends Connector{
- private $filter; //!< filtering mask from incoming request
- private $position; //!< position from incoming request
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="ComboDataItem";
- parent::__construct($res,$type,$item_type,$data_type);
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- function parse_request(){
- parent::parse_request();
-
- if (isset($_GET["pos"])){
- if (!$this->dload) //not critical, so just write a log message
- LogMaster::log("Dyn loading request received, but server side was not configured to process dyn. loading. ");
- else
- $this->request->set_limit($_GET["pos"],$this->dload);
- }
-
- if (isset($_GET["mask"]))
- $this->request->set_filter($this->config->text[0]["db_name"],$_GET["mask"]."%","LIKE");
-
- LogMaster::log($this->request);
- }
-
-
- /*! renders self as xml, starting part
- */
- public function xml_start(){
- if ($this->request->get_start())
- return "<complete add='true'>";
- else
- return "<complete>";
- }
-
- /*! renders self as xml, ending part
- */
- public function xml_end(){
- return "</complete>";
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/connector.js b/codebase/connector.js
deleted file mode 100644
index 0ee9648..0000000
--- a/codebase/connector.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-if (window.dhtmlXGridObject && !dhtmlXGridObject.prototype._init_point_connector){
- dhtmlXGridObject.prototype._init_point_connector=dhtmlXGridObject.prototype._init_point;
- dhtmlXGridObject.prototype._init_point=function(){
- //make separate config array for each grid
- this._con_f_used = [].concat(this._con_f_used);
- dhtmlXGridObject.prototype._con_f_used=[];
-
- var clear_url=function(url){
- url=url.replace(/(\?|\&)connector[^\f]*/g,"");
- return url+(url.indexOf("?")!=-1?"&":"?")+"connector=true"+(this.hdr.rows.length > 0 ? "&dhx_no_header=1":"");
- };
- var combine_urls=function(url){
- return clear_url.call(this,url)+(this._connector_sorting||"")+(this._connector_filter||"");
- };
- var sorting_url=function(url,ind,dir){
- this._connector_sorting="&dhx_sort["+ind+"]="+dir;
- return combine_urls.call(this,url);
- };
- var filtering_url=function(url,inds,vals){
- var chunks = [];
- for (var i=0; i<inds.length; i++)
- chunks[i]="dhx_filter["+inds[i]+"]="+encodeURIComponent(vals[i]);
- this._connector_filter="&"+chunks.join("&");
- return combine_urls.call(this,url);
- };
- this.attachEvent("onCollectValues",function(ind){
- if (this._con_f_used[ind]){
- if (typeof(this._con_f_used[ind]) == "object")
- return this._con_f_used[ind];
- else
- return false;
- }
- return true;
- });
- this.attachEvent("onDynXLS",function(){
- this.xmlFileUrl=combine_urls.call(this,this.xmlFileUrl);
- return true;
- });
- this.attachEvent("onBeforeSorting",function(ind,type,dir){
- if (type=="connector"){
- var self=this;
- this.clearAndLoad(sorting_url.call(this,this.xmlFileUrl,ind,dir),function(){
- self.setSortImgState(true,ind,dir);
- });
- return false;
- }
- return true;
- });
- this.attachEvent("onFilterStart",function(a,b){
- var ss = this.getSortingState();
- if (this._con_f_used.length){
- var self=this;
- this.clearAndLoad(filtering_url.call(this,this.xmlFileUrl,a,b));
- if (ss.length)
- self.setSortImgState(true,ss[0],ss[1]);
- return false;
- }
- return true;
- });
- this.attachEvent("onXLE",function(a,b,c,xml){
- if (!xml) return;
- });
-
- if (this._init_point_connector) this._init_point_connector();
- };
- dhtmlXGridObject.prototype._con_f_used=[];
- dhtmlXGridObject.prototype._in_header_connector_text_filter=function(t,i){
- if (!this._con_f_used[i])
- this._con_f_used[i]=1;
- return this._in_header_text_filter(t,i);
- };
- dhtmlXGridObject.prototype._in_header_connector_select_filter=function(t,i){
- if (!this._con_f_used[i])
- this._con_f_used[i]=2;
- return this._in_header_select_filter(t,i);
- };
- dhtmlXGridObject.prototype.load_connector=dhtmlXGridObject.prototype.load;
- dhtmlXGridObject.prototype.load=function(url, call, type){
- if (!this._colls_loaded && this.cellType){
- var ar=[];
- for (var i=0; i < this.cellType.length; i++)
- if (this.cellType[i].indexOf("co")==0 || this.cellType[i].indexOf("clist")==0 || this._con_f_used[i]==2) ar.push(i);
- if (ar.length)
- arguments[0]+=(arguments[0].indexOf("?")!=-1?"&":"?")+"connector=true&dhx_colls="+ar.join(",");
- }
- return this.load_connector.apply(this,arguments);
- };
- dhtmlXGridObject.prototype._parseHead_connector=dhtmlXGridObject.prototype._parseHead;
- dhtmlXGridObject.prototype._parseHead=function(url, call, type){
- this._parseHead_connector.apply(this,arguments);
- if (!this._colls_loaded){
- var cols = this.xmlLoader.doXPath("./coll_options", arguments[0]);
- for (var i=0; i < cols.length; i++){
- var f = cols[i].getAttribute("for");
- var v = [];
- var combo=null;
- if (this.cellType[f] == "combo")
- combo = this.getColumnCombo(f);
- else if (this.cellType[f].indexOf("co")==0)
- combo=this.getCombo(f);
-
- var os = this.xmlLoader.doXPath("./item",cols[i]);
- var opts = [];
- for (var j=0; j<os.length; j++){
- var val=os[j].getAttribute("value");
-
- if (combo){
- var lab=os[j].getAttribute("label")||val;
-
- if (combo.addOption)
- opts.push([val, lab]);
- else
- combo.put(val,lab);
-
- v[v.length]=lab;
- } else
- v[v.length]=val;
- }
- if (opts.length){
- if (combo)
- combo.addOption(opts);
- } else if (v.length && !combo)
- if (this.registerCList)
- this.registerCList(f*1, v);
-
-
- if (this._con_f_used[f*1])
- this._con_f_used[f*1]=v;
- }
- this._colls_loaded=true;
- }
- };
-
-
-
-
-}
-
-if (window.dataProcessor && !dataProcessor.prototype.init_original){
- dataProcessor.prototype.init_original=dataProcessor.prototype.init;
- dataProcessor.prototype.init=function(obj){
- this.init_original(obj);
- obj._dataprocessor=this;
-
- this.setTransactionMode("POST",true);
- this.serverProcessor+=(this.serverProcessor.indexOf("?")!=-1?"&":"?")+"editing=true";
- };
-}
-dhtmlxError.catchError("LoadXML",function(a,b,c){
- alert(c[0].responseText);
-});
diff --git a/codebase/crosslink_connector.php b/codebase/crosslink_connector.php
deleted file mode 100644
index 7d5c74c..0000000
--- a/codebase/crosslink_connector.php
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("data_connector.php");
-
-class DelayedConnector extends Connector{
- protected $init_flag=false;//!< used to prevent rendering while initialization
- private $data_mode=false;//!< flag to separate xml and data request modes
- private $data_result=false;//<! store results of query
-
- public function dataMode($name){
- $this->data_mode = $name;
- $this->data_result=array();
- }
- public function getDataResult(){
- return $this->data_result;
- }
-
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
- return parent::render();
- }
-
- protected function output_as_xml($res){
- if ($this->data_mode){
- while ($data=$this->sql->get_next($res)){
- $this->data_result[]=$data[$this->data_mode];
- }
- }
- else
- return parent::output_as_xml($res);
- }
- protected function end_run(){
- if (!$this->data_mode)
- parent::end_run();
- }
-}
-
-class CrossOptionsConnector extends Connector{
- public $options, $link;
- private $master_name, $link_name, $master_value;
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- $this->options = new OptionsConnector($res,$type,$item_type,$data_type);
- $this->link = new DelayedConnector($res,$type,$item_type,$data_type);
-
- EventMaster::attach_static("connectorInit",array($this, "handle"));
- }
- public function handle($conn){
- if ($conn instanceof DelayedConnector) return;
- if ($conn instanceof OptionsConnector) return;
-
- $this->master_name = $this->link->get_config()->id["db_name"];
- $this->link_name = $this->options->get_config()->id["db_name"];
-
- $this->link->event->attach("beforeFilter",array($this, "get_only_related"));
-
- if (isset($_GET["dhx_crosslink_".$this->link_name])){
- $this->get_links($_GET["dhx_crosslink_".$this->link_name]);
- die();
- }
-
- if (!$this->dload){
- $conn->event->attach("beforeRender", array($this, "getOptions"));
- $conn->event->attach("beforeRenderSet", array($this, "prepareConfig"));
- }
-
-
- $conn->event->attach("afterProcessing", array($this, "afterProcessing"));
- }
- public function prepareConfig($conn, $res, $config){
- $config->add_field($this->link_name);
- }
- public function getOptions($data){
- $this->link->dataMode($this->link_name);
-
- $this->get_links($data->get_value($this->master_name));
-
- $data->set_value($this->link_name, implode(",",$this->link->getDataResult()));
- }
- public function get_links($id){
- $this->master_value = $id;
- $this->link->render();
- }
- public function get_only_related($filters){
- $index = $filters->index($this->master_name);
- if ($index!==false){
- $filters->rules[$index]["value"]=$this->master_value;
- } else
- $filters->add($this->master_name, $this->master_value, "=");
- }
- public function afterProcessing($action){
- $status = $action->get_status();
-
- $master_key = $action->get_id();//value($this->master_name);
- $link_key = $action->get_value($this->link_name);
- $link_key = explode(',', $link_key);
-
- if ($status == "inserted")
- $master_key = $action->get_new_id();
-
- switch ($status){
- case "deleted":
- $this->link->delete($master_key);
- break;
- case "updated":
- //cross link options not loaded yet, so we can skip update
- if (!array_key_exists($this->link_name, $action->get_data()))
- break;
- //else, delete old options and continue in insert section to add new values
- $this->link->delete($master_key);
- case "inserted":
- for ($i=0; $i < sizeof($link_key); $i++)
- if ($link_key[$i]!="")
- $this->link->insert(array(
- $this->link_name => $link_key[$i],
- $this->master_name => $master_key
- ));
- break;
- }
- }
-}
-
-
-class JSONCrossOptionsConnector extends CrossOptionsConnector{
- public $options, $link;
- private $master_name, $link_name, $master_value;
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- $this->options = new JSONOptionsConnector($res,$type,$item_type,$data_type);
- $this->link = new DelayedConnector($res,$type,$item_type,$data_type);
-
- EventMaster::attach_static("connectorInit",array($this, "handle"));
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/data_connector.php b/codebase/data_connector.php
deleted file mode 100644
index 165cc0f..0000000
--- a/codebase/data_connector.php
+++ /dev/null
@@ -1,528 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-
-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);
- }
-};
-
-/*! 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.">";
- }
-}
-
-
-/*! Connector class for DataView
-**/
-class DataConnector extends Connector{
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="CommonDataItem";
- if (!$data_type) $data_type="CommonDataProcessor";
-
- $this->sections = array();
-
- if (!$render_type) $render_type="RenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
-
- }
-
- protected $sections;
- public function add_section($name, $string){
- $this->sections[$name] = $string;
- }
-
- protected function parse_request_mode(){
- if (isset($_GET['action']) && $_GET["action"] != "get")
- $this->editing = true;
- else
- parent::parse_request_mode();
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- protected function parse_request(){
- if (isset($_GET['action'])){
- $action = $_GET['action'];
- //simple request mode
- if ($action == "get"){
- //data request
- if (isset($_GET['id'])){
- //single entity data request
- $this->request->set_filter($this->config->id["name"],$_GET['id'],"=");
- } else {
- //loading collection of items
- }
- } else {
- //data saving
- $this->editing = true;
- }
- parent::check_csrf();
- } else {
- if (isset($_GET['editing']) && isset($_POST['ids']))
- $this->editing = true;
- parent::parse_request();
- }
-
- if (isset($_GET["start"]) && isset($_GET["count"]))
- $this->request->set_limit($_GET["start"],$_GET["count"]);
-
- }
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- $start = "<data";
- foreach($this->attributes as $k=>$v)
- $start .= " ".$k."='".$v."'";
- $start.= ">";
-
- foreach($this->sections as $k=>$v)
- $start .= "<".$k.">".$v."</".$k.">\n";
- return $start;
- }
-};
-
-class JSONDataConnector extends DataConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="JSONCommonDataItem";
- if (!$data_type) $data_type="CommonDataProcessor";
- if (!$render_type) $render_type="JSONRenderStrategy";
- $this->data_separator = ",\n";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str=array();
- foreach($options as $k => $v)
- $str[]='{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
- $options=implode(",",$str);
- }
- $this->options[$name]=$options;
- }
-
- /*! generates xml description for options collections
-
- @param list
- comma separated list of column names, for which options need to be generated
- */
- protected function fill_collections($list=""){
- $options = array();
- foreach ($this->options as $k=>$v) {
- $name = $k;
- $option="\"{$name}\":[";
- if (!is_string($this->options[$name]))
- $option.=substr(json_encode($this->options[$name]->render()),1,-1);
- else
- $option.=$this->options[$name];
- $option.="]";
- $options[] = $option;
- }
- $this->extra_output .= implode($this->data_separator, $options);
- }
-
- protected function resolve_parameter($name){
- if (intval($name).""==$name)
- return $this->config->text[intval($name)]["db_name"];
- return $name;
- }
-
- protected function output_as_xml($res){
- $json = $this->render_set($res);
- if ($this->simple) return $json;
- $result = json_encode($json);
-
- $this->fill_collections();
- $is_sections = sizeof($this->sections) && $this->is_first_call();
- if ($this->dload || $is_sections || sizeof($this->attributes) || !empty($this->extra_data)){
-
- $attributes = "";
- foreach($this->attributes as $k=>$v)
- $attributes .= ", \"".$k."\":\"".$v."\"";
-
- $extra = "";
- if (!empty($this->extra_output))
- $extra .= ', "collections": {'.$this->extra_output.'}';
-
- $sections = "";
- if ($is_sections){
- //extra sections
- foreach($this->sections as $k=>$v)
- $sections .= ", \"".$k."\":".$v;
- }
-
- $dyn = "";
- if ($this->dload){
- //info for dyn. loadin
- if ($pos=$this->request->get_start())
- $dyn .= ", \"pos\":".$pos;
- else
- $dyn .= ", \"pos\":0, \"total_count\":".$this->sql->get_size($this->request);
- }
- if ($attributes || $sections || $this->extra_output || $dyn) {
- $result = "{ \"data\":".$result.$attributes.$extra.$sections.$dyn."}";
- }
- }
-
- // return as string
- if ($this->as_string) return $result;
-
- // output direct to response
- $out = new OutputWriter($result, "");
- $out->set_type("json");
- $this->event->trigger("beforeOutput", $this, $out);
- $out->output("", true, $this->encoding);
- return null;
- }
-}
-
-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;
- }
-}
-
-
-/*! wrapper around options collection, used for comboboxes and filters
-**/
-class JSONOptionsConnector extends JSONDataConnector{
- protected $init_flag=false;//!< used to prevent rendering while initialization
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="JSONCommonDataItem";
- if (!$data_type) $data_type=""; //has not sense, options not editable
- parent::__construct($res,$type,$item_type,$data_type);
- }
- /*! render self
- process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
- @return
- data as XML string
- */
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
- $res = $this->sql->select($this->request);
- return $this->render_set($res);
- }
-}
-
-
-class JSONDistinctOptionsConnector extends JSONOptionsConnector{
- /*! render self
- process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
- @return
- data as XML string
- */
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
- $res = $this->sql->get_variants($this->config->text[0]["db_name"],$this->request);
- return $this->render_set($res);
- }
-}
-
-
-
-class TreeCommonDataItem extends CommonDataItem{
- protected $kids=-1;
-
- 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)."'";
-
- if ($this->kids === true)
- $str .=" ".Connector::$kids_var."='1'";
-
- return $str.">";
- }
-
- function has_kids(){
- return $this->kids;
- }
-
- function set_kids($value){
- $this->kids=$value;
- }
-}
-
-
-class TreeDataConnector extends DataConnector{
- protected $parent_name = 'parent';
- public $rootId = "0";
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- * @param render_type
- * name of class which will provides data rendering
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="TreeCommonDataItem";
- if (!$data_type) $data_type="CommonDataProcessor";
- if (!$render_type) $render_type="TreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- protected function parse_request(){
- parent::parse_request();
-
- if (isset($_GET[$this->parent_name]))
- $this->request->set_relation($_GET[$this->parent_name]);
- else
- $this->request->set_relation($this->rootId);
-
- $this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
- }
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- $attributes = " ";
- if (!$this->rootId || $this->rootId != $this->request->get_relation())
- $attributes = " parent='".$this->request->get_relation()."' ";
-
- foreach($this->attributes as $k=>$v)
- $attributes .= " ".$k."='".$v."'";
-
- return "<data".$attributes.">";
- }
-}
-
-
-class JSONTreeDataConnector extends TreeDataConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="JSONTreeCommonDataItem";
- if (!$data_type) $data_type="CommonDataProcessor";
- if (!$render_type) $render_type="JSONTreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- protected function output_as_xml($res){
- $result = $this->render_set($res);
- if ($this->simple) return $result;
-
- $data = array();
- if (!$this->rootId || $this->rootId != $this->request->get_relation())
- $data["parent"] = $this->request->get_relation();
-
- $data["data"] = $result;
-
- $this->fill_collections();
- if (!empty($this->options))
- $data["collections"] = $this->options;
-
-
- foreach($this->attributes as $k=>$v)
- $data[$k] = $v;
-
- $data = json_encode($data);
-
- // return as string
- if ($this->as_string) return $data;
-
- // output direct to response
- $out = new OutputWriter($data, "");
- $out->set_type("json");
- $this->event->trigger("beforeOutput", $this, $out);
- $out->output("", true, $this->encoding);
- }
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str=array();
- foreach($options as $k => $v)
- $str[]=Array("id"=>$this->xmlentities($k), "value"=>$this->xmlentities($v));//'{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
- $options=$str;
- }
- $this->options[$name]=$options;
- }
-
- /*! generates xml description for options collections
-
- @param list
- comma separated list of column names, for which options need to be generated
- */
- protected function fill_collections($list=""){
- $options = array();
- foreach ($this->options as $k=>$v) {
- $name = $k;
- if (!is_array($this->options[$name]))
- $option=$this->options[$name]->render();
- else
- $option=$this->options[$name];
- $options[$name] = $option;
- }
- $this->options = $options;
- $this->extra_output .= "'collections':".json_encode($options);
- }
-
-}
-
-
-class JSONTreeCommonDataItem extends TreeCommonDataItem{
- /*! return self as XML string
- */
- function to_xml_start(){
- 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"];
- if (isset($this->data[$extra]))
- $data[$extra]=$this->data[$extra];
- }
-
- if ($this->userdata !== false)
- foreach ($this->userdata as $key => $value)
- $data[$key]=$value;
-
- if ($this->kids === true)
- $data[Connector::$kids_var] = 1;
-
- return $data;
- }
-
- function to_xml_end(){
- return "";
- }
-}
-
-
-?>
diff --git a/codebase/dataprocessor.php b/codebase/dataprocessor.php
deleted file mode 100644
index 89a4460..0000000
--- a/codebase/dataprocessor.php
+++ /dev/null
@@ -1,521 +0,0 @@
-<?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: {$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>";
- }
-
-}
-
-/*! 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."='".$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/dataview_connector.php b/codebase/dataview_connector.php
deleted file mode 100644
index fe2c9fd..0000000
--- a/codebase/dataview_connector.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-
-/*! DataItem class for DataView component
-**/
-class DataViewDataItem extends DataItem{
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
-
- $str="<item id='".$this->get_id()."' >";
- for ($i=0; $i<sizeof($this->config->text); $i++){
- $extra = $this->config->text[$i]["name"];
- $str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
- }
- return $str."</item>";
- }
-}
-
-
-/*! Connector class for DataView
-**/
-class DataViewConnector extends Connector{
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="DataViewDataItem";
- if (!$data_type) $data_type="DataProcessor";
- parent::__construct($res,$type,$item_type,$data_type);
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- function parse_request(){
- parent::parse_request();
-
- if (isset($_GET["posStart"]) && isset($_GET["count"]))
- $this->request->set_limit($_GET["posStart"],$_GET["count"]);
- }
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- $attributes = "";
- foreach($this->attributes as $k=>$v)
- $attributes .= " ".$k."='".$v."'";
-
- if ($this->dload){
- if ($pos=$this->request->get_start())
- return "<data pos='".$pos."'".$attributes.">";
- else
- return "<data total_count='".$this->sql->get_size($this->request)."'".$attributes.">";
- }
- else
- return "<data".$attributes.">";
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_adodb.php b/codebase/db_adodb.php
deleted file mode 100644
index 5250c21..0000000
--- a/codebase/db_adodb.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! Implementation of DataWrapper for PostgreSQL
-**/
-class AdoDBDataWrapper extends DBDataWrapper{
- protected $last_result;
- public function query($sql){
- LogMaster::log($sql);
- if (is_array($sql)) {
- $res = $this->connection->SelectLimit($sql['sql'], $sql['numrows'], $sql['offset']);
- } else {
- $res = $this->connection->Execute($sql);
- }
-
- if ($res===false) throw new Exception("ADODB operation failed\n".$this->connection->ErrorMsg());
- $this->last_result = $res;
- return $res;
- }
-
- public function get_next($res){
- if (!$res)
- $res = $this->last_result;
-
- if ($res->EOF)
- return false;
-
- $row = $res->GetRowAssoc(false);
- $res->MoveNext();
- return $row;
- }
-
- protected function get_new_id(){
- return $this->connection->Insert_ID();
- }
-
- public function escape($data){
- return $this->connection->addq($data);
- }
-
- /*! escape field name to prevent sql reserved words conflict
- @param data
- unescaped data
- @return
- escaped data
- */
- public function escape_name($data){
- if ((strpos($data,"`")!==false || is_int($data)) || (strpos($data,".")!==false))
- return $data;
- return '`'.$data.'`';
- }
-
-
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
-
- if ($start || $count) {
- $sql=array("sql"=>$sql,'numrows'=>$count, 'offset'=>$start);
- }
- return $sql;
- }
-
-}
-?> \ No newline at end of file
diff --git a/codebase/db_common.php b/codebase/db_common.php
deleted file mode 100644
index f6391d2..0000000
--- a/codebase/db_common.php
+++ /dev/null
@@ -1,1157 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("tools.php");
-
-/*! manager of data request
-**/
-class DataRequestConfig{
- private $filters; //!< array of filtering rules
- private $relation=false; //!< ID or other element used for linking hierarchy
- private $sort_by; //!< sorting field
- private $start; //!< start of requested data
- private $count; //!< length of requested data
-
- private $order = false;
- private $user;
- private $version;
-
- //for render_sql
- private $source; //!< souce table or another source destination
- private $fieldset; //!< set of data, which need to be retrieved from source
-
- /*! constructor
-
- @param proto
- DataRequestConfig object, optional, if provided then new request object will copy all properties from provided one
- */
- public function __construct($proto=false){
- if ($proto)
- $this->copy($proto);
- else{
- $start=0;
- $this->filters=array();
- $this->sort_by=array();
- }
- }
-
- /*! copy parameters of source object into self
-
- @param proto
- source object
- */
- public function copy($proto){
- $this->filters =$proto->get_filters();
- $this->sort_by =$proto->get_sort_by();
- $this->count =$proto->get_count();
- $this->start =$proto->get_start();
- $this->source =$proto->get_source();
- $this->fieldset =$proto->get_fieldset();
- $this->relation =$proto->get_relation();
- $this->user = $proto->user;
- $this->version = $proto->version;
- }
-
- /*! convert self to string ( for logs )
- @return
- self as plain string,
- */
- public function __toString(){
- $str="Source:{$this->source}\nFieldset:{$this->fieldset}\nWhere:";
- for ($i=0; $i < sizeof($this->filters); $i++)
- $str.=$this->filters[$i]["name"]." ".$this->filters[$i]["operation"]." ".$this->filters[$i]["value"].";";
- $str.="\nStart:{$this->start}\nCount:{$this->count}\n";
- for ($i=0; $i < sizeof($this->sort_by); $i++)
- $str.=$this->sort_by[$i]["name"]."=".$this->sort_by[$i]["direction"].";";
- $str.="\nRelation:{$this->relation}";
- return $str;
- }
-
- /*! returns set of filtering rules
- @return
- set of filtering rules
- */
- public function get_filters(){
- return $this->filters;
- }
- public function &get_filters_ref(){
- return $this->filters;
- }
- public function set_filters($data){
- $this->filters=$data;
- }
-
-
- public function get_order(){
- return $this->order;
- }
- public function set_order($order){
- $this->order = $order;
- }
- public function get_user(){
- return $this->user;
- }
- public function set_user($user){
- $this->user = $user;
- }
- public function get_version(){
- return $this->version;
- }
- public function set_version($version){
- $this->version = $version;
- }
-
- /*! returns list of used fields
- @return
- list of used fields
- */
- public function get_fieldset(){
- return $this->fieldset;
- }
- /*! returns name of source table
- @return
- name of source table
- */
- public function get_source(){
- return $this->source;
- }
- /*! returns set of sorting rules
- @return
- set of sorting rules
- */
- public function get_sort_by(){
- return $this->sort_by;
- }
- public function &get_sort_by_ref(){
- return $this->sort_by;
- }
- public function set_sort_by($data){
- $this->sort_by=$data;
- }
-
- /*! returns start index
- @return
- start index
- */
- public function get_start(){
- return $this->start;
- }
- /*! returns count of requested records
- @return
- count of requested records
- */
- public function get_count(){
- return $this->count;
- }
- /*! returns name of relation id
- @return
- relation id name
- */
- public function get_relation(){
- return $this->relation;
- }
-
- /*! sets sorting rule
-
- @param field
- name of column
- @param order
- direction of sorting
- */
- public function set_sort($field,$order=false){
- if (!$field && !$order)
- $this->sort_by=array();
- else{
- if ($order===false)
- $this->sort_by[] = $field;
- else {
- $order=strtolower($order)=="asc"?"ASC":"DESC";
- $this->sort_by[]=array("name"=>$field,"direction" => $order);
- }
- }
- }
- /*! sets filtering rule
-
- @param field
- name of column
- @param value
- value for filtering
- @param operation
- operation for filtering, optional , LIKE by default
- */
- public function set_filter($field,$value=false,$operation=false){
- if ($value === false)
- array_push($this->filters,$field);
- else
- array_push($this->filters,array("name"=>$field,"value"=>$value,"operation"=>$operation));
- }
-
- /*! sets list of used fields
-
- @param value
- list of used fields
- */
- public function set_fieldset($value){
- $this->fieldset=$value;
- }
- /*! sets name of source table
-
- @param value
- name of source table
- */
- public function set_source($value){
- if (is_string($value))
- $value = trim($value);
- $this->source = $value;
- if (!$this->source) throw new Exception("Source of data can't be empty");
- }
- /*! sets data limits
-
- @param start
- start index
- @param count
- requested count of data
- */
- public function set_limit($start,$count){
- $this->start=$start;
- $this->count=$count;
- }
- /*! sets name of relation id
-
- @param value
- name of relation id field
- */
- public function set_relation($value){
- $this->relation=$value;
- }
- /*! parse incoming sql, to fill other properties
-
- @param sql
- incoming sql string
- */
- public function parse_sql($sql, $as_is = false){
- if ($as_is){
- $this->fieldset = $sql;
- return;
- }
-
- $sql= preg_replace("/[ \n\t]+limit[\n\t ,0-9]*$/i","",$sql);
-
- $data = preg_split("/[ \n\t]+\\_from\\_/i",$sql,2);
- if (count($data)!=2)
- $data = preg_split("/[ \n\t]+from/i",$sql,2);
- $this->fieldset = preg_replace("/^[\s]*select/i","",$data[0],1);
-
- //Ignore next type of calls
- //direct call to stored procedure without FROM
- if ((count($data) == 1) ||
- //UNION select
- preg_match("#[ \n\r\t]union[ \n\t\r]#i", $sql)){
- $this->fieldset = $sql;
- return;
- }
-
- $table_data = preg_split("/[ \n\t]+where/i",$data[1],2);
- /*
- if sql code contains group_by we will place all sql query in the FROM
- it will not allow to use any filtering against the query
- still it is better than just generate incorrect sql commands for any group by query
- */
- if (sizeof($table_data)>1 && !preg_match("#.*group by.*#i",$table_data[1])){ //where construction exists
- $this->set_source($table_data[0]);
- $where_data = preg_split("/[ \n\t]+order[ ]+by/i",$table_data[1],2);
- $this->filters[]=$where_data[0];
- if (sizeof($where_data)==1) return; //end of line detected
- $data=$where_data[1];
- } else {
- $table_data = preg_split("/[ \n\t]+order[ ]+by/i",$data[1],2);
- $this->set_source($table_data[0]);
- if (sizeof($table_data)==1) return; //end of line detected
- $data=$table_data[1];
- }
-
- if (trim($data)){ //order by construction exists
- $s_data = preg_split("/\\,/",trim($data));
- for ($i=0; $i < count($s_data); $i++) {
- $data=preg_split("/[ ]+/",trim($s_data[$i]),2);
- if (sizeof($data)>1)
- $this->set_sort($data[0],$data[1]);
- else
- $this->set_sort($data[0]);
- }
-
- }
- }
-}
-
-/*! manager of data configuration
-**/
-class DataConfig{
- public $id;////!< name of ID field
- public $relation_id;//!< name or relation ID field
- public $text;//!< array of text fields
- public $data;//!< array of all known fields , fields which exists only in this collection will not be included in dataprocessor's operations
-
-
- /*! converts self to the string, for logging purposes
- **/
- public function __toString(){
- $str="ID:{$this->id['db_name']}(ID:{$this->id['name']})\n";
- $str.="Relation ID:{$this->relation_id['db_name']}({$this->relation_id['name']})\n";
- $str.="Data:";
- for ($i=0; $i<sizeof($this->text); $i++)
- $str.="{$this->text[$i]['db_name']}({$this->text[$i]['name']}),";
-
- $str.="\nExtra:";
- for ($i=0; $i<sizeof($this->data); $i++)
- $str.="{$this->data[$i]['db_name']}({$this->data[$i]['name']}),";
-
- return $str;
- }
-
- /*! removes un-used fields from configuration
- @param name
- name of field , which need to be preserved
- */
- public function minimize($name){
- for ($i=0; $i < sizeof($this->text); $i++){
- if ($this->text[$i]["db_name"]==$name || $this->text[$i]["name"]==$name){
- $this->text[$i]["name"]="value";
- $this->data=array($this->text[$i]);
- $this->text=array($this->text[$i]);
- return;
- }
- }
- throw new Exception("Incorrect dataset minimization, master field not found.");
- }
-
- public function limit_fields($data){
- if (isset($this->full_field_list))
- $this->restore_fields();
- $this->full_field_list = $this->text;
- $this->text = array();
-
- for ($i=0; $i < sizeof($this->full_field_list); $i++) {
- if (array_key_exists($this->full_field_list[$i]["name"],$data))
- $this->text[] = $this->full_field_list[$i];
- }
- }
-
- public function restore_fields(){
- if (isset($this->full_field_list))
- $this->text = $this->full_field_list;
- }
-
- /*! initialize inner state by parsing configuration parameters
-
- @param id
- name of id field
- @param fields
- name of data field(s)
- @param extra
- name of extra field(s)
- @param relation
- name of relation field
-
- */
- public function init($id,$fields,$extra,$relation){
- $this->id = $this->parse($id,false);
- $this->text = $this->parse($fields,true);
- $this->data = array_merge($this->text,$this->parse($extra,true));
- $this->relation_id = $this->parse($relation,false);
- }
-
- /*! parse configuration string
-
- @param key
- key string from configuration
- @param mode
- multi names flag
- @return
- parsed field name object
- */
- private function parse($key,$mode){
- if ($mode){
- if (!$key) return array();
- $key=explode(",",$key);
- for ($i=0; $i < sizeof($key); $i++)
- $key[$i]=$this->parse($key[$i],false);
- return $key;
- }
- $key=explode("(",$key);
- $data=array("db_name"=>trim($key[0]), "name"=>trim($key[0]));
- if (sizeof($key)>1)
- $data["name"]=substr(trim($key[1]),0,-1);
- return $data;
- }
-
- /*! constructor
- init public collectons
- @param proto
- DataConfig object used as prototype for new one, optional
- */
- public function __construct($proto=false){
- if ($proto!==false)
- $this->copy($proto);
- else {
- $this->text=array();
- $this->data=array();
- $this->id=array("name"=>"dhx_auto_id", "db_name"=>"dhx_auto_id");
- $this->relation_id=array("name"=>"", "db_name"=>"");
- }
- }
-
- /*! copy properties from source object
-
- @param proto
- source object
- */
- public function copy($proto){
- $this->id = $proto->id;
- $this->relation_id = $proto->relation_id;
- $this->text = $proto->text;
- $this->data = $proto->data;
- }
-
- /*! returns list of data fields (db_names)
- @return
- list of data fields ( ready to be used in SQL query )
- */
- public function db_names_list($db){
- $out=array();
- if ($this->id["db_name"])
- array_push($out,$db->escape_name($this->id["db_name"]));
- if ($this->relation_id["db_name"])
- array_push($out,$db->escape_name($this->relation_id["db_name"]));
-
- for ($i=0; $i < sizeof($this->data); $i++){
- if ($this->data[$i]["db_name"]!=$this->data[$i]["name"])
- $out[]=$db->escape_name($this->data[$i]["db_name"])." as ".$this->data[$i]["name"];
- else
- $out[]=$db->escape_name($this->data[$i]["db_name"]);
- }
-
- return $out;
- }
-
- /*! add field to dataset config ($text collection)
-
- added field will be used in all auto-generated queries
- @param name
- name of field
- @param aliase
- aliase of field, optional
- */
- public function add_field($name,$aliase=false){
- if ($aliase===false) $aliase=$name;
-
- //adding to list of data-active fields
- if ($this->id["db_name"]==$name || $this->relation_id["db_name"] == $name){
- LogMaster::log("Field name already used as ID, be sure that it is really necessary.");
- }
- if ($this->is_field($name,$this->text)!=-1)
- throw new Exception('Data field already registered: '.$name);
- array_push($this->text,array("db_name"=>$name,"name"=>$aliase));
-
- //adding to list of all fields as well
- if ($this->is_field($name,$this->data)==-1)
- array_push($this->data,array("db_name"=>$name,"name"=>$aliase));
-
- }
-
- /*! remove field from dataset config ($text collection)
-
- removed field will be excluded from all auto-generated queries
- @param name
- name of field, or aliase of field
- */
- public function remove_field($name){
- $ind = $this->is_field($name);
- if ($ind==-1) throw new Exception('There was no such data field registered as: '.$name);
- array_splice($this->text,$ind,1);
- //we not deleting field from $data collection, so it will not be included in data operation, but its data still available
- }
-
- /*! remove field from dataset config ($text and $data collections)
-
- removed field will be excluded from all auto-generated queries
- @param name
- name of field, or aliase of field
- */
- public function remove_field_full($name){
- $ind = $this->is_field($name);
- if ($ind==-1) throw new Exception('There was no such data field registered as: '.$name);
- array_splice($this->text,$ind,1);
-
- $ind = $this->is_field($name, $this->data);
- if ($ind==-1) throw new Exception('There was no such data field registered as: '.$name);
- array_splice($this->data,$ind,1);
- }
-
- /*! check if field is a part of dataset
-
- @param name
- name of field
- @param collection
- collection, against which check will be done, $text collection by default
- @return
- returns true if field already a part of dataset, otherwise returns true
- */
- public function is_field($name,$collection = false){
- if (!$collection)
- $collection=$this->text;
-
- for ($i=0; $i<sizeof($collection); $i++)
- if ($collection[$i]["name"] == $name || $collection[$i]["db_name"] == $name) return $i;
- return -1;
- }
-
-
-}
-
-/*! Base abstraction class, used for data operations
- Class abstract access to data, it is a base class to all DB wrappers
-**/
-abstract class DataWrapper{
- protected $connection;
- protected $config;//!< DataConfig instance
- /*! constructor
- @param connection
- DB connection
- @param config
- DataConfig instance
- */
- public function __construct($connection = false,$config = false){
- $this->config=$config;
- $this->connection=$connection;
- }
-
- /*! insert record in storage
-
- @param data
- DataAction object
- @param source
- DataRequestConfig object
- */
- abstract function insert($data,$source);
-
- /*! delete record from storage
-
- @param data
- DataAction object
- @param source
- DataRequestConfig object
- */
- abstract function delete($data,$source);
-
- /*! update record in storage
-
- @param data
- DataAction object
- @param source
- DataRequestConfig object
- */
- abstract function update($data,$source);
-
- /*! select record from storage
-
- @param source
- DataRequestConfig object
- */
- abstract function select($source);
-
- /*! get size of storage
-
- @param source
- DataRequestConfig object
- */
- abstract function get_size($source);
-
- /*! get all variations of field in storage
-
- @param name
- name of field
- @param source
- DataRequestConfig object
- */
- abstract function get_variants($name,$source);
-
- /*! checks if there is a custom sql string for specified db operation
-
- @param name
- name of DB operation
- @param data
- hash of data
- @return
- sql string
- */
- public function get_sql($name,$data){
- return ""; //custom sql not supported by default
- }
-
- /*! begins DB transaction
- */
- public function begin_transaction(){
- throw new Exception("Data wrapper not supports transactions.");
- }
- /*! commits DB transaction
- */
- public function commit_transaction(){
- throw new Exception("Data wrapper not supports transactions.");
- }
- /*! rollbacks DB transaction
- */
- public function rollback_transaction(){
- throw new Exception("Data wrapper not supports transactions.");
- }
-}
-
-/*! Common database abstraction class
- Class provides base set of methods to access and change data in DB, class used as a base for DB-specific wrappers
-**/
-abstract class DBDataWrapper extends DataWrapper{
- private $transaction = false; //!< type of transaction
- private $sequence=false;//!< sequence name
- private $sqls = array();//!< predefined sql actions
-
-
- /*! assign named sql query
- @param name
- name of sql query
- @param data
- sql query text
- */
- public function attach($name,$data){
- $name=strtolower($name);
- $this->sqls[$name]=$data;
- }
- /*! replace vars in sql string with actual values
-
- @param matches
- array of field name matches
- @return
- value for the var name
- */
- public function get_sql_callback($matches){
- return $this->escape($this->temp->get_value($matches[1]));
- }
- public function get_sql($name,$data){
- $name=strtolower($name);
- if (!array_key_exists($name,$this->sqls)) return "";
-
-
- $str = $this->sqls[$name];
- $this->temp = $data; //dirty
- $str = preg_replace_callback('|\{([^}]+)\}|',array($this,"get_sql_callback"),$str);
- unset ($this->temp); //dirty
- return $str;
- }
-
- public function new_record_order($action, $source){
- $order = $source->get_order();
- if ($order){
- $table = $source->get_source();
- $id = $this->config->id["db_name"];
- $idvalue = $action->get_new_id();
-
- $max = $this->queryOne("SELECT MAX($order) as dhx_maxvalue FROM $table");
- $dhx_maxvalue = $max["dhx_maxvalue"] + 1;
-
- $this->query("UPDATE $table SET $order = $dhx_maxvalue WHERE $id = $idvalue");
- }
- }
-
- public function order($data, $source){
- //id of moved item
- $id1 = $this->escape($data->get_value("id"));
- //id of target item
- $target = $data->get_value("target");
- if (strpos($target, "next:") !== false){
- $dropnext = true;
- $id2 = str_replace("next:", "", $target);
- } else {
- $id2 = $target;
- }
- $id2 = $this->escape($id2);
-
-
- //for tree like components we need to limit out queries to the affected branch only
- $relation_select = $relation_update = $relation_sql_out = $relation_sql = "";
- if ($this->config->relation_id["name"]){
- $relation = $data->get_value($this->config->relation_id["name"]);
- if ($relation !== false && $relation !== ""){
- $relation_sql = " ".$this->config->relation_id["db_name"]." = '".$this->escape($relation)."' AND ";
- $relation_select = $this->config->relation_id["db_name"]." as dhx_parent, ";
- $relation_update = " ".$this->config->relation_id["db_name"]." = '".$this->escape($relation)."', ";
- }
- }
-
-
- $name = $source->get_order();
- $table = $source->get_source();
- $idkey = $this->config->id["db_name"];
-
- $source = $this->queryOne("select $relation_select $name as dhx_index from $table where $idkey = '$id1'");
- $source_index = $source["dhx_index"] ? $source["dhx_index"] : 0;
- if ($relation_sql)
- $relation_sql_out = " ".$this->config->relation_id["db_name"]." = '".$this->escape($source["dhx_parent"])."' AND ";
-
- $this->query("update $table set $name = $name - 1 where $relation_sql_out $name >= $source_index");
-
- if ($id2 !== ""){
- $target = $this->queryOne("select $name as dhx_index from $table where $idkey = '$id2'");
- $target_index = $target["dhx_index"];
- if (!$target_index)
- $target_index = 0;
- if ($dropnext)
- $target_index += 1;
- $this->query("update $table set $name = $name + 1 where $relation_sql $name >= $target_index");
- } else {
- $target = $this->queryOne("select max($name) as dhx_index from $table");
- $target_index = ($target["dhx_index"] ? $target["dhx_index"] : 0)+1;
- }
-
- $this->query("update $table set $relation_update $name = $target_index where $idkey = '$id1'");
- }
-
- public function insert($data,$source){
- $sql=$this->insert_query($data,$source);
- $this->query($sql);
- $data->success($this->get_new_id());
- }
- public function delete($data,$source){
- $sql=$this->delete_query($data,$source);
- $this->query($sql);
- $data->success();
- }
- public function update($data,$source){
- $sql=$this->update_query($data,$source);
- $this->query($sql);
- $data->success();
- }
- public function select($source){
- $select=$source->get_fieldset();
- if (!$select){
- $select=$this->config->db_names_list($this);
- $select = implode(",",$select);
- }
-
- $where=$this->build_where($source->get_filters(),$source->get_relation());
- $sort=$this->build_order($source->get_sort_by());
-
- return $this->query($this->select_query($select,$source->get_source(),$where,$sort,$source->get_start(),$source->get_count()));
- }
- public function queryOne($sql){
- $res = $this->query($sql);
- if ($res)
- return $this->get_next($res);
- return false;
- }
- public function get_size($source){
- $count = new DataRequestConfig($source);
-
- $count->set_fieldset("COUNT(*) as DHX_COUNT ");
- $count->set_sort(null);
- $count->set_limit(0,0);
-
- $res=$this->select($count);
- $data=$this->get_next($res);
- if (array_key_exists("DHX_COUNT",$data)) return $data["DHX_COUNT"];
- else return $data["dhx_count"]; //postgresql
- }
- public function get_variants($name,$source){
- $count = new DataRequestConfig($source);
- $count->set_fieldset("DISTINCT ".$this->escape_name($name)." as value");
- $sort = new SortInterface($source);
- $count->set_sort(null);
- for ($i = 0; $i < count($sort->rules); $i++) {
- if ($sort->rules[$i]['name'] == $name)
- $count->set_sort($sort->rules[$i]['name'], $sort->rules[$i]['direction']);
- }
- $count->set_limit(0,0);
- return $this->select($count);
- }
-
- public function sequence($sec){
- $this->sequence=$sec;
- }
-
-
- /*! create an sql string for filtering rules
-
- @param rules
- set of filtering rules
- @param relation
- name of relation id field
- @return
- sql string with filtering rules
- */
- protected function build_where($rules,$relation=false){
- $sql=array();
- for ($i=0; $i < sizeof($rules); $i++)
- if (is_string($rules[$i]))
- array_push($sql,"(".$rules[$i].")");
- else {
- $filtervalue = $rules[$i]["value"];
- $filteroperation = $rules[$i]["operation"];
- if ($filtervalue!=""){
- if (!$filteroperation)
- array_push($sql,$this->escape_name($rules[$i]["name"])." LIKE '%".$this->escape($filtervalue)."%'");
- else {
- if ($filteroperation != "IN")
- $filtervalue = "'".$this->escape($filtervalue)."'";
-
- array_push($sql,$this->escape_name($rules[$i]["name"])." ".$filteroperation." ".$filtervalue);
- }
- }
- }
-
- if ($relation !== false && $relation !== ""){
- $relsql = $this->escape_name($this->config->relation_id["db_name"])." = '".$this->escape($relation)."'";
- if ($relation == "0")
- $relsql = "( ".$relsql." OR ".$this->escape_name($this->config->relation_id["db_name"])." IS NULL )";
-
- array_push($sql,$relsql);
- }
- return implode(" AND ",$sql);
- }
- /*! convert sorting rules to sql string
-
- @param by
- set of sorting rules
- @return
- sql string for set of sorting rules
- */
- protected function build_order($by){
- if (!sizeof($by)) return "";
- $out = array();
- for ($i=0; $i < sizeof($by); $i++)
- if (is_string($by[$i]))
- $out[] = $by[$i];
- else if ($by[$i]["name"])
- $out[]=$this->escape_name($by[$i]["name"])." ".$by[$i]["direction"];
- return implode(",",$out);
- }
-
- /*! generates sql code for select operation
-
- @param select
- list of fields in select
- @param from
- table name
- @param where
- list of filtering rules
- @param sort
- list of sorting rules
- @param start
- start index of fetching
- @param count
- count of records to fetch
- @return
- sql string for select operation
- */
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
- if ($start || $count) $sql.=" LIMIT ".$start.",".$count;
- return $sql;
- }
- /*! generates update sql
-
- @param data
- DataAction object
- @param request
- DataRequestConfig object
- @return
- sql string, which updates record with provided data
- */
- protected function update_query($data,$request){
- $sql="UPDATE ".$request->get_source()." SET ";
- $temp=array();
- for ($i=0; $i < sizeof($this->config->text); $i++) {
- $step=$this->config->text[$i];
-
- if ($data->get_value($step["name"])===Null)
- $step_value ="Null";
- else
- $step_value = "'".$this->escape($data->get_value($step["name"]))."'";
- $temp[$i]= $this->escape_name($step["db_name"])."=". $step_value;
- }
- if ($relation = $this->config->relation_id["db_name"]){
- $temp[]= $this->escape_name($relation)."='".$this->escape($data->get_value($relation))."'";
- }
- $sql.=implode(",",$temp)." WHERE ".$this->escape_name($this->config->id["db_name"])."='".$this->escape($data->get_id())."'";
-
- //if we have limited set - set constraints
- $where=$this->build_where($request->get_filters());
- if ($where) $sql.=" AND (".$where.")";
-
- return $sql;
- }
-
- /*! generates delete sql
-
- @param data
- DataAction object
- @param request
- DataRequestConfig object
- @return
- sql string, which delete record
- */
- protected function delete_query($data,$request){
- $sql="DELETE FROM ".$request->get_source();
- $sql.=" WHERE ".$this->escape_name($this->config->id["db_name"])."='".$this->escape($data->get_id())."'";
-
- //if we have limited set - set constraints
- $where=$this->build_where($request->get_filters());
- if ($where) $sql.=" AND (".$where.")";
-
- return $sql;
- }
-
- /*! generates insert sql
-
- @param data
- DataAction object
- @param request
- DataRequestConfig object
- @return
- sql string, which inserts new record with provided data
- */
- protected function insert_query($data,$request){
- $temp_n=array();
- $temp_v=array();
- foreach($this->config->text as $k => $v){
- $temp_n[$k]=$this->escape_name($v["db_name"]);
- if ($data->get_value($v["name"])===Null)
- $temp_v[$k]="Null";
- else
- $temp_v[$k]="'".$this->escape($data->get_value($v["name"]))."'";
- }
- if ($relation = $this->config->relation_id["db_name"]){
- $temp_n[]=$this->escape_name($relation);
- $temp_v[]="'".$this->escape($data->get_value($relation))."'";
- }
- if ($this->sequence){
- $temp_n[]=$this->escape_name($this->config->id["db_name"]);
- $temp_v[]=$this->sequence;
- }
-
- $sql="INSERT INTO ".$request->get_source()."(".implode(",",$temp_n).") VALUES (".implode(",",$temp_v).")";
-
- return $sql;
- }
-
- /*! sets the transaction mode, used by dataprocessor
-
- @param mode
- mode name
- */
- public function set_transaction_mode($mode){
- if ($mode!="none" && $mode!="global" && $mode!="record")
- throw new Exception("Unknown transaction mode");
- $this->transaction=$mode;
- }
- /*! returns true if global transaction mode was specified
- @return
- true if global transaction mode was specified
- */
- public function is_global_transaction(){
- return $this->transaction == "global";
- }
- /*! returns true if record transaction mode was specified
- @return
- true if record transaction mode was specified
- */
- public function is_record_transaction(){
- return $this->transaction == "record";
- }
-
-
- public function begin_transaction(){
- $this->query("BEGIN");
- }
- public function commit_transaction(){
- $this->query("COMMIT");
- }
- public function rollback_transaction(){
- $this->query("ROLLBACK");
- }
-
- /*! exec sql string
-
- @param sql
- sql string
- @return
- sql result set
- */
- abstract public function query($sql);
- /*! returns next record from result set
-
- @param res
- sql result set
- @return
- hash of data
- */
- abstract public function get_next($res);
- /*! returns new id value, for newly inserted row
- @return
- new id value, for newly inserted row
- */
- abstract public function get_new_id();
- /*! escape data to prevent sql injections
- @param data
- unescaped data
- @return
- escaped data
- */
- abstract public function escape($data);
-
- /*! escape field name to prevent sql reserved words conflict
- @param data
- unescaped data
- @return
- escaped data
- */
- public function escape_name($data){
- return $data;
- }
-
- /*! get list of tables in the database
-
- @return
- array of table names
- */
- public function tables_list() {
- throw new Exception("Not implemented");
- }
-
- /*! returns list of fields for the table in question
-
- @param table
- name of table in question
- @return
- array of field names
- */
- public function fields_list($table) {
- throw new Exception("Not implemented");
- }
-
-}
-
-class ArrayDBDataWrapper extends DBDataWrapper{
- public function get_next($res){
- if ($res->index < sizeof($res->data))
- return $res->data[$res->index++];
- }
- public function select($sql){
- if ($this->config->relation_id["db_name"] == "") {
- if ($sql->get_relation() == "0" || $sql->get_relation() == "") {
- return new ArrayQueryWrapper($this->connection);
- } else {
- return new ArrayQueryWrapper(array());
- }
- }
-
- $relation_id = $this->config->relation_id["db_name"];
- $result = array();
-
- for ($i = 0; $i < count($this->connection); $i++) {
- $item = $this->connection[$i];
- if (!isset($item[$relation_id])) continue;
- if ($item[$relation_id] == $sql->get_relation())
- $result[] = $item;
-
- }
-
- return new ArrayQueryWrapper($result);
- }
- public function query($sql){
- throw new Exception("Not implemented");
- }
- public function escape($value){
- throw new Exception("Not implemented");
- }
- public function get_new_id(){
- throw new Exception("Not implemented");
- }
-}
-
-class ArrayQueryWrapper{
- public function __construct($data){
- $this->data = $data;
- $this->index = 0;
- }
-}
-/*! Implementation of DataWrapper for MySQL
-**/
-class MySQLDBDataWrapper extends DBDataWrapper{
- protected $last_result;
- public function query($sql){
- LogMaster::log($sql);
- $res=mysql_query($sql,$this->connection);
- if ($res===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
- $this->last_result = $res;
- return $res;
- }
-
- public function get_next($res){
- if (!$res)
- $res = $this->last_result;
-
- return mysql_fetch_assoc($res);
- }
-
- public function get_new_id(){
- return mysql_insert_id($this->connection);
- }
-
- public function escape($data){
- return mysql_real_escape_string($data, $this->connection);
- }
-
- public function tables_list() {
- $result = mysql_query("SHOW TABLES");
- if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
-
- $tables = array();
- while ($table = mysql_fetch_array($result)) {
- $tables[] = $table[0];
- }
- return $tables;
- }
-
- public function fields_list($table) {
- $result = mysql_query("SHOW COLUMNS FROM `".$table."`");
- if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
-
- $fields = array();
- $id = "";
- while ($field = mysql_fetch_assoc($result)) {
- if ($field['Key'] == "PRI")
- $id = $field["Field"];
- else
- $fields[] = $field["Field"];
- }
- return array("fields" => $fields, "key" => $id );
- }
-
- /*! escape field name to prevent sql reserved words conflict
- @param data
- unescaped data
- @return
- escaped data
- */
- public function escape_name($data){
- if ((strpos($data,"`")!==false || is_int($data)) || (strpos($data,".")!==false))
- return $data;
- return '`'.$data.'`';
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_excel.php b/codebase/db_excel.php
deleted file mode 100644
index 6c0e347..0000000
--- a/codebase/db_excel.php
+++ /dev/null
@@ -1,190 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once('db_common.php');
-
-if (!defined('DHX_IGNORE_EMPTY_ROWS')) {
- define('DHX_IGNORE_EMPTY_ROWS', true);
-}
-
-class ExcelDBDataWrapper extends DBDataWrapper {
-
- public $emptyLimit = 10;
- public function excel_data($points){
- $path = $this->connection;
- $excel = PHPExcel_IOFactory::createReaderForFile($path);
- $excel = $excel->load($path);
- $result = array();
- $excelWS = $excel->getActiveSheet();
-
- for ($i=0; $i < sizeof($points); $i++) {
- $c = array();
- preg_match("/^([a-zA-Z]+)(\d+)/", $points[$i], $c);
- if (count($c) > 0) {
- $col = PHPExcel_Cell::columnIndexFromString($c[1]) - 1;
- $cell = $excelWS->getCellByColumnAndRow($col, (int)$c[2]);
- $result[] = $cell->getValue();
- }
- }
-
- return $result;
- }
- public function select($source) {
- $path = $this->connection;
- $excel = PHPExcel_IOFactory::createReaderForFile($path);
- $excel->setReadDataOnly(false);
- $excel = $excel->load($path);
- $excRes = new ExcelResult();
- $excelWS = $excel->getActiveSheet();
- $addFields = true;
-
- $coords = array();
- if ($source->get_source() == '*') {
- $coords['start_row'] = 0;
- $coords['end_row'] = false;
- } else {
- $c = array();
- preg_match("/^([a-zA-Z]+)(\d+)/", $source->get_source(), $c);
- if (count($c) > 0) {
- $coords['start_row'] = (int) $c[2];
- } else {
- $coords['start_row'] = 0;
- }
- $c = array();
- preg_match("/:(.+)(\d+)$/U", $source->get_source(), $c);
- if (count($c) > 0) {
- $coords['end_row'] = (int) $c[2];
- } else {
- $coords['end_row'] = false;
- }
- }
-
- $i = $coords['start_row'];
- $end = 0;
- while ((($coords['end_row'] == false)&&($end < $this->emptyLimit))||(($coords['end_row'] !== false)&&($i < $coords['end_row']))) {
- $r = Array();
- $emptyNum = 0;
- for ($j = 0; $j < count($this->config->text); $j++) {
- $col = PHPExcel_Cell::columnIndexFromString($this->config->text[$j]['name']) - 1;
- $cell = $excelWS->getCellByColumnAndRow($col, $i);
- if (PHPExcel_Shared_Date::isDateTime($cell)) {
- $r[PHPExcel_Cell::stringFromColumnIndex($col)] = PHPExcel_Shared_Date::ExcelToPHP($cell->getValue());
- } else if ($cell->getDataType() == 'f') {
- $r[PHPExcel_Cell::stringFromColumnIndex($col)] = $cell->getCalculatedValue();
- } else {
- $r[PHPExcel_Cell::stringFromColumnIndex($col)] = $cell->getValue();
- }
- if ($r[PHPExcel_Cell::stringFromColumnIndex($col)] == '') {
- $emptyNum++;
- }
- }
- if ($emptyNum < count($this->config->text)) {
- $r['id'] = $i;
- $excRes->addRecord($r);
- $end = 0;
- } else {
- if (DHX_IGNORE_EMPTY_ROWS == false) {
- $r['id'] = $i;
- $excRes->addRecord($r);
- }
- $end++;
- }
- $i++;
- }
- return $excRes;
- }
-
- public function query($sql) {
- }
-
- public function get_new_id() {
- }
-
- public function escape($data) {
- }
-
- public function get_next($res) {
- return $res->next();
- }
-
-}
-
-
-class ExcelResult {
- private $rows;
- private $currentRecord = 0;
-
-
- // add record to output list
- public function addRecord($file) {
- $this->rows[] = $file;
- }
-
-
- // return next record
- public function next() {
- if ($this->currentRecord < count($this->rows)) {
- $row = $this->rows[$this->currentRecord];
- $this->currentRecord++;
- return $row;
- } else {
- return false;
- }
- }
-
-
- // sorts records under $sort array
- public function sort($sort, $data) {
- if (count($this->files) == 0) {
- return $this;
- }
- // defines fields list if it's need
- for ($i = 0; $i < count($sort); $i++) {
- $fieldname = $sort[$i]['name'];
- if (!isset($this->files[0][$fieldname])) {
- if (isset($data[$fieldname])) {
- $fieldname = $data[$fieldname]['db_name'];
- $sort[$i]['name'] = $fieldname;
- } else {
- $fieldname = false;
- }
- }
- }
-
- // for every sorting field will sort
- for ($i = 0; $i < count($sort); $i++) {
- // if field, setted in sort parameter doesn't exist, continue
- if ($sort[$i]['name'] == false) {
- continue;
- }
- // sorting by current field
- $flag = true;
- while ($flag == true) {
- $flag = false;
- // checks if previous sorting fields are equal
- for ($j = 0; $j < count($this->files) - 1; $j++) {
- $equal = true;
- for ($k = 0; $k < $i; $k++) {
- if ($this->files[$j][$sort[$k]['name']] != $this->files[$j + 1][$sort[$k]['name']]) {
- $equal = false;
- }
- }
- // compares two records in list under current sorting field and sorting direction
- if (((($this->files[$j][$sort[$i]['name']] > $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'ASC'))||(($this->files[$j][$sort[$i]['name']] < $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'DESC')))&&($equal == true)) {
- $c = $this->files[$j];
- $this->files[$j] = $this->files[$j+1];
- $this->files[$j+1] = $c;
- $flag = true;
- }
- }
- }
- }
- return $this;
- }
-
-}
-
-
-?> \ No newline at end of file
diff --git a/codebase/db_filesystem.php b/codebase/db_filesystem.php
deleted file mode 100644
index b3d16d2..0000000
--- a/codebase/db_filesystem.php
+++ /dev/null
@@ -1,345 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once('db_common.php');
-require_once('tree_connector.php');
-
-/*
-Most execution time is a standart functions for workin with FileSystem: is_dir(), dir(), readdir(), stat()
-*/
-
-class FileSystemDBDataWrapper extends DBDataWrapper {
-
-
- // returns list of files and directories
- public function select($source) {
- $relation = $this->getFileName($source->get_relation());
- // for tree checks relation id and forms absolute path
- if ($relation == '0') {
- $relation = '';
- } else {
- $path = $source->get_source();
- }
- $path = $source->get_source();
- $path = $this->getFileName($path);
- $path = realpath($path);
- if ($path == false) {
- return new FileSystemResult();
- }
-
- if (strpos(realpath($path.'/'.$relation), $path) !== 0) {
- return new FileSystemResult();
- }
- // gets files and directories list
- $res = $this->getFilesList($path, $relation);
- // sorts list
- $res = $res->sort($source->get_sort_by(), $this->config->data);
- return $res;
- }
-
-
- // gets files and directory list
- private function getFilesList($path, $relation) {
- $fileSystemTypes = FileSystemTypes::getInstance();
- LogMaster::log("Query filesystem: ".$path);
- $dir = opendir($path.'/'.$relation);
- $result = new FileSystemResult();
- // forms fields list
- for ($i = 0; $i < count($this->config->data); $i++) {
- $fields[] = $this->config->data[$i]['db_name'];
- }
- // for every file and directory of folder
- while ($file = readdir($dir)) {
- // . and .. should not be in output list
- if (($file == '.')||($file == '..')) {
- continue;
- }
- $newFile = array();
- // parse file name as Array('name', 'ext', 'is_dir')
- $fileNameExt = $this->parseFileName($path.'/'.$relation, $file);
- // checks if file should be in output array
- if (!$fileSystemTypes->checkFile($file, $fileNameExt)) {
- continue;
- }
- // takes file stat if it's need
- if ((in_array('size', $fields))||(in_array('date', $fields))) {
- $fileInfo = stat($path.'/'.$file);
- }
-
- // for every field forms list of fields
- for ($i = 0; $i < count($fields); $i++) {
- $field = $fields[$i];
- switch ($field) {
- case 'filename':
- $newFile['filename'] = $file;
- break;
- case 'full_filename':
- $newFile['full_filename'] = $path."/".$file;
- break;
- case 'size':
- $newFile['size'] = $fileInfo['size'];
- break;
- case 'extention':
- $newFile['extention'] = $fileNameExt['ext'];
- break;
- case 'name':
- $newFile['name'] = $fileNameExt['name'];
- break;
- case 'date':
- $newFile['date'] = date("Y-m-d H:i:s", $fileInfo['ctime']);
- break;
- }
- $newFile['relation_id'] = $relation.'/'.$file;
- $newFile['safe_name'] = $this->setFileName($relation.'/'.$file);
- $newFile['is_folder'] = $fileNameExt['is_dir'];
- }
- // add file in output list
- $result->addFile($newFile);
- }
- return $result;
- }
-
-
- // replaces '.' and '_' in id
- private function setFileName($filename) {
- $filename = str_replace(".", "{-dot-}", $filename);
- $filename = str_replace("_", "{-nizh-}", $filename);
- return $filename;
- }
-
-
- // replaces '{-dot-}' and '{-nizh-}' in id
- private function getFileName($filename) {
- $filename = str_replace("{-dot-}", ".", $filename);
- $filename = str_replace("{-nizh-}", "_", $filename);
- return $filename;
- }
-
-
- // parses file name and checks if is directory
- private function parseFileName($path, $file) {
- $result = Array();
- if (is_dir($path.'/'.$file)) {
- $result['name'] = $file;
- $result['ext'] = 'dir';
- $result['is_dir'] = 1;
- } else {
- $pos = strrpos($file, '.');
- $result['name'] = substr($file, 0, $pos);
- $result['ext'] = substr($file, $pos + 1);
- $result['is_dir'] = 0;
- }
- return $result;
- }
-
- public function query($sql) {
- }
-
- public function get_new_id() {
- }
-
- public function escape($data) {
- }
-
- public function get_next($res) {
- return $res->next();
- }
-
-}
-
-
-class FileSystemResult {
- private $files;
- private $currentRecord = 0;
-
-
- // add record to output list
- public function addFile($file) {
- $this->files[] = $file;
- }
-
-
- // return next record
- public function next() {
- if ($this->currentRecord < count($this->files)) {
- $file = $this->files[$this->currentRecord];
- $this->currentRecord++;
- return $file;
- } else {
- return false;
- }
- }
-
-
- // sorts records under $sort array
- public function sort($sort, $data) {
- if (count($this->files) == 0) {
- return $this;
- }
- // defines fields list if it's need
- for ($i = 0; $i < count($sort); $i++) {
- $fieldname = $sort[$i]['name'];
- if (!isset($this->files[0][$fieldname])) {
- if (isset($data[$fieldname])) {
- $fieldname = $data[$fieldname]['db_name'];
- $sort[$i]['name'] = $fieldname;
- } else {
- $fieldname = false;
- }
- }
- }
-
- // for every sorting field will sort
- for ($i = 0; $i < count($sort); $i++) {
- // if field, setted in sort parameter doesn't exist, continue
- if ($sort[$i]['name'] == false) {
- continue;
- }
- // sorting by current field
- $flag = true;
- while ($flag == true) {
- $flag = false;
- // checks if previous sorting fields are equal
- for ($j = 0; $j < count($this->files) - 1; $j++) {
- $equal = true;
- for ($k = 0; $k < $i; $k++) {
- if ($this->files[$j][$sort[$k]['name']] != $this->files[$j + 1][$sort[$k]['name']]) {
- $equal = false;
- }
- }
- // compares two records in list under current sorting field and sorting direction
- if (((($this->files[$j][$sort[$i]['name']] > $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'ASC'))||(($this->files[$j][$sort[$i]['name']] < $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'DESC')))&&($equal == true)) {
- $c = $this->files[$j];
- $this->files[$j] = $this->files[$j+1];
- $this->files[$j+1] = $c;
- $flag = true;
- }
- }
- }
- }
- return $this;
- }
-
-}
-
-
-// singleton class for setting file types filter
-class FileSystemTypes {
-
- static private $instance = NULL;
- private $extentions = Array();
- private $extentions_not = Array();
- private $all = true;
- private $patterns = Array();
- // predefined types
- private $types = Array(
- 'image' => Array('jpg', 'jpeg', 'gif', 'png', 'tiff', 'bmp', 'psd', 'dir'),
- 'document' => Array('txt', 'doc', 'docx', 'xls', 'xlsx', 'rtf', 'dir'),
- 'web' => Array('php', 'html', 'htm', 'js', 'css', 'dir'),
- 'audio' => Array('mp3', 'wav', 'ogg', 'dir'),
- 'video' => Array('avi', 'mpg', 'mpeg', 'mp4', 'dir'),
- 'only_dir' => Array('dir')
- );
-
-
- static function getInstance() {
- if (self::$instance == NULL) {
- self::$instance = new FileSystemTypes();
- }
- return self::$instance;
- }
-
- // sets array of extentions
- public function setExtentions($ext) {
- $this->all = false;
- $this->extentions = $ext;
- }
-
- // adds one extention in array
- public function addExtention($ext) {
- $this->all = false;
- $this->extentions[] = $ext;
- }
-
-
- // adds one extention which will not ouputed in array
- public function addExtentionNot($ext) {
- $this->extentions_not[] = $ext;
- }
-
-
- // returns array of extentions
- public function getExtentions() {
- return $this->extentions;
- }
-
- // adds regexp pattern
- public function addPattern($pattern) {
- $this->all = false;
- $this->patterns[] = $pattern;
- }
-
- // clear extentions array
- public function clearExtentions() {
- $this->all = true;
- $this->extentions = Array();
- }
-
- // clear regexp patterns array
- public function clearPatterns() {
- $this->all = true;
- $this->patterns = Array();
- }
-
- // clear all filters
- public function clearAll() {
- $this->clearExtentions();
- $this->clearPatterns();
- }
-
- // sets predefined type
- public function setType($type, $clear = false) {
- $this->all = false;
- if ($type == 'all') {
- $this->all = true;
- return true;
- }
- if (isset($this->types[$type])) {
- if ($clear) {
- $this->clearExtentions();
- }
- for ($i = 0; $i < count($this->types[$type]); $i++) {
- $this->extentions[] = $this->types[$type][$i];
- }
- return true;
- } else {
- return false;
- }
- }
-
-
- // check file under setted filter
- public function checkFile($filename, $fileNameExt) {
- if (in_array($fileNameExt['ext'], $this->extentions_not)) {
- return false;
- }
- if ($this->all) {
- return true;
- }
-
- if ((count($this->extentions) > 0)&&(!in_array($fileNameExt['ext'], $this->extentions))) {
- return false;
- }
-
- for ($i = 0; $i < count($this->patterns); $i++) {
- if (!preg_match($this->patterns[$i], $filename)) {
- return false;
- }
- }
- return true;
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/db_mssql.php b/codebase/db_mssql.php
deleted file mode 100644
index 0acab93..0000000
--- a/codebase/db_mssql.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! MSSQL implementation of DataWrapper
-**/
-class MsSQLDBDataWrapper extends DBDataWrapper{
- private $last_id=""; //!< ID of previously inserted record
- private $insert_operation=false; //!< flag of insert operation
- private $start_from=false; //!< index of start position
-
- public function query($sql){
- LogMaster::log($sql);
- $res = mssql_query($sql,$this->connection);
- if ($this->insert_operation){
- $last = mssql_fetch_assoc($res);
- $this->last_id = $last["dhx_id"];
- mssql_free_result($res);
- }
- if ($this->start_from)
- mssql_data_seek($res,$this->start_from);
- return $res;
- }
-
- public function get_next($res){
- return mssql_fetch_assoc($res);
- }
-
- public function get_new_id(){
- /*
- MSSQL doesn't support identity or auto-increment fields
- Insert SQL returns new ID value, which stored in last_id field
- */
- return $this->last_id;
- }
-
- protected function insert_query($data,$request){
- $sql = parent::insert_query($data,$request);
- $this->insert_operation=true;
- return $sql.";SELECT @@IDENTITY AS dhx_id";
- }
-
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT " ;
- if ($count)
- $sql.=" TOP ".($count+$start);
- $sql.=" ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
- if ($start && $count)
- $this->start_from=$start;
- else
- $this->start_from=false;
- return $sql;
- }
-
- public function escape($data){
- /*
- there is no special escaping method for mssql - use common logic
- */
- return str_replace("'","''",$data);
- }
-
- public function begin_transaction(){
- $this->query("BEGIN TRAN");
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_mysqli.php b/codebase/db_mysqli.php
deleted file mode 100644
index 6740a3b..0000000
--- a/codebase/db_mysqli.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-
-class MySQLiDBDataWrapper extends MySQLDBDataWrapper{
-
- public function query($sql){
- LogMaster::log($sql);
- $res = $this->connection->query($sql);
- if ($res===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
- return $res;
- }
-
- public function get_next($res){
- return $res->fetch_assoc();
- }
-
- public function get_new_id(){
- return $this->connection->insert_id;
- }
-
- public function escape($data){
- return $this->connection->real_escape_string($data);
- }
-
- public function tables_list() {
- $result = $this->connection->query("SHOW TABLES");
- if ($result===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
-
- $tables = array();
- while ($table = $result->fetch_array()) {
- $tables[] = $table[0];
- }
- return $tables;
- }
-
- public function fields_list($table) {
- $result = $this->connection->query("SHOW COLUMNS FROM `".$table."`");
- if ($result===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
- $fields = array();
- while ($field = $result->fetch_array()) {
- if ($field['Key'] == "PRI") {
- $fields[$field[0]] = 1;
- } else {
- $fields[$field[0]] = 0;
- }
- }
- return $fields;
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/db_oracle.php b/codebase/db_oracle.php
deleted file mode 100644
index 703d3a4..0000000
--- a/codebase/db_oracle.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! Implementation of DataWrapper for Oracle
-**/
-class OracleDBDataWrapper extends DBDataWrapper{
- private $last_id=""; //id of previously inserted record
- private $insert_operation=false; //flag of insert operation
-
- public function query($sql){
- LogMaster::log($sql);
- $stm = oci_parse($this->connection,$sql);
- if ($stm===false) throw new Exception("Oracle - sql parsing failed\n".oci_error($this->connection));
-
- $out = array(0=>null);
- if($this->insert_operation){
- oci_bind_by_name($stm,":outID",$out[0],999);
- $this->insert_operation=false;
- }
-
-
- $mode = ($this->is_record_transaction() || $this->is_global_transaction())?OCI_DEFAULT:OCI_COMMIT_ON_SUCCESS;
- $res = @oci_execute($stm,$mode);
- if ($res===false) throw new Exception(oci_error($this->connection));
-
- $this->last_id=$out[0];
-
- return $stm;
- }
-
- public function get_next($res){
- $data = oci_fetch_assoc($res);
- if ($data){
- foreach ($data as $k => $v)
- $data[strtolower($k)] = $v;
- }
- return $data;
- }
-
- public function get_new_id(){
- /*
- Oracle doesn't support identity or auto-increment fields
- Insert SQL returns new ID value, which stored in last_id field
- */
- return $this->last_id;
- }
-
- protected function insert_query($data,$request){
- $sql = parent::insert_query($data,$request);
- $this->insert_operation=true;
- return $sql." returning ".$this->config->id["db_name"]." into :outID";
- }
-
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
- if ($start || $count)
- $sql="SELECT * FROM ( select /*+ FIRST_ROWS(".$count.")*/dhx_table.*, ROWNUM rnum FROM (".$sql.") dhx_table where ROWNUM <= ".($count+$start)." ) where rnum >".$start;
- return $sql;
- }
-
- public function escape($data){
- /*
- as far as I can see the only way to escape data is by using oci_bind_by_name
- while it is neat solution in common case, it conflicts with existing SQL building logic
- fallback to simple escaping
- */
- return str_replace("'","''",$data);
- }
-
- public function begin_transaction(){
- //auto-start of transaction
- }
- public function commit_transaction(){
- oci_commit($this->connection);
- }
- public function rollback_transaction(){
- oci_rollback($this->connection);
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_phpcake.php b/codebase/db_phpcake.php
deleted file mode 100644
index 4df0289..0000000
--- a/codebase/db_phpcake.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-
-//DataProcessor::$action_param ="dhx_editor_status";
-
-/*! Implementation of DataWrapper for PDO
-
-if you plan to use it for Oracle - use Oracle connection type instead
-**/
-class PHPCakeDBDataWrapper extends ArrayDBDataWrapper{
- public function select($sql){
- $source = $sql->get_source();
- if (is_array($source)) //result of find
- $res = $source;
- else
- $res = $this->connection->find("all");
-
- $temp = array();
- if (sizeof($res)){
- $name = get_class($this->connection);
- for ($i=sizeof($res)-1; $i>=0; $i--)
- $temp[]=&$res[$i][$name];
- }
- return new ArrayQueryWrapper($temp);
- }
-
- protected function getErrorMessage(){
- $errors = $this->connection->invalidFields();
- $text = array();
- foreach ($errors as $key => $value){
- $text[] = $key." - ".$value[0];
- }
- return implode("\n", $text);
- }
-
- public function insert($data,$source){
- $name = get_class($this->connection);
- $save = array();
- $temp_data = $data->get_data();
- unset($temp_data[$this->config->id['db_name']]);
- unset($temp_data["!nativeeditor_status"]);
- $save[$name] = $temp_data;
-
- if ($this->connection->save($save)){
- $data->success($this->connection->getLastInsertID());
- } else {
- $data->set_response_attribute("details", $this->getErrorMessage());
- $data->invalid();
- }
- }
- public function delete($data,$source){
- $id = $data->get_id();
- $this->connection->delete($id);
- $data->success();
- }
- public function update($data,$source){
- $name = get_class($this->connection);
- $save = array();
- $save[$name] = &$data->get_data();
-
- if ($this->connection->save($save)){
- $data->success();
- } else {
- $data->set_response_attribute("details", $this->getErrorMessage());
- $data->invalid();
- }
- }
-
-
- public function escape($str){
- throw new Exception("Not implemented");
- }
- public function query($str){
- throw new Exception("Not implemented");
- }
- public function get_new_id(){
- throw new Exception("Not implemented");
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/db_phpci.php b/codebase/db_phpci.php
deleted file mode 100644
index 9d10d99..0000000
--- a/codebase/db_phpci.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-
-/*! Implementation of DataWrapper for PDO
-
-if you plan to use it for Oracle - use Oracle connection type instead
-**/
-class PHPCIDBDataWrapper extends DBDataWrapper{
- private $last_result;//!< store result or last operation
-
- public function query($sql){
- LogMaster::log($sql);
-
- $res=$this->connection->query($sql);
- if ($res===false) {
- throw new Exception("CI - sql execution failed");
- }
-
- if (is_object($res))
- return new PHPCIResultSet($res);
- return new ArrayQueryWrapper(array());
- }
-
- public function get_next($res){
- $data = $res->next();
- return $data;
- }
-
- public function get_new_id(){
- return $this->connection->insert_id();
- }
-
- public function escape($str){
- return $this->connection->escape_str($str);
- }
-
- public function escape_name($data){
- return $this->connection->protect_identifiers($data);
- }
-}
-
-class PHPCIResultSet{
- private $res;
- private $start;
- private $count;
-
- public function __construct($res){
- $this->res = $res;
- $this->start = $res->current_row;
- $this->count = $res->num_rows;
- }
- public function next(){
- if ($this->start != $this->count){
- return $this->res->row($this->start++,'array');
- } else {
- $this->res->free_result();
- return null;
- }
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_postgre.php b/codebase/db_postgre.php
deleted file mode 100644
index a7d1598..0000000
--- a/codebase/db_postgre.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! Implementation of DataWrapper for PostgreSQL
-**/
-class PostgreDBDataWrapper extends DBDataWrapper{
- public function query($sql){
- LogMaster::log($sql);
-
- $res=pg_query($this->connection,$sql);
- if ($res===false) throw new Exception("Postgre - sql execution failed\n".pg_last_error($this->connection));
-
- return $res;
- }
-
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
- if ($start || $count)
- $sql.=" OFFSET ".$start." LIMIT ".$count;
- return $sql;
- }
-
- public function get_next($res){
- return pg_fetch_assoc($res);
- }
-
- public function get_new_id(){
- $res = pg_query( $this->connection, "SELECT LASTVAL() AS seq");
- $data = pg_fetch_assoc($res);
- pg_free_result($res);
- return $data['seq'];
- }
-
- public function escape($data){
- //need to use oci_bind_by_name
- return pg_escape_string($this->connection,$data);
- }
-
- public function tables_list() {
- $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
- $res = pg_query($this->connection, $sql);
- $tables = array();
- while ($table = pg_fetch_assoc($res)) {
- $tables[] = $table['table_name'];
- }
- return $tables;
- }
-
- public function fields_list($table) {
- $sql = "SELECT * FROM information_schema.constraint_column_usage";
- $result = pg_query($this->connection, $sql);
- $field = pg_fetch_assoc($result);
- $id = $field['column_name'];
-
- $sql = "SELECT * FROM information_schema.columns WHERE table_name ='".$table."';";
- $result = pg_query($this->connection, $sql);
- $fields = array();
- $id = "";
- while ($field = pg_fetch_assoc($result)) {
- $fields[] = $field["column_name"];
- }
- return array('fields' => $fields, 'key' => $id );
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_sasql.php b/codebase/db_sasql.php
deleted file mode 100644
index 025f5ef..0000000
--- a/codebase/db_sasql.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-require_once("db_common.php");
-/*! SaSQL implementation of DataWrapper
-**/
-class SaSQLDBDataWrapper extends DBDataWrapper{
- private $last_id=""; //!< ID of previously inserted record
-
- public function query($sql){
- LogMaster::log($sql);
- $res=sasql_query($this->connection, $sql);
- if ($res===false) throw new Exception("SaSQL operation failed\n".sasql_error($this->connection));
- $this->last_result = $res;
- return $res;
- }
-
- public function get_next($res){
- if (!$res)
- $res = $this->last_result;
-
- return sasql_fetch_assoc($res);
- }
-
- public function get_new_id(){
- return sasql_insert_id($this->connection);
- }
-
- protected function insert_query($data,$request){
- $sql = parent::insert_query($data,$request);
- $this->insert_operation=true;
- return $sql;
- }
-
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT " ;
- if ($count)
- $sql.=" TOP ".($count+$start);
- $sql.=" ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
- return $sql;
- }
-
- public function escape($data){
- return sasql_escape_string($this->connection, $data);
- }
-
- public function begin_transaction(){
- $this->query("BEGIN TRAN");
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_sqlite.php b/codebase/db_sqlite.php
deleted file mode 100644
index 04df7e5..0000000
--- a/codebase/db_sqlite.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! SQLite implementation of DataWrapper
-**/
-class SQLiteDBDataWrapper extends DBDataWrapper{
-
- public function query($sql){
- LogMaster::log($sql);
-
- $res = sqlite_query($this->connection,$sql);
- if ($res === false)
- throw new Exception("SQLLite - sql execution failed\n".sqlite_error_string(sqlite_last_error($this->connection)));
-
- return $res;
- }
-
- public function get_next($res){
- $data = sqlite_fetch_array($res, SQLITE_ASSOC);
- return $data;
- }
-
- public function get_new_id(){
- return sqlite_last_insert_rowid($this->connection);
- }
-
- public function escape($data){
- return sqlite_escape_string($data);
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_sqlite3.php b/codebase/db_sqlite3.php
deleted file mode 100644
index 349490b..0000000
--- a/codebase/db_sqlite3.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! SQLite implementation of DataWrapper
-**/
-class SQLite3DBDataWrapper extends DBDataWrapper{
-
- public function query($sql){
- LogMaster::log($sql);
-
- $res = $this->connection->query($sql);
- if ($res === false)
- throw new Exception("SQLLite - sql execution failed\n".$this->connection->lastErrorMsg());
-
- return $res;
- }
-
- public function get_next($res){
- return $res->fetchArray();
- }
-
- public function get_new_id(){
- return $this->connection->lastInsertRowID();
- }
-
- public function escape($data){
- return $this->connection->escapeString($data);
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/db_sqlsrv.php b/codebase/db_sqlsrv.php
deleted file mode 100644
index 1b27020..0000000
--- a/codebase/db_sqlsrv.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-/*
-This software is allowed to use under GPL or you need to obtain Commercial or Enterise License
-to use it in non-GPL project. Please contact sales@dhtmlx.com for details
-*/
-?><?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("db_common.php");
-/*! MSSQL implementation of DataWrapper
-**/
-class SQLSrvDBDataWrapper extends DBDataWrapper{
- private $last_id=""; //!< ID of previously inserted record
- private $insert_operation=false; //!< flag of insert operation
- private $start_from=false; //!< index of start position
-
- public function query($sql){
- LogMaster::log($sql);
- if ($this->start_from)
- $res = sqlsrv_query($this->connection,$sql, array(), array("Scrollable" => SQLSRV_CURSOR_STATIC));
- else
- $res = sqlsrv_query($this->connection,$sql);
-
- if ($res === false){
- $errors = sqlsrv_errors();
- $message = Array();
- foreach($errors as $error)
- $message[]=$error["SQLSTATE"].$error["code"].$error["message"];
- throw new Exception("SQLSrv operation failed\n".implode("\n\n", $message));
- }
-
- if ($this->insert_operation){
- sqlsrv_next_result($res);
- $last = sqlsrv_fetch_array($res);
- $this->last_id = $last["dhx_id"];
- sqlsrv_free_stmt($res);
- }
- if ($this->start_from)
- $data = sqlsrv_fetch($res, SQLSRV_SCROLL_ABSOLUTE, $this->start_from-1);
- return $res;
- }
-
- public function get_next($res){
- $data = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC);
- if ($data)
- foreach ($data as $key => $value)
- if (is_a($value, "DateTime"))
- $data[$key] = $value->format("Y-m-d H:i");
- return $data;
- }
-
- public function get_new_id(){
- /*
- MSSQL doesn't support identity or auto-increment fields
- Insert SQL returns new ID value, which stored in last_id field
- */
- return $this->last_id;
- }
-
- protected function insert_query($data,$request){
- $sql = parent::insert_query($data,$request);
- $this->insert_operation=true;
- return $sql.";SELECT SCOPE_IDENTITY() as dhx_id";
- }
-
- protected function select_query($select,$from,$where,$sort,$start,$count){
- if (!$from)
- return $select;
-
- $sql="SELECT " ;
- if ($count)
- $sql.=" TOP ".($count+$start);
- $sql.=" ".$select." FROM ".$from;
- if ($where) $sql.=" WHERE ".$where;
- if ($sort) $sql.=" ORDER BY ".$sort;
- if ($start && $count)
- $this->start_from=$start;
- else
- $this->start_from=false;
- return $sql;
- }
-
- public function escape($data){
- /*
- there is no special escaping method for mssql - use common logic
- */
- return str_replace("'","''",$data);
- }
-
- public function begin_transaction(){
- sqlsrv_begin_transaction($this->connection);
- }
- public function commit_transaction(){
- sqlsrv_commit($this->connection);
- }
- public function rollback_transaction(){
- sqlsrv_rollback($this->connection);
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/filesystem_item.php b/codebase/filesystem_item.php
deleted file mode 100644
index 046ad98..0000000
--- a/codebase/filesystem_item.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-
-class FileTreeDataItem extends TreeDataItem {
-
- function has_kids(){
- if ($this->data['is_folder'] == '1') {
- return true;
- } else {
- return false;
- }
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/form_connector.php b/codebase/form_connector.php
deleted file mode 100644
index 5eeea38..0000000
--- a/codebase/form_connector.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-
-/*! DataItem class for dhxForm component
-**/
-class FormDataItem extends DataItem{
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
- $str="";
- for ($i = 0; $i < count($this->config->data); $i++) {
- $str .= "<".$this->config->data[$i]['name']."><![CDATA[".$this->data[$this->config->data[$i]['name']]."]]></".$this->config->data[$i]['name'].">";
- }
- return $str;
- }
-}
-
-
-/*! Connector class for dhtmlxForm
-**/
-class FormConnector extends Connector{
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="FormDataItem";
- if (!$data_type) $data_type="FormDataProcessor";
- parent::__construct($res,$type,$item_type,$data_type);
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- function parse_request(){
- parent::parse_request();
- if (isset($_GET["id"]))
- $this->request->set_filter($this->config->id["name"],$_GET["id"],"=");
- else if (!$_POST["ids"])
- throw new Exception("ID parameter is missed");
- }
-
-}
-
-/*! DataProcessor class for dhxForm component
-**/
-class FormDataProcessor extends DataProcessor{
-
-}
-?> \ No newline at end of file
diff --git a/codebase/gantt_connector.php b/codebase/gantt_connector.php
deleted file mode 100644
index 3577835..0000000
--- a/codebase/gantt_connector.php
+++ /dev/null
@@ -1,364 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-require_once("data_connector.php");
-
-/*! DataItem class for Gantt component
-**/
-class GanttDataItem extends DataItem{
-
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
-
- $str="<task id='".$this->get_id()."' >";
- $str.="<start_date><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]></start_date>";
- $str.="<".$this->config->text[1]["name"]."><![CDATA[".$this->data[$this->config->text[1]["name"]]."]]></".$this->config->text[1]["name"].">";
- $str.="<text><![CDATA[".$this->data[$this->config->text[2]["name"]]."]]></text>";
- for ($i=3; $i<sizeof($this->config->text); $i++){
- $extra = $this->config->text[$i]["name"];
- $str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
- }
- if ($this->userdata !== false)
- foreach ($this->userdata as $key => $value)
- $str.="<".$key."><![CDATA[".$value."]]></".$key.">";
-
- return $str."</task>";
- }
-}
-
-
-/*! Connector class for dhtmlxGantt
-**/
-class GanttConnector extends Connector{
-
- protected $extra_output="";//!< extra info which need to be sent to client side
- protected $options=array();//!< hash of OptionsConnector
- protected $links_mode = false;
-
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str="";
- foreach($options as $k => $v)
- $str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
- $options=$str;
- }
- $this->options[$name]=$options;
- }
-
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- * @param render_type
- name of class which will be used for rendering.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="GanttDataItem";
- if (!$data_type) $data_type="GanttDataProcessor";
- if (!$render_type) $render_type="RenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
-
- $this->event->attach("afterDelete", array($this, "delete_related_links"));
- $this->event->attach("afterOrder", array($this, "order_set_parent"));
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- function parse_request(){
- parent::parse_request();
-
- if (isset($_GET["gantt_mode"]) && $_GET["gantt_mode"] == "links")
- $this->links_mode = true;
-
- if (count($this->config->text)){
- if (isset($_GET["to"]))
- $this->request->set_filter($this->config->text[0]["name"],$_GET["to"],"<");
- if (isset($_GET["from"]))
- $this->request->set_filter($this->config->text[1]["name"],$_GET["from"],">");
- }
- }
-
- function order_set_parent($action){
- $value = $action->get_id();
- $parent = $action->get_value("parent");
-
- $table = $this->request->get_source();
- $id = $this->config->id["db_name"];
-
- $this->sql->query("UPDATE $table SET parent = $parent WHERE $id = $value");
- }
-
- function delete_related_links($action){
- if (isset($this->options["links"])){
- $links = $this->options["links"];
- $value = $this->sql->escape($action->get_new_id());
- $table = $links->get_request()->get_source();
-
- $this->sql->query("DELETE FROM $table WHERE source = '$value'");
- $this->sql->query("DELETE FROM $table WHERE target = '$value'");
- }
- }
-
- public function render_links($table,$id="",$fields=false,$extra=false,$relation_id=false) {
- $links = new GanttLinksConnector($this->get_connection(),$this->names["db_class"]);
- $links->render_table($table,$id,$fields,$extra);
- $this->set_options("links", $links);
- }
-}
-
-/*! DataProcessor class for Gantt component
-**/
-class GanttDataProcessor extends DataProcessor{
- function name_data($data){
- if ($data=="start_date")
- return $this->config->text[0]["name"];
- if ($data=="id")
- return $this->config->id["name"];
- if ($data=="duration" && $this->config->text[1]["name"] == "duration")
- return $this->config->text[1]["name"];
- if ($data=="end_date" && $this->config->text[1]["name"] == "end_date")
- return $this->config->text[1]["name"];
- if ($data=="text")
- return $this->config->text[2]["name"];
-
- return $data;
- }
-}
-
-
-class JSONGanttDataItem extends GanttDataItem{
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
-
- $obj = array();
- $obj['id'] = $this->get_id();
- $obj['start_date'] = $this->data[$this->config->text[0]["name"]];
- $obj[$this->config->text[1]["name"]] = $this->data[$this->config->text[1]["name"]];
- $obj['text'] = $this->data[$this->config->text[2]["name"]];
- for ($i=3; $i<sizeof($this->config->text); $i++){
- $extra = $this->config->text[$i]["name"];
- $obj[$extra]=$this->data[$extra];
- }
-
- if ($this->userdata !== false)
- foreach ($this->userdata as $key => $value)
- $obj[$key]=$value;
-
- return $obj;
- }
-}
-
-
-class JSONGanttConnector extends GanttConnector {
-
- protected $data_separator = ",";
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="JSONGanttDataItem";
- if (!$data_type) $data_type="GanttDataProcessor";
- if (!$render_type) $render_type="JSONRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- protected function xml_start() {
- return '{ "data":';
- }
-
- protected function xml_end() {
- $this->fill_collections();
- $end = (!empty($this->extra_output)) ? ', "collections": {'.$this->extra_output.'}' : '';
- foreach ($this->attributes as $k => $v)
- $end.=", \"".$k."\":\"".$v."\"";
- $end .= '}';
- return $end;
- }
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str=array();
- foreach($options as $k => $v)
- $str[]='{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
- $options=implode(",",$str);
- }
- $this->options[$name]=$options;
- }
-
-
- /*! generates xml description for options collections
-
- @param list
- comma separated list of column names, for which options need to be generated
- */
- protected function fill_collections($list=""){
- $options = array();
- foreach ($this->options as $k=>$v) {
- $name = $k;
- $option="\"{$name}\":[";
- if (!is_string($this->options[$name])){
- $data = json_encode($this->options[$name]->render());
- $option.=substr($data,1,-1);
- } else
- $option.=$this->options[$name];
- $option.="]";
- $options[] = $option;
- }
- $this->extra_output .= implode($this->data_separator, $options);
- }
-
-
- /*! output fetched data as XML
- @param res
- DB resultset
- */
- protected function output_as_xml($res){
- $result = $this->render_set($res);
- if ($this->simple) return $result;
-
- $data=$this->xml_start().json_encode($result).$this->xml_end();
-
- if ($this->as_string) return $data;
-
- $out = new OutputWriter($data, "");
- $out->set_type("json");
- $this->event->trigger("beforeOutput", $this, $out);
- $out->output("", true, $this->encoding);
- }
-
- public function render_links($table,$id="",$fields=false,$extra=false,$relation_id=false) {
- $links = new JSONGanttLinksConnector($this->get_connection(),$this->names["db_class"]);
- $links->render_table($table,$id,$fields,$extra);
- $this->set_options("links", $links);
- }
-
-
- /*! render self
- process commands, output requested data as XML
- */
- public function render(){
- $this->event->trigger("onInit", $this);
- EventMaster::trigger_static("connectorInit",$this);
-
- if (!$this->as_string)
- $this->parse_request();
- $this->set_relation();
-
- if ($this->live_update !== false && $this->updating!==false) {
- $this->live_update->get_updates();
- } else {
- if ($this->editing){
- if ($this->links_mode && isset($this->options["links"])) {
- $this->options["links"]->save();
- } else {
- $dp = new $this->names["data_class"]($this,$this->config,$this->request);
- $dp->process($this->config,$this->request);
- }
- } else {
- if (!$this->access->check("read")){
- LogMaster::log("Access control: read operation blocked");
- echo "Access denied";
- die();
- }
- $wrap = new SortInterface($this->request);
- $this->apply_sorts($wrap);
- $this->event->trigger("beforeSort",$wrap);
- $wrap->store();
-
- $wrap = new FilterInterface($this->request);
- $this->apply_filters($wrap);
- $this->event->trigger("beforeFilter",$wrap);
- $wrap->store();
-
- if ($this->model && method_exists($this->model, "get")){
- $this->sql = new ArrayDBDataWrapper();
- $result = new ArrayQueryWrapper(call_user_func(array($this->model, "get"), $this->request));
- $out = $this->output_as_xml($result);
- } else {
- $out = $this->output_as_xml($this->get_resource());
-
- if ($out !== null) return $out;
- }
-
- }
- }
- $this->end_run();
- }
-}
-
-
-class GanttLinksConnector extends OptionsConnector {
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
-
- $res = $this->sql->select($this->request);
- return $this->render_set($res);
- }
-
- public function save() {
- $dp = new $this->names["data_class"]($this,$this->config,$this->request);
- $dp->process($this->config,$this->request);
- }
-}
-
-
-class JSONGanttLinksConnector extends JSONOptionsConnector {
- public function render(){
- if (!$this->init_flag){
- $this->init_flag=true;
- return "";
- }
-
- $res = $this->sql->select($this->request);
- return $this->render_set($res);
- }
-
- public function save() {
- $dp = new $this->names["data_class"]($this,$this->config,$this->request);
- $dp->process($this->config,$this->request);
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/grid_config.php b/codebase/grid_config.php
deleted file mode 100644
index 24297b2..0000000
--- a/codebase/grid_config.php
+++ /dev/null
@@ -1,423 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-
-class GridConfiguration{
-
- /*! attaching header functionality
- */
- protected $headerDelimiter = ',';
- protected $headerNames = false;
- protected $headerAttaches = array();
- protected $footerAttaches = array();
- protected $headerWidthsUnits = 'px';
-
- protected $headerIds = false;
- protected $headerWidths = false;
- protected $headerTypes = false;
- protected $headerAlign = false;
- protected $headerVAlign = false;
- protected $headerSorts = false;
- protected $headerColors = false;
- protected $headerHidden = false;
- protected $headerFormat = false;
-
- protected $convert_mode = false;
-
- function __construct($headers = false){
- if ($headers === false || $headers === true )
- $this->headerNames = $headers;
- else
- $this->setHeader($headers);
- }
-
- /*! brief convert list of parameters to an array
- @param param
- list of values or array of values
- @return array of parameters
- */
- private function parse_param_array($param, $check=false, $default = ""){
- if (gettype($param) == 'string')
- $param = explode($this->headerDelimiter, $param);
-
- if ($check){
- for ($i=0; $i < sizeof($param); $i++) {
- if (!array_key_exists($param[$i],$check))
- $param[$i] = $default;
- }
- }
- return $param;
- }
-
- /*! sets delimiter for string arguments in attach header functions (default is ,)
- @param headerDelimiter
- string delimiter
- */
- public function setHeaderDelimiter($headerDelimiter) {
- $this->headerDelimiter = $headerDelimiter;
- }
-
- /*! sets header
- @param names
- array of names or string of names, delimited by headerDelimiter (default is ,)
- */
- public function setHeader($names) {
- if ($names instanceof DataConfig){
- $out = array();
- for ($i=0; $i < sizeof($names->text); $i++)
- $out[]=$names->text[$i]["name"];
- $names = $out;
- }
-
- $this->headerNames = $this->parse_param_array($names);
- }
-
- /*! sets init columns width in pixels
- @param wp
- array of widths or string of widths, delimited by headerDelimiter (default is ,)
- */
- public function setInitWidths($wp) {
- $this->headerWidths = $this->parse_param_array($wp);
- $this->headerWidthsUnits = 'px';
- }
-
- /*! sets init columns width in persents
- @param wp
- array of widths or string of widths, delimited by headerDelimiter (default is ,)
- */
- public function setInitWidthsP($wp) {
- $this->setInitWidths($wp);
- $this->headerWidthsUnits = '%';
- }
-
- /*! sets columns align
- @param alStr
- array of aligns or string of aligns, delimited by headerDelimiter (default is ,)
- */
- public function setColAlign($alStr) {
- $this->headerAlign = $this->parse_param_array($alStr,
- array("right"=>1, "left"=>1, "center"=>1, "justify"=>1),
- "left");
- }
-
- /*! sets columns vertical align
- @param alStr
- array of vertical aligns or string of vertical aligns, delimited by headerDelimiter (default is ,)
- */
- public function setColVAlign($alStr) {
- $this->headerVAlign = $this->parse_param_array($alStr,
- array("baseline"=>1, "sub"=>1, "super"=>1, "top"=>1, "text-top"=>1, "middle"=>1, "bottom"=>1, "text-bottom"=>1),
- "top");
- }
-
- /*! sets column types
- @param typeStr
- array of types or string of types, delimited by headerDelimiter (default is ,)
- */
- public function setColTypes($typeStr) {
- $this->headerTypes = $this->parse_param_array($typeStr);
- }
-
- /*! sets columns sorting
- @param sortStr
- array if sortings or string of sortings, delimited by headerDelimiter (default is ,)
- */
- public function setColSorting($sortStr) {
- $this->headerSorts = $this->parse_param_array($sortStr);
- }
-
- /*! sets columns colors
- @param colorStr
- array of colors or string of colors, delimited by headerDelimiter (default is ,)
- if (color should not be applied it's value should be null)
- */
- public function setColColor($colorStr) {
- $this->headerColors = $this->parse_param_array($colorStr);
- }
-
- /*! sets hidden columns
- @param hidStr
- array of bool values or string of bool values, delimited by headerDelimiter (default is ,)
- */
- public function setColHidden($hidStr) {
- $this->headerHidden = $this->parse_param_array($hidStr);
- }
-
- /*! sets columns id
- @param idsStr
- array of ids or string of ids, delimited by headerDelimiter (default is ,)
- */
- public function setColIds($idsStr) {
- $this->headerIds = $this->parse_param_array($idsStr);
- }
-
- /*! sets number/date format
- @param formatArr
- array of mask formats for number/dates , delimited by headerDelimiter (default is ,)
- */
- public function setColFormat($formatArr) {
- $this->headerFormat = $this->parse_param_array($formatArr);
- }
-
- /*! attaches header
- @param values
- array of header names or string of header names, delimited by headerDelimiter (default is ,)
- @param styles
- array of header styles or string of header styles, delimited by headerDelimiter (default is ,)
- */
- public function attachHeader($values, $styles = null, $footer = false) {
- $header = array();
- $header['values'] = $this->parse_param_array($values);
- if ($styles != null) {
- $header['styles'] = $this->parse_param_array($styles);
- } else {
- $header['styles'] = null;
- }
- if ($footer)
- $this->footerAttaches[] = $header;
- else
- $this->headerAttaches[] = $header;
- }
-
- /*! attaches footer
- @param values
- array of footer names or string of footer names, delimited by headerDelimiter (default is ,)
- @param styles
- array of footer styles or string of footer styles, delimited by headerDelimiter (default is ,)
- */
- public function attachFooter($values, $styles = null) {
- $this->attachHeader($values, $styles, true);
- }
-
- private function auto_fill($mode){
- $headerWidths = array();
- $headerTypes = array();
- $headerSorts = array();
- $headerAttaches = array();
-
- for ($i=0; $i < sizeof($this->headerNames); $i++) {
- $headerWidths[] = 100;
- $headerTypes[] = "ro";
- $headerSorts[] = "connector";
- $headerAttaches[] = "#connector_text_filter";
- }
- if ($this->headerWidths == false)
- $this->setInitWidths($headerWidths);
- if ($this->headerTypes == false)
- $this->setColTypes($headerTypes);
-
- if ($mode){
- if ($this->headerSorts == false)
- $this->setColSorting($headerSorts);
- $this->attachHeader($headerAttaches);
- }
- }
-
- public function defineOptions($conn){
- if (!$conn->is_first_call()) return; //render head only for first call
-
- $config = $conn->get_config();
- $full_header = ($this->headerNames === true);
-
- if (gettype($this->headerNames) == 'boolean') //auto-config
- $this->setHeader($config);
- $this->auto_fill($full_header);
-
- if (isset($_GET["dhx_colls"])) return;
-
- $fillList = array();
- for ($i = 0; $i < count($this->headerNames); $i++)
- if ($this->headerTypes[$i] == "co" || $this->headerTypes[$i] == "coro")
- $fillList[$i] = true;
-
- for ($i = 0; $i < count($this->headerAttaches); $i++) {
- for ($j = 0; $j < count($this->headerAttaches[$i]['values']); $j++) {
- if ($this->headerAttaches[$i]['values'][$j] == "#connector_select_filter"
- || $this->headerAttaches[$i]['values'][$j] == "#select_filter") {
- $fillList[$j] = true;;
- }
- }
- }
-
- $temp = array();
- foreach($fillList as $k => $v)
- $temp[] = $k;
- if (count($temp))
- $_GET["dhx_colls"] = implode(",",$temp);
- }
-
-
- /*! gets header as array
- */
- private function getHeaderArray() {
- $head = Array();
- $head[0] = $this->headerNames;
- $head = $this->getAttaches($head, $this->headerAttaches);
- return $head;
- }
-
-
- /*! get footer as array
- */
- private function getFooterArray() {
- $foot = Array();
- $foot = $this->getAttaches($foot, $this->footerAttaches);
- return $foot;
- }
-
-
- /*! gets array of data with attaches
- */
- private function getAttaches($to, $from) {
- for ($i = 0; $i < count($from); $i++) {
- $line = $from[$i]['values'];
- $to[] = $line;
- }
- return $to;
- }
-
-
- /*! calculates rowspan array according #cspan markers
- */
- private function processCspan($data) {
- $rspan = Array();
- for ($i = 0; $i < count($data); $i++) {
- $last = 0;
- $rspan[$i] = Array();
- for ($j = 0; $j < count($data[$i]); $j++) {
- $rspan[$i][$j] = 0;
- if ($data[$i][$j] === '#cspan') {
- $rspan[$i][$last]++;
- } else {
- $last = $j;
- }
- }
- }
- return $rspan;
- }
-
-
- /*! calculates colspan array according #rspan markers
- */
- private function processRspan($data) {
- $last = Array();
- $cspan = Array();
- for ($i = 0; $i < count($data); $i++) {
- $cspan[$i] = Array();
- for ($j = 0; $j < count($data[$i]); $j++) {
- $cspan[$i][$j] = 0;
- if (!isset($last[$j])) $last[$j] = 0;
- if ($data[$i][$j] === '#rspan') {
- $cspan[$last[$j]][$j]++;
- } else {
- $last[$j] = $i;
- }
- }
- }
- return $cspan;
- }
-
-
- /*! sets mode of output format: usual mode or convert mode.
- * @param mode
- * true - convert mode, false - otherwise
- */
- public function set_convert_mode($mode) {
- $this->convert_mode = $mode;
- }
-
-
- /*! adds header configuration in output XML
- */
- public function attachHeaderToXML($conn, $out) {
- if (!$conn->is_first_call()) return; //render head only for first call
-
- $head = $this->getHeaderArray();
- $foot = $this->getFooterArray();
- $rspan = $this->processRspan($head);
- $cspan = $this->processCspan($head);
-
- $str = '<head>';
-
- if ($this->convert_mode) $str .= "<columns>";
-
- for ($i = 0; $i < count($this->headerNames); $i++) {
- $str .= '<column';
- $str .= ' type="'. $this->headerTypes[$i].'"';
- $str .= ' width="'.$this->headerWidths[$i].'"';
- $str .= $this->headerIds ? ' id="'.$this->headerIds[$i].'"' : '';
- $str .= $this->headerAlign[$i] ? ' align="'.$this->headerAlign[$i].'"' : '';
- $str .= $this->headerVAlign[$i] ? ' valign="'.$this->headerVAlign[$i].'"' : '';
- $str .= $this->headerSorts[$i] ? ' sort="'.$this->headerSorts[$i].'"' : '';
- $str .= $this->headerColors[$i] ? ' color="'.$this->headerColors[$i].'"' : '';
- $str .= $this->headerHidden[$i] ? ' hidden="'.$this->headerHidden[$i].'"' : '';
- $str .= $this->headerFormat[$i] ? ' format="'.$this->headerFormat[$i].'"' : '';
- $str .= $cspan[0][$i] ? ' colspan="'.($cspan[0][$i] + 1).'"' : '';
- $str .= $rspan[0][$i] ? ' rowspan="'.($rspan[0][$i] + 1).'"' : '';
- $str .= '>'.$this->headerNames[$i].'</column>';
- }
-
- if (!$this->convert_mode) {
- $str .= '<settings><colwidth>'.$this->headerWidthsUnits.'</colwidth></settings>';
- if ((count($this->headerAttaches) > 0)||(count($this->footerAttaches) > 0)) {
- $str .= '<afterInit>';
- }
- for ($i = 0; $i < count($this->headerAttaches); $i++) {
- $str .= '<call command="attachHeader">';
- $str .= '<param>'.implode(",",$this->headerAttaches[$i]['values']).'</param>';
- if ($this->headerAttaches[$i]['styles'] != null) {
- $str .= '<param>'.implode(",",$this->headerAttaches[$i]['styles']).'</param>';
- }
- $str .= '</call>';
- }
- for ($i = 0; $i < count($this->footerAttaches); $i++) {
- $str .= '<call command="attachFooter">';
- $str .= '<param>'.implode(",",$this->footerAttaches[$i]['values']).'</param>';
- if ($this->footerAttaches[$i]['styles'] != null) {
- $str .= '<param>'.implode(",",$this->footerAttaches[$i]['styles']).'</param>';
- }
- $str .= '</call>';
- }
- if ((count($this->headerAttaches) > 0)||(count($this->footerAttaches) > 0)) {
- $str .= '</afterInit>';
- }
- } else {
- $str .= "</columns>";
- for ($i = 1; $i < count($head); $i++) {
- $str .= "<columns>";
- for ($j = 0; $j < count($head[$i]); $j++) {
- $str .= '<column';
- $str .= $cspan[$i][$j] ? ' colspan="'.($cspan[$i][$j] + 1).'"' : '';
- $str .= $rspan[$i][$j] ? ' rowspan="'.($rspan[$i][$j] + 1).'"' : '';
- $str .= '>'.$head[$i][$j].'</column>';
- }
- $str .= "</columns>\n";
- }
- }
- $str .= '</head>';
-
-
- if ($this->convert_mode && count($foot) > 0) {
- $rspan = $this->processRspan($foot);
- $cspan = $this->processCspan($foot);
- $str .= "<foot>";
- for ($i = 0; $i < count($foot); $i++) {
- $str .= "<columns>";
- for ($j = 0; $j < count($foot[$i]); $j++) {
- $str .= '<column';
- $str .= $cspan[$i][$j] ? ' colspan="'.($cspan[$i][$j] + 1).'"' : '';
- $str .= $rspan[$i][$j] ? ' rowspan="'.($rspan[$i][$j] + 1).'"' : '';
- $str .= '>'.$foot[$i][$j].'</column>';
- }
- $str .= "</columns>\n";
- }
- $str .= "</foot>";
- }
-
- $out->add($str);
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/grid_connector.php b/codebase/grid_connector.php
deleted file mode 100644
index d9be16a..0000000
--- a/codebase/grid_connector.php
+++ /dev/null
@@ -1,269 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-require_once("grid_config.php");
-
-//require_once("grid_dataprocessor.php");
-
-/*! DataItem class for Grid component
-**/
-
-class GridDataItem extends DataItem{
- protected $row_attrs;//!< hash of row attributes
- protected $cell_attrs;//!< hash of cell attributes
-
- function __construct($data,$name,$index=0){
- parent::__construct($data,$name,$index);
-
- $this->row_attrs=array();
- $this->cell_attrs=array();
- }
- /*! set color of row
-
- @param color
- color of row
- */
- function set_row_color($color){
- $this->row_attrs["bgColor"]=$color;
- }
- /*! set style of row
-
- @param color
- color of row
- */
- function set_row_style($color){
- $this->row_attrs["style"]=$color;
- }
- /*! assign custom style to the cell
-
- @param name
- name of column
- @param value
- css style string
- */
- function set_cell_style($name,$value){
- $this->set_cell_attribute($name,"style",$value);
- }
- /*! assign custom class to specific cell
-
- @param name
- name of column
- @param value
- css class name
- */
- function set_cell_class($name,$value){
- $this->set_cell_attribute($name,"class",$value);
- }
- /*! set custom cell attribute
-
- @param name
- name of column
- @param attr
- name of attribute
- @param value
- value of attribute
- */
- function set_cell_attribute($name,$attr,$value){
- if (!array_key_exists($name, $this->cell_attrs)) $this->cell_attrs[$name]=array();
- $this->cell_attrs[$name][$attr]=$value;
- }
-
- /*! set custom row attribute
-
- @param attr
- name of attribute
- @param value
- value of attribute
- */
- function set_row_attribute($attr,$value){
- $this->row_attrs[$attr]=$value;
- }
-
- /*! return self as XML string, starting part
- */
- public function to_xml_start(){
- if ($this->skip) return "";
-
- $str="<row id='".$this->xmlentities($this->get_id())."'";
- foreach ($this->row_attrs as $k=>$v)
- $str.=" ".$k."='".$v."'";
- $str.=">";
- for ($i=0; $i < sizeof($this->config->text); $i++){
- $str.="<cell";
- $name=$this->config->text[$i]["name"];
- $xmlcontent = false;
- if (isset($this->cell_attrs[$name])){
- $cattrs=$this->cell_attrs[$name];
- foreach ($cattrs as $k => $v){
- $str.=" ".$k."='".$this->xmlentities($v)."'";
- if ($k == "xmlcontent")
- $xmlcontent = true;
- }
- }
- $value = isset($this->data[$name]) ? $this->data[$name] : '';
- if (!$xmlcontent)
- $str.="><![CDATA[".$value."]]></cell>";
- else
- $str.=">".$value."</cell>";
- }
- if ($this->userdata !== false)
- foreach ($this->userdata as $key => $value)
- $str.="<userdata name='".$key."'><![CDATA[".$value."]]></userdata>";
-
- return $str;
- }
- /*! return self as XML string, ending part
- */
- public function to_xml_end(){
- if ($this->skip) return "";
-
- return "</row>";
- }
-}
-/*! Connector for the dhtmlxgrid
-**/
-class GridConnector extends Connector{
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="GridDataItem";
- if (!$data_type) $data_type="GridDataProcessor";
- if (!$render_type) $render_type="RenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
-
- protected function parse_request(){
- parent::parse_request();
-
- if (isset($_GET["dhx_colls"]))
- $this->fill_collections($_GET["dhx_colls"]);
- }
- protected function resolve_parameter($name){
- if (intval($name).""==$name)
- return $this->config->text[intval($name)]["db_name"];
- return $name;
- }
-
- /*! replace xml unsafe characters
-
- @param string
- string to be escaped
- @return
- escaped string
- */
- protected function xmlentities($string) {
- return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string);
- }
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str="";
- foreach($options as $k => $v)
- $str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
- $options=$str;
- }
- $this->options[$name]=$options;
- }
- /*! generates xml description for options collections
-
- @param list
- comma separated list of column names, for which options need to be generated
- */
- protected function fill_collections($list=""){
- $names=explode(",",$list);
- for ($i=0; $i < sizeof($names); $i++) {
- $name = $this->resolve_parameter($names[$i]);
- if (!array_key_exists($name,$this->options)){
- $this->options[$name] = new DistinctOptionsConnector($this->get_connection(),$this->names["db_class"]);
- $c = new DataConfig($this->config);
- $r = new DataRequestConfig($this->request);
- $c->minimize($name);
-
- $this->options[$name]->render_connector($c,$r);
- }
-
- $this->extra_output.="<coll_options for='{$names[$i]}'>";
- if (!is_string($this->options[$name]))
- $this->extra_output.=$this->options[$name]->render();
- else
- $this->extra_output.=$this->options[$name];
- $this->extra_output.="</coll_options>";
- }
- }
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- $attributes = "";
- foreach($this->attributes as $k=>$v)
- $attributes .= " ".$k."='".$v."'";
-
- if ($this->dload){
- if ($pos=$this->request->get_start())
- return "<rows pos='".$pos."'".$attributes.">";
- else
- return "<rows total_count='".$this->sql->get_size($this->request)."'".$attributes.">";
- }
- else
- return "<rows".$attributes.">";
- }
-
-
- /*! renders self as xml, ending part
- */
- protected function xml_end(){
- return $this->extra_output."</rows>";
- }
-
- public function set_config($config = false){
- if (gettype($config) == 'boolean')
- $config = new GridConfiguration($config);
-
- $this->event->attach("beforeOutput", Array($config, "attachHeaderToXML"));
- $this->event->attach("onInit", Array($config, "defineOptions"));
- }
-}
-
-/*! 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/keygrid_connector.php b/codebase/keygrid_connector.php
deleted file mode 100644
index 3942ac2..0000000
--- a/codebase/keygrid_connector.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("grid_connector.php");
-class KeyGridConnector extends GridConnector{
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="GridDataItem";
- if (!$data_type) $data_type="KeyGridDataProcessor";
- parent::__construct($res,$type,$item_type,$data_type);
-
- $this->event->attach("beforeProcessing",array($this,"before_check_key"));
- $this->event->attach("afterProcessing",array($this,"after_check_key"));
- }
-
- public function before_check_key($action){
- if ($action->get_value($this->config->id["name"])=="")
- $action->error();
- }
- public function after_check_key($action){
- if ($action->get_status()=="inserted" || $action->get_status()=="updated"){
- $action->success($action->get_value($this->config->id["name"]));
- $action->set_status("inserted");
- }
- }
-};
-
-class KeyGridDataProcessor 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 "__dummy__id__"; //ignore ID
- $parts=explode("c",$data);
- if ($parts[0]=="" && intval($parts[1])==$parts[1])
- return $this->config->text[intval($parts[1])]["name"];
- return $data;
- }
-}
-
-
-?> \ No newline at end of file
diff --git a/codebase/mixed_connector.php b/codebase/mixed_connector.php
deleted file mode 100644
index 461d6ec..0000000
--- a/codebase/mixed_connector.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-
-class MixedConnector extends Connector {
-
- protected $connectors = array();
-
- public function add($name, $conn) {
- $this->connectors[$name] = $conn;
- }
-
- public function render() {
- $result = "{";
- $parts = array();
- foreach($this->connectors as $name => $conn) {
- $conn->asString(true);
- $parts[] = "\"".$name."\":".($conn->render())."\n";
- }
- $result .= implode(",\n", $parts)."}";
- echo $result;
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/options_connector.php b/codebase/options_connector.php
deleted file mode 100644
index dc72eb2..0000000
--- a/codebase/options_connector.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-
-/*! DataItem class for dhxForm:options
-**/
-class OptionsDataItem extends DataItem{
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
- $str ="";
-
- $str .= "<item value=\"".$this->xmlentities($this->data[$this->config->data[0]['db_name']])."\" label=\"".$this->xmlentities($this->data[$this->config->data[1]['db_name']])."\" />";
- return $str;
- }
-}
-
-/*! Connector class for dhtmlxForm:options
-**/
-class SelectOptionsConnector extends Connector{
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false){
- if (!$item_type) $item_type="OptionsDataItem";
- parent::__construct($res,$type,$item_type,$data_type);
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/scheduler_connector.php b/codebase/scheduler_connector.php
deleted file mode 100644
index ee0cd20..0000000
--- a/codebase/scheduler_connector.php
+++ /dev/null
@@ -1,230 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-require_once("data_connector.php");
-
-/*! DataItem class for Scheduler component
-**/
-class SchedulerDataItem extends DataItem{
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
-
- $str="<event id='".$this->get_id()."' >";
- $str.="<start_date><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]></start_date>";
- $str.="<end_date><![CDATA[".$this->data[$this->config->text[1]["name"]]."]]></end_date>";
- $str.="<text><![CDATA[".$this->data[$this->config->text[2]["name"]]."]]></text>";
- for ($i=3; $i<sizeof($this->config->text); $i++){
- $extra = $this->config->text[$i]["name"];
- $str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
- }
- if ($this->userdata !== false)
- foreach ($this->userdata as $key => $value)
- $str.="<".$key."><![CDATA[".$value."]]></".$key.">";
-
- return $str."</event>";
- }
-}
-
-
-/*! Connector class for dhtmlxScheduler
-**/
-class SchedulerConnector extends Connector{
-
- protected $extra_output="";//!< extra info which need to be sent to client side
- protected $options=array();//!< hash of OptionsConnector
-
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str="";
- foreach($options as $k => $v)
- $str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
- $options=$str;
- }
- $this->options[$name]=$options;
- }
-
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- * @param render_type
- name of class which will be used for rendering.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="SchedulerDataItem";
- if (!$data_type) $data_type="SchedulerDataProcessor";
- if (!$render_type) $render_type="RenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- function parse_request(){
- parent::parse_request();
- if (count($this->config->text)){
- if (isset($_GET["to"]))
- $this->request->set_filter($this->config->text[0]["name"],$_GET["to"],"<");
- if (isset($_GET["from"]))
- $this->request->set_filter($this->config->text[1]["name"],$_GET["from"],">");
- }
- }
-}
-
-/*! DataProcessor class for Scheduler component
-**/
-class SchedulerDataProcessor extends DataProcessor{
- function name_data($data){
- if ($data=="start_date")
- return $this->config->text[0]["db_name"];
- if ($data=="id")
- return $this->config->id["db_name"];
- if ($data=="end_date")
- return $this->config->text[1]["db_name"];
- if ($data=="text")
- return $this->config->text[2]["db_name"];
-
- return $data;
- }
-}
-
-
-class JSONSchedulerDataItem extends SchedulerDataItem{
- /*! return self as XML string
- */
- function to_xml(){
- if ($this->skip) return "";
-
- $obj = array();
- $obj['id'] = $this->get_id();
- $obj['start_date'] = $this->data[$this->config->text[0]["name"]];
- $obj['end_date'] = $this->data[$this->config->text[1]["name"]];
- $obj['text'] = $this->data[$this->config->text[2]["name"]];
- for ($i=3; $i<sizeof($this->config->text); $i++){
- $extra = $this->config->text[$i]["name"];
- $obj[$extra]=$this->data[$extra];
- }
-
- if ($this->userdata !== false)
- foreach ($this->userdata as $key => $value)
- $obj[$key]=$value;
-
- return $obj;
- }
-}
-
-
-class JSONSchedulerConnector extends SchedulerConnector {
-
- protected $data_separator = ",";
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="JSONSchedulerDataItem";
- if (!$data_type) $data_type="SchedulerDataProcessor";
- if (!$render_type) $render_type="JSONRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- protected function xml_start() {
- return '{ "data":';
- }
-
- protected function xml_end() {
- $this->fill_collections();
- $end = (!empty($this->extra_output)) ? ', "collections": {'.$this->extra_output.'}' : '';
- foreach ($this->attributes as $k => $v)
- $end.=", \"".$k."\":\"".$v."\"";
- $end .= '}';
- return $end;
- }
-
- /*! assign options collection to the column
-
- @param name
- name of the column
- @param options
- array or connector object
- */
- public function set_options($name,$options){
- if (is_array($options)){
- $str=array();
- foreach($options as $k => $v)
- $str[]='{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
- $options=implode(",",$str);
- }
- $this->options[$name]=$options;
- }
-
-
- /*! generates xml description for options collections
-
- @param list
- comma separated list of column names, for which options need to be generated
- */
- protected function fill_collections($list=""){
- $options = array();
- foreach ($this->options as $k=>$v) {
- $name = $k;
- $option="\"{$name}\":[";
- if (!is_string($this->options[$name])){
- $data = json_encode($this->options[$name]->render());
- $option.=substr($data,1,-1);
- } else
- $option.=$this->options[$name];
- $option.="]";
- $options[] = $option;
- }
- $this->extra_output .= implode($this->data_separator, $options);
- }
-
-
- /*! output fetched data as XML
- @param res
- DB resultset
- */
- protected function output_as_xml($res){
- $result = $this->render_set($res);
- if ($this->simple) return $result;
-
- $data=$this->xml_start().json_encode($result).$this->xml_end();
-
- if ($this->as_string) return $data;
-
- $out = new OutputWriter($data, "");
- $out->set_type("json");
- $this->event->trigger("beforeOutput", $this, $out);
- $out->output("", true, $this->encoding);
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/strategy.php b/codebase/strategy.php
deleted file mode 100644
index 344dcf2..0000000
--- a/codebase/strategy.php
+++ /dev/null
@@ -1,508 +0,0 @@
-<?php
-
-class RenderStrategy {
-
- protected $conn = null;
-
- public function __construct($conn) {
- $this->conn = $conn;
- }
-
- /*! adds mix fields into DataConfig
- * @param config
- * DataConfig object
- * @param mix
- * mix structure
- */
- protected function mix($config, $mix) {
- for ($i = 0; $i < count($mix); $i++) {
- if ($config->is_field($mix[$i]['name'])===-1) {
- $config->add_field($mix[$i]['name']);
- }
- }
- }
-
- /*! remove mix fields from DataConfig
- * @param config
- * DataConfig object
- * @param mix
- * mix structure
- */
- protected function unmix($config, $mix) {
- for ($i = 0; $i < count($mix); $i++) {
- if ($config->is_field($mix[$i]['name'])!==-1) {
- $config->remove_field_full($mix[$i]['name']);
- }
- }
- }
-
- /*! adds mix fields in item
- * simple mix adds only strings specified by user
- * @param mix
- * mix structure
- * @param data
- * array of selected data
- */
- protected function simple_mix($mix, $data) {
- // get mix details
- for ($i = 0; $i < count($mix); $i++)
- $data[$mix[$i]["name"]] = is_object($mix[$i]["value"]) ? "" : $mix[$i]["value"];
- return $data;
- }
-
- /*! adds mix fields in item
- * complex mix adds strings specified by user and results of subrequests
- * @param mix
- * mix structure
- * @param data
- * array of selected data
- */
- protected function complex_mix($mix, $data) {
- // get mix details
- for ($i = 0; $i < count($mix); $i++) {
- $mixname = $mix[$i]["name"];
- if ($mix[$i]['filter'] !== false) {
- $subconn = $mix[$i]["value"];
- $filter = $mix[$i]["filter"];
-
- // setting relationships
- $subconn->clear_filter();
- foreach ($filter as $k => $v)
- if (isset($data[$v]))
- $subconn->filter($k, $data[$v], "=");
- else
- throw new Exception('There was no such data field registered as: '.$k);
-
- $subconn->asString(true);
- $data[$mixname]=$subconn->simple_render();
- if (is_array($data[$mixname]) && count($data[$mixname]) == 1)
- $data[$mixname] = $data[$mixname][0];
- } else {
- $data[$mixname] = $mix[$i]["value"];
- }
- }
- return $data;
- }
-
- /*! render from DB resultset
- @param res
- DB resultset
- process commands, output requested data as XML
- */
- public function render_set($res, $name, $dload, $sep, $config, $mix){
- $output="";
- $index=0;
- $conn = $this->conn;
- $this->mix($config, $mix);
- $conn->event->trigger("beforeRenderSet",$conn,$res,$config);
- while ($data=$conn->sql->get_next($res)){
- $data = $this->simple_mix($mix, $data);
-
- $data = new $name($data,$config,$index);
- if ($data->get_id()===false)
- $data->set_id($conn->uuid());
- $conn->event->trigger("beforeRender",$data);
- $output.=$data->to_xml().$sep;
- $index++;
- }
- $this->unmix($config, $mix);
- return $output;
- }
-
-}
-
-class JSONRenderStrategy extends RenderStrategy {
-
- /*! render from DB resultset
- @param res
- DB resultset
- process commands, output requested data as json
- */
- public function render_set($res, $name, $dload, $sep, $config, $mix){
- $output=array();
- $index=0;
- $conn = $this->conn;
- $this->mix($config, $mix);
- $conn->event->trigger("beforeRenderSet",$conn,$res,$config);
- while ($data=$conn->sql->get_next($res)){
- $data = $this->complex_mix($mix, $data);
- $data = new $name($data,$config,$index);
- if ($data->get_id()===false)
- $data->set_id($conn->uuid());
- $conn->event->trigger("beforeRender",$data);
- $item = $data->to_xml();
- if ($item !== false)
- $output[]=$item;
- $index++;
- }
- $this->unmix($config, $mix);
- return $output;
- }
-
-}
-
-class TreeRenderStrategy extends RenderStrategy {
-
- protected $id_swap = array();
-
- public function __construct($conn) {
- parent::__construct($conn);
- $conn->event->attach("afterInsert",array($this,"parent_id_correction_a"));
- $conn->event->attach("beforeProcessing",array($this,"parent_id_correction_b"));
- }
-
- public function render_set($res, $name, $dload, $sep, $config, $mix){
- $output="";
- $index=0;
- $conn = $this->conn;
- $config_copy = new DataConfig($config);
- $this->mix($config, $mix);
- while ($data=$conn->sql->get_next($res)){
- $data = $this->simple_mix($mix, $data);
- $data = new $name($data,$config,$index);
- $conn->event->trigger("beforeRender",$data);
- //there is no info about child elements,
- //if we are using dyn. loading - assume that it has,
- //in normal mode juse exec sub-render routine
- if ($data->has_kids()===-1 && $dload)
- $data->set_kids(true);
- $output.=$data->to_xml_start();
- if ($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload)){
- $sub_request = new DataRequestConfig($conn->get_request());
- //$sub_request->set_fieldset(implode(",",$config_copy->db_names_list($conn->sql)));
- $sub_request->set_relation($data->get_id());
- $output.=$this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config_copy, $mix);
- }
- $output.=$data->to_xml_end();
- $index++;
- }
- $this->unmix($config, $mix);
- return $output;
- }
-
- /*! store info about ID changes during insert operation
- @param dataAction
- data action object during insert operation
- */
- public function parent_id_correction_a($dataAction){
- $this->id_swap[$dataAction->get_id()]=$dataAction->get_new_id();
- }
-
- /*! update ID if it was affected by previous operation
- @param dataAction
- data action object, before any processing operation
- */
- public function parent_id_correction_b($dataAction){
- $relation = $this->conn->get_config()->relation_id["db_name"];
- $value = $dataAction->get_value($relation);
-
- if (array_key_exists($value,$this->id_swap))
- $dataAction->set_value($relation,$this->id_swap[$value]);
- }
-}
-
-
-
-class JSONTreeRenderStrategy extends TreeRenderStrategy {
-
- public function render_set($res, $name, $dload, $sep, $config,$mix){
- $output=array();
- $index=0;
- $conn = $this->conn;
- $config_copy = new DataConfig($config);
- $this->mix($config, $mix);
- while ($data=$conn->sql->get_next($res)){
- $data = $this->complex_mix($mix, $data);
- $data = new $name($data,$config,$index);
- $conn->event->trigger("beforeRender",$data);
- //there is no info about child elements,
- //if we are using dyn. loading - assume that it has,
- //in normal mode just exec sub-render routine
- if ($data->has_kids()===-1 && $dload)
- $data->set_kids(true);
- $record = $data->to_xml_start();
- if ($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload)){
- $sub_request = new DataRequestConfig($conn->get_request());
- //$sub_request->set_fieldset(implode(",",$config_copy->db_names_list($conn->sql)));
- $sub_request->set_relation($data->get_id());
- //$sub_request->set_filters(array());
- $temp = $this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config_copy, $mix);
- if (sizeof($temp))
- $record["data"] = $temp;
- }
- if ($record !== false)
- $output[] = $record;
- $index++;
- }
- $this->unmix($config, $mix);
- return $output;
- }
-
-}
-
-
-class MultitableTreeRenderStrategy extends TreeRenderStrategy {
-
- private $level = 0;
- private $max_level = null;
- protected $sep = "-@level@-";
-
- public function __construct($conn) {
- parent::__construct($conn);
- $conn->event->attach("beforeProcessing", Array($this, 'id_translate_before'));
- $conn->event->attach("afterProcessing", Array($this, 'id_translate_after'));
- }
-
- public function set_separator($sep) {
- $this->sep = $sep;
- }
-
- public function render_set($res, $name, $dload, $sep, $config, $mix){
- $output="";
- $index=0;
- $conn = $this->conn;
- $this->mix($config, $mix);
- while ($data=$conn->sql->get_next($res)){
- $data = $this->simple_mix($mix, $data);
- $data[$config->id['name']] = $this->level_id($data[$config->id['name']]);
- $data = new $name($data,$config,$index);
- $conn->event->trigger("beforeRender",$data);
- if (($this->max_level !== null)&&($conn->get_level() == $this->max_level)) {
- $data->set_kids(false);
- } else {
- if ($data->has_kids()===-1)
- $data->set_kids(true);
- }
- $output.=$data->to_xml_start();
- $output.=$data->to_xml_end();
- $index++;
- }
- $this->unmix($config, $mix);
- return $output;
- }
-
-
- public function level_id($id, $level = null) {
- return ($level === null ? $this->level : $level).$this->sep.$id;
- }
-
-
- /*! remove level prefix from id, parent id and set new id before processing
- @param action
- DataAction object
- */
- public function id_translate_before($action) {
- $id = $action->get_id();
- $id = $this->parse_id($id, false);
- $action->set_id($id);
- $action->set_value('tr_id', $id);
- $action->set_new_id($id);
- $pid = $action->get_value($this->conn->get_config()->relation_id['db_name']);
- $pid = $this->parse_id($pid, false);
- $action->set_value($this->conn->get_config()->relation_id['db_name'], $pid);
- }
-
-
- /*! add level prefix in id and new id after processing
- @param action
- DataAction object
- */
- public function id_translate_after($action) {
- $id = $action->get_id();
- $action->set_id($this->level_id($id));
- $id = $action->get_new_id();
- $action->success($this->level_id($id));
- }
-
-
- public function get_level($parent_name) {
- if ($this->level) return $this->level;
- if (!isset($_GET[$parent_name])) {
- if (isset($_POST['ids'])) {
- $ids = explode(",",$_POST["ids"]);
- $id = $this->parse_id($ids[0]);
- $this->level--;
- }
- $this->conn->get_request()->set_relation(false);
- } else {
- $id = $this->parse_id($_GET[$parent_name]);
- $_GET[$parent_name] = $id;
- }
- return $this->level;
- }
-
-
- public function is_max_level() {
- if (($this->max_level !== null) && ($this->level >= $this->max_level))
- return true;
- return false;
- }
- public function set_max_level($max_level) {
- $this->max_level = $max_level;
- }
- public function parse_id($id, $set_level = true) {
- $parts = explode($this->sep, $id, 2);
- if (count($parts) === 2) {
- $level = $parts[0] + 1;
- $id = $parts[1];
- } else {
- $level = 0;
- $id = '';
- }
- if ($set_level) $this->level = $level;
- return $id;
- }
-
-}
-
-
-class JSONMultitableTreeRenderStrategy extends MultitableTreeRenderStrategy {
-
- public function render_set($res, $name, $dload, $sep, $config, $mix){
- $output=array();
- $index=0;
- $conn = $this->conn;
- $this->mix($config, $mix);
- while ($data=$conn->sql->get_next($res)){
- $data = $this->complex_mix($mix, $data);
- $data[$config->id['name']] = $this->level_id($data[$config->id['name']]);
- $data = new $name($data,$config,$index);
- $conn->event->trigger("beforeRender",$data);
-
- if ($this->is_max_level()) {
- $data->set_kids(false);
- } else {
- if ($data->has_kids()===-1)
- $data->set_kids(true);
- }
- $record = $data->to_xml_start($output);
- $output[] = $record;
- $index++;
- }
- $this->unmix($config, $mix);
- return $output;
- }
-
-}
-
-
-class GroupRenderStrategy extends RenderStrategy {
-
- protected $id_postfix = '__{group_param}';
-
- public function __construct($conn) {
- parent::__construct($conn);
- $conn->event->attach("beforeProcessing", Array($this, 'check_id'));
- $conn->event->attach("onInit", Array($this, 'replace_postfix'));
- }
-
- public function render_set($res, $name, $dload, $sep, $config, $mix, $usemix = false){
- $output="";
- $index=0;
- $conn = $this->conn;
- if ($usemix) $this->mix($config, $mix);
- while ($data=$conn->sql->get_next($res)){
- if (isset($data[$config->id['name']])) {
- $this->simple_mix($mix, $data);
- $has_kids = false;
- } else {
- $data[$config->id['name']] = $data['value'].$this->id_postfix;
- $data[$config->text[0]['name']] = $data['value'];
- $has_kids = true;
- }
- $data = new $name($data,$config,$index);
- $conn->event->trigger("beforeRender",$data);
- if ($has_kids === false) {
- $data->set_kids(false);
- }
-
- if ($data->has_kids()===-1 && $dload)
- $data->set_kids(true);
- $output.=$data->to_xml_start();
- if (($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload))&&($has_kids == true)){
- $sub_request = new DataRequestConfig($conn->get_request());
- $sub_request->set_relation(str_replace($this->id_postfix, "", $data->get_id()));
- $output.=$this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config, $mix, true);
- }
- $output.=$data->to_xml_end();
- $index++;
- }
- if ($usemix) $this->unmix($config, $mix);
- return $output;
- }
-
- public function check_id($action) {
- if (isset($_GET['editing'])) {
- $config = $this->conn->get_config();
- $id = $action->get_id();
- $pid = $action->get_value($config->relation_id['name']);
- $pid = str_replace($this->id_postfix, "", $pid);
- $action->set_value($config->relation_id['name'], $pid);
- if (!empty($pid)) {
- return $action;
- } else {
- $action->error();
- $action->set_response_text("This record can't be updated!");
- return $action;
- }
- } else {
- return $action;
- }
- }
-
- public function replace_postfix() {
- if (isset($_GET['id'])) {
- $_GET['id'] = str_replace($this->id_postfix, "", $_GET['id']);
- }
- }
-
- public function get_postfix() {
- return $this->id_postfix;
- }
-
-}
-
-
-class JSONGroupRenderStrategy extends GroupRenderStrategy {
-
- public function render_set($res, $name, $dload, $sep, $config, $mix, $usemix = false){
- $output=array();
- $index=0;
- $conn = $this->conn;
- if ($usemix) $this->mix($config, $mix);
- while ($data=$conn->sql->get_next($res)){
- if (isset($data[$config->id['name']])) {
- $data = $this->complex_mix($mix, $data);
- $has_kids = false;
- } else {
- $data[$config->id['name']] = $data['value'].$this->id_postfix;
- $data[$config->text[0]['name']] = $data['value'];
- $has_kids = true;
- }
- $data = new $name($data,$config,$index);
- $conn->event->trigger("beforeRender",$data);
- if ($has_kids === false) {
- $data->set_kids(false);
- }
-
- if ($data->has_kids()===-1 && $dload)
- $data->set_kids(true);
- $record = $data->to_xml_start();
- if (($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload))&&($has_kids == true)){
- $sub_request = new DataRequestConfig($conn->get_request());
- $sub_request->set_relation(str_replace($this->id_postfix, "", $data->get_id()));
- $temp = $this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config, $mix, true);
- if (sizeof($temp))
- $record["data"] = $temp;
- }
- $output[] = $record;
- $index++;
- }
- if ($usemix) $this->unmix($config, $mix);
- return $output;
- }
-
-}
-
-
-?> \ No newline at end of file
diff --git a/codebase/tools.php b/codebase/tools.php
deleted file mode 100644
index 5017a72..0000000
--- a/codebase/tools.php
+++ /dev/null
@@ -1,267 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-
-/*! Class which allows to assign|fire events.
-*/
-class EventMaster{
- private $events;//!< hash of event handlers
- private $master;
- private static $eventsStatic=array();
-
- /*! constructor
- */
- function __construct(){
- $this->events=array();
- $this->master = false;
- }
- /*! Method check if event with such name already exists.
- @param name
- name of event, case non-sensitive
- @return
- true if event with such name registered, false otherwise
- */
- public function exist($name){
- $name=strtolower($name);
- return (isset($this->events[$name]) && sizeof($this->events[$name]));
- }
- /*! Attach custom code to event.
-
- Only on event handler can be attached in the same time. If new event handler attached - old will be detached.
-
- @param name
- name of event, case non-sensitive
- @param method
- function which will be attached. You can use array(class, method) if you want to attach the method of the class.
- */
- public function attach($name,$method=false){
- //use class for event handling
- if ($method === false){
- $this->master = $name;
- return;
- }
- //use separate functions
- $name=strtolower($name);
- if (!array_key_exists($name,$this->events))
- $this->events[$name]=array();
- $this->events[$name][]=$method;
- }
-
- public static function attach_static($name, $method){
- $name=strtolower($name);
- if (!array_key_exists($name,EventMaster::$eventsStatic))
- EventMaster::$eventsStatic[$name]=array();
- EventMaster::$eventsStatic[$name][]=$method;
- }
-
- public static function trigger_static($name, $method){
- $arg_list = func_get_args();
- $name=strtolower(array_shift($arg_list));
-
- if (isset(EventMaster::$eventsStatic[$name]))
- foreach(EventMaster::$eventsStatic[$name] as $method){
- if (is_array($method) && !method_exists($method[0],$method[1]))
- throw new Exception("Incorrect method assigned to event: ".$method[0].":".$method[1]);
- if (!is_array($method) && !function_exists($method))
- throw new Exception("Incorrect function assigned to event: ".$method);
- call_user_func_array($method, $arg_list);
- }
- return true;
- }
-
- /*! Detach code from event
- @param name
- name of event, case non-sensitive
- */
- public function detach($name){
- $name=strtolower($name);
- unset($this->events[$name]);
- }
- /*! Trigger event.
- @param name
- name of event, case non-sensitive
- @param data
- value which will be provided as argument for event function,
- you can provide multiple data arguments, method accepts variable number of parameters
- @return
- true if event handler was not assigned , result of event hangler otherwise
- */
- public function trigger($name,$data){
- $arg_list = func_get_args();
- $name=strtolower(array_shift($arg_list));
-
- if (isset($this->events[$name]))
- foreach($this->events[$name] as $method){
- if (is_array($method) && !method_exists($method[0],$method[1]))
- throw new Exception("Incorrect method assigned to event: ".$method[0].":".$method[1]);
- if (!is_array($method) && !function_exists($method))
- throw new Exception("Incorrect function assigned to event: ".$method);
- call_user_func_array($method, $arg_list);
- }
-
- if ($this->master !== false)
- if (method_exists($this->master, $name))
- call_user_func_array(array($this->master, $name), $arg_list);
-
- return true;
- }
-}
-
-/*! Class which handles access rules.
-**/
-class AccessMaster{
- private $rules,$local;
- /*! constructor
-
- Set next access right to "allowed" by default : read, insert, update, delete
- Basically - all common data operations allowed by default
- */
- function __construct(){
- $this->rules=array("read" => true, "insert" => true, "update" => true, "delete" => true);
- $this->local=true;
- }
- /*! change access rule to "allow"
- @param name
- name of access right
- */
- public function allow($name){
- $this->rules[$name]=true;
- }
- /*! change access rule to "deny"
-
- @param name
- name of access right
- */
- public function deny($name){
- $this->rules[$name]=false;
- }
-
- /*! change all access rules to "deny"
- */
- public function deny_all(){
- $this->rules=array();
- }
-
- /*! check access rule
-
- @param name
- name of access right
- @return
- true if access rule allowed, false otherwise
- */
- public function check($name){
- if ($this->local){
- /*!
- todo
- add referrer check, to prevent access from remote points
- */
- }
- if (!isset($this->rules[$name]) || !$this->rules[$name]){
- return false;
- }
- return true;
- }
-}
-
-/*! Controls error and debug logging.
- Class designed to be used as static object.
-**/
-class LogMaster{
- private static $_log=false;//!< logging mode flag
- private static $_output=false;//!< output error infor to client flag
- private static $session="";//!< all messages generated for current request
-
- /*! convert array to string representation ( it is a bit more readable than var_dump )
-
- @param data
- data object
- @param pref
- prefix string, used for formating, optional
- @return
- string with array description
- */
- private static function log_details($data,$pref=""){
- if (is_array($data)){
- $str=array("");
- foreach($data as $k=>$v)
- array_push($str,$pref.$k." => ".LogMaster::log_details($v,$pref."\t"));
- return implode("\n",$str);
- }
- return $data;
- }
- /*! put record in log
-
- @param str
- string with log info, optional
- @param data
- data object, which will be added to log, optional
- */
- public static function log($str="",$data=""){
- if (LogMaster::$_log){
- $message = $str.LogMaster::log_details($data)."\n\n";
- LogMaster::$session.=$message;
- error_log($message,3,LogMaster::$_log);
- }
- }
-
- /*! get logs for current request
- @return
- string, which contains all log messages generated for current request
- */
- public static function get_session_log(){
- return LogMaster::$session;
- }
-
- /*! error handler, put normal php errors in log file
-
- @param errn
- error number
- @param errstr
- error description
- @param file
- error file
- @param line
- error line
- @param context
- error cntext
- */
- public static function error_log($errn,$errstr,$file,$line,$context){
- LogMaster::log($errstr." at ".$file." line ".$line);
- }
-
- /*! exception handler, used as default reaction on any error - show execution log and stop processing
-
- @param exception
- instance of Exception
- */
- public static function exception_log($exception){
- LogMaster::log("!!!Uncaught Exception\nCode: " . $exception->getCode() . "\nMessage: " . $exception->getMessage());
- if (LogMaster::$_output){
- echo "<pre><xmp>\n";
- echo LogMaster::get_session_log();
- echo "\n</xmp></pre>";
- }
- die();
- }
-
- /*! enable logging
-
- @param name
- path to the log file, if boolean false provided as value - logging will be disabled
- @param output
- flag of client side output, if enabled - session log will be sent to client side in case of an error.
- */
- public static function enable_log($name,$output=false){
- LogMaster::$_log=$name;
- LogMaster::$_output=$output;
- if ($name){
- set_error_handler(array("LogMaster","error_log"),E_ALL);
- set_exception_handler(array("LogMaster","exception_log"));
- LogMaster::log("\n\n====================================\nLog started, ".date("d/m/Y h:i:s")."\n====================================");
- }
- }
-}
-
-?> \ No newline at end of file
diff --git a/codebase/tree_connector.php b/codebase/tree_connector.php
deleted file mode 100644
index 63d4442..0000000
--- a/codebase/tree_connector.php
+++ /dev/null
@@ -1,231 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("base_connector.php");
-
-/*! DataItem class for Tree component
-**/
-
-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->xmlentities($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>";
- }
-
-}
-
-require_once("filesystem_item.php");
-
-/*! Connector for the dhtmlxtree
-**/
-class TreeConnector extends Connector{
- protected $parent_name = 'id';
- public $rootId = "0";
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- * @param render_type
- * name of class which will provides data rendering
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false, $render_type=false){
- if (!$item_type) $item_type="TreeDataItem";
- if (!$data_type) $data_type="TreeDataProcessor";
- if (!$render_type) $render_type="TreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- //parse GET scoope, all operations with incoming request must be done here
- public function parse_request(){
- parent::parse_request();
-
- if (isset($_GET[$this->parent_name]))
- $this->request->set_relation($_GET[$this->parent_name]);
- else
- $this->request->set_relation($this->rootId);
-
- $this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
- }
-
- /*! renders self as xml, starting part
- */
- public function xml_start(){
- $attributes = "";
- foreach($this->attributes as $k=>$v)
- $attributes .= " ".$k."='".$v."'";
-
- return "<tree id='".$this->request->get_relation()."'".$attributes.">";
- }
-
- /*! renders self as xml, ending part
- */
- public function xml_end(){
- $this->fill_collections();
- return $this->extra_output."</tree>";
- }
-}
-
-
-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
diff --git a/codebase/treedatagroup_connector.php b/codebase/treedatagroup_connector.php
deleted file mode 100644
index 336915a..0000000
--- a/codebase/treedatagroup_connector.php
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("data_connector.php");
-
-class TreeDataGroupConnector extends TreeDataConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$render_type) $render_type="GroupRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- /*! if not isset $_GET[id] then it's top level
- */
- protected function set_relation() {
- if (!isset($_GET[$this->parent_name])) $this->request->set_relation(false);
- }
-
- /*! if it's first level then distinct level
- * else select by parent
- */
- protected function get_resource() {
- $resource = null;
- if (isset($_GET[$this->parent_name]))
- $resource = $this->sql->select($this->request);
- else
- $resource = $this->sql->get_variants($this->config->relation_id['name'], $this->request);
- return $resource;
- }
-
-
- /*! renders self as xml, starting part
- */
- public function xml_start(){
- if (isset($_GET[$this->parent_name])) {
- return "<data parent='".$_GET[$this->parent_name].$this->render->get_postfix()."'>";
- } else {
- return "<data parent='0'>";
- }
- }
-
-}
-
-
-
-
-class JSONTreeDataGroupConnector extends JSONTreeDataConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$render_type) $render_type="JSONGroupRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- /*! if not isset $_GET[id] then it's top level
- */
- protected function set_relation() {
- if (!isset($_GET[$this->parent_name])) $this->request->set_relation(false);
- }
-
- /*! if it's first level then distinct level
- * else select by parent
- */
- protected function get_resource() {
- $resource = null;
- if (isset($_GET[$this->parent_name]))
- $resource = $this->sql->select($this->request);
- else
- $resource = $this->sql->get_variants($this->config->relation_id['name'], $this->request);
- return $resource;
- }
-
-
- /*! renders self as xml, starting part
- */
- public function xml_start(){
- if (isset($_GET[$this->parent_name])) {
- return "<data parent='".$_GET[$this->parent_name].$this->render->get_postfix()."'>";
- } else {
- return "<data parent='0'>";
- }
- }
-
-}
-
-
-
-?> \ No newline at end of file
diff --git a/codebase/treedatamultitable_connector.php b/codebase/treedatamultitable_connector.php
deleted file mode 100644
index 104770e..0000000
--- a/codebase/treedatamultitable_connector.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("data_connector.php");
-
-class TreeDataMultitableConnector extends TreeDataConnector{
-
- protected $parent_name = 'parent';
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$data_type) $data_type="TreeDataProcessor";
- if (!$render_type) $render_type="MultitableTreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- public function render(){
- $this->dload = true;
- return parent::render();
- }
-
- /*! sets relation for rendering */
- protected function set_relation() {
- if (!isset($_GET[$this->parent_name]))
- $this->request->set_relation(false);
- }
-
- public function xml_start(){
- if (isset($_GET[$this->parent_name])) {
- return "<data parent='".$this->xmlentities($this->render->level_id($_GET[$this->parent_name], $this->render->get_level() - 1))."'>";
- } else {
- return "<data parent='0'>";
- }
- }
-
- /*! set maximum level of tree
- @param max_level
- maximum level
- */
- public function setMaxLevel($max_level) {
- $this->render->set_max_level($max_level);
- }
-
- public function get_level() {
- return $this->render->get_level($this->parent_name);
- }
-
-}
-
-
-
-
-
-
-class JSONTreeDataMultitableConnector extends TreeDataMultitableConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="JSONTreeCommonDataItem";
- if (!$data_type) $data_type="CommonDataProcessor";
- if (!$render_type) $render_type="JSONMultitableTreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- protected function output_as_xml($res){
- $result = $this->render_set($res);
- if ($this->simple) return $result;
-
- $data = array();
- if (isset($_GET['parent']))
- $data["parent"] = $this->render->level_id($_GET[$this->parent_name], $this->render->get_level() - 1);
- else
- $data["parent"] = "0";
- $data["data"] = $result;
-
- $result = json_encode($data);
- if ($this->as_string) return $result;
-
- $out = new OutputWriter($result, "");
- $out->set_type("json");
- $this->event->trigger("beforeOutput", $this, $out);
- $out->output("", true, $this->encoding);
- }
-
- public function xml_start(){
- return '';
- }
-}
-
-
-?> \ No newline at end of file
diff --git a/codebase/treegrid_connector.php b/codebase/treegrid_connector.php
deleted file mode 100644
index 1f89137..0000000
--- a/codebase/treegrid_connector.php
+++ /dev/null
@@ -1,121 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("grid_connector.php");
-
-/*! DataItem class for TreeGrid component
-**/
-class TreeGridDataItem extends GridDataItem{
- private $kids=-1;//!< checked state
-
- function __construct($data,$config,$index){
- parent::__construct($data,$config,$index);
- $this->im0=false;
- }
- /*! return id of parent record
-
- @return
- id of parent record
- */
- function get_parent_id(){
- return $this->data[$this->config->relation_id["name"]];
- }
- /*! assign image to treegrid's item
- longer description
- @param img
- relative path to the image
- */
- function set_image($img){
- $this->set_cell_attribute($this->config->text[0]["name"],"image",$img);
- }
-
- /*! 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;
- if ($value)
- $this->set_row_attribute("xmlkids",$value);
- }
-}
-/*! Connector for dhtmlxTreeGrid
-**/
-class TreeGridConnector extends GridConnector{
- protected $parent_name = 'id';
- protected $rootId = "0";
-
- /*! constructor
-
- Here initilization of all Masters occurs, execution timer initialized
- @param res
- db connection resource
- @param type
- string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
- @param item_type
- name of class, which will be used for item rendering, optional, DataItem will be used by default
- @param data_type
- name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
- * @param render_type
- * name of class which will provides data rendering
- */
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$item_type) $item_type="TreeGridDataItem";
- if (!$data_type) $data_type="TreeGridDataProcessor";
- if (!$render_type) $render_type="TreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- /*! process treegrid specific options in incoming request */
- public function parse_request(){
- parent::parse_request();
-
- if (isset($_GET[$this->parent_name]))
- $this->request->set_relation($_GET[$this->parent_name]);
- else
- $this->request->set_relation($this->rootId);
-
- $this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
- }
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- return "<rows parent='".$this->xmlentities( $this->request->get_relation() )."'>";
- }
-}
-
-/*! DataProcessor class for Grid component
-**/
-class TreeGridDataProcessor extends GridDataProcessor{
-
- 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=="gr_pid")
- return $this->config->relation_id["name"];
- else return parent::name_data($data);
- }
-}
-?> \ No newline at end of file
diff --git a/codebase/treegridgroup_connector.php b/codebase/treegridgroup_connector.php
deleted file mode 100644
index cd8fdf2..0000000
--- a/codebase/treegridgroup_connector.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("treegrid_connector.php");
-
-class TreeGridGroupConnector extends TreeGridConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$render_type) $render_type="GroupRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- /*! if not isset $_GET[id] then it's top level
- */
- protected function set_relation() {
- if (!isset($_GET[$this->parent_name])) $this->request->set_relation(false);
- }
-
- /*! if it's first level then distinct level
- * else select by parent
- */
- protected function get_resource() {
- $resource = null;
- if (isset($_GET[$this->parent_name]))
- $resource = $this->sql->select($this->request);
- else
- $resource = $this->sql->get_variants($this->config->relation_id['name'], $this->request);
- return $resource;
- }
-
-
- /*! renders self as xml, starting part
- */
- protected function xml_start(){
- if (isset($_GET[$this->parent_name])) {
- return "<rows parent='".$_GET[$this->parent_name].$this->render->get_postfix()."'>";
- } else {
- return "<rows parent='0'>";
- }
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/treegridmultitable_connector.php b/codebase/treegridmultitable_connector.php
deleted file mode 100644
index 31217f9..0000000
--- a/codebase/treegridmultitable_connector.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("treegrid_connector.php");
-
-class TreeGridMultitableConnector extends TreeGridConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- $data_type="TreeGridMultitableDataProcessor";
- if (!$render_type) $render_type="MultitableTreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- public function render(){
- $this->dload = true;
- return parent::render();
- }
-
- /*! sets relation for rendering */
- protected function set_relation() {
- if (!isset($_GET['id']))
- $this->request->set_relation(false);
- }
-
- public function xml_start(){
- if (isset($_GET['id'])) {
- return "<rows parent='".$this->xmlentities($this->render->level_id($_GET['id'], $this->get_level() - 1))."'>";
- } else {
- return "<rows parent='0'>";
- }
- }
-
- /*! set maximum level of tree
- @param max_level
- maximum level
- */
- public function setMaxLevel($max_level) {
- $this->render->set_max_level($max_level);
- }
-
- public function get_level() {
- return $this->render->get_level($this->parent_name);
- }
-
-
-}
-
-
-class TreeGridMultitableDataProcessor extends DataProcessor {
-
- function name_data($data){
- if ($data=="gr_pid")
- return $this->config->relation_id["name"];
- if ($data=="gr_id")
- return $this->config->id["name"];
- preg_match('/^c([%\d]+)$/', $data, $data_num);
- if (!isset($data_num[1])) return $data;
- $data_num = $data_num[1];
- if (isset($this->config->data[$data_num]["db_name"])) {
- return $this->config->data[$data_num]["db_name"];
- }
- return $data;
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/treegroup_connector.php b/codebase/treegroup_connector.php
deleted file mode 100644
index 5266d0b..0000000
--- a/codebase/treegroup_connector.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("tree_connector.php");
-
-class TreeGroupConnector extends TreeConnector{
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$render_type) $render_type="GroupRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- /*! if not isset $_GET[id] then it's top level
- */
- protected function set_relation() {
- if (!isset($_GET[$this->parent_name])) $this->request->set_relation(false);
- }
-
- /*! if it's first level then distinct level
- * else select by parent
- */
- protected function get_resource() {
- $resource = null;
- if (isset($_GET[$this->parent_name]))
- $resource = $this->sql->select($this->request);
- else
- $resource = $this->sql->get_variants($this->config->relation_id['name'], $this->request);
- return $resource;
- }
-
-
- /*! renders self as xml, starting part
- */
- public function xml_start(){
- if (isset($_GET[$this->parent_name])) {
- return "<tree id='".$_GET[$this->parent_name].$this->render->get_postfix()."'>";
- } else {
- return "<tree id='0'>";
- }
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/treemultitable_connector.php b/codebase/treemultitable_connector.php
deleted file mode 100644
index b06164c..0000000
--- a/codebase/treemultitable_connector.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-/*
- @author dhtmlx.com
- @license GPL, see license.txt
-*/
-require_once("tree_connector.php");
-
-class TreeMultitableConnector extends TreeConnector{
-
- protected $parent_name = 'id';
-
- public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
- if (!$data_type) $data_type="TreeDataProcessor";
- if (!$render_type) $render_type="MultitableTreeRenderStrategy";
- parent::__construct($res,$type,$item_type,$data_type,$render_type);
- }
-
- public function render(){
- $this->dload = true;
- return parent::render();
- }
-
- /*! sets relation for rendering */
- protected function set_relation() {
- if (!isset($_GET[$this->parent_name]))
- $this->request->set_relation(false);
- }
-
- public function xml_start(){
- if (isset($_GET[$this->parent_name])) {
- return "<tree id='".$this->xmlentities($this->render->level_id($_GET[$this->parent_name], $this->get_level() - 1))."'>";
- } else {
- return "<tree id='0'>";
- }
- }
-
- /*! set maximum level of tree
- @param max_level
- maximum level
- */
- public function setMaxLevel($max_level) {
- $this->render->set_max_level($max_level);
- }
-
- public function get_level() {
- return $this->render->get_level($this->parent_name);
- }
-
-}
-
-?> \ No newline at end of file
diff --git a/codebase/update.php b/codebase/update.php
deleted file mode 100644
index dacc211..0000000
--- a/codebase/update.php
+++ /dev/null
@@ -1,266 +0,0 @@
-<?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.
-*/
-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");
- }
- }
-}
-
-
-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/xss_filter.php b/codebase/xss_filter.php
deleted file mode 100644
index ed0a309..0000000
--- a/codebase/xss_filter.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-// +----------------------------------------------------------------------+
-// | Copyright (c) 2001-2008 Liip AG |
-// +----------------------------------------------------------------------+
-// | Licensed under the Apache License, Version 2.0 (the "License"); |
-// | you may not use this file except in compliance with the License. |
-// | You may obtain a copy of the License at |
-// | http://www.apache.org/licenses/LICENSE-2.0 |
-// | Unless required by applicable law or agreed to in writing, software |
-// | distributed under the License is distributed on an "AS IS" BASIS, |
-// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
-// | implied. See the License for the specific language governing |
-// | permissions and limitations under the License. |
-// +----------------------------------------------------------------------+
-// | Author: Christian Stocker <christian.stocker@liip.ch> |
-// +----------------------------------------------------------------------+
-
-
-//original name was lx_externalinput_clean
-//renamed to prevent possible conflicts
-class dhx_externalinput_clean {
- // this basic clean should clean html code from
- // lot of possible malicious code for Cross Site Scripting
- // use it whereever you get external input
-
- // you can also set $filterOut to some use html cleaning, but I don't know of any code, which could
- // exploit that. But if you want to be sure, set it to eg. array("Tidy","Dom");
- static function basic($string, $filterIn = array("Tidy","Dom","Striptags"), $filterOut = "none") {
- $string = self::tidyUp($string, $filterIn);
- $string = str_replace(array("&amp;", "&lt;", "&gt;"), array("&amp;amp;", "&amp;lt;", "&amp;gt;"), $string);
-
- // fix &entitiy\n;
- $string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u', "$1;", $string);
- $string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $string);
-
- $string = html_entity_decode($string, ENT_COMPAT, "UTF-8");
-
- // remove any attribute starting with "on" or xmlns
- $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])(on|xmlns)[^>]*>#iUu', "$1>", $string);
-
- // remove javascript: and vbscript: protocol
- $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2nojavascript...', $string);
- $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2novbscript...', $string);
- $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*-moz-binding[\x00-\x20]*:#Uu', '$1=$2nomozbinding...', $string);
- $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*data[\x00-\x20]*:#Uu', '$1=$2nodata...', $string);
-
- //remove any style attributes, IE allows too much stupid things in them, eg.
- //<span style="width: expression(alert('Ping!'));"></span>
- // and in general you really don't want style declarations in your UGC
-
- $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])style[^>]*>#iUu', "$1>", $string);
-
- //remove namespaced elements (we do not need them...)
- $string = preg_replace('#</*\w+:\w[^>]*>#i', "", $string);
-
- //remove really unwanted tags
- do {
- $oldstring = $string;
- $string = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $string);
- } while ($oldstring != $string);
-
- return self::tidyUp($string, $filterOut);
- }
-
- static function tidyUp($string, $filters) {
- if (is_array($filters)) {
- foreach ($filters as $filter) {
- $return = self::tidyUpWithFilter($string, $filter);
- if ($return !== false) {
- return $return;
- }
- }
- } else {
- $return = self::tidyUpWithFilter($string, $filters);
- }
- // if no filter matched, use the Striptags filter to be sure.
- if ($return === false) {
- return self::tidyUpModuleStriptags($string);
- } else {
- return $return;
- }
- }
-
- static private function tidyUpWithFilter($string, $filter) {
- if (is_callable(array("self", "tidyUpModule" . $filter))) {
- return call_user_func(array("self", "tidyUpModule" . $filter), $string);
- }
- return false;
- }
-
- static private function tidyUpModuleStriptags($string) {
-
- return strip_tags($string);
- }
-
- static private function tidyUpModuleNone($string) {
- return $string;
- }
-
- static private function tidyUpModuleDom($string) {
- $dom = new domdocument();
- @$dom->loadHTML("<html><body>" . $string . "</body></html>");
- $string = '';
- foreach ($dom->documentElement->firstChild->childNodes as $child) {
- $string .= $dom->saveXML($child);
- }
- return $string;
- }
-
- static private function tidyUpModuleTidy($string) {
- if (class_exists("tidy")) {
- $tidy = new tidy();
- $tidyOptions = array("output-xhtml" => true,
- "show-body-only" => true,
- "clean" => true,
- "wrap" => "350",
- "indent" => true,
- "indent-spaces" => 1,
- "ascii-chars" => false,
- "wrap-attributes" => false,
- "alt-text" => "",
- "doctype" => "loose",
- "numeric-entities" => true,
- "drop-proprietary-attributes" => true,
- "enclose-text" => false,
- "enclose-block-text" => false
-
- );
- $tidy->parseString($string, $tidyOptions, "utf8");
- $tidy->cleanRepair();
- return (string) $tidy;
- } else {
- return false;
- }
- }
-}
-
-define("DHX_SECURITY_SAFETEXT", 1);
-define("DHX_SECURITY_SAFEHTML", 2);
-define("DHX_SECURITY_TRUSTED", 3);
-
-class ConnectorSecurity{
- static public $xss = DHX_SECURITY_SAFETEXT;
- static public $security_key = false;
- static public $security_var = "dhx_security";
-
- static private $filterClass = null;
- static function filter($value, $mode = false){
- if ($mode === false)
- $mode = ConnectorSecurity::$xss;
-
- if ($mode == DHX_SECURITY_TRUSTED)
- return $value;
- if ($mode == DHX_SECURITY_SAFETEXT)
- return filter_var($value, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
- if ($mode == DHX_SECURITY_SAFEHTML){
- if (ConnectorSecurity::$filterClass == null)
- ConnectorSecurity::$filterClass = new dhx_externalinput_clean();
- return ConnectorSecurity::$filterClass->basic($value);
- }
- throw new Error("Invalid security mode:"+$mode);
- }
-
- static function CSRF_detected(){
- LogMaster::log("[SECURITY] Possible CSRF attack detected", array(
- "referer" => $_SERVER["HTTP_REFERER"],
- "remote" => $_SERVER["REMOTE_ADDR"]
- ));
- LogMaster::log("Request data", $_POST);
- die();
- }
- static function checkCSRF($edit){
- if (ConnectorSecurity::$security_key){
- if (!isset($_SESSION))
- @session_start();
-
- if ($edit=== true){
- if (!isset($_POST[ConnectorSecurity::$security_var]))
- return ConnectorSecurity::CSRF_detected();
- $master_key = $_SESSION[ConnectorSecurity::$security_var];
- $update_key = $_POST[ConnectorSecurity::$security_var];
- if ($master_key != $update_key)
- return ConnectorSecurity::CSRF_detected();
-
- return "";
- }
- //data loading
- if (!array_key_exists(ConnectorSecurity::$security_var,$_SESSION)){
- $_SESSION[ConnectorSecurity::$security_var] = md5(uniqid());
- }
-
- return $_SESSION[ConnectorSecurity::$security_var];
- }
-
- return "";
- }
-
-} \ No newline at end of file