Add version files and new GIF images for UI components
839
themes/connector/codebase/base_connector.php
Normal file
@ -0,0 +1,839 @@
|
||||
<?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("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){
|
||||
$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( '&' , '"', ''' , '<' , '>', ''' ), $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"];
|
||||
$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 $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 $options = array();
|
||||
|
||||
/*! 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->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);
|
||||
$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, null);
|
||||
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);
|
||||
|
||||
$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->event->trigger("beforeSort",$wrap);
|
||||
$wrap->store();
|
||||
|
||||
$wrap = new FilterInterface($this->request);
|
||||
$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));
|
||||
$this->output_as_xml($result);
|
||||
} else {
|
||||
$this->output_as_xml($this->get_resource());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
$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["dhx_sort"]))
|
||||
foreach($_GET["dhx_sort"] as $k => $v){
|
||||
$k = $this->safe_field_name($k);
|
||||
$this->request->set_sort($this->resolve_parameter($k),$v);
|
||||
}
|
||||
|
||||
if (isset($_GET["dhx_filter"]))
|
||||
foreach($_GET["dhx_filter"] as $k => $v){
|
||||
$k = $this->safe_field_name($k);
|
||||
$this->request->set_filter($this->resolve_parameter($k),$v);
|
||||
}
|
||||
|
||||
$key = ConnectorSecurity::checkCSRF($this->editing);
|
||||
if ($key !== "")
|
||||
$this->add_top_attribute("dhx_security", $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( '&' , '"', ''' , '<' , '>', ''' ), $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);
|
||||
}
|
||||
|
||||
/*! output fetched data as XML
|
||||
@param res
|
||||
DB resultset
|
||||
*/
|
||||
protected function output_as_xml($res){
|
||||
$start="<?xml version='1.0' encoding='".$this->encoding."' ?>".$this->xml_start();
|
||||
$end=$this->render_set($res).$this->xml_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 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 = "";
|
||||
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();
|
||||
return $this->extra_output."</data>";
|
||||
}
|
||||
|
||||
protected function fill_collections(){
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! 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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
23
themes/connector/codebase/chart_connector.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?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("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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
99
themes/connector/codebase/combo_connector.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?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("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->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>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
1
themes/connector/codebase/connector.js
Normal file
@ -0,0 +1 @@
|
||||
if(window.dhtmlXGridObject){dhtmlXGridObject.prototype._init_point_connector=dhtmlXGridObject.prototype._init_point;dhtmlXGridObject.prototype._init_point=function(){this._con_f_used=[].concat(this._con_f_used);dhtmlXGridObject.prototype._con_f_used=[];var A=function(E){E=E.replace(/(\?|\&)connector[^\f]*/g,"");return E+(E.indexOf("?")!=-1?"&":"?")+"connector=true"+(this.hdr.rows.length>0?"&dhx_no_header=1":"")};var D=function(E){return A.call(this,E)+(this._connector_sorting||"")+(this._connector_filter||"")};var C=function(F,G,E){this._connector_sorting="&dhx_sort["+G+"]="+E;return D.call(this,F)};var B=function(F,E,H){for(var G=0;G<E.length;G++){E[G]="dhx_filter["+E[G]+"]="+encodeURIComponent(H[G])}this._connector_filter="&"+E.join("&");return D.call(this,F)};this.attachEvent("onCollectValues",function(E){if(this._con_f_used[E]){if(typeof (this._con_f_used[E])=="object"){return this._con_f_used[E]}else{return false}}return true});this.attachEvent("onDynXLS",function(){this.xmlFileUrl=D.call(this,this.xmlFileUrl);return true});this.attachEvent("onBeforeSorting",function(H,G,F){if(G=="connector"){var E=this;this.clearAndLoad(C.call(this,this.xmlFileUrl,H,F),function(){E.setSortImgState(true,H,F)});return false}return true});this.attachEvent("onFilterStart",function(F,E){if(this._con_f_used.length){this.clearAndLoad(B.call(this,this.xmlFileUrl,F,E));return false}return true});this.attachEvent("onXLE",function(F,E,H,G){if(!G){return }});if(this._init_point_connector){this._init_point_connector()}};dhtmlXGridObject.prototype._con_f_used=[];dhtmlXGridObject.prototype._in_header_connector_text_filter=function(B,A){if(!this._con_f_used[A]){this._con_f_used[A]=1}return this._in_header_text_filter(B,A)};dhtmlXGridObject.prototype._in_header_connector_select_filter=function(B,A){if(!this._con_f_used[A]){this._con_f_used[A]=2}return this._in_header_select_filter(B,A)};dhtmlXGridObject.prototype.load_connector=dhtmlXGridObject.prototype.load;dhtmlXGridObject.prototype.load=function(B,E,D){if(!this._colls_loaded&&this.cellType){var A=[];for(var C=0;C<this.cellType.length;C++){if(this.cellType[C].indexOf("co")==0||this._con_f_used[C]==2){A.push(C)}}if(A.length){arguments[0]+=(arguments[0].indexOf("?")!=-1?"&":"?")+"connector=true&dhx_colls="+A.join(",")}}return this.load_connector.apply(this,arguments)};dhtmlXGridObject.prototype._parseHead_connector=dhtmlXGridObject.prototype._parseHead;dhtmlXGridObject.prototype._parseHead=function(B,M,J){this._parseHead_connector.apply(this,arguments);if(!this._colls_loaded){var K=this.xmlLoader.doXPath("./coll_options",arguments[0]);for(var G=0;G<K.length;G++){var I=K[G].getAttribute("for");var L=[];var D=null;if(this.cellType[I]=="combo"){D=this.getColumnCombo(I)}else{if(this.cellType[I].indexOf("co")==0){D=this.getCombo(I)}}var F=this.xmlLoader.doXPath("./item",K[G]);var A=[];for(var E=0;E<F.length;E++){var C=F[E].getAttribute("value");if(D){var H=F[E].getAttribute("label")||C;if(D.addOption){A.push([C,H])}else{D.put(C,H)}L[L.length]=H}else{L[L.length]=C}}if(A.length){D.addOption(A)}if(this._con_f_used[I*1]){this._con_f_used[I*1]=L}}this._colls_loaded=true}}}if(window.dataProcessor){dataProcessor.prototype.init_original=dataProcessor.prototype.init;dataProcessor.prototype.init=function(A){this.init_original(A);A._dataprocessor=this;this.setTransactionMode("POST",true);this.serverProcessor+=(this.serverProcessor.indexOf("?")!=-1?"&":"?")+"editing=true"}}dhtmlxError.catchError("LoadXML",function(B,A,C){alert(C[0].responseText)});
|
||||
70
themes/connector/codebase/convert.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?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
|
||||
*/
|
||||
class ConvertService{
|
||||
private $url;
|
||||
private $type;
|
||||
private $name;
|
||||
private $inline;
|
||||
|
||||
public function __construct($url){
|
||||
$this->url = $url;
|
||||
$this->pdf();
|
||||
EventMaster::attach_static("connectorInit",array($this, "handle"));
|
||||
}
|
||||
public function pdf($name = "data.pdf", $inline = false){
|
||||
$this->type = "pdf";
|
||||
$this->name = $name;
|
||||
$this->inline = $inline;
|
||||
}
|
||||
public function excel($name = "data.xls", $inline = false){
|
||||
$this->type = "excel";
|
||||
$this->name = $name;
|
||||
$this->inline = $inline;
|
||||
}
|
||||
public function handle($conn){
|
||||
$conn->event->attach("beforeOutput",array($this,"convert"));
|
||||
}
|
||||
private function as_file($size, $name, $inline){
|
||||
header('Content-Type: application/force-download');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Type: application/download');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
header('Content-Length: '.$size);
|
||||
if ($inline)
|
||||
header('Content-Disposition: inline; filename="'.$name.'";');
|
||||
else
|
||||
header('Content-Disposition: attachment; filename="'.basename($name).'";');
|
||||
}
|
||||
public function convert($conn, $out){
|
||||
|
||||
if ($this->type == "pdf")
|
||||
header("Content-type: application/pdf");
|
||||
else
|
||||
header("Content-type: application/ms-excel");
|
||||
|
||||
$handle = curl_init($this->url);
|
||||
curl_setopt($handle, CURLOPT_POST, true);
|
||||
curl_setopt($handle, CURLOPT_HEADER, false);
|
||||
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($handle, CURLOPT_POSTFIELDS, "grid_xml=".urlencode(str_replace("<rows>","<rows profile='color'>", $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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
142
themes/connector/codebase/crosslink_connector.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?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("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_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":
|
||||
$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"));
|
||||
}
|
||||
}
|
||||
?>
|
||||
450
themes/connector/codebase/data_connector.php
Normal file
@ -0,0 +1,450 @@
|
||||
<?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("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(){
|
||||
//do nothing, at least for now
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
} 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){
|
||||
if (!$item_type) $item_type="JSONCommonDataItem";
|
||||
if (!$data_type) $data_type="CommonDataProcessor";
|
||||
$this->data_separator = ",\n";
|
||||
parent::__construct($res,$type,$item_type,$data_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(){
|
||||
$options = array();
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
$option="\"{$name}\":[";
|
||||
if (!is_string($this->options[$name]))
|
||||
$option.=substr($this->options[$name]->render(),0,-2);
|
||||
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){
|
||||
$start = "";
|
||||
$end = "{ \"data\":[\n".substr($this->render_set($res),0,-2)."\n]";
|
||||
|
||||
$collections = $this->fill_collections();
|
||||
if (!empty($this->extra_output))
|
||||
$end .= ', "collections": {'.$this->extra_output.'}';
|
||||
|
||||
|
||||
$is_sections = sizeof($this->sections) && $this->is_first_call();
|
||||
if ($this->dload || $is_sections || sizeof($this->attributes)){
|
||||
$start = $start.$end;
|
||||
$end="";
|
||||
|
||||
$attributes = "";
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$end .= ", ".$k.":\"".$v."\"";
|
||||
|
||||
if ($is_sections){
|
||||
//extra sections
|
||||
foreach($this->sections as $k=>$v)
|
||||
$end.= ", ".$k.":".$v;
|
||||
}
|
||||
|
||||
if ($this->dload){
|
||||
//info for dyn. loadin
|
||||
if ($pos=$this->request->get_start())
|
||||
$end .= ", \"pos\":".$pos;
|
||||
else
|
||||
$end .= ", \"pos\":0, \"total_count\":".$this->sql->get_size($this->request);
|
||||
}
|
||||
}
|
||||
$end .= " }";
|
||||
$out = new OutputWriter($start, $end);
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
}
|
||||
|
||||
class JSONCommonDataItem extends DataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$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 ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$data[$key]=$value;
|
||||
|
||||
return json_encode($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 .=" dhx_kids='1'";
|
||||
|
||||
return $str.">";
|
||||
}
|
||||
|
||||
function has_kids(){
|
||||
return $this->kids;
|
||||
}
|
||||
|
||||
function set_kids($value){
|
||||
$this->kids=$value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TreeDataConnector extends DataConnector{
|
||||
protected $parent_name = 'parent';
|
||||
|
||||
/*! 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("0");
|
||||
|
||||
$this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
protected function xml_start(){
|
||||
return "<data parent='".$this->request->get_relation()."'>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONTreeDataConnector extends TreeDataConnector{
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type){
|
||||
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){
|
||||
$data = array();
|
||||
$data["parent"] = $this->request->get_relation();
|
||||
$data["data"] = $this->render_set($res);
|
||||
$out = new OutputWriter(json_encode($data), "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class JSONTreeCommonDataItem extends TreeCommonDataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml_start(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$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 ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$data[$key]=$value;
|
||||
|
||||
if ($this->kids === true)
|
||||
$data["dhx_kids"] = 1;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function to_xml_end(){
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
510
themes/connector/codebase/dataprocessor.php
Normal file
@ -0,0 +1,510 @@
|
||||
<?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
|
||||
*/
|
||||
/*! Base DataProcessor handling
|
||||
**/
|
||||
|
||||
require_once("xss_filter.php");
|
||||
|
||||
class DataProcessor{
|
||||
protected $connector;//!< Connector instance
|
||||
protected $config;//!< DataConfig instance
|
||||
protected $request;//!< DataRequestConfig instance
|
||||
static public $action_param ="!nativeeditor_status";
|
||||
|
||||
/*! constructor
|
||||
|
||||
@param connector
|
||||
Connector object
|
||||
@param config
|
||||
DataConfig object
|
||||
@param request
|
||||
DataRequestConfig object
|
||||
*/
|
||||
function __construct($connector,$config,$request){
|
||||
$this->connector= $connector;
|
||||
$this->config=$config;
|
||||
$this->request=$request;
|
||||
}
|
||||
|
||||
/*! convert incoming data name to valid db name
|
||||
redirect to Connector->name_data by default
|
||||
@param data
|
||||
data name from incoming request
|
||||
@return
|
||||
related db_name
|
||||
*/
|
||||
function name_data($data){
|
||||
return $data;
|
||||
}
|
||||
/*! retrieve data from incoming request and normalize it
|
||||
|
||||
@param ids
|
||||
array of extected IDs
|
||||
@return
|
||||
hash of data
|
||||
*/
|
||||
protected function get_post_values($ids){
|
||||
$data=array();
|
||||
for ($i=0; $i < sizeof($ids); $i++)
|
||||
$data[$ids[$i]]=array();
|
||||
|
||||
foreach ($_POST as $key => $value) {
|
||||
$details=explode("_",$key,2);
|
||||
if (sizeof($details)==1) continue;
|
||||
|
||||
$name=$this->name_data($details[1]);
|
||||
$data[$details[0]][$name]=ConnectorSecurity::filter($value);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
protected function get_ids(){
|
||||
if (!isset($_POST["ids"]))
|
||||
throw new Exception("Incorrect incoming data, ID of incoming records not recognized");
|
||||
return explode(",",$_POST["ids"]);
|
||||
}
|
||||
|
||||
protected function get_operation($rid){
|
||||
if (!isset($_POST[$rid."_".DataProcessor::$action_param]))
|
||||
throw new Exception("Status of record [{$rid}] not found in incoming request");
|
||||
return $_POST[$rid."_".DataProcessor::$action_param];
|
||||
}
|
||||
/*! process incoming request ( save|update|delete )
|
||||
*/
|
||||
function process(){
|
||||
LogMaster::log("DataProcessor object initialized",$_POST);
|
||||
|
||||
$results=array();
|
||||
|
||||
$ids=$this->get_ids();
|
||||
$rows_data=$this->get_post_values($ids);
|
||||
$failed=false;
|
||||
|
||||
try{
|
||||
if ($this->connector->sql->is_global_transaction())
|
||||
$this->connector->sql->begin_transaction();
|
||||
|
||||
for ($i=0; $i < sizeof($ids); $i++) {
|
||||
$rid = $ids[$i];
|
||||
LogMaster::log("Row data [{$rid}]",$rows_data[$rid]);
|
||||
$status = $this->get_operation($rid);
|
||||
|
||||
$action=new DataAction($status,$rid,$rows_data[$rid]);
|
||||
$results[]=$action;
|
||||
$this->inner_process($action);
|
||||
}
|
||||
|
||||
} catch(Exception $e){
|
||||
LogMaster::log($e);
|
||||
$failed=true;
|
||||
}
|
||||
|
||||
if ($this->connector->sql->is_global_transaction()){
|
||||
if (!$failed)
|
||||
for ($i=0; $i < sizeof($results); $i++)
|
||||
if ($results[$i]->get_status()=="error" || $results[$i]->get_status()=="invalid"){
|
||||
$failed=true;
|
||||
break;
|
||||
}
|
||||
if ($failed){
|
||||
for ($i=0; $i < sizeof($results); $i++)
|
||||
$results[$i]->error();
|
||||
$this->connector->sql->rollback_transaction();
|
||||
}
|
||||
else
|
||||
$this->connector->sql->commit_transaction();
|
||||
}
|
||||
|
||||
$this->output_as_xml($results);
|
||||
}
|
||||
|
||||
/*! converts status string to the inner mode name
|
||||
|
||||
@param status
|
||||
external status string
|
||||
@return
|
||||
inner mode name
|
||||
*/
|
||||
protected function status_to_mode($status){
|
||||
switch($status){
|
||||
case "updated":
|
||||
return "update";
|
||||
break;
|
||||
case "inserted":
|
||||
return "insert";
|
||||
break;
|
||||
case "deleted":
|
||||
return "delete";
|
||||
break;
|
||||
default:
|
||||
return $status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*! process data updated request received
|
||||
|
||||
@param action
|
||||
DataAction object
|
||||
@return
|
||||
DataAction object with details of processing
|
||||
*/
|
||||
protected function inner_process($action){
|
||||
|
||||
if ($this->connector->sql->is_record_transaction())
|
||||
$this->connector->sql->begin_transaction();
|
||||
|
||||
try{
|
||||
|
||||
$mode = $this->status_to_mode($action->get_status());
|
||||
if (!$this->connector->access->check($mode)){
|
||||
LogMaster::log("Access control: {$operation} operation blocked");
|
||||
$action->error();
|
||||
} else {
|
||||
$check = $this->connector->event->trigger("beforeProcessing",$action);
|
||||
if (!$action->is_ready())
|
||||
$this->check_exts($action,$mode);
|
||||
$check = $this->connector->event->trigger("afterProcessing",$action);
|
||||
}
|
||||
|
||||
} catch (Exception $e){
|
||||
LogMaster::log($e);
|
||||
$action->set_status("error");
|
||||
if ($action)
|
||||
$this->connector->event->trigger("onDBError", $action, $e);
|
||||
}
|
||||
|
||||
if ($this->connector->sql->is_record_transaction()){
|
||||
if ($action->get_status()=="error" || $action->get_status()=="invalid")
|
||||
$this->connector->sql->rollback_transaction();
|
||||
else
|
||||
$this->connector->sql->commit_transaction();
|
||||
}
|
||||
|
||||
return $action;
|
||||
}
|
||||
/*! check if some event intercepts processing, send data to DataWrapper in other case
|
||||
|
||||
@param action
|
||||
DataAction object
|
||||
@param mode
|
||||
name of inner mode ( will be used to generate event names )
|
||||
*/
|
||||
function check_exts($action,$mode){
|
||||
$old_config = new DataConfig($this->config);
|
||||
|
||||
$this->connector->event->trigger("before".$mode,$action);
|
||||
if ($action->is_ready())
|
||||
LogMaster::log("Event code for ".$mode." processed");
|
||||
else {
|
||||
//check if custom sql defined
|
||||
$sql = $this->connector->sql->get_sql($mode,$action);
|
||||
if ($sql){
|
||||
$this->connector->sql->query($sql);
|
||||
}
|
||||
else{
|
||||
$action->sync_config($this->config);
|
||||
if ($this->connector->model && method_exists($this->connector->model, $mode)){
|
||||
call_user_func(array($this->connector->model, $mode), $action);
|
||||
LogMaster::log("Model object process action: ".$mode);
|
||||
}
|
||||
if (!$action->is_ready()){
|
||||
$method=array($this->connector->sql,$mode);
|
||||
if (!is_callable($method))
|
||||
throw new Exception("Unknown dataprocessing action: ".$mode);
|
||||
call_user_func($method,$action,$this->request);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->connector->event->trigger("after".$mode,$action);
|
||||
|
||||
$this->config = $old_config;
|
||||
}
|
||||
|
||||
/*! output xml response for dataprocessor
|
||||
|
||||
@param results
|
||||
array of DataAction objects
|
||||
*/
|
||||
function output_as_xml($results){
|
||||
LogMaster::log("Edit operation finished",$results);
|
||||
ob_clean();
|
||||
header("Content-type:text/xml");
|
||||
echo "<?xml version='1.0' ?>";
|
||||
echo "<data>";
|
||||
for ($i=0; $i < sizeof($results); $i++)
|
||||
echo $results[$i]->to_xml();
|
||||
echo "</data>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*! contain all info related to action and controls customizaton
|
||||
**/
|
||||
class DataAction{
|
||||
private $status; //!< cuurent status of record
|
||||
private $id;//!< id of record
|
||||
private $data;//!< data hash of record
|
||||
private $userdata;//!< hash of extra data , attached to record
|
||||
private $nid;//!< new id value , after operation executed
|
||||
private $output;//!< custom output to client side code
|
||||
private $attrs;//!< hash of custtom attributes
|
||||
private $ready;//!< flag of operation's execution
|
||||
private $addf;//!< array of added fields
|
||||
private $delf;//!< array of deleted fields
|
||||
|
||||
|
||||
/*! constructor
|
||||
|
||||
@param status
|
||||
current operation status
|
||||
@param id
|
||||
record id
|
||||
@param data
|
||||
hash of data
|
||||
*/
|
||||
function __construct($status,$id,$data){
|
||||
$this->status=$status;
|
||||
$this->id=$id;
|
||||
$this->data=$data;
|
||||
$this->nid=$id;
|
||||
|
||||
$this->output="";
|
||||
$this->attrs=array();
|
||||
$this->ready=false;
|
||||
|
||||
$this->addf=array();
|
||||
$this->delf=array();
|
||||
}
|
||||
|
||||
|
||||
/*! add custom field and value to DB operation
|
||||
|
||||
@param name
|
||||
name of field which will be added to DB operation
|
||||
@param value
|
||||
value which will be used for related field in DB operation
|
||||
*/
|
||||
function add_field($name,$value){
|
||||
LogMaster::log("adding field: ".$name.", with value: ".$value);
|
||||
$this->data[$name]=$value;
|
||||
$this->addf[]=$name;
|
||||
}
|
||||
/*! remove field from DB operation
|
||||
|
||||
@param name
|
||||
name of field which will be removed from DB operation
|
||||
*/
|
||||
function remove_field($name){
|
||||
LogMaster::log("removing field: ".$name);
|
||||
$this->delf[]=$name;
|
||||
}
|
||||
|
||||
/*! sync field configuration with external object
|
||||
|
||||
@param slave
|
||||
SQLMaster object
|
||||
@todo
|
||||
check , if all fields removed then cancel action
|
||||
*/
|
||||
function sync_config($slave){
|
||||
foreach ($this->addf as $k => $v)
|
||||
$slave->add_field($v);
|
||||
foreach ($this->delf as $k => $v)
|
||||
$slave->remove_field($v);
|
||||
}
|
||||
/*! get value of some record's propery
|
||||
|
||||
@param name
|
||||
name of record's property ( name of db field or alias )
|
||||
@return
|
||||
value of related property
|
||||
*/
|
||||
function get_value($name){
|
||||
if (!array_key_exists($name,$this->data)){
|
||||
LogMaster::log("Incorrect field name used: ".$name);
|
||||
LogMaster::log("data",$this->data);
|
||||
return "";
|
||||
}
|
||||
return $this->data[$name];
|
||||
}
|
||||
/*! set value of some record's propery
|
||||
|
||||
@param name
|
||||
name of record's property ( name of db field or alias )
|
||||
@param value
|
||||
value of related property
|
||||
*/
|
||||
function set_value($name,$value){
|
||||
LogMaster::log("change value of: ".$name." as: ".$value);
|
||||
$this->data[$name]=$value;
|
||||
}
|
||||
/*! get hash of data properties
|
||||
|
||||
@return
|
||||
hash of data properties
|
||||
*/
|
||||
function get_data(){
|
||||
return $this->data;
|
||||
}
|
||||
/*! get some extra info attached to record
|
||||
deprecated, exists just for backward compatibility, you can use set_value instead of it
|
||||
@param name
|
||||
name of userdata property
|
||||
@return
|
||||
value of related userdata property
|
||||
*/
|
||||
function get_userdata_value($name){
|
||||
return $this->get_value($name);
|
||||
}
|
||||
/*! set some extra info attached to record
|
||||
deprecated, exists just for backward compatibility, you can use get_value instead of it
|
||||
@param name
|
||||
name of userdata property
|
||||
@param value
|
||||
value of userdata property
|
||||
*/
|
||||
function set_userdata_value($name,$value){
|
||||
return $this->set_value($name,$value);
|
||||
}
|
||||
/*! get current status of record
|
||||
|
||||
@return
|
||||
string with status value
|
||||
*/
|
||||
function get_status(){
|
||||
return $this->status;
|
||||
}
|
||||
/*! assign new status to the record
|
||||
|
||||
@param status
|
||||
new status value
|
||||
*/
|
||||
function set_status($status){
|
||||
$this->status=$status;
|
||||
}
|
||||
/*! set id
|
||||
@param id
|
||||
id value
|
||||
*/
|
||||
function set_id($id) {
|
||||
$this->id = $id;
|
||||
LogMaster::log("Change id: ".$id);
|
||||
}
|
||||
/*! set id
|
||||
@param id
|
||||
id value
|
||||
*/
|
||||
function set_new_id($id) {
|
||||
$this->nid = $id;
|
||||
LogMaster::log("Change new id: ".$id);
|
||||
}
|
||||
/*! get id of current record
|
||||
|
||||
@return
|
||||
id of record
|
||||
*/
|
||||
function get_id(){
|
||||
return $this->id;
|
||||
}
|
||||
/*! sets custom response text
|
||||
|
||||
can be accessed through defineAction on client side. Text wrapped in CDATA, so no extra escaping necessary
|
||||
@param text
|
||||
custom response text
|
||||
*/
|
||||
function set_response_text($text){
|
||||
$this->set_response_xml("<![CDATA[".$text."]]>");
|
||||
}
|
||||
/*! sets custom response xml
|
||||
|
||||
can be accessed through defineAction on client side
|
||||
@param text
|
||||
string with XML data
|
||||
*/
|
||||
function set_response_xml($text){
|
||||
$this->output=$text;
|
||||
}
|
||||
/*! sets custom response attributes
|
||||
|
||||
can be accessed through defineAction on client side
|
||||
@param name
|
||||
name of custom attribute
|
||||
@param value
|
||||
value of custom attribute
|
||||
*/
|
||||
function set_response_attribute($name,$value){
|
||||
$this->attrs[$name]=$value;
|
||||
}
|
||||
/*! check if action finished
|
||||
|
||||
@return
|
||||
true if action finished, false otherwise
|
||||
*/
|
||||
function is_ready(){
|
||||
return $this->ready;
|
||||
}
|
||||
/*! return new id value
|
||||
|
||||
equal to original ID normally, after insert operation - value assigned for new DB record
|
||||
@return
|
||||
new id value
|
||||
*/
|
||||
function get_new_id(){
|
||||
return $this->nid;
|
||||
}
|
||||
|
||||
/*! set result of operation as error
|
||||
*/
|
||||
function error(){
|
||||
$this->status="error";
|
||||
$this->ready=true;
|
||||
}
|
||||
/*! set result of operation as invalid
|
||||
*/
|
||||
function invalid(){
|
||||
$this->status="invalid";
|
||||
$this->ready=true;
|
||||
}
|
||||
/*! confirm successful opeation execution
|
||||
@param id
|
||||
new id value, optional
|
||||
*/
|
||||
function success($id=false){
|
||||
if ($id!==false)
|
||||
$this->nid = $id;
|
||||
$this->ready=true;
|
||||
}
|
||||
/*! convert DataAction to xml format compatible with client side dataProcessor
|
||||
@return
|
||||
DataAction operation report as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
$str="<action type='{$this->status}' sid='{$this->id}' tid='{$this->nid}' ";
|
||||
foreach ($this->attrs as $k => $v) {
|
||||
$str.=$k."='".$v."' ";
|
||||
}
|
||||
$str.=">{$this->output}</action>";
|
||||
return $str;
|
||||
}
|
||||
/*! convert self to string ( for logs )
|
||||
|
||||
@return
|
||||
DataAction operation report as plain string
|
||||
*/
|
||||
function __toString(){
|
||||
return "action:{$this->status}; sid:{$this->id}; tid:{$this->nid};";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
79
themes/connector/codebase/dataview_connector.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?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("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."'";
|
||||
|
||||
$start.= ">";
|
||||
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.">";
|
||||
}
|
||||
}
|
||||
?>
|
||||
1023
themes/connector/codebase/db_common.php
Normal file
192
themes/connector/codebase/db_excel.php
Normal file
@ -0,0 +1,192 @@
|
||||
<?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');
|
||||
|
||||
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 = $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 ($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;
|
||||
}
|
||||
|
||||
protected function query($sql) {
|
||||
}
|
||||
|
||||
protected 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
350
themes/connector/codebase/db_filesystem.php
Normal file
@ -0,0 +1,350 @@
|
||||
<?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');
|
||||
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;
|
||||
}
|
||||
|
||||
protected function query($sql) {
|
||||
}
|
||||
|
||||
protected 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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
78
themes/connector/codebase/db_mssql.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?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 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);
|
||||
}
|
||||
|
||||
protected 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");
|
||||
}
|
||||
}
|
||||
?>
|
||||
61
themes/connector/codebase/db_mysqli.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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");
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
protected 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
96
themes/connector/codebase/db_oracle.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?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");
|
||||
/*! 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("Oracle - sql execution failed\n".oci_error($this->connection));
|
||||
|
||||
$this->last_id=$out[0];
|
||||
|
||||
return $stm;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = oci_fetch_assoc($res);
|
||||
if ($data){
|
||||
if (array_key_exists("VALUE",$data))
|
||||
$data["value"]=$data["VALUE"];
|
||||
if (array_key_exists("LABEL",$data))
|
||||
$data["label"]=$data["LABEL"];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected 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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
80
themes/connector/codebase/db_pdo.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?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");
|
||||
/*! 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;
|
||||
if ($start || $count) {
|
||||
if ($this->connection->getAttribute(PDO::ATTR_DRIVER_NAME)=="pgsql")
|
||||
$sql.=" OFFSET ".$start." LIMIT ".$count;
|
||||
else
|
||||
$sql.=" LIMIT ".$start.",".$count;
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
public function get_next($res){
|
||||
$data = $res->next();
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected 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 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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
85
themes/connector/codebase/db_phpcake.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?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");
|
||||
|
||||
//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){
|
||||
$res = $this->connection->find("all");
|
||||
if (sizeof($res)){
|
||||
$name = get_class($this->connection);
|
||||
$temp = array();
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
68
themes/connector/codebase/db_phpci.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?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");
|
||||
|
||||
/*! 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");
|
||||
}
|
||||
|
||||
return new PHPCIResultSet($res);
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = $res->next();
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
93
themes/connector/codebase/db_phpyii.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?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");
|
||||
|
||||
class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
|
||||
public function select($sql){
|
||||
$res = $this->connection->findAll();
|
||||
if (sizeof($res)){
|
||||
$name = get_class($this->connection);
|
||||
$temp = array();
|
||||
foreach ($res as $obj)
|
||||
$temp[]=&$obj->getAttributes();
|
||||
}
|
||||
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);
|
||||
$obj = new $name();
|
||||
|
||||
$this->fill_model_and_save($obj, $data);
|
||||
}
|
||||
public function delete($data,$source){
|
||||
$obj = $this->connection->findByPk($data->get_id());
|
||||
if ($obj->delete()){
|
||||
$data->success();
|
||||
$data->set_new_id($obj->getPrimaryKey());
|
||||
} else {
|
||||
$data->set_response_attribute("details", $this->errors_to_string($obj->getErrors()));
|
||||
$data->invalid();
|
||||
}
|
||||
}
|
||||
public function update($data,$source){
|
||||
$obj = $this->connection->findByPk($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"]));
|
||||
}
|
||||
if ($relation = $this->config->relation_id["db_name"])
|
||||
$obj->setAttribute($relation, $data->get_value($relation));
|
||||
|
||||
//save model
|
||||
if ($obj->save()){
|
||||
$data->success();
|
||||
$data->set_new_id($obj->getPrimaryKey());
|
||||
} else {
|
||||
$data->set_response_attribute("details", $this->errors_to_string($obj->getErrors()));
|
||||
$data->invalid();
|
||||
}
|
||||
}
|
||||
|
||||
protected function errors_to_string($errors){
|
||||
$text = array();
|
||||
foreach($errors as $value)
|
||||
$text[]=implode("\n", $value);
|
||||
return implode("\n",$text);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
78
themes/connector/codebase/db_postgre.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?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");
|
||||
/*! 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);
|
||||
}
|
||||
|
||||
protected 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 );
|
||||
}
|
||||
}
|
||||
?>
|
||||
59
themes/connector/codebase/db_sasql.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?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
|
||||
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);
|
||||
}
|
||||
|
||||
protected 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");
|
||||
}
|
||||
}
|
||||
?>
|
||||
39
themes/connector/codebase/db_sqlite.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?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");
|
||||
/*! 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;
|
||||
}
|
||||
|
||||
protected function get_new_id(){
|
||||
return sqlite_last_insert_rowid($this->connection);
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return sqlite_escape_string($data);
|
||||
}
|
||||
}
|
||||
?>
|
||||
38
themes/connector/codebase/db_sqlite3.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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");
|
||||
/*! 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();
|
||||
}
|
||||
|
||||
protected function get_new_id(){
|
||||
return $this->connection->lastInsertRowID();
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return $this->connection->escapeString($data);
|
||||
}
|
||||
}
|
||||
?>
|
||||
101
themes/connector/codebase/db_sqlsrv.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?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[$i]["SQLSTATE"].$error[$i]["code'"].$error[$i]["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);
|
||||
foreach ($data as $key => $value)
|
||||
if (is_a($value, "DateTime"))
|
||||
$data[$key] = $value->format("Y-m-d H:i");
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected 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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
24
themes/connector/codebase/filesystem_item.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
class FileTreeDataItem extends TreeDataItem {
|
||||
|
||||
function has_kids(){
|
||||
if ($this->data['is_folder'] == '1') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
67
themes/connector/codebase/form_connector.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?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("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{
|
||||
|
||||
}
|
||||
?>
|
||||
428
themes/connector/codebase/grid_config.php
Normal file
@ -0,0 +1,428 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
272
themes/connector/codebase/grid_connector.php
Normal file
@ -0,0 +1,272 @@
|
||||
<?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("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->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"];
|
||||
if (isset($this->cell_attrs[$name])){
|
||||
$cattrs=$this->cell_attrs[$name];
|
||||
foreach ($cattrs as $k => $v)
|
||||
$str.=" ".$k."='".$this->xmlentities($v)."'";
|
||||
}
|
||||
$value = isset($this->data[$name]) ? $this->data[$name] : '';
|
||||
$str.="><![CDATA[".$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{
|
||||
protected $extra_output="";//!< extra info which need to be sent to client side
|
||||
protected $options=array();//!< hash of OptionsConnector
|
||||
|
||||
/*! 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"]);
|
||||
|
||||
if (isset($_GET["posStart"]) && isset($_GET["count"]))
|
||||
$this->request->set_limit($_GET["posStart"],$_GET["count"]);
|
||||
}
|
||||
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( '&' , '"', ''' , '<' , '>', ''' ), $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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
53
themes/connector/codebase/keygrid_connector.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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("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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
50
themes/connector/codebase/options_connector.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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("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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
231
themes/connector/codebase/scheduler_connector.php
Normal file
@ -0,0 +1,231 @@
|
||||
<?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("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(){
|
||||
$options = array();
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
$option="\"{$name}\":[";
|
||||
if (!is_string($this->options[$name]))
|
||||
$option.=substr($this->options[$name]->render(),0,-2);
|
||||
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){
|
||||
$data=$this->xml_start();
|
||||
$data.=$this->render_set($res);
|
||||
$data.=$this->xml_end();
|
||||
|
||||
$out = new OutputWriter($data, "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
}
|
||||
?>
|
||||
404
themes/connector/codebase/strategy.php
Normal file
@ -0,0 +1,404 @@
|
||||
<?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
|
||||
|
||||
class RenderStrategy {
|
||||
|
||||
protected $conn = null;
|
||||
|
||||
public function __construct($conn) {
|
||||
$this->conn = $conn;
|
||||
}
|
||||
|
||||
/*! render from DB resultset
|
||||
@param res
|
||||
DB resultset
|
||||
process commands, output requested data as XML
|
||||
*/
|
||||
public function render_set($res, $name, $dload, $sep, $config){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$conn->event->trigger("beforeRenderSet",$conn,$res,$config);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$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++;
|
||||
}
|
||||
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){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$conn->event->trigger("beforeRenderSet",$conn,$res,$config);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$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();
|
||||
$index++;
|
||||
}
|
||||
return json_encode($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){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$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_relation($data->get_id());
|
||||
$output.=$this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config);
|
||||
}
|
||||
$output.=$data->to_xml_end();
|
||||
$index++;
|
||||
}
|
||||
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){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$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_relation($data->get_id());
|
||||
$temp = $this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config);
|
||||
if (sizeof($temp))
|
||||
$record["data"] = $temp;
|
||||
}
|
||||
$output[] = $record;
|
||||
$index++;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MultitableTreeRenderStrategy extends TreeRenderStrategy {
|
||||
|
||||
private $level = 0;
|
||||
private $max_level = null;
|
||||
protected $sep = "#";
|
||||
|
||||
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){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$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++;
|
||||
}
|
||||
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('#', urldecode($id));
|
||||
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){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$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++;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class GroupRenderStrategy extends RenderStrategy {
|
||||
|
||||
private $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){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
if (isset($data[$config->id['name']])) {
|
||||
$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);
|
||||
}
|
||||
$output.=$data->to_xml_end();
|
||||
$index++;
|
||||
}
|
||||
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){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
if (isset($data[$config->id['name']])) {
|
||||
$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);
|
||||
if (sizeof($temp))
|
||||
$record["data"] = $temp;
|
||||
}
|
||||
$output[] = $record;
|
||||
$index++;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
272
themes/connector/codebase/tools.php
Normal file
@ -0,0 +1,272 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/*! 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:m:s")."\n====================================");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
234
themes/connector/codebase/tree_connector.php
Normal file
@ -0,0 +1,234 @@
|
||||
<?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("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->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';
|
||||
|
||||
/*! 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("0");
|
||||
|
||||
$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(){
|
||||
return "</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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
94
themes/connector/codebase/treedatagroup_connector.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?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("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'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
||||
90
themes/connector/codebase/treedatamultitable_connector.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?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("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->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){
|
||||
$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"] = $this->render_set($res);
|
||||
|
||||
$out = new OutputWriter(json_encode($data), "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
|
||||
public function xml_start(){
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
125
themes/connector/codebase/treegrid_connector.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?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("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';
|
||||
|
||||
/*! 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("0");
|
||||
|
||||
$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->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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
51
themes/connector/codebase/treegridgroup_connector.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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("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'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
75
themes/connector/codebase/treegridmultitable_connector.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?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("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);
|
||||
$this->render->set_separator("%23");
|
||||
}
|
||||
|
||||
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->render->level_id($_GET['id'], $this->render->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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
51
themes/connector/codebase/treegroup_connector.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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("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'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
56
themes/connector/codebase/treemultitable_connector.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?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("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->render->level_id($_GET[$this->parent_name], $this->render->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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
271
themes/connector/codebase/update.php
Normal file
@ -0,0 +1,271 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
/*! 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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
202
themes/connector/codebase/xss_filter.php
Normal file
@ -0,0 +1,202 @@
|
||||
<?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
|
||||
|
||||
// +----------------------------------------------------------------------+
|
||||
// | 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("&", "<", ">"), array("&amp;", "&lt;", "&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 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){
|
||||
@session_start();
|
||||
|
||||
if (ConnectorSecurity::$security_key){
|
||||
if ($edit=== true){
|
||||
if (!isset($_POST['dhx_security']))
|
||||
return ConnectorSecurity::CSRF_detected();
|
||||
$master_key = $_SESSION['dhx_security'];
|
||||
$update_key = $_POST['dhx_security'];
|
||||
if ($master_key != $update_key)
|
||||
return ConnectorSecurity::CSRF_detected();
|
||||
|
||||
return "";
|
||||
}
|
||||
//data loading
|
||||
if (!array_key_exists("dhx_security",$_SESSION)){
|
||||
$_SESSION["dhx_security"] = md5(uniqid());
|
||||
}
|
||||
|
||||
return $_SESSION["dhx_security"];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
BIN
themes/connector/doc/connector.chm
Normal file
BIN
themes/connector/doc/connector_doc.zip
Normal file
5
themes/connector/readme.txt
Normal file
@ -0,0 +1,5 @@
|
||||
dhtmlxConnector for PHP v.1.5
|
||||
|
||||
Online Documentation: http://www.dhtmlx.com/dhxdocs/doku.php?id=dhtmlxconnector:start
|
||||
|
||||
(c) Dinamenta, UAB
|
||||
46
themes/connector/samples/combo/01_basic.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Filtering and Autocomplete mode</title>
|
||||
<script>
|
||||
window.dhx_globalImgPath="../dhtmlx/imgs/";
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script src="../dhtmlx/dhtmlx.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="../../codebase/connector.js" type="text/javascript" charset="utf-8"></script>
|
||||
<link rel="stylesheet" href="../dhtmlx/dhtmlx.css" type="text/css" charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="combo_zone4" style="width:200px; height:30px;"></div>
|
||||
<hr/>
|
||||
<div id="combo_zone5" style="width:200px; height:30px;"></div>
|
||||
<hr/>
|
||||
<div id="combo_zone6" style="width:200px; height:30px;"></div>
|
||||
<script>
|
||||
var z=new dhtmlXCombo("combo_zone4","alfa4",200);
|
||||
z.loadXML("01_basic_connector.php");
|
||||
</script>
|
||||
<script>
|
||||
var z=new dhtmlXCombo("combo_zone5","alfa4",200);
|
||||
z.enableFilteringMode(true,"01_basic_connector.php",true);
|
||||
</script>
|
||||
<script>
|
||||
var z=new dhtmlXCombo("combo_zone6","alfa4",200);
|
||||
z.enableFilteringMode(true,"01_basic_srnd_connector.php",true,true);
|
||||
</script>
|
||||
<div class='code'><code><span style="color: #000000">
|
||||
<span style="color: #0000BB"><?php
|
||||
<br /> </span><span style="color: #007700">require_once(</span><span style="color: #DD0000">"../config.php"</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$res</span><span style="color: #007700">=</span><span style="color: #0000BB">mysql_connect</span><span style="color: #007700">(</span><span style="color: #0000BB">$mysql_server</span><span style="color: #007700">,</span><span style="color: #0000BB">$mysql_user</span><span style="color: #007700">,</span><span style="color: #0000BB">$mysql_pass</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">mysql_select_db</span><span style="color: #007700">(</span><span style="color: #0000BB">$mysql_db</span><span style="color: #007700">);
|
||||
<br />
|
||||
<br /> require(</span><span style="color: #DD0000">"../../codebase/combo_connector.php"</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$combo </span><span style="color: #007700">= new </span><span style="color: #0000BB">ComboConnector</span><span style="color: #007700">(</span><span style="color: #0000BB">$res</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$combo</span><span style="color: #007700">-></span><span style="color: #0000BB">enable_log</span><span style="color: #007700">(</span><span style="color: #DD0000">"temp.log"</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$combo</span><span style="color: #007700">-></span><span style="color: #0000BB">render_table</span><span style="color: #007700">(</span><span style="color: #DD0000">"country_data"</span><span style="color: #007700">,</span><span style="color: #DD0000">"country_id"</span><span style="color: #007700">,</span><span style="color: #DD0000">"name"</span><span style="color: #007700">);
|
||||
<br /></span><span style="color: #0000BB">?></span>
|
||||
</span>
|
||||
</code></div></body>
|
||||
</html>
|
||||
10
themes/connector/samples/combo/01_basic_connector.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once("../config.php");
|
||||
$res=mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
require("../../codebase/combo_connector.php");
|
||||
$combo = new ComboConnector($res);
|
||||
// $combo->enable_log("temp.log");
|
||||
$combo->render_table("country_data","country_id","name");
|
||||
?>
|
||||
11
themes/connector/samples/combo/01_basic_srnd_connector.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
require_once("../config.php");
|
||||
$res=mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
require("../../codebase/combo_connector.php");
|
||||
$combo = new ComboConnector($res);
|
||||
// $combo->enable_log("temp.log");
|
||||
$combo->dynamic_loading(2);
|
||||
$combo->render_table("country_data","country_id","name");
|
||||
?>
|
||||
46
themes/connector/samples/combo/02_sql.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Filtering and Autocomplete mode</title>
|
||||
<script>
|
||||
window.dhx_globalImgPath="../dhtmlx/imgs/";
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script src="../dhtmlx/dhtmlx.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="../../codebase/connector.js" type="text/javascript" charset="utf-8"></script>
|
||||
<link rel="stylesheet" href="../dhtmlx/dhtmlx.css" type="text/css" charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="combo_zone4" style="width:200px; height:30px;"></div>
|
||||
<hr/>
|
||||
<div id="combo_zone5" style="width:200px; height:30px;"></div>
|
||||
<hr/>
|
||||
<div id="combo_zone6" style="width:200px; height:30px;"></div>
|
||||
<script>
|
||||
var z=new dhtmlXCombo("combo_zone4","alfa4",200);
|
||||
z.loadXML("02_sql_connector.php");
|
||||
</script>
|
||||
<script>
|
||||
var z=new dhtmlXCombo("combo_zone5","alfa4",200);
|
||||
z.enableFilteringMode(true,"02_sql_connector.php",true);
|
||||
</script>
|
||||
<script>
|
||||
var z=new dhtmlXCombo("combo_zone6","alfa4",200);
|
||||
z.enableFilteringMode(true,"02_sql_srnd_connector.php",true,true);
|
||||
</script>
|
||||
<div class='code'><code><span style="color: #000000">
|
||||
<span style="color: #0000BB"><?php
|
||||
<br /> </span><span style="color: #007700">require_once(</span><span style="color: #DD0000">"../config.php"</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$res</span><span style="color: #007700">=</span><span style="color: #0000BB">mysql_connect</span><span style="color: #007700">(</span><span style="color: #0000BB">$mysql_server</span><span style="color: #007700">,</span><span style="color: #0000BB">$mysql_user</span><span style="color: #007700">,</span><span style="color: #0000BB">$mysql_pass</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">mysql_select_db</span><span style="color: #007700">(</span><span style="color: #0000BB">$mysql_db</span><span style="color: #007700">);
|
||||
<br />
|
||||
<br /> require(</span><span style="color: #DD0000">"../../codebase/combo_connector.php"</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$combo </span><span style="color: #007700">= new </span><span style="color: #0000BB">ComboConnector</span><span style="color: #007700">(</span><span style="color: #0000BB">$res</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$combo</span><span style="color: #007700">-></span><span style="color: #0000BB">enable_log</span><span style="color: #007700">(</span><span style="color: #DD0000">"temp.log"</span><span style="color: #007700">);
|
||||
<br /> </span><span style="color: #0000BB">$combo</span><span style="color: #007700">-></span><span style="color: #0000BB">render_sql</span><span style="color: #007700">(</span><span style="color: #DD0000">"SELECT * FROM country_data WHERE country_id >40 "</span><span style="color: #007700">,</span><span style="color: #DD0000">"country_id"</span><span style="color: #007700">,</span><span style="color: #DD0000">"name"</span><span style="color: #007700">);
|
||||
<br /></span><span style="color: #0000BB">?></span>
|
||||
</span>
|
||||
</code></div></body>
|
||||
</html>
|
||||
10
themes/connector/samples/combo/02_sql_connector.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once("../config.php");
|
||||
$res=mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
require("../../codebase/combo_connector.php");
|
||||
$combo = new ComboConnector($res);
|
||||
//$combo->enable_log("temp.log");
|
||||
$combo->render_sql("SELECT * FROM country_data WHERE country_id >40 ","country_id","name");
|
||||
?>
|
||||
11
themes/connector/samples/combo/02_sql_srnd_connector.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
require_once("../config.php");
|
||||
$res=mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
require("../../codebase/combo_connector.php");
|
||||
$combo = new ComboConnector($res);
|
||||
// $combo->enable_log("temp.log");
|
||||
$combo->dynamic_loading(2);
|
||||
$combo->render_sql("SELECT * FROM country_data WHERE country_id >40 ","country_id","name");
|
||||
?>
|
||||
26
themes/connector/samples/combo/index.html
Normal file
@ -0,0 +1,26 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<style type="text/css" media="screen">
|
||||
*{
|
||||
font-family:Tahoma;
|
||||
}
|
||||
div,li{
|
||||
font-size:10pt;
|
||||
}
|
||||
div{
|
||||
padding-bottom:20px;
|
||||
}
|
||||
li{
|
||||
padding-left:50px;
|
||||
padding-bottom:10px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h2>dhtmlxConnector for PHP :: Samples</h2>
|
||||
|
||||
<li><a href="01_basic.html">Basic init</a></li>
|
||||
<li><a href="02_sql.html">Basic init by sql string</a></li>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
14
themes/connector/samples/config.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
$mysql_server="192.168.1.251";
|
||||
$mysql_user = "sampleDB";
|
||||
$mysql_pass = "sampleDB";
|
||||
$mysql_db = "sampleDB";
|
||||
$excel_file = "../common/excel_sample.xls";
|
||||
|
||||
//necessary for PostgreSQL related samples only
|
||||
$postrgre_connection = "host=localhost port=5432 dbname=sampleDB user=root password=1234";
|
||||
//necessary for Oracle related samples only
|
||||
$oci_connection = "some here";
|
||||
//necessart for SQL Anywhere connection
|
||||
$sasql_conn = "uid=DBA;pwd=sql";
|
||||
?>
|
||||
30
themes/connector/samples/dataview/01_static_loading.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Static loading</title>
|
||||
<script src="../dhtmlx/dhtmlx.js" type="text/javascript"></script>
|
||||
<script src="../../codebase/connector.js" type="text/javascript" charset="utf-8"></script>
|
||||
<link rel="STYLESHEET" type="text/css" href="../dhtmlx/dhtmlx.css">
|
||||
<style type="text/css" media="screen">
|
||||
body { background-color:#EBEBEB; };
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Static loading</h1>
|
||||
<p>All data is loaded at once</p>
|
||||
<div id="data_container" style="border:1px solid #A4BED4; background-color:white; width:710px;height:392px;"></div>
|
||||
<script>
|
||||
data = new dhtmlXDataView({
|
||||
container:"data_container",
|
||||
type:{
|
||||
template:"<span class='dhx_strong'>{obj.Maintainer}</span>{obj.Package} <span class='dhx_light'>{obj.Version}</span>",
|
||||
height:35
|
||||
}
|
||||
});
|
||||
data.load("01_static_loading.php");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
10
themes/connector/samples/dataview/01_static_loading.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once("../../codebase/dataview_connector.php");
|
||||
require_once("../config.php");
|
||||
|
||||
$conn = mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
$data = new DataViewConnector($conn);
|
||||
$data->render_sql(" SELECT * FROM packages_plain WHERE Id < 1000","Id","Package,Version,Maintainer");
|
||||
?>
|
||||
32
themes/connector/samples/dataview/02_dynamic_loading.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Dynamic loading</title>
|
||||
<script src="../dhtmlx/dhtmlx.js" type="text/javascript"></script>
|
||||
<script src="../../codebase/connector.js" type="text/javascript" charset="utf-8"></script>
|
||||
<link rel="STYLESHEET" type="text/css" href="../dhtmlx/dhtmlx.css">
|
||||
<style type="text/css" media="screen">
|
||||
body { background-color:#EBEBEB; };
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Dynamic loading</h1>
|
||||
<p>Data is loaded to the DataView on demand</p>
|
||||
|
||||
<div id="data_container" style="border:1px solid #A4BED4; background-color:white; width:710px;height:392px;"></div>
|
||||
<br>
|
||||
<script>
|
||||
data = new dhtmlXDataView({
|
||||
container:"data_container",
|
||||
type:{
|
||||
template:"<span class='dhx_strong'>{obj.Maintainer}</span>{obj.Package} <span class='dhx_light'>{obj.Version}</span>",
|
||||
height:35
|
||||
}
|
||||
});
|
||||
data.load("02_dynamic_loading.php");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
12
themes/connector/samples/dataview/02_dynamic_loading.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
require_once("../../codebase/dataview_connector.php");
|
||||
require_once("../config.php");
|
||||
|
||||
$conn = mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
$data = new DataViewConnector($conn);
|
||||
$data->dynamic_loading(50);
|
||||
$data->render_table("packages_plain","Id","Package,Version,Maintainer");
|
||||
?>
|
||||
67
themes/connector/samples/dataview/03_adding.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!--conf
|
||||
<sample in_favorites="true">
|
||||
<product version="1.0" edition="std"/>
|
||||
<modifications>
|
||||
<modified date="080205"/>
|
||||
</modifications>
|
||||
<sampledescription><![CDATA[ ]]></sampledescription></sample>
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Connecting to database</title>
|
||||
<script src="../dhtmlx/dhtmlx.js" type="text/javascript"></script>
|
||||
<script src="../dhtmlx/dhtmlxdataprocessor.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="../../codebase/connector.js" type="text/javascript" charset="utf-8"></script>
|
||||
<link rel="STYLESHEET" type="text/css" href="../dhtmlx/dhtmlx.css">
|
||||
<style type="text/css" media="screen">
|
||||
body { background-color:#EBEBEB; };
|
||||
</style>
|
||||
<body>
|
||||
<h1>Connecting to database</h1>
|
||||
|
||||
<form style="float:right;">
|
||||
Product <input type="text" id="p_name" value="dhtmlxDataView"><br>
|
||||
Version <input type="text" id="v_name" value="3.0"><br>
|
||||
Maintainer <input type="text" id="m_name" value="Ivan"><br>
|
||||
<input type="button" value="Add →" onclick='add_data()'>
|
||||
<hr>
|
||||
<input type="button" value="Remove selected →" onclick='remove_data()'>
|
||||
</form>
|
||||
|
||||
<div id="data_container" style="border:1px solid #A4BED4; background-color:white;width:596px;height:396px;"></div>
|
||||
<script>
|
||||
data = new dhtmlXDataView({
|
||||
|
||||
container:"data_container",
|
||||
edit:true,
|
||||
type:{
|
||||
template:"{obj.Package} : {obj.Version}<br/>{obj.Maintainer}",
|
||||
template_edit:"<input class='dhx_item_editor' bind='obj.Package'>",
|
||||
height:40
|
||||
}
|
||||
});
|
||||
data.load("03_adding.php");
|
||||
|
||||
var dp = new dataProcessor("03_adding.php");
|
||||
dp.init(data);
|
||||
|
||||
function add_data(argument) {
|
||||
data.add({
|
||||
Package: document.getElementById("p_name").value,
|
||||
Version: document.getElementById("v_name").value,
|
||||
Maintainer: document.getElementById("m_name").value,
|
||||
},0)
|
||||
}
|
||||
function remove_data(){
|
||||
data.remove(data.getSelected());
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
10
themes/connector/samples/dataview/03_adding.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once("../../codebase/dataview_connector.php");
|
||||
require_once("../config.php");
|
||||
|
||||
$conn = mysql_connect($mysql_server,$mysql_user,$mysql_pass);
|
||||
mysql_select_db($mysql_db);
|
||||
|
||||
$data = new DataViewConnector($conn);
|
||||
$data->render_table("packages_small","Id","Package,Version,Maintainer");
|
||||
?>
|
||||
25
themes/connector/samples/dataview/index.html
Normal file
@ -0,0 +1,25 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<style type="text/css" media="screen">
|
||||
*{
|
||||
font-family:Tahoma;
|
||||
}
|
||||
div,li{
|
||||
font-size:10pt;
|
||||
}
|
||||
div{
|
||||
padding-bottom:20px;
|
||||
}
|
||||
li{
|
||||
padding-left:50px;
|
||||
padding-bottom:10px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h2>dhtmlxConnector for PHP :: Samples</h2>
|
||||
<li><a href="01_static_loading.html">Static loading</a></li>
|
||||
<li><a href="02_dynamic_loading.html">Dynamic loading</a></li>
|
||||
<li><a href="03_adding.html">Adding</a></li>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
1
themes/connector/samples/dhtmlx/dhtmlx.css
Normal file
1896
themes/connector/samples/dhtmlx/dhtmlx.js
Normal file
32
themes/connector/samples/dhtmlx/dhtmlxdataprocessor.js
Normal file
@ -0,0 +1,32 @@
|
||||
//v.3.0 build 110704
|
||||
|
||||
/*
|
||||
Copyright Dinamenta, UAB http://www.dhtmlx.com
|
||||
You allowed to use this component or parts of it under GPL terms
|
||||
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
|
||||
*/
|
||||
function dataProcessor(a){this.serverProcessor=a;this.action_param="!nativeeditor_status";this.object=null;this.updatedRows=[];this.autoUpdate=!0;this.updateMode="cell";this._tMode="GET";this.post_delim="_";this._waitMode=0;this._in_progress={};this._invalid={};this.mandatoryFields=[];this.messages=[];this.styles={updated:"font-weight:bold;",inserted:"font-weight:bold;",deleted:"text-decoration : line-through;",invalid:"background-color:FFE0E0;",invalid_cell:"border-bottom:2px solid red;",clear:"font-weight:normal;text-decoration:none;"};
|
||||
this.enableUTFencoding(!0);dhtmlxEventable(this);return this}
|
||||
dataProcessor.prototype={setTransactionMode:function(a,b){this._tMode=a;this._tSend=b},escape:function(a){return this._utf?encodeURIComponent(a):escape(a)},enableUTFencoding:function(a){this._utf=convertStringToBoolean(a)},setDataColumns:function(a){this._columns=typeof a=="string"?a.split(","):a},getSyncState:function(){return!this.updatedRows.length},enableDataNames:function(a){this._endnm=convertStringToBoolean(a)},enablePartialDataSend:function(a){this._changed=convertStringToBoolean(a)},setUpdateMode:function(a,
|
||||
b){this.autoUpdate=a=="cell";this.updateMode=a;this.dnd=b},ignore:function(a,b){this._silent_mode=!0;a.call(b||window);this._silent_mode=!1},setUpdated:function(a,b,c){if(!this._silent_mode){var d=this.findRow(a),c=c||"updated",e=this.obj.getUserData(a,this.action_param);e&&c=="updated"&&(c=e);b?(this.set_invalid(a,!1),this.updatedRows[d]=a,this.obj.setUserData(a,this.action_param,c),this._in_progress[a]&&(this._in_progress[a]="wait")):this.is_invalid(a)||(this.updatedRows.splice(d,1),this.obj.setUserData(a,
|
||||
this.action_param,""));b||this._clearUpdateFlag(a);this.markRow(a,b,c);b&&this.autoUpdate&&this.sendData(a)}},_clearUpdateFlag:function(){},markRow:function(a,b,c){var d="",e=this.is_invalid(a);e&&(d=this.styles[e],b=!0);if(this.callEvent("onRowMark",[a,b,c,e])&&(d=this.styles[b?c:"clear"]+d,this.obj[this._methods[0]](a,d),e&&e.details)){d+=this.styles[e+"_cell"];for(var f=0;f<e.details.length;f++)if(e.details[f])this.obj[this._methods[1]](a,f,d)}},getState:function(a){return this.obj.getUserData(a,
|
||||
this.action_param)},is_invalid:function(a){return this._invalid[a]},set_invalid:function(a,b,c){c&&(b={value:b,details:c,toString:function(){return this.value.toString()}});this._invalid[a]=b},checkBeforeUpdate:function(){return!0},sendData:function(a){if(!this._waitMode||!(this.obj.mytype=="tree"||this.obj._h2)){this.obj.editStop&&this.obj.editStop();if(typeof a=="undefined"||this._tSend)return this.sendAllData();if(this._in_progress[a])return!1;this.messages=[];if(!this.checkBeforeUpdate(a)&&this.callEvent("onValidationError",
|
||||
[a,this.messages]))return!1;this._beforeSendData(this._getRowData(a),a)}},_beforeSendData:function(a,b){if(!this.callEvent("onBeforeUpdate",[b,this.getState(b),a]))return!1;this._sendData(a,b)},serialize:function(a,b){if(typeof a=="string")return a;if(typeof b!="undefined")return this.serialize_one(a,"");else{var c=[],d=[],e;for(e in a)a.hasOwnProperty(e)&&(c.push(this.serialize_one(a[e],e+this.post_delim)),d.push(e));c.push("ids="+this.escape(d.join(",")));return c.join("&")}},serialize_one:function(a,
|
||||
b){if(typeof a=="string")return a;var c=[],d;for(d in a)a.hasOwnProperty(d)&&c.push(this.escape((b||"")+d)+"="+this.escape(a[d]));return c.join("&")},_sendData:function(a,b){if(a){if(!this.callEvent("onBeforeDataSending",b?[b,this.getState(b),a]:[null,null,a]))return!1;b&&(this._in_progress[b]=(new Date).valueOf());var c=new dtmlXMLLoaderObject(this.afterUpdate,this,!0),d=this.serverProcessor+(this._user?getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+this.obj.getUserData(0,
|
||||
"version")].join("&"):"");this._tMode!="POST"?c.loadXML(d+(d.indexOf("?")!=-1?"&":"?")+this.serialize(a,b)):c.loadXML(d,!0,this.serialize(a,b));this._waitMode++}},sendAllData:function(){if(this.updatedRows.length){this.messages=[];for(var a=!0,b=0;b<this.updatedRows.length;b++)a&=this.checkBeforeUpdate(this.updatedRows[b]);if(!a&&!this.callEvent("onValidationError",["",this.messages]))return!1;if(this._tSend)this._sendData(this._getAllData());else for(b=0;b<this.updatedRows.length;b++)if(!this._in_progress[this.updatedRows[b]]&&
|
||||
!this.is_invalid(this.updatedRows[b])&&(this._beforeSendData(this._getRowData(this.updatedRows[b]),this.updatedRows[b]),this._waitMode&&(this.obj.mytype=="tree"||this.obj._h2)))break}},_getAllData:function(){for(var a={},b=!1,c=0;c<this.updatedRows.length;c++){var d=this.updatedRows[c];!this._in_progress[d]&&!this.is_invalid(d)&&this.callEvent("onBeforeUpdate",[d,this.getState(d)])&&(a[d]=this._getRowData(d,d+this.post_delim),b=!0,this._in_progress[d]=(new Date).valueOf())}return b?a:null},setVerificator:function(a,
|
||||
b){this.mandatoryFields[a]=b||function(a){return a!=""}},clearVerificator:function(a){this.mandatoryFields[a]=!1},findRow:function(a){for(var b=0,b=0;b<this.updatedRows.length;b++)if(a==this.updatedRows[b])break;return b},defineAction:function(a,b){if(!this._uActions)this._uActions=[];this._uActions[a]=b},afterUpdateCallback:function(a,b,c,d){var e=a,f=c!="error"&&c!="invalid";f||this.set_invalid(a,c);if(this._uActions&&this._uActions[c]&&!this._uActions[c](d))return delete this._in_progress[e];this._in_progress[e]!=
|
||||
"wait"&&this.setUpdated(a,!1);var g=a;switch(c){case "inserted":case "insert":b!=a&&(this.obj[this._methods[2]](a,b),a=b);break;case "delete":case "deleted":return this.obj.setUserData(a,this.action_param,"true_deleted"),this.obj[this._methods[3]](a),delete this._in_progress[e],this.callEvent("onAfterUpdate",[a,c,b,d])}this._in_progress[e]!="wait"?(f&&this.obj.setUserData(a,this.action_param,""),delete this._in_progress[e]):(delete this._in_progress[e],this.setUpdated(b,!0,this.obj.getUserData(a,
|
||||
this.action_param)));this.callEvent("onAfterUpdate",[a,c,b,d])},afterUpdate:function(a,b,c,d,e){e.getXMLTopNode("data");if(e.xmlDoc.responseXML){for(var f=e.doXPath("//data/action"),g=0;g<f.length;g++){var h=f[g],i=h.getAttribute("type"),j=h.getAttribute("sid"),k=h.getAttribute("tid");a.afterUpdateCallback(j,k,i,h)}a.finalizeUpdate()}},finalizeUpdate:function(){this._waitMode&&this._waitMode--;(this.obj.mytype=="tree"||this.obj._h2)&&this.updatedRows.length&&this.sendData();this.callEvent("onAfterUpdateFinish",
|
||||
[]);this.updatedRows.length||this.callEvent("onFullSync",[])},init:function(a){this.obj=a;this.obj._dp_init&&this.obj._dp_init(this)},setOnAfterUpdate:function(a){this.attachEvent("onAfterUpdate",a)},enableDebug:function(){},setOnBeforeUpdateHandler:function(a){this.attachEvent("onBeforeDataSending",a)},setAutoUpdate:function(a,b){a=a||2E3;this._user=b||(new Date).valueOf();this._need_update=!1;this._loader=null;this._update_busy=!1;this.attachEvent("onAfterUpdate",function(a,b,c,g){this.afterAutoUpdate(a,
|
||||
b,c,g)});this.attachEvent("onFullSync",function(){this.fullSync()});var c=this;window.setInterval(function(){c.loadUpdate()},a)},afterAutoUpdate:function(a,b){return b=="collision"?(this._need_update=!0,!1):!0},fullSync:function(){if(this._need_update==!0)this._need_update=!1,this.loadUpdate();return!0},getUpdates:function(a,b){if(this._update_busy)return!1;else this._update_busy=!0;this._loader=this._loader||new dtmlXMLLoaderObject(!0);this._loader.async=!0;this._loader.waitCall=b;this._loader.loadXML(a)},
|
||||
_v:function(a){return a.firstChild?a.firstChild.nodeValue:""},_a:function(a){for(var b=[],c=0;c<a.length;c++)b[c]=this._v(a[c]);return b},loadUpdate:function(){var a=this,b=this.obj.getUserData(0,"version"),c=this.serverProcessor+getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+b].join("&"),c=c.replace("editing=true&","");this.getUpdates(c,function(){var b=a._loader.doXPath("//userdata");a.obj.setUserData(0,"version",a._v(b[0]));var c=a._loader.doXPath("//update");if(c.length){a._silent_mode=
|
||||
!0;for(var f=0;f<c.length;f++){var g=c[f].getAttribute("status"),h=c[f].getAttribute("id"),i=c[f].getAttribute("parent");switch(g){case "inserted":a.callEvent("insertCallback",[c[f],h,i]);break;case "updated":a.callEvent("updateCallback",[c[f],h,i]);break;case "deleted":a.callEvent("deleteCallback",[c[f],h,i])}}a._silent_mode=!1}a._update_busy=!1;a=null})}};
|
||||
|
||||
//v.3.0 build 110704
|
||||
|
||||
/*
|
||||
Copyright Dinamenta, UAB http://www.dhtmlx.com
|
||||
You allowed to use this component or parts of it under GPL terms
|
||||
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
|
||||
*/
|
||||
1
themes/connector/samples/dhtmlx/dhtmlxscheduler.css
Normal file
31
themes/connector/samples/dhtmlx/dhtmlxscheduler.js
Normal file
31
themes/connector/samples/dhtmlx/dhtmlxscheduler_recurring.js
Normal file
@ -0,0 +1,31 @@
|
||||
scheduler.form_blocks.recurring={render:function(){return scheduler.__recurring_template},_ds:{},_init_set_value:function(a,b,c){function d(a){for(var b=0;b<a.length;b++){var c=a[b];c.type=="checkbox"||c.type=="radio"?(g[c.name]||(g[c.name]=[]),g[c.name].push(c)):g[c.name]=c}}function f(a){for(var b=g[a],c=0;c<b.length;c++)if(b[c].checked)return b[c].value}function e(){m("dhx_repeat_day").style.display="none";m("dhx_repeat_week").style.display="none";m("dhx_repeat_month").style.display="none";m("dhx_repeat_year").style.display=
|
||||
"none";m("dhx_repeat_"+this.value).style.display="block"}function h(a){var b=[f("repeat")];for(p[b[0]](b,a);b.length<5;)b.push("");var c="";if(g.end[0].checked)a.end=new Date(9999,1,1),c="no";else if(g.end[2].checked)a.end=i(g.date_of_end.value);else{scheduler.transpose_type(b.join("_"));var c=Math.max(1,g.occurences_count.value),e=b[0]=="week"&&b[4]&&b[4].toString().indexOf(scheduler.config.start_on_monday?1:0)==-1?1:0;a.end=scheduler.date.add(new Date(a.start),c+e,b.join("_"))}return b.join("_")+
|
||||
"#"+c}function j(a,b){var c=a.split("#"),a=c[0].split("_");q[a[0]](a,b);var e=g.repeat[{day:0,week:1,month:2,year:3}[a[0]]];switch(c[1]){case "no":g.end[0].checked=!0;break;case "":g.end[2].checked=!0;g.date_of_end.value=k(b.end);break;default:g.end[1].checked=!0,g.occurences_count.value=c[1]}e.checked=!0;e.onclick()}scheduler.form_blocks.recurring._ds={start:c.start_date,end:c._end_date};var i=scheduler.date.str_to_date(scheduler.config.repeat_date),k=scheduler.date.date_to_str(scheduler.config.repeat_date),
|
||||
l=a.getElementsByTagName("FORM")[0],g=[];d(l.getElementsByTagName("INPUT"));d(l.getElementsByTagName("SELECT"));var m=function(a){return document.getElementById(a)};scheduler.form_blocks.recurring._get_repeat_code=h;var p={month:function(a,b){f("month_type")=="d"?(a.push(Math.max(1,g.month_count.value)),b.start.setDate(g.month_day.value)):(a.push(Math.max(1,g.month_count2.value)),a.push(g.month_day2.value),a.push(Math.max(1,g.month_week2.value)),b.start.setDate(1));b._start=!0},week:function(a,b){a.push(Math.max(1,
|
||||
g.week_count.value));a.push("");a.push("");for(var c=[],e=g.week_day,d=0;d<e.length;d++)e[d].checked&&c.push(e[d].value);c.length||c.push(b.start.getDay());b.start=scheduler.date.week_start(b.start);b._start=!0;a.push(c.sort().join(","))},day:function(a){f("day_type")=="d"?a.push(Math.max(1,g.day_count.value)):(a.push("week"),a.push(1),a.push(""),a.push(""),a.push("1,2,3,4,5"),a.splice(0,1))},year:function(a,b){f("year_type")=="d"?(a.push("1"),b.start.setMonth(0),b.start.setDate(g.year_day.value),
|
||||
b.start.setMonth(g.year_month.value)):(a.push("1"),a.push(g.year_day2.value),a.push(g.year_week2.value),b.start.setDate(1),b.start.setMonth(g.year_month2.value));b._start=!0}},q={week:function(a){g.week_count.value=a[1];for(var b=g.week_day,c=a[4].split(","),e={},d=0;d<c.length;d++)e[c[d]]=!0;for(d=0;d<b.length;d++)b[d].checked=!!e[b[d].value]},month:function(a,b){a[2]==""?(g.month_type[0].checked=!0,g.month_count.value=a[1],g.month_day.value=b.start.getDate()):(g.month_type[1].checked=!0,g.month_count2.value=
|
||||
a[1],g.month_week2.value=a[3],g.month_day2.value=a[2])},day:function(a){g.day_type[0].checked=!0;g.day_count.value=a[1]},year:function(a,b){a[2]==""?(g.year_type[0].checked=!0,g.year_day.value=b.start.getDate(),g.year_month.value=b.start.getMonth()):(g.year_type[1].checked=!0,g.year_week2.value=a[3],g.year_day2.value=a[2],g.year_month2.value=b.start.getMonth())}};scheduler.form_blocks.recurring._set_repeat_code=j;for(var n=0;n<l.elements.length;n++){var o=l.elements[n];switch(o.name){case "repeat":o.onclick=
|
||||
e}}scheduler._lightbox._rec_init_done=!0},set_value:function(a,b,c){var d=scheduler.form_blocks.recurring;scheduler._lightbox._rec_init_done||d._init_set_value(a,b,c);a.open=!c.rec_type;a.blocked=c.event_pid&&c.event_pid!="0"?!0:!1;var f=d._ds;f.start=c.start_date;f.end=c._end_date;d.button_click(0,a.previousSibling.firstChild.firstChild,a,a);b&&d._set_repeat_code(b,f)},get_value:function(a,b){if(a.open){var c=scheduler.form_blocks.recurring._ds;b.rec_type=scheduler.form_blocks.recurring._get_repeat_code(c);
|
||||
c._start?(b.start_date=new Date(c.start),b._start_date=new Date(c.start),c._start=!1):b._start_date=null;b._end_date=b.end_date=c.end;b.rec_pattern=b.rec_type.split("#")[0]}else b.rec_type=b.rec_pattern="",b._end_date=b.end_date;return b.rec_type},focus:function(){},button_click:function(a,b,c,d){!d.open&&!d.blocked?(d.style.height="115px",b.style.backgroundPosition="-5px 0px",b.nextSibling.innerHTML=scheduler.locale.labels.button_recurring_open):(d.style.height="0px",b.style.backgroundPosition="-5px 20px",
|
||||
b.nextSibling.innerHTML=scheduler.locale.labels.button_recurring);d.open=!d.open;scheduler.setLightboxSize()}};scheduler._rec_markers={};scheduler._rec_markers_pull={};scheduler._add_rec_marker=function(a,b){a._pid_time=b;this._rec_markers[a.id]=a;this._rec_markers_pull[a.event_pid]||(this._rec_markers_pull[a.event_pid]={});this._rec_markers_pull[a.event_pid][b]=a};scheduler._get_rec_marker=function(a,b){var c=this._rec_markers_pull[b];return c?c[a]:null};
|
||||
scheduler._get_rec_markers=function(a){return this._rec_markers_pull[a]||[]};scheduler._rec_temp=[];scheduler.attachEvent("onEventLoading",function(a){a.event_pid!=0&&scheduler._add_rec_marker(a,a.event_length*1E3);if(a.rec_type)a.rec_pattern=a.rec_type.split("#")[0];return!0});
|
||||
scheduler.attachEvent("onEventIdChange",function(a,b){if(!this._ignore_call){this._ignore_call=!0;for(var c=0;c<this._rec_temp.length;c++){var d=this._rec_temp[c];if(d.event_pid==a)d.event_pid=b,this.changeEventId(d.id,b+"#"+d.id.split("#")[1])}delete this._ignore_call}});
|
||||
scheduler.attachEvent("onBeforeEventDelete",function(a){var b=this.getEvent(a);if(a.toString().indexOf("#")!=-1||b.event_pid&&b.event_pid!="0"&&b.rec_type!="none"){var a=a.split("#"),c=this.uid(),d=a[1]?a[1]:b._pid_time/1E3,f=this._copy_event(b);f.id=c;f.event_pid=b.event_pid||a[0];f.event_length=d;f.rec_type=f.rec_pattern="none";this.addEvent(f);this._add_rec_marker(f,d*1E3)}else{b.rec_type&&this._roll_back_dates(b);var e=this._get_rec_markers(a),h;for(h in e)e.hasOwnProperty(h)&&this.deleteEvent(e[h].id,
|
||||
!0)}return!0});
|
||||
scheduler.attachEvent("onEventChanged",function(a){if(this._loading)return!0;var b=this.getEvent(a);if(a.toString().indexOf("#")!=-1){var a=a.split("#"),c=this.uid();this._not_render=!0;var d=this._copy_event(b);d.id=c;d.event_pid=a[0];d.event_length=a[1];d.rec_type=d.rec_pattern="";this.addEvent(d);this._not_render=!1;this._add_rec_marker(d,a[1]*1E3)}else{b.rec_type&&this._roll_back_dates(b);var f=this._get_rec_markers(a),e;for(e in f)f.hasOwnProperty(e)&&(delete this._rec_markers[f[e].id],this.deleteEvent(f[e].id,
|
||||
!0));delete this._rec_markers_pull[a];for(var h=!1,j=0;j<this._rendered.length;j++)this._rendered[j].getAttribute("event_id")==a&&(h=!0);if(!h)this._select_id=null}return!0});scheduler.attachEvent("onEventAdded",function(a){if(!this._loading){var b=this.getEvent(a);b.rec_type&&!b.event_length&&this._roll_back_dates(b)}return!0});scheduler.attachEvent("onEventSave",function(a,b){var c=this.getEvent(a);if(!c.rec_type&&b.rec_type&&(a+"").indexOf("#")==-1)this._select_id=null;return!0});
|
||||
scheduler.attachEvent("onEventCreated",function(a){var b=this.getEvent(a);if(!b.rec_type)b.rec_type=b.rec_pattern=b.event_length=b.event_pid="";return!0});scheduler.attachEvent("onEventCancel",function(a){var b=this.getEvent(a);b.rec_type&&(this._roll_back_dates(b),this.render_view_data())});
|
||||
scheduler._roll_back_dates=function(a){a.event_length=(a.end_date.valueOf()-a.start_date.valueOf())/1E3;a.end_date=a._end_date;a._start_date&&(a.start_date.setMonth(0),a.start_date.setDate(a._start_date.getDate()),a.start_date.setMonth(a._start_date.getMonth()),a.start_date.setFullYear(a._start_date.getFullYear()))};scheduler.validId=function(a){return a.toString().indexOf("#")==-1};scheduler.showLightbox_rec=scheduler.showLightbox;
|
||||
scheduler.showLightbox=function(a){var b=this.getEvent(a).event_pid;a.toString().indexOf("#")!=-1&&(b=a.split("#")[0]);if(!b||b==0||!this.locale.labels.confirm_recurring||!confirm(this.locale.labels.confirm_recurring))return this.showLightbox_rec(a);b=this.getEvent(b);b._end_date=b.end_date;b.end_date=new Date(b.start_date.valueOf()+b.event_length*1E3);return this.showLightbox_rec(b.id)};scheduler.get_visible_events_rec=scheduler.get_visible_events;
|
||||
scheduler.get_visible_events=function(){for(var a=0;a<this._rec_temp.length;a++)delete this._events[this._rec_temp[a].id];this._rec_temp=[];for(var b=this.get_visible_events_rec(),c=[],a=0;a<b.length;a++)b[a].rec_type?b[a].rec_pattern!="none"&&this.repeat_date(b[a],c):c.push(b[a]);return c};(function(){var a=scheduler.is_one_day_event;scheduler.is_one_day_event=function(b){return b.rec_type?!0:a.call(this,b)}})();scheduler.transponse_size={day:1,week:7,month:1,year:12};
|
||||
scheduler.date.day_week=function(a,b,c){a.setDate(1);var c=(c-1)*7,d=a.getDay(),f=b*1+c-d+1;a.setDate(f<=c?f+7:f)};scheduler.transpose_day_week=function(a,b,c,d,f){for(var e=(a.getDay()||(scheduler.config.start_on_monday?7:0))-c,h=0;h<b.length;h++)if(b[h]>e)return a.setDate(a.getDate()+b[h]*1-e-(d?c:f));this.transpose_day_week(a,b,c+d,null,c)};
|
||||
scheduler.transpose_type=function(a){var b="transpose_"+a;if(!this.date[b]){var c=a.split("_"),d=864E5,f="add_"+a,e=this.transponse_size[c[0]]*c[1];if(c[0]=="day"||c[0]=="week"){var h=null;if(c[4]&&(h=c[4].split(","),scheduler.config.start_on_monday)){for(var j=0;j<h.length;j++)h[j]=h[j]*1||7;h.sort()}this.date[b]=function(a,b){var c=Math.floor((b.valueOf()-a.valueOf())/(d*e));c>0&&a.setDate(a.getDate()+c*e);h&&scheduler.transpose_day_week(a,h,1,e)};this.date[f]=function(a,b){var c=new Date(a.valueOf());
|
||||
if(h)for(var d=0;d<b;d++)scheduler.transpose_day_week(c,h,0,e);else c.setDate(c.getDate()+b*e);return c}}else if(c[0]=="month"||c[0]=="year")this.date[b]=function(a,b){var d=Math.ceil((b.getFullYear()*12+b.getMonth()*1-(a.getFullYear()*12+a.getMonth()*1))/e);d>=0&&a.setMonth(a.getMonth()+d*e);c[3]&&scheduler.date.day_week(a,c[2],c[3])},this.date[f]=function(a,b){var d=new Date(a.valueOf());d.setMonth(d.getMonth()+b*e);c[3]&&scheduler.date.day_week(d,c[2],c[3]);return d}}};
|
||||
scheduler.repeat_date=function(a,b,c,d,f){var d=d||this._min_date,f=f||this._max_date,e=new Date(a.start_date.valueOf());if(!a.rec_pattern&&a.rec_type)a.rec_pattern=a.rec_type.split("#")[0];this.transpose_type(a.rec_pattern);for(scheduler.date["transpose_"+a.rec_pattern](e,d);e<a.start_date||e.valueOf()+a.event_length*1E3<=d.valueOf();)e=this.date.add(e,1,a.rec_pattern);for(;e<f&&e<a.end_date;){var h=this._get_rec_marker(e.valueOf(),a.id);if(h)c&&b.push(h);else{var j=new Date(e.valueOf()+a.event_length*
|
||||
1E3),i=this._copy_event(a);i.text=a.text;i.start_date=e;i.event_pid=a.id;i.id=a.id+"#"+Math.ceil(e.valueOf()/1E3);i.end_date=j;var k=i.start_date.getTimezoneOffset()-i.end_date.getTimezoneOffset();if(k)i.end_date=k>0?new Date(e.valueOf()+a.event_length*1E3-k*6E4):new Date(i.end_date.valueOf()+k*6E4);i._timed=this.is_one_day_event(i);if(!i._timed&&!this._table_view&&!this.config.multi_day)break;b.push(i);c||(this._events[i.id]=i,this._rec_temp.push(i))}e=this.date.add(e,1,a.rec_pattern)}};
|
||||
scheduler.getRecDates=function(a,b){var c=typeof a=="object"?a:scheduler.getEvent(a),d=0,f=[],b=b||1E3,e=new Date(c.start_date.valueOf()),h=new Date(e.valueOf());if(!c.rec_type)return[{start_date:c.start_date,end_date:c.end_date}];this.transpose_type(c.rec_pattern);for(scheduler.date["transpose_"+c.rec_pattern](e,h);e<c.start_date||e.valueOf()+c.event_length*1E3<=h.valueOf();)e=this.date.add(e,1,c.rec_pattern);for(;e<c.end_date;){var j=this._get_rec_marker(e.valueOf(),c.id),i=!0;if(j)j.rec_type==
|
||||
"none"?i=!1:f.push({start_date:j.start_date,end_date:j.end_date});else{var k=new Date(e.valueOf()+c.event_length*1E3),l=new Date(e);f.push({start_date:l,end_date:k})}e=this.date.add(e,1,c.rec_pattern);if(i&&(d++,d==b))break}return f};
|
||||
scheduler.getEvents=function(a,b){var c=[],d;for(d in this._events){var f=this._events[d];if(f&&f.start_date<b&&f.end_date>a)if(f.rec_pattern){if(f.rec_pattern!="none"){var e=[];this.repeat_date(f,e,!0,a,b);for(var h=0;h<e.length;h++)!e[h].rec_pattern&&e[h].start_date<b&&e[h].end_date>a&&!this._rec_markers[e[h].id]&&c.push(e[h])}}else f.id.toString().indexOf("#")==-1&&c.push(f)}return c};scheduler.config.repeat_date="%m.%d.%Y";
|
||||
scheduler.config.lightbox.sections=[{name:"description",height:130,map_to:"text",type:"textarea",focus:!0},{name:"recurring",type:"recurring",map_to:"rec_type",button:"recurring"},{name:"time",height:72,type:"time",map_to:"auto"}];scheduler._copy_dummy=function(){this.start_date=new Date(this.start_date);this.end_date=new Date(this.end_date);this.event_length=this.event_pid=this.rec_pattern=this.rec_type=this._timed=null};
|
||||
scheduler.__recurring_template='<div class="dhx_form_repeat"> <form> <div class="dhx_repeat_left"> <label><input class="dhx_repeat_radio" type="radio" name="repeat" value="day" />Daily</label><br /> <label><input class="dhx_repeat_radio" type="radio" name="repeat" value="week"/>Weekly</label><br /> <label><input class="dhx_repeat_radio" type="radio" name="repeat" value="month" checked />Monthly</label><br /> <label><input class="dhx_repeat_radio" type="radio" name="repeat" value="year" />Yearly</label> </div> <div class="dhx_repeat_divider"></div> <div class="dhx_repeat_center"> <div style="display:none;" id="dhx_repeat_day"> <label><input class="dhx_repeat_radio" type="radio" name="day_type" value="d"/>Every</label><input class="dhx_repeat_text" type="text" name="day_count" value="1" />day<br /> <label><input class="dhx_repeat_radio" type="radio" name="day_type" checked value="w"/>Every workday</label> </div> <div style="display:none;" id="dhx_repeat_week"> Repeat every<input class="dhx_repeat_text" type="text" name="week_count" value="1" />week next days:<br /> <table class="dhx_repeat_days"> <tr> <td> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="1" />Monday</label><br /> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="4" />Thursday</label> </td> <td> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="2" />Tuesday</label><br /> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="5" />Friday</label> </td> <td> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="3" />Wednesday</label><br /> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="6" />Saturday</label> </td> <td> <label><input class="dhx_repeat_checkbox" type="checkbox" name="week_day" value="0" />Sunday</label><br /><br /> </td> </tr> </table> </div> <div id="dhx_repeat_month"> <label><input class="dhx_repeat_radio" type="radio" name="month_type" value="d"/>Repeat</label><input class="dhx_repeat_text" type="text" name="month_day" value="1" />day every<input class="dhx_repeat_text" type="text" name="month_count" value="1" />month<br /> <label><input class="dhx_repeat_radio" type="radio" name="month_type" checked value="w"/>On</label><input class="dhx_repeat_text" type="text" name="month_week2" value="1" /><select name="month_day2"><option value="1" selected >Monday<option value="2">Tuesday<option value="3">Wednesday<option value="4">Thursday<option value="5">Friday<option value="6">Saturday<option value="0">Sunday</select>every<input class="dhx_repeat_text" type="text" name="month_count2" value="1" />month<br /> </div> <div style="display:none;" id="dhx_repeat_year"> <label><input class="dhx_repeat_radio" type="radio" name="year_type" value="d"/>Every</label><input class="dhx_repeat_text" type="text" name="year_day" value="1" />day<select name="year_month"><option value="0" selected >January<option value="1">February<option value="2">March<option value="3">April<option value="4">May<option value="5">June<option value="6">July<option value="7">August<option value="8">September<option value="9">October<option value="10">November<option value="11">December</select>month<br /> <label><input class="dhx_repeat_radio" type="radio" name="year_type" checked value="w"/>On</label><input class="dhx_repeat_text" type="text" name="year_week2" value="1" /><select name="year_day2"><option value="1" selected >Monday<option value="2">Tuesday<option value="3">Wednesday<option value="4">Thursday<option value="5">Friday<option value="6">Saturday<option value="7">Sunday</select>of<select name="year_month2"><option value="0" selected >January<option value="1">February<option value="2">March<option value="3">April<option value="4">May<option value="5">June<option value="6">July<option value="7">August<option value="8">September<option value="9">October<option value="10">November<option value="11">December</select><br /> </div> </div> <div class="dhx_repeat_divider"></div> <div class="dhx_repeat_right"> <label><input class="dhx_repeat_radio" type="radio" name="end" checked/>No end date</label><br /> <label><input class="dhx_repeat_radio" type="radio" name="end" />After</label><input class="dhx_repeat_text" type="text" name="occurences_count" value="1" />occurrences<br /> <label><input class="dhx_repeat_radio" type="radio" name="end" />End by</label><input class="dhx_repeat_date" type="text" name="date_of_end" value="'+scheduler.config.repeat_date_of_end+
|
||||
'" /><br /> </div> </form> </div> <div style="clear:both"> </div>';
|
||||
BIN
themes/connector/samples/dhtmlx/imgs/arrow.gif
Normal file
|
After Width: | Height: | Size: 827 B |
BIN
themes/connector/samples/dhtmlx/imgs/bg_selection.gif
Normal file
|
After Width: | Height: | Size: 264 B |
BIN
themes/connector/samples/dhtmlx/imgs/blanc.gif
Normal file
|
After Width: | Height: | Size: 56 B |
BIN
themes/connector/samples/dhtmlx/imgs/blank.gif
Normal file
|
After Width: | Height: | Size: 56 B |
1
themes/connector/samples/dhtmlx/imgs/blank.html
Normal file
@ -0,0 +1 @@
|
||||
|
||||
BIN
themes/connector/samples/dhtmlx/imgs/but_repeat.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
themes/connector/samples/dhtmlx/imgs/buttons.png
Normal file
|
After Width: | Height: | Size: 281 B |
BIN
themes/connector/samples/dhtmlx/imgs/calendar.gif
Normal file
|
After Width: | Height: | Size: 622 B |
BIN
themes/connector/samples/dhtmlx/imgs/clock_big.gif
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
themes/connector/samples/dhtmlx/imgs/clock_small.gif
Normal file
|
After Width: | Height: | Size: 388 B |
BIN
themes/connector/samples/dhtmlx/imgs/colapce-expand-icon.gif
Normal file
|
After Width: | Height: | Size: 452 B |
|
After Width: | Height: | Size: 411 B |
BIN
themes/connector/samples/dhtmlx/imgs/controls.gif
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
themes/connector/samples/dhtmlx/imgs/databg.png
Normal file
|
After Width: | Height: | Size: 152 B |
BIN
themes/connector/samples/dhtmlx/imgs/databg_now.png
Normal file
|
After Width: | Height: | Size: 152 B |
BIN
themes/connector/samples/dhtmlx/imgs/dataview/bottom.png
Normal file
|
After Width: | Height: | Size: 851 B |
BIN
themes/connector/samples/dhtmlx/imgs/dataview/dnd_selector.png
Normal file
|
After Width: | Height: | Size: 121 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 206 B |
BIN
themes/connector/samples/dhtmlx/imgs/dataview/marker.png
Normal file
|
After Width: | Height: | Size: 921 B |
BIN
themes/connector/samples/dhtmlx/imgs/dataview/selection_bg.png
Normal file
|
After Width: | Height: | Size: 921 B |
BIN
themes/connector/samples/dhtmlx/imgs/dataview/sky_blue_grid.gif
Normal file
|
After Width: | Height: | Size: 554 B |
BIN
themes/connector/samples/dhtmlx/imgs/dyn_down.gif
Normal file
|
After Width: | Height: | Size: 189 B |
BIN
themes/connector/samples/dhtmlx/imgs/dyn_up.gif
Normal file
|
After Width: | Height: | Size: 184 B |
BIN
themes/connector/samples/dhtmlx/imgs/folder.gif
Normal file
|
After Width: | Height: | Size: 374 B |
BIN
themes/connector/samples/dhtmlx/imgs/folderClosed.gif
Normal file
|
After Width: | Height: | Size: 135 B |
BIN
themes/connector/samples/dhtmlx/imgs/folderOpen.gif
Normal file
|
After Width: | Height: | Size: 139 B |
BIN
themes/connector/samples/dhtmlx/imgs/icon.png
Normal file
|
After Width: | Height: | Size: 230 B |
BIN
themes/connector/samples/dhtmlx/imgs/iconCheckAll.gif
Normal file
|
After Width: | Height: | Size: 123 B |
BIN
themes/connector/samples/dhtmlx/imgs/iconCheckDis.gif
Normal file
|
After Width: | Height: | Size: 126 B |
BIN
themes/connector/samples/dhtmlx/imgs/iconCheckGray.gif
Normal file
|
After Width: | Height: | Size: 126 B |
BIN
themes/connector/samples/dhtmlx/imgs/iconUncheckAll.gif
Normal file
|
After Width: | Height: | Size: 111 B |
BIN
themes/connector/samples/dhtmlx/imgs/iconUncheckDis.gif
Normal file
|
After Width: | Height: | Size: 117 B |