Moving dhtmlxGantt library to 'libraries' folder
This commit is contained in:
parent
dbcdde741c
commit
5e16eb66dd
162 changed files with 6 additions and 5 deletions
948
libraries/dhtmlxgantt/connector/base_connector.php
Normal file
948
libraries/dhtmlxgantt/connector/base_connector.php
Normal file
|
@ -0,0 +1,948 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("tools.php");
|
||||
require_once("db_common.php");
|
||||
require_once("dataprocessor.php");
|
||||
require_once("strategy.php");
|
||||
require_once("update.php");
|
||||
|
||||
//enable buffering to catch and ignore any custom output before XML generation
|
||||
//because of this command, it strongly recommended to include connector's file before any other libs
|
||||
//in such case it will handle any extra output from not well formed code of other libs
|
||||
ini_set("output_buffering","On");
|
||||
ob_start();
|
||||
|
||||
class OutputWriter{
|
||||
private $start;
|
||||
private $end;
|
||||
private $type;
|
||||
|
||||
public function __construct($start, $end = ""){
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
$this->type = "xml";
|
||||
}
|
||||
public function add($add){
|
||||
$this->start.=$add;
|
||||
}
|
||||
public function reset(){
|
||||
$this->start="";
|
||||
$this->end="";
|
||||
}
|
||||
public function set_type($add){
|
||||
$this->type=$add;
|
||||
}
|
||||
public function output($name="", $inline=true, $encoding=""){
|
||||
ob_clean();
|
||||
|
||||
if ($this->type == "xml"){
|
||||
$header = "Content-type: text/xml";
|
||||
if ("" != $encoding)
|
||||
$header.="; charset=".$encoding;
|
||||
header($header);
|
||||
}
|
||||
|
||||
echo $this->__toString();
|
||||
}
|
||||
public function __toString(){
|
||||
return $this->start.$this->end;
|
||||
}
|
||||
}
|
||||
|
||||
/*! EventInterface
|
||||
Base class , for iterable collections, which are used in event
|
||||
**/
|
||||
class EventInterface{
|
||||
protected $request; ////!< DataRequestConfig instance
|
||||
public $rules=array(); //!< array of sorting rules
|
||||
|
||||
/*! constructor
|
||||
creates a new interface based on existing request
|
||||
@param request
|
||||
DataRequestConfig object
|
||||
*/
|
||||
public function __construct($request){
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/*! remove all elements from collection
|
||||
*/
|
||||
public function clear(){
|
||||
array_splice($rules,0);
|
||||
}
|
||||
/*! get index by name
|
||||
|
||||
@param name
|
||||
name of field
|
||||
@return
|
||||
index of named field
|
||||
*/
|
||||
public function index($name){
|
||||
$len = sizeof($this->rules);
|
||||
for ($i=0; $i < $len; $i++) {
|
||||
if ($this->rules[$i]["name"]==$name)
|
||||
return $i;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*! Wrapper for collection of sorting rules
|
||||
**/
|
||||
class SortInterface extends EventInterface{
|
||||
/*! constructor
|
||||
creates a new interface based on existing request
|
||||
@param request
|
||||
DataRequestConfig object
|
||||
*/
|
||||
public function __construct($request){
|
||||
parent::__construct($request);
|
||||
$this->rules = &$request->get_sort_by_ref();
|
||||
}
|
||||
/*! add new sorting rule
|
||||
|
||||
@param name
|
||||
name of field
|
||||
@param dir
|
||||
direction of sorting
|
||||
*/
|
||||
public function add($name,$dir){
|
||||
if ($dir === false)
|
||||
$this->request->set_sort($name);
|
||||
else
|
||||
$this->request->set_sort($name,$dir);
|
||||
}
|
||||
public function store(){
|
||||
$this->request->set_sort_by($this->rules);
|
||||
}
|
||||
}
|
||||
/*! Wrapper for collection of filtering rules
|
||||
**/
|
||||
class FilterInterface extends EventInterface{
|
||||
/*! constructor
|
||||
creates a new interface based on existing request
|
||||
@param request
|
||||
DataRequestConfig object
|
||||
*/
|
||||
public function __construct($request){
|
||||
$this->request = $request;
|
||||
$this->rules = &$request->get_filters_ref();
|
||||
}
|
||||
/*! add new filatering rule
|
||||
|
||||
@param name
|
||||
name of field
|
||||
@param value
|
||||
value to filter by
|
||||
@param rule
|
||||
filtering rule
|
||||
*/
|
||||
public function add($name,$value,$rule){
|
||||
$this->request->set_filter($name,$value,$rule);
|
||||
}
|
||||
public function store(){
|
||||
$this->request->set_filters($this->rules);
|
||||
}
|
||||
}
|
||||
|
||||
/*! base class for component item representation
|
||||
**/
|
||||
class DataItem{
|
||||
protected $data; //!< hash of data
|
||||
protected $config;//!< DataConfig instance
|
||||
protected $index;//!< index of element
|
||||
protected $skip;//!< flag , which set if element need to be skiped during rendering
|
||||
protected $userdata;
|
||||
|
||||
/*! constructor
|
||||
|
||||
@param data
|
||||
hash of data
|
||||
@param config
|
||||
DataConfig object
|
||||
@param index
|
||||
index of element
|
||||
*/
|
||||
function __construct($data,$config,$index){
|
||||
$this->config=$config;
|
||||
$this->data=$data;
|
||||
$this->index=$index;
|
||||
$this->skip=false;
|
||||
$this->userdata=false;
|
||||
}
|
||||
|
||||
//set userdata for the item
|
||||
function set_userdata($name, $value){
|
||||
if ($this->userdata === false)
|
||||
$this->userdata = array();
|
||||
|
||||
$this->userdata[$name]=$value;
|
||||
}
|
||||
/*! get named value
|
||||
|
||||
@param name
|
||||
name or alias of field
|
||||
@return
|
||||
value from field with provided name or alias
|
||||
*/
|
||||
public function get_value($name){
|
||||
return $this->data[$name];
|
||||
}
|
||||
/*! set named value
|
||||
|
||||
@param name
|
||||
name or alias of field
|
||||
@param value
|
||||
value for field with provided name or alias
|
||||
*/
|
||||
public function set_value($name,$value){
|
||||
return $this->data[$name]=$value;
|
||||
}
|
||||
/*! get id of element
|
||||
@return
|
||||
id of element
|
||||
*/
|
||||
public function get_id(){
|
||||
$id = $this->config->id["name"];
|
||||
if (array_key_exists($id,$this->data))
|
||||
return $this->data[$id];
|
||||
return false;
|
||||
}
|
||||
/*! change id of element
|
||||
|
||||
@param value
|
||||
new id value
|
||||
*/
|
||||
public function set_id($value){
|
||||
$this->data[$this->config->id["name"]]=$value;
|
||||
}
|
||||
/*! get index of element
|
||||
|
||||
@return
|
||||
index of element
|
||||
*/
|
||||
public function get_index(){
|
||||
return $this->index;
|
||||
}
|
||||
/*! mark element for skiping ( such element will not be rendered )
|
||||
*/
|
||||
public function skip(){
|
||||
$this->skip=true;
|
||||
}
|
||||
|
||||
/*! return self as XML string
|
||||
*/
|
||||
public function to_xml(){
|
||||
return $this->to_xml_start().$this->to_xml_end();
|
||||
}
|
||||
|
||||
/*! replace xml unsafe characters
|
||||
|
||||
@param string
|
||||
string to be escaped
|
||||
@return
|
||||
escaped string
|
||||
*/
|
||||
public function xmlentities($string) {
|
||||
return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&' , '"', ''' , '<' , '>', ''' ), $string);
|
||||
}
|
||||
|
||||
/*! return starting tag for self as XML string
|
||||
*/
|
||||
public function to_xml_start(){
|
||||
$str="<item";
|
||||
for ($i=0; $i < sizeof($this->config->data); $i++){
|
||||
$name=$this->config->data[$i]["name"];
|
||||
$db_name=$this->config->data[$i]["db_name"];
|
||||
$str.=" ".$name."='".$this->xmlentities($this->data[$name])."'";
|
||||
}
|
||||
//output custom data
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value){
|
||||
$str.=" ".$key."='".$this->xmlentities($value)."'";
|
||||
}
|
||||
|
||||
return $str.">";
|
||||
}
|
||||
/*! return ending tag for XML string
|
||||
*/
|
||||
public function to_xml_end(){
|
||||
return "</item>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*! Base connector class
|
||||
This class used as a base for all component specific connectors.
|
||||
Can be used on its own to provide raw data.
|
||||
**/
|
||||
class Connector {
|
||||
protected $config;//DataConfig instance
|
||||
protected $request;//DataRequestConfig instance
|
||||
protected $names;//!< hash of names for used classes
|
||||
protected $encoding="utf-8";//!< assigned encoding (UTF-8 by default)
|
||||
protected $editing=false;//!< flag of edit mode ( response for dataprocessor )
|
||||
|
||||
public static $filter_var="dhx_filter";
|
||||
public static $sort_var="dhx_sort";
|
||||
public static $kids_var="dhx_kids";
|
||||
|
||||
public $model=false;
|
||||
|
||||
private $updating=false;//!< flag of update mode ( response for data-update )
|
||||
private $db; //!< db connection resource
|
||||
protected $dload;//!< flag of dyn. loading mode
|
||||
public $access; //!< AccessMaster instance
|
||||
protected $data_separator = "\n";
|
||||
|
||||
public $sql; //DataWrapper instance
|
||||
public $event; //EventMaster instance
|
||||
public $limit=false;
|
||||
|
||||
private $id_seed=0; //!< default value, used to generate auto-IDs
|
||||
protected $live_update = false; // actions table name for autoupdating
|
||||
protected $extra_output="";//!< extra info which need to be sent to client side
|
||||
protected $options=array();//!< hash of OptionsConnector
|
||||
protected $as_string = false; // render() returns string, don't send result in response
|
||||
protected $simple = false; // render only data without any other info
|
||||
protected $filters;
|
||||
protected $sorts;
|
||||
protected $mix;
|
||||
protected $order = false;
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param db
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($db,$type=false, $item_type=false, $data_type=false, $render_type = false){
|
||||
$this->exec_time=microtime(true);
|
||||
|
||||
if (!$type) $type="MySQL";
|
||||
if (class_exists($type."DBDataWrapper",false)) $type.="DBDataWrapper";
|
||||
if (!$item_type) $item_type="DataItem";
|
||||
if (!$data_type) $data_type="DataProcessor";
|
||||
if (!$render_type) $render_type="RenderStrategy";
|
||||
|
||||
$this->names=array(
|
||||
"db_class"=>$type,
|
||||
"item_class"=>$item_type,
|
||||
"data_class"=>$data_type,
|
||||
"render_class"=>$render_type
|
||||
);
|
||||
$this->attributes = array();
|
||||
$this->filters = array();
|
||||
$this->sorts = array();
|
||||
$this->mix = array();
|
||||
|
||||
$this->config = new DataConfig();
|
||||
$this->request = new DataRequestConfig();
|
||||
$this->event = new EventMaster();
|
||||
$this->access = new AccessMaster();
|
||||
|
||||
if (!class_exists($this->names["db_class"],false))
|
||||
throw new Exception("DB class not found: ".$this->names["db_class"]);
|
||||
$this->sql = new $this->names["db_class"]($db,$this->config);
|
||||
$this->render = new $this->names["render_class"]($this);
|
||||
|
||||
$this->db=$db;//saved for options connectors, if any
|
||||
|
||||
EventMaster::trigger_static("connectorCreate",$this);
|
||||
}
|
||||
|
||||
/*! return db connection resource
|
||||
nested class may neeed to access live connection object
|
||||
@return
|
||||
DB connection resource
|
||||
*/
|
||||
protected function get_connection(){
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
public function get_config(){
|
||||
return new DataConfig($this->config);
|
||||
}
|
||||
|
||||
public function get_request(){
|
||||
return new DataRequestConfig($this->request);
|
||||
}
|
||||
|
||||
|
||||
protected $attributes;
|
||||
public function add_top_attribute($name, $string){
|
||||
$this->attributes[$name] = $string;
|
||||
}
|
||||
|
||||
//model is a class, which will be used for all data operations
|
||||
//we expect that it has next methods get, update, insert, delete
|
||||
//if method was not defined - we will use default logic
|
||||
public function useModel($model){
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
|
||||
/*! config connector based on table
|
||||
|
||||
@param table
|
||||
name of table in DB
|
||||
@param id
|
||||
name of id field
|
||||
@param fields
|
||||
list of fields names
|
||||
@param extra
|
||||
list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
|
||||
@param relation_id
|
||||
name of field used to define relations for hierarchical data organization, optional
|
||||
*/
|
||||
public function render_table($table,$id="",$fields=false,$extra=false,$relation_id=false){
|
||||
$this->configure($table,$id,$fields,$extra,$relation_id);
|
||||
return $this->render();
|
||||
}
|
||||
public function configure($table,$id="",$fields=false,$extra=false,$relation_id=false){
|
||||
if ($fields === false){
|
||||
//auto-config
|
||||
$info = $this->sql->fields_list($table);
|
||||
$fields = implode(",",$info["fields"]);
|
||||
if ($info["key"])
|
||||
$id = $info["key"];
|
||||
}
|
||||
$this->config->init($id,$fields,$extra,$relation_id);
|
||||
if (strpos(trim($table), " ")!==false)
|
||||
$this->request->parse_sql($table);
|
||||
else
|
||||
$this->request->set_source($table);
|
||||
}
|
||||
|
||||
public function uuid(){
|
||||
return time()."x".$this->id_seed++;
|
||||
}
|
||||
|
||||
/*! config connector based on sql
|
||||
|
||||
@param sql
|
||||
sql query used as base of configuration
|
||||
@param id
|
||||
name of id field
|
||||
@param fields
|
||||
list of fields names
|
||||
@param extra
|
||||
list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
|
||||
@param relation_id
|
||||
name of field used to define relations for hierarchical data organization, optional
|
||||
*/
|
||||
public function render_sql($sql,$id,$fields,$extra=false,$relation_id=false){
|
||||
$this->config->init($id,$fields,$extra,$relation_id);
|
||||
$this->request->parse_sql($sql);
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
public function render_array($data, $id, $fields, $extra=false, $relation_id=false){
|
||||
$this->configure("-",$id,$fields,$extra,$relation_id);
|
||||
$this->sql = new ArrayDBDataWrapper($data, $this->config);
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
public function render_complex_sql($sql,$id,$fields,$extra=false,$relation_id=false){
|
||||
$this->config->init($id,$fields,$extra,$relation_id);
|
||||
$this->request->parse_sql($sql, true);
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
/*! render already configured connector
|
||||
|
||||
@param config
|
||||
configuration of data
|
||||
@param request
|
||||
configuraton of request
|
||||
*/
|
||||
public function render_connector($config,$request){
|
||||
$this->config->copy($config);
|
||||
$this->request->copy($request);
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
/*! render self
|
||||
process commands, output requested data as XML
|
||||
*/
|
||||
public function render(){
|
||||
$this->event->trigger("onInit", $this);
|
||||
EventMaster::trigger_static("connectorInit",$this);
|
||||
|
||||
if (!$this->as_string)
|
||||
$this->parse_request();
|
||||
$this->set_relation();
|
||||
|
||||
if ($this->live_update !== false && $this->updating!==false) {
|
||||
$this->live_update->get_updates();
|
||||
} else {
|
||||
if ($this->editing){
|
||||
$dp = new $this->names["data_class"]($this,$this->config,$this->request);
|
||||
$dp->process($this->config,$this->request);
|
||||
} else {
|
||||
if (!$this->access->check("read")){
|
||||
LogMaster::log("Access control: read operation blocked");
|
||||
echo "Access denied";
|
||||
die();
|
||||
}
|
||||
$wrap = new SortInterface($this->request);
|
||||
$this->apply_sorts($wrap);
|
||||
$this->event->trigger("beforeSort",$wrap);
|
||||
$wrap->store();
|
||||
|
||||
$wrap = new FilterInterface($this->request);
|
||||
$this->apply_filters($wrap);
|
||||
$this->event->trigger("beforeFilter",$wrap);
|
||||
$wrap->store();
|
||||
|
||||
if ($this->model && method_exists($this->model, "get")){
|
||||
$this->sql = new ArrayDBDataWrapper();
|
||||
$result = new ArrayQueryWrapper(call_user_func(array($this->model, "get"), $this->request));
|
||||
$out = $this->output_as_xml($result);
|
||||
} else {
|
||||
$out = $this->output_as_xml($this->get_resource());
|
||||
|
||||
if ($out !== null) return $out;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$this->end_run();
|
||||
}
|
||||
|
||||
|
||||
/*! empty call which used for tree-logic
|
||||
* to prevent code duplicating
|
||||
*/
|
||||
protected function set_relation() {}
|
||||
|
||||
/*! gets resource for rendering
|
||||
*/
|
||||
protected function get_resource() {
|
||||
return $this->sql->select($this->request);
|
||||
}
|
||||
|
||||
|
||||
/*! prevent SQL injection through column names
|
||||
replace dangerous chars in field names
|
||||
@param str
|
||||
incoming field name
|
||||
@return
|
||||
safe field name
|
||||
*/
|
||||
protected function safe_field_name($str){
|
||||
return strtok($str, " \n\t;',");
|
||||
}
|
||||
|
||||
/*! limit max count of records
|
||||
connector will ignore any records after outputing max count
|
||||
@param limit
|
||||
max count of records
|
||||
@return
|
||||
none
|
||||
*/
|
||||
public function set_limit($limit){
|
||||
$this->limit = $limit;
|
||||
}
|
||||
|
||||
|
||||
public function limit($start, $count, $sort_field=false, $sort_dir=false){
|
||||
$this->request->set_limit($start, $count);
|
||||
if ($sort_field)
|
||||
$this->request->set_sort($sort_field, $sort_dir);
|
||||
}
|
||||
|
||||
protected function parse_request_mode(){
|
||||
//detect edit mode
|
||||
if (isset($_GET["editing"])){
|
||||
$this->editing=true;
|
||||
} else if (isset($_POST["ids"])){
|
||||
$this->editing=true;
|
||||
LogMaster::log('While there is no edit mode mark, POST parameters similar to edit mode detected. \n Switching to edit mode ( to disable behavior remove POST[ids]');
|
||||
} else if (isset($_GET['dhx_version'])){
|
||||
$this->updating = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*! parse incoming request, detects commands and modes
|
||||
*/
|
||||
protected function parse_request(){
|
||||
//set default dyn. loading params, can be reset in child classes
|
||||
if ($this->dload)
|
||||
$this->request->set_limit(0,$this->dload);
|
||||
else if ($this->limit)
|
||||
$this->request->set_limit(0,$this->limit);
|
||||
|
||||
if (isset($_GET["posStart"]) && isset($_GET["count"])) {
|
||||
$this->request->set_limit($_GET["posStart"],$_GET["count"]);
|
||||
}
|
||||
|
||||
$this->parse_request_mode();
|
||||
|
||||
if ($this->live_update && ($this->updating || $this->editing)){
|
||||
$this->request->set_version($_GET["dhx_version"]);
|
||||
$this->request->set_user($_GET["dhx_user"]);
|
||||
}
|
||||
|
||||
if (isset($_GET[Connector::$sort_var]))
|
||||
foreach($_GET[Connector::$sort_var] as $k => $v){
|
||||
$k = $this->safe_field_name($k);
|
||||
$this->request->set_sort($this->resolve_parameter($k),$v);
|
||||
}
|
||||
|
||||
if (isset($_GET[Connector::$filter_var]))
|
||||
foreach($_GET[Connector::$filter_var] as $k => $v){
|
||||
$k = $this->safe_field_name($k);
|
||||
if ($v !== "")
|
||||
$this->request->set_filter($this->resolve_parameter($k),$v);
|
||||
}
|
||||
|
||||
$this->check_csrf();
|
||||
}
|
||||
|
||||
protected function check_csrf(){
|
||||
$key = ConnectorSecurity::checkCSRF($this->editing);
|
||||
if ($key !== "")
|
||||
$this->add_top_attribute(ConnectorSecurity::$security_var, $key);
|
||||
}
|
||||
|
||||
/*! convert incoming request name to the actual DB name
|
||||
@param name
|
||||
incoming parameter name
|
||||
@return
|
||||
name of related DB field
|
||||
*/
|
||||
protected function resolve_parameter($name){
|
||||
return $name;
|
||||
}
|
||||
|
||||
|
||||
/*! replace xml unsafe characters
|
||||
|
||||
@param string
|
||||
string to be escaped
|
||||
@return
|
||||
escaped string
|
||||
*/
|
||||
protected function xmlentities($string) {
|
||||
return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&' , '"', ''' , '<' , '>', ''' ), $string);
|
||||
}
|
||||
|
||||
public function getRecord($id){
|
||||
LogMaster::log("Retreiving data for record: ".$id);
|
||||
$source = new DataRequestConfig($this->request);
|
||||
$source->set_filter($this->config->id["name"],$id, "=");
|
||||
|
||||
$res = $this->sql->select($source);
|
||||
|
||||
$temp = $this->data_separator;
|
||||
$this->data_separator="";
|
||||
$output = $this->render_set($res);
|
||||
$this->data_separato=$temp;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/*! render from DB resultset
|
||||
@param res
|
||||
DB resultset
|
||||
process commands, output requested data as XML
|
||||
*/
|
||||
protected function render_set($res){
|
||||
return $this->render->render_set($res, $this->names["item_class"], $this->dload, $this->data_separator, $this->config, $this->mix);
|
||||
}
|
||||
|
||||
/*! output fetched data as XML
|
||||
@param res
|
||||
DB resultset
|
||||
*/
|
||||
protected function output_as_xml($res){
|
||||
$result = $this->render_set($res);
|
||||
if ($this->simple) return $result;
|
||||
|
||||
$start="<?xml version='1.0' encoding='".$this->encoding."' ?>".$this->xml_start();
|
||||
$end=$result.$this->xml_end();
|
||||
|
||||
if ($this->as_string) return $start.$end;
|
||||
|
||||
$out = new OutputWriter($start, $end);
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
|
||||
|
||||
/*! end processing
|
||||
stop execution timer, kill the process
|
||||
*/
|
||||
protected function end_run(){
|
||||
$time=microtime(true)-$this->exec_time;
|
||||
LogMaster::log("Done in {$time}s");
|
||||
flush();
|
||||
die();
|
||||
}
|
||||
|
||||
/*! set xml encoding
|
||||
|
||||
methods sets only attribute in XML, no real encoding conversion occurs
|
||||
@param encoding
|
||||
value which will be used as XML encoding
|
||||
*/
|
||||
public function set_encoding($encoding){
|
||||
$this->encoding=$encoding;
|
||||
}
|
||||
|
||||
/*! enable or disable dynamic loading mode
|
||||
|
||||
@param count
|
||||
count of rows loaded from server, actual only for grid-connector, can be skiped in other cases.
|
||||
If value is a false or 0 - dyn. loading will be disabled
|
||||
*/
|
||||
public function dynamic_loading($count){
|
||||
$this->dload=$count;
|
||||
}
|
||||
|
||||
/*! enable or disable data reordering
|
||||
|
||||
@param name
|
||||
name of field, which will be used for order storing, optional
|
||||
by default 'sortorder' field will be used
|
||||
*/
|
||||
public function enable_order($name = true){
|
||||
if ($name === true)
|
||||
$name = "sortorder";
|
||||
|
||||
$this->sort($name);
|
||||
$this->access->allow("order");
|
||||
$this->request->set_order($name);
|
||||
$this->order = $name;
|
||||
}
|
||||
|
||||
/*! enable logging
|
||||
|
||||
@param path
|
||||
path to the log file. If set as false or empty strig - logging will be disabled
|
||||
@param client_log
|
||||
enable output of log data to the client side
|
||||
*/
|
||||
public function enable_log($path=true,$client_log=false){
|
||||
LogMaster::enable_log($path,$client_log);
|
||||
}
|
||||
|
||||
/*! provides infor about current processing mode
|
||||
@return
|
||||
true if processing dataprocessor command, false otherwise
|
||||
*/
|
||||
public function is_select_mode(){
|
||||
$this->parse_request_mode();
|
||||
return !$this->editing;
|
||||
}
|
||||
|
||||
public function is_first_call(){
|
||||
$this->parse_request_mode();
|
||||
return !($this->editing || $this->updating || $this->request->get_start() || isset($_GET['dhx_no_header']));
|
||||
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
protected function xml_start(){
|
||||
$attributes = "";
|
||||
|
||||
if ($this->dload){
|
||||
//info for dyn. loadin
|
||||
if ($pos=$this->request->get_start())
|
||||
$attributes .= " pos='".$pos."'";
|
||||
else
|
||||
$attributes .= " total_count='".$this->sql->get_size($this->request)."'";
|
||||
}
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$attributes .= " ".$k."='".$v."'";
|
||||
|
||||
return "<data".$attributes.">";
|
||||
}
|
||||
/*! renders self as xml, ending part
|
||||
*/
|
||||
protected function xml_end(){
|
||||
$this->fill_collections();
|
||||
if (isset($this->extra_output))
|
||||
return $this->extra_output."</data>";
|
||||
else
|
||||
return "</data>";
|
||||
}
|
||||
|
||||
protected function fill_collections($list=""){
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
$this->extra_output.="<coll_options for='{$name}'>";
|
||||
if (!is_string($this->options[$name]))
|
||||
$this->extra_output.=$this->options[$name]->render();
|
||||
else
|
||||
$this->extra_output.=$this->options[$name];
|
||||
$this->extra_output.="</coll_options>";
|
||||
}
|
||||
}
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str="";
|
||||
foreach($options as $k => $v)
|
||||
$str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
|
||||
$options=$str;
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
|
||||
public function insert($data) {
|
||||
$action = new DataAction('inserted', false, $data);
|
||||
$request = new DataRequestConfig();
|
||||
$request->set_source($this->request->get_source());
|
||||
|
||||
$this->config->limit_fields($data);
|
||||
$this->sql->insert($action,$request);
|
||||
$this->config->restore_fields($data);
|
||||
|
||||
return $action->get_new_id();
|
||||
}
|
||||
|
||||
public function delete($id) {
|
||||
$action = new DataAction('deleted', $id, array());
|
||||
$request = new DataRequestConfig();
|
||||
$request->set_source($this->request->get_source());
|
||||
|
||||
$this->sql->delete($action,$request);
|
||||
return $action->get_status();
|
||||
}
|
||||
|
||||
public function update($data) {
|
||||
$action = new DataAction('updated', $data[$this->config->id["name"]], $data);
|
||||
$request = new DataRequestConfig();
|
||||
$request->set_source($this->request->get_source());
|
||||
|
||||
$this->config->limit_fields($data);
|
||||
$this->sql->update($action,$request);
|
||||
$this->config->restore_fields($data);
|
||||
|
||||
return $action->get_status();
|
||||
}
|
||||
|
||||
/*! sets actions_table for Optimistic concurrency control mode and start it
|
||||
@param table_name
|
||||
name of database table which will used for saving actions
|
||||
@param url
|
||||
url used for update notifications
|
||||
*/
|
||||
public function enable_live_update($table, $url=false){
|
||||
$this->live_update = new DataUpdate($this->sql, $this->config, $this->request, $table,$url);
|
||||
$this->live_update->set_event($this->event,$this->names["item_class"]);
|
||||
$this->event->attach("beforeOutput", Array($this->live_update, "version_output"));
|
||||
$this->event->attach("beforeFiltering", Array($this->live_update, "get_updates"));
|
||||
$this->event->attach("beforeProcessing", Array($this->live_update, "check_collision"));
|
||||
$this->event->attach("afterProcessing", Array($this->live_update, "log_operations"));
|
||||
}
|
||||
|
||||
/*! render() returns result as string or send to response
|
||||
*/
|
||||
public function asString($as_string) {
|
||||
$this->as_string = $as_string;
|
||||
}
|
||||
|
||||
public function simple_render() {
|
||||
$this->simple = true;
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
public function filter($name, $value = false, $operation = '=') {
|
||||
$this->filters[] = array('name' => $name, 'value' => $value, 'operation' => $operation);
|
||||
}
|
||||
|
||||
public function clear_filter() {
|
||||
$this->filters = array();
|
||||
$this->request->set_filters(array());
|
||||
}
|
||||
|
||||
protected function apply_filters($wrap) {
|
||||
for ($i = 0; $i < count($this->filters); $i++) {
|
||||
$f = $this->filters[$i];
|
||||
$wrap->add($f['name'], $f['value'], $f['operation']);
|
||||
}
|
||||
}
|
||||
|
||||
public function sort($name, $direction = false) {
|
||||
$this->sorts[] = array('name' => $name, 'direction' => $direction);
|
||||
}
|
||||
|
||||
protected function apply_sorts($wrap) {
|
||||
for ($i = 0; $i < count($this->sorts); $i++) {
|
||||
$s = $this->sorts[$i];
|
||||
$wrap->add($s['name'], $s['direction']);
|
||||
}
|
||||
}
|
||||
|
||||
public function mix($name, $value, $filter=false) {
|
||||
$this->mix[] = Array('name'=>$name, 'value'=>$value, 'filter'=>$filter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! wrapper around options collection, used for comboboxes and filters
|
||||
**/
|
||||
class OptionsConnector extends Connector{
|
||||
protected $init_flag=false;//!< used to prevent rendering while initialization
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
||||
if (!$item_type) $item_type="DataItem";
|
||||
if (!$data_type) $data_type=""; //has not sense, options not editable
|
||||
parent::__construct($res,$type,$item_type,$data_type);
|
||||
}
|
||||
/*! render self
|
||||
process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
|
||||
@return
|
||||
data as XML string
|
||||
*/
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
$res = $this->sql->select($this->request);
|
||||
return $this->render_set($res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class DistinctOptionsConnector extends OptionsConnector{
|
||||
/*! render self
|
||||
process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
|
||||
@return
|
||||
data as XML string
|
||||
*/
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
$res = $this->sql->get_variants($this->config->text[0]["db_name"],$this->request);
|
||||
return $this->render_set($res);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
18
libraries/dhtmlxgantt/connector/chart_connector.php
Normal file
18
libraries/dhtmlxgantt/connector/chart_connector.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
94
libraries/dhtmlxgantt/connector/combo_connector.php
Normal file
94
libraries/dhtmlxgantt/connector/combo_connector.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
|
||||
require_once("base_connector.php");
|
||||
/*! DataItem class for Combo component
|
||||
**/
|
||||
class ComboDataItem extends DataItem{
|
||||
private $selected;//!< flag of selected option
|
||||
|
||||
function __construct($data,$config,$index){
|
||||
parent::__construct($data,$config,$index);
|
||||
|
||||
$this->selected=false;
|
||||
}
|
||||
/*! mark option as selected
|
||||
*/
|
||||
function select(){
|
||||
$this->selected=true;
|
||||
}
|
||||
/*! return self as XML string, starting part
|
||||
*/
|
||||
function to_xml_start(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
return "<option ".($this->selected?"selected='true'":"")."value='".$this->xmlentities($this->get_id())."'><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]>";
|
||||
}
|
||||
/*! return self as XML string, ending part
|
||||
*/
|
||||
function to_xml_end(){
|
||||
if ($this->skip) return "";
|
||||
return "</option>";
|
||||
}
|
||||
}
|
||||
|
||||
/*! Connector for the dhtmlxCombo
|
||||
**/
|
||||
class ComboConnector extends Connector{
|
||||
private $filter; //!< filtering mask from incoming request
|
||||
private $position; //!< position from incoming request
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
||||
if (!$item_type) $item_type="ComboDataItem";
|
||||
parent::__construct($res,$type,$item_type,$data_type);
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET["pos"])){
|
||||
if (!$this->dload) //not critical, so just write a log message
|
||||
LogMaster::log("Dyn loading request received, but server side was not configured to process dyn. loading. ");
|
||||
else
|
||||
$this->request->set_limit($_GET["pos"],$this->dload);
|
||||
}
|
||||
|
||||
if (isset($_GET["mask"]))
|
||||
$this->request->set_filter($this->config->text[0]["db_name"],$_GET["mask"]."%","LIKE");
|
||||
|
||||
LogMaster::log($this->request);
|
||||
}
|
||||
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
public function xml_start(){
|
||||
if ($this->request->get_start())
|
||||
return "<complete add='true'>";
|
||||
else
|
||||
return "<complete>";
|
||||
}
|
||||
|
||||
/*! renders self as xml, ending part
|
||||
*/
|
||||
public function xml_end(){
|
||||
return "</complete>";
|
||||
}
|
||||
}
|
||||
?>
|
69
libraries/dhtmlxgantt/connector/convert.php
Normal file
69
libraries/dhtmlxgantt/connector/convert.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?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){
|
||||
|
||||
$str_out = str_replace("<rows>","<rows profile='color'>", $out);
|
||||
$str_out = str_replace("<head>","<head><columns>", $str_out);
|
||||
$str_out = str_replace("</head>","</columns></head>", $str_out);
|
||||
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
141
libraries/dhtmlxgantt/connector/crosslink_connector.php
Normal file
141
libraries/dhtmlxgantt/connector/crosslink_connector.php
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("data_connector.php");
|
||||
|
||||
class DelayedConnector extends Connector{
|
||||
protected $init_flag=false;//!< used to prevent rendering while initialization
|
||||
private $data_mode=false;//!< flag to separate xml and data request modes
|
||||
private $data_result=false;//<! store results of query
|
||||
|
||||
public function dataMode($name){
|
||||
$this->data_mode = $name;
|
||||
$this->data_result=array();
|
||||
}
|
||||
public function getDataResult(){
|
||||
return $this->data_result;
|
||||
}
|
||||
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
protected function output_as_xml($res){
|
||||
if ($this->data_mode){
|
||||
while ($data=$this->sql->get_next($res)){
|
||||
$this->data_result[]=$data[$this->data_mode];
|
||||
}
|
||||
}
|
||||
else
|
||||
return parent::output_as_xml($res);
|
||||
}
|
||||
protected function end_run(){
|
||||
if (!$this->data_mode)
|
||||
parent::end_run();
|
||||
}
|
||||
}
|
||||
|
||||
class CrossOptionsConnector extends Connector{
|
||||
public $options, $link;
|
||||
private $master_name, $link_name, $master_value;
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
||||
$this->options = new OptionsConnector($res,$type,$item_type,$data_type);
|
||||
$this->link = new DelayedConnector($res,$type,$item_type,$data_type);
|
||||
|
||||
EventMaster::attach_static("connectorInit",array($this, "handle"));
|
||||
}
|
||||
public function handle($conn){
|
||||
if ($conn instanceof DelayedConnector) return;
|
||||
if ($conn instanceof OptionsConnector) return;
|
||||
|
||||
$this->master_name = $this->link->get_config()->id["db_name"];
|
||||
$this->link_name = $this->options->get_config()->id["db_name"];
|
||||
|
||||
$this->link->event->attach("beforeFilter",array($this, "get_only_related"));
|
||||
|
||||
if (isset($_GET["dhx_crosslink_".$this->link_name])){
|
||||
$this->get_links($_GET["dhx_crosslink_".$this->link_name]);
|
||||
die();
|
||||
}
|
||||
|
||||
if (!$this->dload){
|
||||
$conn->event->attach("beforeRender", array($this, "getOptions"));
|
||||
$conn->event->attach("beforeRenderSet", array($this, "prepareConfig"));
|
||||
}
|
||||
|
||||
|
||||
$conn->event->attach("afterProcessing", array($this, "afterProcessing"));
|
||||
}
|
||||
public function prepareConfig($conn, $res, $config){
|
||||
$config->add_field($this->link_name);
|
||||
}
|
||||
public function getOptions($data){
|
||||
$this->link->dataMode($this->link_name);
|
||||
|
||||
$this->get_links($data->get_value($this->master_name));
|
||||
|
||||
$data->set_value($this->link_name, implode(",",$this->link->getDataResult()));
|
||||
}
|
||||
public function get_links($id){
|
||||
$this->master_value = $id;
|
||||
$this->link->render();
|
||||
}
|
||||
public function get_only_related($filters){
|
||||
$index = $filters->index($this->master_name);
|
||||
if ($index!==false){
|
||||
$filters->rules[$index]["value"]=$this->master_value;
|
||||
} else
|
||||
$filters->add($this->master_name, $this->master_value, "=");
|
||||
}
|
||||
public function afterProcessing($action){
|
||||
$status = $action->get_status();
|
||||
|
||||
$master_key = $action->get_id();//value($this->master_name);
|
||||
$link_key = $action->get_value($this->link_name);
|
||||
$link_key = explode(',', $link_key);
|
||||
|
||||
if ($status == "inserted")
|
||||
$master_key = $action->get_new_id();
|
||||
|
||||
switch ($status){
|
||||
case "deleted":
|
||||
$this->link->delete($master_key);
|
||||
break;
|
||||
case "updated":
|
||||
//cross link options not loaded yet, so we can skip update
|
||||
if (!array_key_exists($this->link_name, $action->get_data()))
|
||||
break;
|
||||
//else, delete old options and continue in insert section to add new values
|
||||
$this->link->delete($master_key);
|
||||
case "inserted":
|
||||
for ($i=0; $i < sizeof($link_key); $i++)
|
||||
if ($link_key[$i]!="")
|
||||
$this->link->insert(array(
|
||||
$this->link_name => $link_key[$i],
|
||||
$this->master_name => $master_key
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONCrossOptionsConnector extends CrossOptionsConnector{
|
||||
public $options, $link;
|
||||
private $master_name, $link_name, $master_value;
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
||||
$this->options = new JSONOptionsConnector($res,$type,$item_type,$data_type);
|
||||
$this->link = new DelayedConnector($res,$type,$item_type,$data_type);
|
||||
|
||||
EventMaster::attach_static("connectorInit",array($this, "handle"));
|
||||
}
|
||||
}
|
||||
?>
|
528
libraries/dhtmlxgantt/connector/data_connector.php
Normal file
528
libraries/dhtmlxgantt/connector/data_connector.php
Normal file
|
@ -0,0 +1,528 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("base_connector.php");
|
||||
|
||||
class CommonDataProcessor extends DataProcessor{
|
||||
protected function get_post_values($ids){
|
||||
if (isset($_GET['action'])){
|
||||
$data = array();
|
||||
if (isset($_POST["id"])){
|
||||
$dataset = array();
|
||||
foreach($_POST as $key=>$value)
|
||||
$dataset[$key] = ConnectorSecurity::filter($value);
|
||||
|
||||
$data[$_POST["id"]] = $dataset;
|
||||
}
|
||||
else
|
||||
$data["dummy_id"] = $_POST;
|
||||
return $data;
|
||||
}
|
||||
return parent::get_post_values($ids);
|
||||
}
|
||||
|
||||
protected function get_ids(){
|
||||
if (isset($_GET['action'])){
|
||||
if (isset($_POST["id"]))
|
||||
return array($_POST['id']);
|
||||
else
|
||||
return array("dummy_id");
|
||||
}
|
||||
return parent::get_ids();
|
||||
}
|
||||
|
||||
protected function get_operation($rid){
|
||||
if (isset($_GET['action']))
|
||||
return $_GET['action'];
|
||||
return parent::get_operation($rid);
|
||||
}
|
||||
|
||||
public function output_as_xml($results){
|
||||
if (isset($_GET['action'])){
|
||||
LogMaster::log("Edit operation finished",$results);
|
||||
ob_clean();
|
||||
$type = $results[0]->get_status();
|
||||
if ($type == "error" || $type == "invalid"){
|
||||
echo "false";
|
||||
} else if ($type=="insert"){
|
||||
echo "true\n".$results[0]->get_new_id();
|
||||
} else
|
||||
echo "true";
|
||||
} else
|
||||
return parent::output_as_xml($results);
|
||||
}
|
||||
};
|
||||
|
||||
/*! DataItem class for DataView component
|
||||
**/
|
||||
class CommonDataItem extends DataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
return $this->to_xml_start().$this->to_xml_end();
|
||||
}
|
||||
|
||||
function to_xml_start(){
|
||||
$str="<item id='".$this->get_id()."' ";
|
||||
for ($i=0; $i < sizeof($this->config->text); $i++){
|
||||
$name=$this->config->text[$i]["name"];
|
||||
$str.=" ".$name."='".$this->xmlentities($this->data[$name])."'";
|
||||
}
|
||||
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$str.=" ".$key."='".$this->xmlentities($value)."'";
|
||||
|
||||
return $str.">";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Connector class for DataView
|
||||
**/
|
||||
class DataConnector extends Connector{
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="CommonDataItem";
|
||||
if (!$data_type) $data_type="CommonDataProcessor";
|
||||
|
||||
$this->sections = array();
|
||||
|
||||
if (!$render_type) $render_type="RenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
|
||||
}
|
||||
|
||||
protected $sections;
|
||||
public function add_section($name, $string){
|
||||
$this->sections[$name] = $string;
|
||||
}
|
||||
|
||||
protected function parse_request_mode(){
|
||||
if (isset($_GET['action']) && $_GET["action"] != "get")
|
||||
$this->editing = true;
|
||||
else
|
||||
parent::parse_request_mode();
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
protected function parse_request(){
|
||||
if (isset($_GET['action'])){
|
||||
$action = $_GET['action'];
|
||||
//simple request mode
|
||||
if ($action == "get"){
|
||||
//data request
|
||||
if (isset($_GET['id'])){
|
||||
//single entity data request
|
||||
$this->request->set_filter($this->config->id["name"],$_GET['id'],"=");
|
||||
} else {
|
||||
//loading collection of items
|
||||
}
|
||||
} else {
|
||||
//data saving
|
||||
$this->editing = true;
|
||||
}
|
||||
parent::check_csrf();
|
||||
} else {
|
||||
if (isset($_GET['editing']) && isset($_POST['ids']))
|
||||
$this->editing = true;
|
||||
parent::parse_request();
|
||||
}
|
||||
|
||||
if (isset($_GET["start"]) && isset($_GET["count"]))
|
||||
$this->request->set_limit($_GET["start"],$_GET["count"]);
|
||||
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
protected function xml_start(){
|
||||
$start = "<data";
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$start .= " ".$k."='".$v."'";
|
||||
$start.= ">";
|
||||
|
||||
foreach($this->sections as $k=>$v)
|
||||
$start .= "<".$k.">".$v."</".$k.">\n";
|
||||
return $start;
|
||||
}
|
||||
};
|
||||
|
||||
class JSONDataConnector extends DataConnector{
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="JSONCommonDataItem";
|
||||
if (!$data_type) $data_type="CommonDataProcessor";
|
||||
if (!$render_type) $render_type="JSONRenderStrategy";
|
||||
$this->data_separator = ",\n";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str=array();
|
||||
foreach($options as $k => $v)
|
||||
$str[]='{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
|
||||
$options=implode(",",$str);
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
/*! generates xml description for options collections
|
||||
|
||||
@param list
|
||||
comma separated list of column names, for which options need to be generated
|
||||
*/
|
||||
protected function fill_collections($list=""){
|
||||
$options = array();
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
$option="\"{$name}\":[";
|
||||
if (!is_string($this->options[$name]))
|
||||
$option.=substr(json_encode($this->options[$name]->render()),1,-1);
|
||||
else
|
||||
$option.=$this->options[$name];
|
||||
$option.="]";
|
||||
$options[] = $option;
|
||||
}
|
||||
$this->extra_output .= implode($this->data_separator, $options);
|
||||
}
|
||||
|
||||
protected function resolve_parameter($name){
|
||||
if (intval($name).""==$name)
|
||||
return $this->config->text[intval($name)]["db_name"];
|
||||
return $name;
|
||||
}
|
||||
|
||||
protected function output_as_xml($res){
|
||||
$json = $this->render_set($res);
|
||||
if ($this->simple) return $json;
|
||||
$result = json_encode($json);
|
||||
|
||||
$this->fill_collections();
|
||||
$is_sections = sizeof($this->sections) && $this->is_first_call();
|
||||
if ($this->dload || $is_sections || sizeof($this->attributes) || !empty($this->extra_data)){
|
||||
|
||||
$attributes = "";
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$attributes .= ", \"".$k."\":\"".$v."\"";
|
||||
|
||||
$extra = "";
|
||||
if (!empty($this->extra_output))
|
||||
$extra .= ', "collections": {'.$this->extra_output.'}';
|
||||
|
||||
$sections = "";
|
||||
if ($is_sections){
|
||||
//extra sections
|
||||
foreach($this->sections as $k=>$v)
|
||||
$sections .= ", \"".$k."\":".$v;
|
||||
}
|
||||
|
||||
$dyn = "";
|
||||
if ($this->dload){
|
||||
//info for dyn. loadin
|
||||
if ($pos=$this->request->get_start())
|
||||
$dyn .= ", \"pos\":".$pos;
|
||||
else
|
||||
$dyn .= ", \"pos\":0, \"total_count\":".$this->sql->get_size($this->request);
|
||||
}
|
||||
if ($attributes || $sections || $this->extra_output || $dyn) {
|
||||
$result = "{ \"data\":".$result.$attributes.$extra.$sections.$dyn."}";
|
||||
}
|
||||
}
|
||||
|
||||
// return as string
|
||||
if ($this->as_string) return $result;
|
||||
|
||||
// output direct to response
|
||||
$out = new OutputWriter($result, "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class JSONCommonDataItem extends DataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return false;
|
||||
|
||||
$data = array(
|
||||
'id' => $this->get_id()
|
||||
);
|
||||
for ($i=0; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
$data[$extra]=$this->data[$extra];
|
||||
if (is_null($data[$extra]))
|
||||
$data[$extra] = "";
|
||||
}
|
||||
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value){
|
||||
if ($value === null)
|
||||
$data[$key]="";
|
||||
$data[$key]=$value;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! wrapper around options collection, used for comboboxes and filters
|
||||
**/
|
||||
class JSONOptionsConnector extends JSONDataConnector{
|
||||
protected $init_flag=false;//!< used to prevent rendering while initialization
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
||||
if (!$item_type) $item_type="JSONCommonDataItem";
|
||||
if (!$data_type) $data_type=""; //has not sense, options not editable
|
||||
parent::__construct($res,$type,$item_type,$data_type);
|
||||
}
|
||||
/*! render self
|
||||
process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
|
||||
@return
|
||||
data as XML string
|
||||
*/
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
$res = $this->sql->select($this->request);
|
||||
return $this->render_set($res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONDistinctOptionsConnector extends JSONOptionsConnector{
|
||||
/*! render self
|
||||
process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
|
||||
@return
|
||||
data as XML string
|
||||
*/
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
$res = $this->sql->get_variants($this->config->text[0]["db_name"],$this->request);
|
||||
return $this->render_set($res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class TreeCommonDataItem extends CommonDataItem{
|
||||
protected $kids=-1;
|
||||
|
||||
function to_xml_start(){
|
||||
$str="<item id='".$this->get_id()."' ";
|
||||
for ($i=0; $i < sizeof($this->config->text); $i++){
|
||||
$name=$this->config->text[$i]["name"];
|
||||
$str.=" ".$name."='".$this->xmlentities($this->data[$name])."'";
|
||||
}
|
||||
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$str.=" ".$key."='".$this->xmlentities($value)."'";
|
||||
|
||||
if ($this->kids === true)
|
||||
$str .=" ".Connector::$kids_var."='1'";
|
||||
|
||||
return $str.">";
|
||||
}
|
||||
|
||||
function has_kids(){
|
||||
return $this->kids;
|
||||
}
|
||||
|
||||
function set_kids($value){
|
||||
$this->kids=$value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TreeDataConnector extends DataConnector{
|
||||
protected $parent_name = 'parent';
|
||||
public $rootId = "0";
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
* @param render_type
|
||||
* name of class which will provides data rendering
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="TreeCommonDataItem";
|
||||
if (!$data_type) $data_type="CommonDataProcessor";
|
||||
if (!$render_type) $render_type="TreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
protected function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET[$this->parent_name]))
|
||||
$this->request->set_relation($_GET[$this->parent_name]);
|
||||
else
|
||||
$this->request->set_relation($this->rootId);
|
||||
|
||||
$this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
protected function xml_start(){
|
||||
$attributes = " ";
|
||||
if (!$this->rootId || $this->rootId != $this->request->get_relation())
|
||||
$attributes = " parent='".$this->request->get_relation()."' ";
|
||||
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$attributes .= " ".$k."='".$v."'";
|
||||
|
||||
return "<data".$attributes.">";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONTreeDataConnector extends TreeDataConnector{
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="JSONTreeCommonDataItem";
|
||||
if (!$data_type) $data_type="CommonDataProcessor";
|
||||
if (!$render_type) $render_type="JSONTreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
protected function output_as_xml($res){
|
||||
$result = $this->render_set($res);
|
||||
if ($this->simple) return $result;
|
||||
|
||||
$data = array();
|
||||
if (!$this->rootId || $this->rootId != $this->request->get_relation())
|
||||
$data["parent"] = $this->request->get_relation();
|
||||
|
||||
$data["data"] = $result;
|
||||
|
||||
$this->fill_collections();
|
||||
if (!empty($this->options))
|
||||
$data["collections"] = $this->options;
|
||||
|
||||
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$data[$k] = $v;
|
||||
|
||||
$data = json_encode($data);
|
||||
|
||||
// return as string
|
||||
if ($this->as_string) return $data;
|
||||
|
||||
// output direct to response
|
||||
$out = new OutputWriter($data, "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str=array();
|
||||
foreach($options as $k => $v)
|
||||
$str[]=Array("id"=>$this->xmlentities($k), "value"=>$this->xmlentities($v));//'{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
|
||||
$options=$str;
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
/*! generates xml description for options collections
|
||||
|
||||
@param list
|
||||
comma separated list of column names, for which options need to be generated
|
||||
*/
|
||||
protected function fill_collections($list=""){
|
||||
$options = array();
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
if (!is_array($this->options[$name]))
|
||||
$option=$this->options[$name]->render();
|
||||
else
|
||||
$option=$this->options[$name];
|
||||
$options[$name] = $option;
|
||||
}
|
||||
$this->options = $options;
|
||||
$this->extra_output .= "'collections':".json_encode($options);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class JSONTreeCommonDataItem extends TreeCommonDataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml_start(){
|
||||
if ($this->skip) return false;
|
||||
|
||||
$data = array( "id" => $this->get_id() );
|
||||
for ($i=0; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
if (isset($this->data[$extra]))
|
||||
$data[$extra]=$this->data[$extra];
|
||||
}
|
||||
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$data[$key]=$value;
|
||||
|
||||
if ($this->kids === true)
|
||||
$data[Connector::$kids_var] = 1;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function to_xml_end(){
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
521
libraries/dhtmlxgantt/connector/dataprocessor.php
Normal file
521
libraries/dhtmlxgantt/connector/dataprocessor.php
Normal file
|
@ -0,0 +1,521 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
/*! Base DataProcessor handling
|
||||
**/
|
||||
|
||||
require_once("xss_filter.php");
|
||||
|
||||
class DataProcessor{
|
||||
protected $connector;//!< Connector instance
|
||||
protected $config;//!< DataConfig instance
|
||||
protected $request;//!< DataRequestConfig instance
|
||||
static public $action_param ="!nativeeditor_status";
|
||||
|
||||
/*! constructor
|
||||
|
||||
@param connector
|
||||
Connector object
|
||||
@param config
|
||||
DataConfig object
|
||||
@param request
|
||||
DataRequestConfig object
|
||||
*/
|
||||
function __construct($connector,$config,$request){
|
||||
$this->connector= $connector;
|
||||
$this->config=$config;
|
||||
$this->request=$request;
|
||||
}
|
||||
|
||||
/*! convert incoming data name to valid db name
|
||||
redirect to Connector->name_data by default
|
||||
@param data
|
||||
data name from incoming request
|
||||
@return
|
||||
related db_name
|
||||
*/
|
||||
function name_data($data){
|
||||
return $data;
|
||||
}
|
||||
/*! retrieve data from incoming request and normalize it
|
||||
|
||||
@param ids
|
||||
array of extected IDs
|
||||
@return
|
||||
hash of data
|
||||
*/
|
||||
protected function get_post_values($ids){
|
||||
$data=array();
|
||||
for ($i=0; $i < sizeof($ids); $i++)
|
||||
$data[$ids[$i]]=array();
|
||||
|
||||
foreach ($_POST as $key => $value) {
|
||||
$details=explode("_",$key,2);
|
||||
if (sizeof($details)==1) continue;
|
||||
|
||||
$name=$this->name_data($details[1]);
|
||||
$data[$details[0]][$name]=ConnectorSecurity::filter($value);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
protected function get_ids(){
|
||||
if (!isset($_POST["ids"]))
|
||||
throw new Exception("Incorrect incoming data, ID of incoming records not recognized");
|
||||
return explode(",",$_POST["ids"]);
|
||||
}
|
||||
|
||||
protected function get_operation($rid){
|
||||
if (!isset($_POST[$rid."_".DataProcessor::$action_param]))
|
||||
throw new Exception("Status of record [{$rid}] not found in incoming request");
|
||||
return $_POST[$rid."_".DataProcessor::$action_param];
|
||||
}
|
||||
/*! process incoming request ( save|update|delete )
|
||||
*/
|
||||
function process(){
|
||||
LogMaster::log("DataProcessor object initialized",$_POST);
|
||||
|
||||
$results=array();
|
||||
|
||||
$ids=$this->get_ids();
|
||||
$rows_data=$this->get_post_values($ids);
|
||||
$failed=false;
|
||||
|
||||
try{
|
||||
if ($this->connector->sql->is_global_transaction())
|
||||
$this->connector->sql->begin_transaction();
|
||||
|
||||
for ($i=0; $i < sizeof($ids); $i++) {
|
||||
$rid = $ids[$i];
|
||||
LogMaster::log("Row data [{$rid}]",$rows_data[$rid]);
|
||||
$status = $this->get_operation($rid);
|
||||
|
||||
$action=new DataAction($status,$rid,$rows_data[$rid]);
|
||||
$results[]=$action;
|
||||
$this->inner_process($action);
|
||||
}
|
||||
|
||||
} catch(Exception $e){
|
||||
LogMaster::log($e);
|
||||
$failed=true;
|
||||
}
|
||||
|
||||
if ($this->connector->sql->is_global_transaction()){
|
||||
if (!$failed)
|
||||
for ($i=0; $i < sizeof($results); $i++)
|
||||
if ($results[$i]->get_status()=="error" || $results[$i]->get_status()=="invalid"){
|
||||
$failed=true;
|
||||
break;
|
||||
}
|
||||
if ($failed){
|
||||
for ($i=0; $i < sizeof($results); $i++)
|
||||
$results[$i]->error();
|
||||
$this->connector->sql->rollback_transaction();
|
||||
}
|
||||
else
|
||||
$this->connector->sql->commit_transaction();
|
||||
}
|
||||
|
||||
$this->output_as_xml($results);
|
||||
}
|
||||
|
||||
/*! converts status string to the inner mode name
|
||||
|
||||
@param status
|
||||
external status string
|
||||
@return
|
||||
inner mode name
|
||||
*/
|
||||
protected function status_to_mode($status){
|
||||
switch($status){
|
||||
case "updated":
|
||||
return "update";
|
||||
break;
|
||||
case "inserted":
|
||||
return "insert";
|
||||
break;
|
||||
case "deleted":
|
||||
return "delete";
|
||||
break;
|
||||
default:
|
||||
return $status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*! process data updated request received
|
||||
|
||||
@param action
|
||||
DataAction object
|
||||
@return
|
||||
DataAction object with details of processing
|
||||
*/
|
||||
protected function inner_process($action){
|
||||
|
||||
if ($this->connector->sql->is_record_transaction())
|
||||
$this->connector->sql->begin_transaction();
|
||||
|
||||
try{
|
||||
|
||||
$mode = $this->status_to_mode($action->get_status());
|
||||
if (!$this->connector->access->check($mode)){
|
||||
LogMaster::log("Access control: {$mode} operation blocked");
|
||||
$action->error();
|
||||
} else {
|
||||
$check = $this->connector->event->trigger("beforeProcessing",$action);
|
||||
if (!$action->is_ready())
|
||||
$this->check_exts($action,$mode);
|
||||
if ($mode == "insert" && $action->get_status() != "error" && $action->get_status() != "invalid")
|
||||
$this->connector->sql->new_record_order($action, $this->request);
|
||||
|
||||
$check = $this->connector->event->trigger("afterProcessing",$action);
|
||||
}
|
||||
|
||||
} catch (Exception $e){
|
||||
LogMaster::log($e);
|
||||
$action->set_status("error");
|
||||
if ($action)
|
||||
$this->connector->event->trigger("onDBError", $action, $e);
|
||||
}
|
||||
|
||||
if ($this->connector->sql->is_record_transaction()){
|
||||
if ($action->get_status()=="error" || $action->get_status()=="invalid")
|
||||
$this->connector->sql->rollback_transaction();
|
||||
else
|
||||
$this->connector->sql->commit_transaction();
|
||||
}
|
||||
|
||||
return $action;
|
||||
}
|
||||
|
||||
/*! check if some event intercepts processing, send data to DataWrapper in other case
|
||||
|
||||
@param action
|
||||
DataAction object
|
||||
@param mode
|
||||
name of inner mode ( will be used to generate event names )
|
||||
*/
|
||||
function check_exts($action,$mode){
|
||||
$old_config = new DataConfig($this->config);
|
||||
|
||||
$this->connector->event->trigger("before".$mode,$action);
|
||||
if ($action->is_ready())
|
||||
LogMaster::log("Event code for ".$mode." processed");
|
||||
else {
|
||||
//check if custom sql defined
|
||||
$sql = $this->connector->sql->get_sql($mode,$action);
|
||||
if ($sql){
|
||||
$this->connector->sql->query($sql);
|
||||
}
|
||||
else{
|
||||
$action->sync_config($this->config);
|
||||
if ($this->connector->model && method_exists($this->connector->model, $mode)){
|
||||
call_user_func(array($this->connector->model, $mode), $action);
|
||||
LogMaster::log("Model object process action: ".$mode);
|
||||
}
|
||||
if (!$action->is_ready()){
|
||||
$method=array($this->connector->sql,$mode);
|
||||
if (!is_callable($method))
|
||||
throw new Exception("Unknown dataprocessing action: ".$mode);
|
||||
call_user_func($method,$action,$this->request);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->connector->event->trigger("after".$mode,$action);
|
||||
|
||||
$this->config->copy($old_config);
|
||||
}
|
||||
|
||||
/*! output xml response for dataprocessor
|
||||
|
||||
@param results
|
||||
array of DataAction objects
|
||||
*/
|
||||
function output_as_xml($results){
|
||||
LogMaster::log("Edit operation finished",$results);
|
||||
ob_clean();
|
||||
header("Content-type:text/xml");
|
||||
echo "<?xml version='1.0' ?>";
|
||||
echo "<data>";
|
||||
for ($i=0; $i < sizeof($results); $i++)
|
||||
echo $results[$i]->to_xml();
|
||||
echo "</data>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*! contain all info related to action and controls customizaton
|
||||
**/
|
||||
class DataAction{
|
||||
private $status; //!< cuurent status of record
|
||||
private $id;//!< id of record
|
||||
private $data;//!< data hash of record
|
||||
private $userdata;//!< hash of extra data , attached to record
|
||||
private $nid;//!< new id value , after operation executed
|
||||
private $output;//!< custom output to client side code
|
||||
private $attrs;//!< hash of custtom attributes
|
||||
private $ready;//!< flag of operation's execution
|
||||
private $addf;//!< array of added fields
|
||||
private $delf;//!< array of deleted fields
|
||||
|
||||
|
||||
/*! constructor
|
||||
|
||||
@param status
|
||||
current operation status
|
||||
@param id
|
||||
record id
|
||||
@param data
|
||||
hash of data
|
||||
*/
|
||||
function __construct($status,$id,$data){
|
||||
$this->status=$status;
|
||||
$this->id=$id;
|
||||
$this->data=$data;
|
||||
$this->nid=$id;
|
||||
|
||||
$this->output="";
|
||||
$this->attrs=array();
|
||||
$this->ready=false;
|
||||
|
||||
$this->addf=array();
|
||||
$this->delf=array();
|
||||
}
|
||||
|
||||
|
||||
/*! add custom field and value to DB operation
|
||||
|
||||
@param name
|
||||
name of field which will be added to DB operation
|
||||
@param value
|
||||
value which will be used for related field in DB operation
|
||||
*/
|
||||
function add_field($name,$value){
|
||||
LogMaster::log("adding field: ".$name.", with value: ".$value);
|
||||
$this->data[$name]=$value;
|
||||
$this->addf[]=$name;
|
||||
}
|
||||
/*! remove field from DB operation
|
||||
|
||||
@param name
|
||||
name of field which will be removed from DB operation
|
||||
*/
|
||||
function remove_field($name){
|
||||
LogMaster::log("removing field: ".$name);
|
||||
$this->delf[]=$name;
|
||||
}
|
||||
|
||||
/*! sync field configuration with external object
|
||||
|
||||
@param slave
|
||||
SQLMaster object
|
||||
@todo
|
||||
check , if all fields removed then cancel action
|
||||
*/
|
||||
function sync_config($slave){
|
||||
foreach ($this->addf as $k => $v)
|
||||
$slave->add_field($v);
|
||||
foreach ($this->delf as $k => $v)
|
||||
$slave->remove_field($v);
|
||||
}
|
||||
/*! get value of some record's propery
|
||||
|
||||
@param name
|
||||
name of record's property ( name of db field or alias )
|
||||
@return
|
||||
value of related property
|
||||
*/
|
||||
function get_value($name){
|
||||
if (!array_key_exists($name,$this->data)){
|
||||
LogMaster::log("Incorrect field name used: ".$name);
|
||||
LogMaster::log("data",$this->data);
|
||||
return "";
|
||||
}
|
||||
return $this->data[$name];
|
||||
}
|
||||
/*! set value of some record's propery
|
||||
|
||||
@param name
|
||||
name of record's property ( name of db field or alias )
|
||||
@param value
|
||||
value of related property
|
||||
*/
|
||||
function set_value($name,$value){
|
||||
LogMaster::log("change value of: ".$name." as: ".$value);
|
||||
$this->data[$name]=$value;
|
||||
}
|
||||
/*! get hash of data properties
|
||||
|
||||
@return
|
||||
hash of data properties
|
||||
*/
|
||||
function get_data(){
|
||||
return $this->data;
|
||||
}
|
||||
/*! get some extra info attached to record
|
||||
deprecated, exists just for backward compatibility, you can use set_value instead of it
|
||||
@param name
|
||||
name of userdata property
|
||||
@return
|
||||
value of related userdata property
|
||||
*/
|
||||
function get_userdata_value($name){
|
||||
return $this->get_value($name);
|
||||
}
|
||||
/*! set some extra info attached to record
|
||||
deprecated, exists just for backward compatibility, you can use get_value instead of it
|
||||
@param name
|
||||
name of userdata property
|
||||
@param value
|
||||
value of userdata property
|
||||
*/
|
||||
function set_userdata_value($name,$value){
|
||||
return $this->set_value($name,$value);
|
||||
}
|
||||
/*! get current status of record
|
||||
|
||||
@return
|
||||
string with status value
|
||||
*/
|
||||
function get_status(){
|
||||
return $this->status;
|
||||
}
|
||||
/*! assign new status to the record
|
||||
|
||||
@param status
|
||||
new status value
|
||||
*/
|
||||
function set_status($status){
|
||||
$this->status=$status;
|
||||
}
|
||||
/*! set id
|
||||
@param id
|
||||
id value
|
||||
*/
|
||||
function set_id($id) {
|
||||
$this->id = $id;
|
||||
LogMaster::log("Change id: ".$id);
|
||||
}
|
||||
/*! set id
|
||||
@param id
|
||||
id value
|
||||
*/
|
||||
function set_new_id($id) {
|
||||
$this->nid = $id;
|
||||
LogMaster::log("Change new id: ".$id);
|
||||
}
|
||||
/*! get id of current record
|
||||
|
||||
@return
|
||||
id of record
|
||||
*/
|
||||
function get_id(){
|
||||
return $this->id;
|
||||
}
|
||||
/*! sets custom response text
|
||||
|
||||
can be accessed through defineAction on client side. Text wrapped in CDATA, so no extra escaping necessary
|
||||
@param text
|
||||
custom response text
|
||||
*/
|
||||
function set_response_text($text){
|
||||
$this->set_response_xml("<![CDATA[".$text."]]>");
|
||||
}
|
||||
/*! sets custom response xml
|
||||
|
||||
can be accessed through defineAction on client side
|
||||
@param text
|
||||
string with XML data
|
||||
*/
|
||||
function set_response_xml($text){
|
||||
$this->output=$text;
|
||||
}
|
||||
/*! sets custom response attributes
|
||||
|
||||
can be accessed through defineAction on client side
|
||||
@param name
|
||||
name of custom attribute
|
||||
@param value
|
||||
value of custom attribute
|
||||
*/
|
||||
function set_response_attribute($name,$value){
|
||||
$this->attrs[$name]=$value;
|
||||
}
|
||||
/*! check if action finished
|
||||
|
||||
@return
|
||||
true if action finished, false otherwise
|
||||
*/
|
||||
function is_ready(){
|
||||
return $this->ready;
|
||||
}
|
||||
/*! return new id value
|
||||
|
||||
equal to original ID normally, after insert operation - value assigned for new DB record
|
||||
@return
|
||||
new id value
|
||||
*/
|
||||
function get_new_id(){
|
||||
return $this->nid;
|
||||
}
|
||||
|
||||
/*! set result of operation as error
|
||||
*/
|
||||
function error(){
|
||||
$this->status="error";
|
||||
$this->ready=true;
|
||||
}
|
||||
/*! set result of operation as invalid
|
||||
*/
|
||||
function invalid(){
|
||||
$this->status="invalid";
|
||||
$this->ready=true;
|
||||
}
|
||||
/*! confirm successful opeation execution
|
||||
@param id
|
||||
new id value, optional
|
||||
*/
|
||||
function success($id=false){
|
||||
if ($id!==false)
|
||||
$this->nid = $id;
|
||||
$this->ready=true;
|
||||
}
|
||||
/*! convert DataAction to xml format compatible with client side dataProcessor
|
||||
@return
|
||||
DataAction operation report as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
$str="<action type='{$this->status}' sid='{$this->id}' tid='{$this->nid}' ";
|
||||
foreach ($this->attrs as $k => $v) {
|
||||
$str.=$k."='".$this->xmlentities($v)."' ";
|
||||
}
|
||||
$str.=">{$this->output}</action>";
|
||||
return $str;
|
||||
}
|
||||
|
||||
/*! replace xml unsafe characters
|
||||
|
||||
@param string
|
||||
string to be escaped
|
||||
@return
|
||||
escaped string
|
||||
*/
|
||||
public function xmlentities($string) {
|
||||
return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&' , '"', ''' , '<' , '>', ''' ), $string);
|
||||
}
|
||||
|
||||
/*! convert self to string ( for logs )
|
||||
|
||||
@return
|
||||
DataAction operation report as plain string
|
||||
*/
|
||||
function __toString(){
|
||||
return "action:{$this->status}; sid:{$this->id}; tid:{$this->nid};";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
73
libraries/dhtmlxgantt/connector/dataview_connector.php
Normal file
73
libraries/dhtmlxgantt/connector/dataview_connector.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("base_connector.php");
|
||||
|
||||
/*! DataItem class for DataView component
|
||||
**/
|
||||
class DataViewDataItem extends DataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$str="<item id='".$this->get_id()."' >";
|
||||
for ($i=0; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
$str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
|
||||
}
|
||||
return $str."</item>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Connector class for DataView
|
||||
**/
|
||||
class DataViewConnector extends Connector{
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
||||
if (!$item_type) $item_type="DataViewDataItem";
|
||||
if (!$data_type) $data_type="DataProcessor";
|
||||
parent::__construct($res,$type,$item_type,$data_type);
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET["posStart"]) && isset($_GET["count"]))
|
||||
$this->request->set_limit($_GET["posStart"],$_GET["count"]);
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
protected function xml_start(){
|
||||
$attributes = "";
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$attributes .= " ".$k."='".$v."'";
|
||||
|
||||
if ($this->dload){
|
||||
if ($pos=$this->request->get_start())
|
||||
return "<data pos='".$pos."'".$attributes.">";
|
||||
else
|
||||
return "<data total_count='".$this->sql->get_size($this->request)."'".$attributes.">";
|
||||
}
|
||||
else
|
||||
return "<data".$attributes.">";
|
||||
}
|
||||
}
|
||||
?>
|
72
libraries/dhtmlxgantt/connector/db_adodb.php
Normal file
72
libraries/dhtmlxgantt/connector/db_adodb.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! Implementation of DataWrapper for PostgreSQL
|
||||
**/
|
||||
class AdoDBDataWrapper extends DBDataWrapper{
|
||||
protected $last_result;
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
if (is_array($sql)) {
|
||||
$res = $this->connection->SelectLimit($sql['sql'], $sql['numrows'], $sql['offset']);
|
||||
} else {
|
||||
$res = $this->connection->Execute($sql);
|
||||
}
|
||||
|
||||
if ($res===false) throw new Exception("ADODB operation failed\n".$this->connection->ErrorMsg());
|
||||
$this->last_result = $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
if (!$res)
|
||||
$res = $this->last_result;
|
||||
|
||||
if ($res->EOF)
|
||||
return false;
|
||||
|
||||
$row = $res->GetRowAssoc(false);
|
||||
$res->MoveNext();
|
||||
return $row;
|
||||
}
|
||||
|
||||
protected function get_new_id(){
|
||||
return $this->connection->Insert_ID();
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return $this->connection->addq($data);
|
||||
}
|
||||
|
||||
/*! escape field name to prevent sql reserved words conflict
|
||||
@param data
|
||||
unescaped data
|
||||
@return
|
||||
escaped data
|
||||
*/
|
||||
public function escape_name($data){
|
||||
if ((strpos($data,"`")!==false || is_int($data)) || (strpos($data,".")!==false))
|
||||
return $data;
|
||||
return '`'.$data.'`';
|
||||
}
|
||||
|
||||
|
||||
protected function select_query($select,$from,$where,$sort,$start,$count){
|
||||
if (!$from)
|
||||
return $select;
|
||||
|
||||
$sql="SELECT ".$select." FROM ".$from;
|
||||
if ($where) $sql.=" WHERE ".$where;
|
||||
if ($sort) $sql.=" ORDER BY ".$sort;
|
||||
|
||||
if ($start || $count) {
|
||||
$sql=array("sql"=>$sql,'numrows'=>$count, 'offset'=>$start);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
1149
libraries/dhtmlxgantt/connector/db_common.php
Normal file
1149
libraries/dhtmlxgantt/connector/db_common.php
Normal file
File diff suppressed because it is too large
Load diff
190
libraries/dhtmlxgantt/connector/db_excel.php
Normal file
190
libraries/dhtmlxgantt/connector/db_excel.php
Normal file
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once('db_common.php');
|
||||
|
||||
if (!defined('DHX_IGNORE_EMPTY_ROWS')) {
|
||||
define('DHX_IGNORE_EMPTY_ROWS', true);
|
||||
}
|
||||
|
||||
class ExcelDBDataWrapper extends DBDataWrapper {
|
||||
|
||||
public $emptyLimit = 10;
|
||||
public function excel_data($points){
|
||||
$path = $this->connection;
|
||||
$excel = PHPExcel_IOFactory::createReaderForFile($path);
|
||||
$excel = $excel->load($path);
|
||||
$result = array();
|
||||
$excelWS = $excel->getActiveSheet();
|
||||
|
||||
for ($i=0; $i < sizeof($points); $i++) {
|
||||
$c = array();
|
||||
preg_match("/^([a-zA-Z]+)(\d+)/", $points[$i], $c);
|
||||
if (count($c) > 0) {
|
||||
$col = PHPExcel_Cell::columnIndexFromString($c[1]) - 1;
|
||||
$cell = $excelWS->getCellByColumnAndRow($col, (int)$c[2]);
|
||||
$result[] = $cell->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
public function select($source) {
|
||||
$path = $this->connection;
|
||||
$excel = PHPExcel_IOFactory::createReaderForFile($path);
|
||||
$excel->setReadDataOnly(false);
|
||||
$excel = $excel->load($path);
|
||||
$excRes = new ExcelResult();
|
||||
$excelWS = $excel->getActiveSheet();
|
||||
$addFields = true;
|
||||
|
||||
$coords = array();
|
||||
if ($source->get_source() == '*') {
|
||||
$coords['start_row'] = 0;
|
||||
$coords['end_row'] = false;
|
||||
} else {
|
||||
$c = array();
|
||||
preg_match("/^([a-zA-Z]+)(\d+)/", $source->get_source(), $c);
|
||||
if (count($c) > 0) {
|
||||
$coords['start_row'] = (int) $c[2];
|
||||
} else {
|
||||
$coords['start_row'] = 0;
|
||||
}
|
||||
$c = array();
|
||||
preg_match("/:(.+)(\d+)$/U", $source->get_source(), $c);
|
||||
if (count($c) > 0) {
|
||||
$coords['end_row'] = (int) $c[2];
|
||||
} else {
|
||||
$coords['end_row'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$i = $coords['start_row'];
|
||||
$end = 0;
|
||||
while ((($coords['end_row'] == false)&&($end < $this->emptyLimit))||(($coords['end_row'] !== false)&&($i < $coords['end_row']))) {
|
||||
$r = Array();
|
||||
$emptyNum = 0;
|
||||
for ($j = 0; $j < count($this->config->text); $j++) {
|
||||
$col = PHPExcel_Cell::columnIndexFromString($this->config->text[$j]['name']) - 1;
|
||||
$cell = $excelWS->getCellByColumnAndRow($col, $i);
|
||||
if (PHPExcel_Shared_Date::isDateTime($cell)) {
|
||||
$r[PHPExcel_Cell::stringFromColumnIndex($col)] = PHPExcel_Shared_Date::ExcelToPHP($cell->getValue());
|
||||
} else if ($cell->getDataType() == 'f') {
|
||||
$r[PHPExcel_Cell::stringFromColumnIndex($col)] = $cell->getCalculatedValue();
|
||||
} else {
|
||||
$r[PHPExcel_Cell::stringFromColumnIndex($col)] = $cell->getValue();
|
||||
}
|
||||
if ($r[PHPExcel_Cell::stringFromColumnIndex($col)] == '') {
|
||||
$emptyNum++;
|
||||
}
|
||||
}
|
||||
if ($emptyNum < count($this->config->text)) {
|
||||
$r['id'] = $i;
|
||||
$excRes->addRecord($r);
|
||||
$end = 0;
|
||||
} else {
|
||||
if (DHX_IGNORE_EMPTY_ROWS == false) {
|
||||
$r['id'] = $i;
|
||||
$excRes->addRecord($r);
|
||||
}
|
||||
$end++;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return $excRes;
|
||||
}
|
||||
|
||||
public function query($sql) {
|
||||
}
|
||||
|
||||
public function get_new_id() {
|
||||
}
|
||||
|
||||
public function escape($data) {
|
||||
}
|
||||
|
||||
public function get_next($res) {
|
||||
return $res->next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class ExcelResult {
|
||||
private $rows;
|
||||
private $currentRecord = 0;
|
||||
|
||||
|
||||
// add record to output list
|
||||
public function addRecord($file) {
|
||||
$this->rows[] = $file;
|
||||
}
|
||||
|
||||
|
||||
// return next record
|
||||
public function next() {
|
||||
if ($this->currentRecord < count($this->rows)) {
|
||||
$row = $this->rows[$this->currentRecord];
|
||||
$this->currentRecord++;
|
||||
return $row;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sorts records under $sort array
|
||||
public function sort($sort, $data) {
|
||||
if (count($this->files) == 0) {
|
||||
return $this;
|
||||
}
|
||||
// defines fields list if it's need
|
||||
for ($i = 0; $i < count($sort); $i++) {
|
||||
$fieldname = $sort[$i]['name'];
|
||||
if (!isset($this->files[0][$fieldname])) {
|
||||
if (isset($data[$fieldname])) {
|
||||
$fieldname = $data[$fieldname]['db_name'];
|
||||
$sort[$i]['name'] = $fieldname;
|
||||
} else {
|
||||
$fieldname = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for every sorting field will sort
|
||||
for ($i = 0; $i < count($sort); $i++) {
|
||||
// if field, setted in sort parameter doesn't exist, continue
|
||||
if ($sort[$i]['name'] == false) {
|
||||
continue;
|
||||
}
|
||||
// sorting by current field
|
||||
$flag = true;
|
||||
while ($flag == true) {
|
||||
$flag = false;
|
||||
// checks if previous sorting fields are equal
|
||||
for ($j = 0; $j < count($this->files) - 1; $j++) {
|
||||
$equal = true;
|
||||
for ($k = 0; $k < $i; $k++) {
|
||||
if ($this->files[$j][$sort[$k]['name']] != $this->files[$j + 1][$sort[$k]['name']]) {
|
||||
$equal = false;
|
||||
}
|
||||
}
|
||||
// compares two records in list under current sorting field and sorting direction
|
||||
if (((($this->files[$j][$sort[$i]['name']] > $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'ASC'))||(($this->files[$j][$sort[$i]['name']] < $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'DESC')))&&($equal == true)) {
|
||||
$c = $this->files[$j];
|
||||
$this->files[$j] = $this->files[$j+1];
|
||||
$this->files[$j+1] = $c;
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
345
libraries/dhtmlxgantt/connector/db_filesystem.php
Normal file
345
libraries/dhtmlxgantt/connector/db_filesystem.php
Normal file
|
@ -0,0 +1,345 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once('db_common.php');
|
||||
require_once('tree_connector.php');
|
||||
|
||||
/*
|
||||
Most execution time is a standart functions for workin with FileSystem: is_dir(), dir(), readdir(), stat()
|
||||
*/
|
||||
|
||||
class FileSystemDBDataWrapper extends DBDataWrapper {
|
||||
|
||||
|
||||
// returns list of files and directories
|
||||
public function select($source) {
|
||||
$relation = $this->getFileName($source->get_relation());
|
||||
// for tree checks relation id and forms absolute path
|
||||
if ($relation == '0') {
|
||||
$relation = '';
|
||||
} else {
|
||||
$path = $source->get_source();
|
||||
}
|
||||
$path = $source->get_source();
|
||||
$path = $this->getFileName($path);
|
||||
$path = realpath($path);
|
||||
if ($path == false) {
|
||||
return new FileSystemResult();
|
||||
}
|
||||
|
||||
if (strpos(realpath($path.'/'.$relation), $path) !== 0) {
|
||||
return new FileSystemResult();
|
||||
}
|
||||
// gets files and directories list
|
||||
$res = $this->getFilesList($path, $relation);
|
||||
// sorts list
|
||||
$res = $res->sort($source->get_sort_by(), $this->config->data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
// gets files and directory list
|
||||
private function getFilesList($path, $relation) {
|
||||
$fileSystemTypes = FileSystemTypes::getInstance();
|
||||
LogMaster::log("Query filesystem: ".$path);
|
||||
$dir = opendir($path.'/'.$relation);
|
||||
$result = new FileSystemResult();
|
||||
// forms fields list
|
||||
for ($i = 0; $i < count($this->config->data); $i++) {
|
||||
$fields[] = $this->config->data[$i]['db_name'];
|
||||
}
|
||||
// for every file and directory of folder
|
||||
while ($file = readdir($dir)) {
|
||||
// . and .. should not be in output list
|
||||
if (($file == '.')||($file == '..')) {
|
||||
continue;
|
||||
}
|
||||
$newFile = array();
|
||||
// parse file name as Array('name', 'ext', 'is_dir')
|
||||
$fileNameExt = $this->parseFileName($path.'/'.$relation, $file);
|
||||
// checks if file should be in output array
|
||||
if (!$fileSystemTypes->checkFile($file, $fileNameExt)) {
|
||||
continue;
|
||||
}
|
||||
// takes file stat if it's need
|
||||
if ((in_array('size', $fields))||(in_array('date', $fields))) {
|
||||
$fileInfo = stat($path.'/'.$file);
|
||||
}
|
||||
|
||||
// for every field forms list of fields
|
||||
for ($i = 0; $i < count($fields); $i++) {
|
||||
$field = $fields[$i];
|
||||
switch ($field) {
|
||||
case 'filename':
|
||||
$newFile['filename'] = $file;
|
||||
break;
|
||||
case 'full_filename':
|
||||
$newFile['full_filename'] = $path."/".$file;
|
||||
break;
|
||||
case 'size':
|
||||
$newFile['size'] = $fileInfo['size'];
|
||||
break;
|
||||
case 'extention':
|
||||
$newFile['extention'] = $fileNameExt['ext'];
|
||||
break;
|
||||
case 'name':
|
||||
$newFile['name'] = $fileNameExt['name'];
|
||||
break;
|
||||
case 'date':
|
||||
$newFile['date'] = date("Y-m-d H:i:s", $fileInfo['ctime']);
|
||||
break;
|
||||
}
|
||||
$newFile['relation_id'] = $relation.'/'.$file;
|
||||
$newFile['safe_name'] = $this->setFileName($relation.'/'.$file);
|
||||
$newFile['is_folder'] = $fileNameExt['is_dir'];
|
||||
}
|
||||
// add file in output list
|
||||
$result->addFile($newFile);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
// replaces '.' and '_' in id
|
||||
private function setFileName($filename) {
|
||||
$filename = str_replace(".", "{-dot-}", $filename);
|
||||
$filename = str_replace("_", "{-nizh-}", $filename);
|
||||
return $filename;
|
||||
}
|
||||
|
||||
|
||||
// replaces '{-dot-}' and '{-nizh-}' in id
|
||||
private function getFileName($filename) {
|
||||
$filename = str_replace("{-dot-}", ".", $filename);
|
||||
$filename = str_replace("{-nizh-}", "_", $filename);
|
||||
return $filename;
|
||||
}
|
||||
|
||||
|
||||
// parses file name and checks if is directory
|
||||
private function parseFileName($path, $file) {
|
||||
$result = Array();
|
||||
if (is_dir($path.'/'.$file)) {
|
||||
$result['name'] = $file;
|
||||
$result['ext'] = 'dir';
|
||||
$result['is_dir'] = 1;
|
||||
} else {
|
||||
$pos = strrpos($file, '.');
|
||||
$result['name'] = substr($file, 0, $pos);
|
||||
$result['ext'] = substr($file, $pos + 1);
|
||||
$result['is_dir'] = 0;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function query($sql) {
|
||||
}
|
||||
|
||||
public function get_new_id() {
|
||||
}
|
||||
|
||||
public function escape($data) {
|
||||
}
|
||||
|
||||
public function get_next($res) {
|
||||
return $res->next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FileSystemResult {
|
||||
private $files;
|
||||
private $currentRecord = 0;
|
||||
|
||||
|
||||
// add record to output list
|
||||
public function addFile($file) {
|
||||
$this->files[] = $file;
|
||||
}
|
||||
|
||||
|
||||
// return next record
|
||||
public function next() {
|
||||
if ($this->currentRecord < count($this->files)) {
|
||||
$file = $this->files[$this->currentRecord];
|
||||
$this->currentRecord++;
|
||||
return $file;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sorts records under $sort array
|
||||
public function sort($sort, $data) {
|
||||
if (count($this->files) == 0) {
|
||||
return $this;
|
||||
}
|
||||
// defines fields list if it's need
|
||||
for ($i = 0; $i < count($sort); $i++) {
|
||||
$fieldname = $sort[$i]['name'];
|
||||
if (!isset($this->files[0][$fieldname])) {
|
||||
if (isset($data[$fieldname])) {
|
||||
$fieldname = $data[$fieldname]['db_name'];
|
||||
$sort[$i]['name'] = $fieldname;
|
||||
} else {
|
||||
$fieldname = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for every sorting field will sort
|
||||
for ($i = 0; $i < count($sort); $i++) {
|
||||
// if field, setted in sort parameter doesn't exist, continue
|
||||
if ($sort[$i]['name'] == false) {
|
||||
continue;
|
||||
}
|
||||
// sorting by current field
|
||||
$flag = true;
|
||||
while ($flag == true) {
|
||||
$flag = false;
|
||||
// checks if previous sorting fields are equal
|
||||
for ($j = 0; $j < count($this->files) - 1; $j++) {
|
||||
$equal = true;
|
||||
for ($k = 0; $k < $i; $k++) {
|
||||
if ($this->files[$j][$sort[$k]['name']] != $this->files[$j + 1][$sort[$k]['name']]) {
|
||||
$equal = false;
|
||||
}
|
||||
}
|
||||
// compares two records in list under current sorting field and sorting direction
|
||||
if (((($this->files[$j][$sort[$i]['name']] > $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'ASC'))||(($this->files[$j][$sort[$i]['name']] < $this->files[$j + 1][$sort[$i]['name']])&&($sort[$i]['direction'] == 'DESC')))&&($equal == true)) {
|
||||
$c = $this->files[$j];
|
||||
$this->files[$j] = $this->files[$j+1];
|
||||
$this->files[$j+1] = $c;
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// singleton class for setting file types filter
|
||||
class FileSystemTypes {
|
||||
|
||||
static private $instance = NULL;
|
||||
private $extentions = Array();
|
||||
private $extentions_not = Array();
|
||||
private $all = true;
|
||||
private $patterns = Array();
|
||||
// predefined types
|
||||
private $types = Array(
|
||||
'image' => Array('jpg', 'jpeg', 'gif', 'png', 'tiff', 'bmp', 'psd', 'dir'),
|
||||
'document' => Array('txt', 'doc', 'docx', 'xls', 'xlsx', 'rtf', 'dir'),
|
||||
'web' => Array('php', 'html', 'htm', 'js', 'css', 'dir'),
|
||||
'audio' => Array('mp3', 'wav', 'ogg', 'dir'),
|
||||
'video' => Array('avi', 'mpg', 'mpeg', 'mp4', 'dir'),
|
||||
'only_dir' => Array('dir')
|
||||
);
|
||||
|
||||
|
||||
static function getInstance() {
|
||||
if (self::$instance == NULL) {
|
||||
self::$instance = new FileSystemTypes();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
// sets array of extentions
|
||||
public function setExtentions($ext) {
|
||||
$this->all = false;
|
||||
$this->extentions = $ext;
|
||||
}
|
||||
|
||||
// adds one extention in array
|
||||
public function addExtention($ext) {
|
||||
$this->all = false;
|
||||
$this->extentions[] = $ext;
|
||||
}
|
||||
|
||||
|
||||
// adds one extention which will not ouputed in array
|
||||
public function addExtentionNot($ext) {
|
||||
$this->extentions_not[] = $ext;
|
||||
}
|
||||
|
||||
|
||||
// returns array of extentions
|
||||
public function getExtentions() {
|
||||
return $this->extentions;
|
||||
}
|
||||
|
||||
// adds regexp pattern
|
||||
public function addPattern($pattern) {
|
||||
$this->all = false;
|
||||
$this->patterns[] = $pattern;
|
||||
}
|
||||
|
||||
// clear extentions array
|
||||
public function clearExtentions() {
|
||||
$this->all = true;
|
||||
$this->extentions = Array();
|
||||
}
|
||||
|
||||
// clear regexp patterns array
|
||||
public function clearPatterns() {
|
||||
$this->all = true;
|
||||
$this->patterns = Array();
|
||||
}
|
||||
|
||||
// clear all filters
|
||||
public function clearAll() {
|
||||
$this->clearExtentions();
|
||||
$this->clearPatterns();
|
||||
}
|
||||
|
||||
// sets predefined type
|
||||
public function setType($type, $clear = false) {
|
||||
$this->all = false;
|
||||
if ($type == 'all') {
|
||||
$this->all = true;
|
||||
return true;
|
||||
}
|
||||
if (isset($this->types[$type])) {
|
||||
if ($clear) {
|
||||
$this->clearExtentions();
|
||||
}
|
||||
for ($i = 0; $i < count($this->types[$type]); $i++) {
|
||||
$this->extentions[] = $this->types[$type][$i];
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check file under setted filter
|
||||
public function checkFile($filename, $fileNameExt) {
|
||||
if (in_array($fileNameExt['ext'], $this->extentions_not)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->all) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((count($this->extentions) > 0)&&(!in_array($fileNameExt['ext'], $this->extentions))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($this->patterns); $i++) {
|
||||
if (!preg_match($this->patterns[$i], $filename)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
73
libraries/dhtmlxgantt/connector/db_mssql.php
Normal file
73
libraries/dhtmlxgantt/connector/db_mssql.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! MSSQL implementation of DataWrapper
|
||||
**/
|
||||
class MsSQLDBDataWrapper extends DBDataWrapper{
|
||||
private $last_id=""; //!< ID of previously inserted record
|
||||
private $insert_operation=false; //!< flag of insert operation
|
||||
private $start_from=false; //!< index of start position
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
$res = mssql_query($sql,$this->connection);
|
||||
if ($this->insert_operation){
|
||||
$last = mssql_fetch_assoc($res);
|
||||
$this->last_id = $last["dhx_id"];
|
||||
mssql_free_result($res);
|
||||
}
|
||||
if ($this->start_from)
|
||||
mssql_data_seek($res,$this->start_from);
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
return mssql_fetch_assoc($res);
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
/*
|
||||
MSSQL doesn't support identity or auto-increment fields
|
||||
Insert SQL returns new ID value, which stored in last_id field
|
||||
*/
|
||||
return $this->last_id;
|
||||
}
|
||||
|
||||
protected function insert_query($data,$request){
|
||||
$sql = parent::insert_query($data,$request);
|
||||
$this->insert_operation=true;
|
||||
return $sql.";SELECT @@IDENTITY AS dhx_id";
|
||||
}
|
||||
|
||||
protected function select_query($select,$from,$where,$sort,$start,$count){
|
||||
if (!$from)
|
||||
return $select;
|
||||
|
||||
$sql="SELECT " ;
|
||||
if ($count)
|
||||
$sql.=" TOP ".($count+$start);
|
||||
$sql.=" ".$select." FROM ".$from;
|
||||
if ($where) $sql.=" WHERE ".$where;
|
||||
if ($sort) $sql.=" ORDER BY ".$sort;
|
||||
if ($start && $count)
|
||||
$this->start_from=$start;
|
||||
else
|
||||
$this->start_from=false;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
/*
|
||||
there is no special escaping method for mssql - use common logic
|
||||
*/
|
||||
return str_replace("'","''",$data);
|
||||
}
|
||||
|
||||
public function begin_transaction(){
|
||||
$this->query("BEGIN TRAN");
|
||||
}
|
||||
}
|
||||
?>
|
56
libraries/dhtmlxgantt/connector/db_mysqli.php
Normal file
56
libraries/dhtmlxgantt/connector/db_mysqli.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
|
||||
class MySQLiDBDataWrapper extends MySQLDBDataWrapper{
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
$res = $this->connection->query($sql);
|
||||
if ($res===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
return $res->fetch_assoc();
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
return $this->connection->insert_id;
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return $this->connection->real_escape_string($data);
|
||||
}
|
||||
|
||||
public function tables_list() {
|
||||
$result = $this->connection->query("SHOW TABLES");
|
||||
if ($result===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
|
||||
|
||||
$tables = array();
|
||||
while ($table = $result->fetch_array()) {
|
||||
$tables[] = $table[0];
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
public function fields_list($table) {
|
||||
$result = $this->connection->query("SHOW COLUMNS FROM `".$table."`");
|
||||
if ($result===false) throw new Exception("MySQL operation failed\n".$this->connection->error);
|
||||
$fields = array();
|
||||
while ($field = $result->fetch_array()) {
|
||||
if ($field['Key'] == "PRI") {
|
||||
$fields[$field[0]] = 1;
|
||||
} else {
|
||||
$fields[$field[0]] = 0;
|
||||
}
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
88
libraries/dhtmlxgantt/connector/db_oracle.php
Normal file
88
libraries/dhtmlxgantt/connector/db_oracle.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! Implementation of DataWrapper for Oracle
|
||||
**/
|
||||
class OracleDBDataWrapper extends DBDataWrapper{
|
||||
private $last_id=""; //id of previously inserted record
|
||||
private $insert_operation=false; //flag of insert operation
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
$stm = oci_parse($this->connection,$sql);
|
||||
if ($stm===false) throw new Exception("Oracle - sql parsing failed\n".oci_error($this->connection));
|
||||
|
||||
$out = array(0=>null);
|
||||
if($this->insert_operation){
|
||||
oci_bind_by_name($stm,":outID",$out[0],999);
|
||||
$this->insert_operation=false;
|
||||
}
|
||||
|
||||
|
||||
$mode = ($this->is_record_transaction() || $this->is_global_transaction())?OCI_DEFAULT:OCI_COMMIT_ON_SUCCESS;
|
||||
$res = @oci_execute($stm,$mode);
|
||||
if ($res===false) throw new Exception(oci_error($this->connection));
|
||||
|
||||
$this->last_id=$out[0];
|
||||
|
||||
return $stm;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = oci_fetch_assoc($res);
|
||||
if ($data){
|
||||
foreach ($data as $k => $v)
|
||||
$data[strtolower($k)] = $v;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
/*
|
||||
Oracle doesn't support identity or auto-increment fields
|
||||
Insert SQL returns new ID value, which stored in last_id field
|
||||
*/
|
||||
return $this->last_id;
|
||||
}
|
||||
|
||||
protected function insert_query($data,$request){
|
||||
$sql = parent::insert_query($data,$request);
|
||||
$this->insert_operation=true;
|
||||
return $sql." returning ".$this->config->id["db_name"]." into :outID";
|
||||
}
|
||||
|
||||
protected function select_query($select,$from,$where,$sort,$start,$count){
|
||||
if (!$from)
|
||||
return $select;
|
||||
|
||||
$sql="SELECT ".$select." FROM ".$from;
|
||||
if ($where) $sql.=" WHERE ".$where;
|
||||
if ($sort) $sql.=" ORDER BY ".$sort;
|
||||
if ($start || $count)
|
||||
$sql="SELECT * FROM ( select /*+ FIRST_ROWS(".$count.")*/dhx_table.*, ROWNUM rnum FROM (".$sql.") dhx_table where ROWNUM <= ".($count+$start)." ) where rnum >".$start;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
/*
|
||||
as far as I can see the only way to escape data is by using oci_bind_by_name
|
||||
while it is neat solution in common case, it conflicts with existing SQL building logic
|
||||
fallback to simple escaping
|
||||
*/
|
||||
return str_replace("'","''",$data);
|
||||
}
|
||||
|
||||
public function begin_transaction(){
|
||||
//auto-start of transaction
|
||||
}
|
||||
public function commit_transaction(){
|
||||
oci_commit($this->connection);
|
||||
}
|
||||
public function rollback_transaction(){
|
||||
oci_rollback($this->connection);
|
||||
}
|
||||
}
|
||||
?>
|
100
libraries/dhtmlxgantt/connector/db_pdo.php
Normal file
100
libraries/dhtmlxgantt/connector/db_pdo.php
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?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 tables_list() {
|
||||
$result = $this->query("SHOW TABLES");
|
||||
if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
|
||||
|
||||
$tables = array();
|
||||
while ($table = $result->next()) {
|
||||
$tables[] = $table[0];
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
public function fields_list($table) {
|
||||
$result = $this->query("SHOW COLUMNS FROM `".$table."`");
|
||||
if ($result===false) throw new Exception("MySQL operation failed\n".mysql_error($this->connection));
|
||||
|
||||
$fields = array();
|
||||
$id = "";
|
||||
while ($field = $result->next()) {
|
||||
if ($field['Key'] == "PRI")
|
||||
$id = $field["Field"];
|
||||
else
|
||||
$fields[] = $field["Field"];
|
||||
}
|
||||
return array("fields" => $fields, "key" => $id );
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = $res->next();
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
public function escape($str){
|
||||
$res=$this->connection->quote($str);
|
||||
if ($res===false) //not supported by pdo driver
|
||||
return str_replace("'","''",$str);
|
||||
return 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
libraries/dhtmlxgantt/connector/db_phpcake.php
Normal file
85
libraries/dhtmlxgantt/connector/db_phpcake.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
|
||||
//DataProcessor::$action_param ="dhx_editor_status";
|
||||
|
||||
/*! Implementation of DataWrapper for PDO
|
||||
|
||||
if you plan to use it for Oracle - use Oracle connection type instead
|
||||
**/
|
||||
class PHPCakeDBDataWrapper extends ArrayDBDataWrapper{
|
||||
public function select($sql){
|
||||
$source = $sql->get_source();
|
||||
if (is_array($source)) //result of find
|
||||
$res = $source;
|
||||
else
|
||||
$res = $this->connection->find("all");
|
||||
|
||||
$temp = array();
|
||||
if (sizeof($res)){
|
||||
$name = get_class($this->connection);
|
||||
for ($i=sizeof($res)-1; $i>=0; $i--)
|
||||
$temp[]=&$res[$i][$name];
|
||||
}
|
||||
return new ArrayQueryWrapper($temp);
|
||||
}
|
||||
|
||||
protected function getErrorMessage(){
|
||||
$errors = $this->connection->invalidFields();
|
||||
$text = array();
|
||||
foreach ($errors as $key => $value){
|
||||
$text[] = $key." - ".$value[0];
|
||||
}
|
||||
return implode("\n", $text);
|
||||
}
|
||||
|
||||
public function insert($data,$source){
|
||||
$name = get_class($this->connection);
|
||||
$save = array();
|
||||
$temp_data = $data->get_data();
|
||||
unset($temp_data[$this->config->id['db_name']]);
|
||||
unset($temp_data["!nativeeditor_status"]);
|
||||
$save[$name] = $temp_data;
|
||||
|
||||
if ($this->connection->save($save)){
|
||||
$data->success($this->connection->getLastInsertID());
|
||||
} else {
|
||||
$data->set_response_attribute("details", $this->getErrorMessage());
|
||||
$data->invalid();
|
||||
}
|
||||
}
|
||||
public function delete($data,$source){
|
||||
$id = $data->get_id();
|
||||
$this->connection->delete($id);
|
||||
$data->success();
|
||||
}
|
||||
public function update($data,$source){
|
||||
$name = get_class($this->connection);
|
||||
$save = array();
|
||||
$save[$name] = &$data->get_data();
|
||||
|
||||
if ($this->connection->save($save)){
|
||||
$data->success();
|
||||
} else {
|
||||
$data->set_response_attribute("details", $this->getErrorMessage());
|
||||
$data->invalid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function escape($str){
|
||||
throw new Exception("Not implemented");
|
||||
}
|
||||
public function query($str){
|
||||
throw new Exception("Not implemented");
|
||||
}
|
||||
public function get_new_id(){
|
||||
throw new Exception("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
65
libraries/dhtmlxgantt/connector/db_phpci.php
Normal file
65
libraries/dhtmlxgantt/connector/db_phpci.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
|
||||
/*! Implementation of DataWrapper for PDO
|
||||
|
||||
if you plan to use it for Oracle - use Oracle connection type instead
|
||||
**/
|
||||
class PHPCIDBDataWrapper extends DBDataWrapper{
|
||||
private $last_result;//!< store result or last operation
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
|
||||
$res=$this->connection->query($sql);
|
||||
if ($res===false) {
|
||||
throw new Exception("CI - sql execution failed");
|
||||
}
|
||||
|
||||
if (is_object($res))
|
||||
return new PHPCIResultSet($res);
|
||||
return new ArrayQueryWrapper(array());
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = $res->next();
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
return $this->connection->insert_id();
|
||||
}
|
||||
|
||||
public function escape($str){
|
||||
return $this->connection->escape_str($str);
|
||||
}
|
||||
|
||||
public function escape_name($data){
|
||||
return $this->connection->protect_identifiers($data);
|
||||
}
|
||||
}
|
||||
|
||||
class PHPCIResultSet{
|
||||
private $res;
|
||||
private $start;
|
||||
private $count;
|
||||
|
||||
public function __construct($res){
|
||||
$this->res = $res;
|
||||
$this->start = $res->current_row;
|
||||
$this->count = $res->num_rows;
|
||||
}
|
||||
public function next(){
|
||||
if ($this->start != $this->count){
|
||||
return $this->res->row($this->start++,'array');
|
||||
} else {
|
||||
$this->res->free_result();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
91
libraries/dhtmlxgantt/connector/db_phpyii.php
Normal file
91
libraries/dhtmlxgantt/connector/db_phpyii.php
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
|
||||
require_once("db_common.php");
|
||||
|
||||
class PHPYiiDBDataWrapper extends ArrayDBDataWrapper{
|
||||
public function select($sql){
|
||||
if (is_array($this->connection)) //result of findAll
|
||||
$res = $this->connection;
|
||||
else
|
||||
$res = $this->connection->findAll();
|
||||
|
||||
$temp = array();
|
||||
if (sizeof($res)){
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
73
libraries/dhtmlxgantt/connector/db_postgre.php
Normal file
73
libraries/dhtmlxgantt/connector/db_postgre.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! Implementation of DataWrapper for PostgreSQL
|
||||
**/
|
||||
class PostgreDBDataWrapper extends DBDataWrapper{
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
|
||||
$res=pg_query($this->connection,$sql);
|
||||
if ($res===false) throw new Exception("Postgre - sql execution failed\n".pg_last_error($this->connection));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function select_query($select,$from,$where,$sort,$start,$count){
|
||||
if (!$from)
|
||||
return $select;
|
||||
|
||||
$sql="SELECT ".$select." FROM ".$from;
|
||||
if ($where) $sql.=" WHERE ".$where;
|
||||
if ($sort) $sql.=" ORDER BY ".$sort;
|
||||
if ($start || $count)
|
||||
$sql.=" OFFSET ".$start." LIMIT ".$count;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
return pg_fetch_assoc($res);
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
$res = pg_query( $this->connection, "SELECT LASTVAL() AS seq");
|
||||
$data = pg_fetch_assoc($res);
|
||||
pg_free_result($res);
|
||||
return $data['seq'];
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
//need to use oci_bind_by_name
|
||||
return pg_escape_string($this->connection,$data);
|
||||
}
|
||||
|
||||
public function tables_list() {
|
||||
$sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
|
||||
$res = pg_query($this->connection, $sql);
|
||||
$tables = array();
|
||||
while ($table = pg_fetch_assoc($res)) {
|
||||
$tables[] = $table['table_name'];
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
public function fields_list($table) {
|
||||
$sql = "SELECT * FROM information_schema.constraint_column_usage";
|
||||
$result = pg_query($this->connection, $sql);
|
||||
$field = pg_fetch_assoc($result);
|
||||
$id = $field['column_name'];
|
||||
|
||||
$sql = "SELECT * FROM information_schema.columns WHERE table_name ='".$table."';";
|
||||
$result = pg_query($this->connection, $sql);
|
||||
$fields = array();
|
||||
$id = "";
|
||||
while ($field = pg_fetch_assoc($result)) {
|
||||
$fields[] = $field["column_name"];
|
||||
}
|
||||
return array('fields' => $fields, 'key' => $id );
|
||||
}
|
||||
}
|
||||
?>
|
54
libraries/dhtmlxgantt/connector/db_sasql.php
Normal file
54
libraries/dhtmlxgantt/connector/db_sasql.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
require_once("db_common.php");
|
||||
/*! SaSQL implementation of DataWrapper
|
||||
**/
|
||||
class SaSQLDBDataWrapper extends DBDataWrapper{
|
||||
private $last_id=""; //!< ID of previously inserted record
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
$res=sasql_query($this->connection, $sql);
|
||||
if ($res===false) throw new Exception("SaSQL operation failed\n".sasql_error($this->connection));
|
||||
$this->last_result = $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
if (!$res)
|
||||
$res = $this->last_result;
|
||||
|
||||
return sasql_fetch_assoc($res);
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
return sasql_insert_id($this->connection);
|
||||
}
|
||||
|
||||
protected function insert_query($data,$request){
|
||||
$sql = parent::insert_query($data,$request);
|
||||
$this->insert_operation=true;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
protected function select_query($select,$from,$where,$sort,$start,$count){
|
||||
if (!$from)
|
||||
return $select;
|
||||
|
||||
$sql="SELECT " ;
|
||||
if ($count)
|
||||
$sql.=" TOP ".($count+$start);
|
||||
$sql.=" ".$select." FROM ".$from;
|
||||
if ($where) $sql.=" WHERE ".$where;
|
||||
if ($sort) $sql.=" ORDER BY ".$sort;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return sasql_escape_string($this->connection, $data);
|
||||
}
|
||||
|
||||
public function begin_transaction(){
|
||||
$this->query("BEGIN TRAN");
|
||||
}
|
||||
}
|
||||
?>
|
34
libraries/dhtmlxgantt/connector/db_sqlite.php
Normal file
34
libraries/dhtmlxgantt/connector/db_sqlite.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! SQLite implementation of DataWrapper
|
||||
**/
|
||||
class SQLiteDBDataWrapper extends DBDataWrapper{
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
|
||||
$res = sqlite_query($this->connection,$sql);
|
||||
if ($res === false)
|
||||
throw new Exception("SQLLite - sql execution failed\n".sqlite_error_string(sqlite_last_error($this->connection)));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = sqlite_fetch_array($res, SQLITE_ASSOC);
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
return sqlite_last_insert_rowid($this->connection);
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return sqlite_escape_string($data);
|
||||
}
|
||||
}
|
||||
?>
|
33
libraries/dhtmlxgantt/connector/db_sqlite3.php
Normal file
33
libraries/dhtmlxgantt/connector/db_sqlite3.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! SQLite implementation of DataWrapper
|
||||
**/
|
||||
class SQLite3DBDataWrapper extends DBDataWrapper{
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
|
||||
$res = $this->connection->query($sql);
|
||||
if ($res === false)
|
||||
throw new Exception("SQLLite - sql execution failed\n".$this->connection->lastErrorMsg());
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
return $res->fetchArray();
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
return $this->connection->lastInsertRowID();
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
return $this->connection->escapeString($data);
|
||||
}
|
||||
}
|
||||
?>
|
102
libraries/dhtmlxgantt/connector/db_sqlsrv.php
Normal file
102
libraries/dhtmlxgantt/connector/db_sqlsrv.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/*
|
||||
This software is allowed to use under GPL or you need to obtain Commercial or Enterise License
|
||||
to use it in non-GPL project. Please contact sales@dhtmlx.com for details
|
||||
*/
|
||||
?><?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("db_common.php");
|
||||
/*! MSSQL implementation of DataWrapper
|
||||
**/
|
||||
class SQLSrvDBDataWrapper extends DBDataWrapper{
|
||||
private $last_id=""; //!< ID of previously inserted record
|
||||
private $insert_operation=false; //!< flag of insert operation
|
||||
private $start_from=false; //!< index of start position
|
||||
|
||||
public function query($sql){
|
||||
LogMaster::log($sql);
|
||||
if ($this->start_from)
|
||||
$res = sqlsrv_query($this->connection,$sql, array(), array("Scrollable" => SQLSRV_CURSOR_STATIC));
|
||||
else
|
||||
$res = sqlsrv_query($this->connection,$sql);
|
||||
|
||||
if ($res === false){
|
||||
$errors = sqlsrv_errors();
|
||||
$message = Array();
|
||||
foreach($errors as $error)
|
||||
$message[]=$error["SQLSTATE"].$error["code"].$error["message"];
|
||||
throw new Exception("SQLSrv operation failed\n".implode("\n\n", $message));
|
||||
}
|
||||
|
||||
if ($this->insert_operation){
|
||||
sqlsrv_next_result($res);
|
||||
$last = sqlsrv_fetch_array($res);
|
||||
$this->last_id = $last["dhx_id"];
|
||||
sqlsrv_free_stmt($res);
|
||||
}
|
||||
if ($this->start_from)
|
||||
$data = sqlsrv_fetch($res, SQLSRV_SCROLL_ABSOLUTE, $this->start_from-1);
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get_next($res){
|
||||
$data = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC);
|
||||
if ($data)
|
||||
foreach ($data as $key => $value)
|
||||
if (is_a($value, "DateTime"))
|
||||
$data[$key] = $value->format("Y-m-d H:i");
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function get_new_id(){
|
||||
/*
|
||||
MSSQL doesn't support identity or auto-increment fields
|
||||
Insert SQL returns new ID value, which stored in last_id field
|
||||
*/
|
||||
return $this->last_id;
|
||||
}
|
||||
|
||||
protected function insert_query($data,$request){
|
||||
$sql = parent::insert_query($data,$request);
|
||||
$this->insert_operation=true;
|
||||
return $sql.";SELECT SCOPE_IDENTITY() as dhx_id";
|
||||
}
|
||||
|
||||
protected function select_query($select,$from,$where,$sort,$start,$count){
|
||||
if (!$from)
|
||||
return $select;
|
||||
|
||||
$sql="SELECT " ;
|
||||
if ($count)
|
||||
$sql.=" TOP ".($count+$start);
|
||||
$sql.=" ".$select." FROM ".$from;
|
||||
if ($where) $sql.=" WHERE ".$where;
|
||||
if ($sort) $sql.=" ORDER BY ".$sort;
|
||||
if ($start && $count)
|
||||
$this->start_from=$start;
|
||||
else
|
||||
$this->start_from=false;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function escape($data){
|
||||
/*
|
||||
there is no special escaping method for mssql - use common logic
|
||||
*/
|
||||
return str_replace("'","''",$data);
|
||||
}
|
||||
|
||||
public function begin_transaction(){
|
||||
sqlsrv_begin_transaction($this->connection);
|
||||
}
|
||||
public function commit_transaction(){
|
||||
sqlsrv_commit($this->connection);
|
||||
}
|
||||
public function rollback_transaction(){
|
||||
sqlsrv_rollback($this->connection);
|
||||
}
|
||||
}
|
||||
?>
|
19
libraries/dhtmlxgantt/connector/filesystem_item.php
Normal file
19
libraries/dhtmlxgantt/connector/filesystem_item.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
62
libraries/dhtmlxgantt/connector/form_connector.php
Normal file
62
libraries/dhtmlxgantt/connector/form_connector.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?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{
|
||||
|
||||
}
|
||||
?>
|
364
libraries/dhtmlxgantt/connector/gantt_connector.php
Normal file
364
libraries/dhtmlxgantt/connector/gantt_connector.php
Normal file
|
@ -0,0 +1,364 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("base_connector.php");
|
||||
require_once("data_connector.php");
|
||||
|
||||
/*! DataItem class for Gantt component
|
||||
**/
|
||||
class GanttDataItem extends DataItem{
|
||||
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$str="<task id='".$this->get_id()."' >";
|
||||
$str.="<start_date><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]></start_date>";
|
||||
$str.="<".$this->config->text[1]["name"]."><![CDATA[".$this->data[$this->config->text[1]["name"]]."]]></".$this->config->text[1]["name"].">";
|
||||
$str.="<text><![CDATA[".$this->data[$this->config->text[2]["name"]]."]]></text>";
|
||||
for ($i=3; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
$str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
|
||||
}
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$str.="<".$key."><![CDATA[".$value."]]></".$key.">";
|
||||
|
||||
return $str."</task>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Connector class for dhtmlxGantt
|
||||
**/
|
||||
class GanttConnector extends Connector{
|
||||
|
||||
protected $extra_output="";//!< extra info which need to be sent to client side
|
||||
protected $options=array();//!< hash of OptionsConnector
|
||||
protected $links_mode = false;
|
||||
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str="";
|
||||
foreach($options as $k => $v)
|
||||
$str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
|
||||
$options=$str;
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
* @param render_type
|
||||
name of class which will be used for rendering.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="GanttDataItem";
|
||||
if (!$data_type) $data_type="GanttDataProcessor";
|
||||
if (!$render_type) $render_type="RenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
|
||||
$this->event->attach("afterDelete", array($this, "delete_related_links"));
|
||||
$this->event->attach("afterOrder", array($this, "order_set_parent"));
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET["gantt_mode"]) && $_GET["gantt_mode"] == "links")
|
||||
$this->links_mode = true;
|
||||
|
||||
if (count($this->config->text)){
|
||||
if (isset($_GET["to"]))
|
||||
$this->request->set_filter($this->config->text[0]["name"],$_GET["to"],"<");
|
||||
if (isset($_GET["from"]))
|
||||
$this->request->set_filter($this->config->text[1]["name"],$_GET["from"],">");
|
||||
}
|
||||
}
|
||||
|
||||
function order_set_parent($action){
|
||||
$value = $action->get_id();
|
||||
$parent = $action->get_value("parent");
|
||||
|
||||
$table = $this->request->get_source();
|
||||
$id = $this->config->id["db_name"];
|
||||
|
||||
$this->sql->query("UPDATE $table SET parent = $parent WHERE $id = $value");
|
||||
}
|
||||
|
||||
function delete_related_links($action){
|
||||
if (isset($this->options["links"])){
|
||||
$links = $this->options["links"];
|
||||
$value = $this->sql->escape($action->get_new_id());
|
||||
$table = $links->get_request()->get_source();
|
||||
|
||||
$this->sql->query("DELETE FROM $table WHERE source = '$value'");
|
||||
$this->sql->query("DELETE FROM $table WHERE target = '$value'");
|
||||
}
|
||||
}
|
||||
|
||||
public function render_links($table,$id="",$fields=false,$extra=false,$relation_id=false) {
|
||||
$links = new GanttLinksConnector($this->get_connection(),$this->names["db_class"]);
|
||||
$links->render_table($table,$id,$fields,$extra);
|
||||
$this->set_options("links", $links);
|
||||
}
|
||||
}
|
||||
|
||||
/*! DataProcessor class for Gantt component
|
||||
**/
|
||||
class GanttDataProcessor extends DataProcessor{
|
||||
function name_data($data){
|
||||
if ($data=="start_date")
|
||||
return $this->config->text[0]["name"];
|
||||
if ($data=="id")
|
||||
return $this->config->id["name"];
|
||||
if ($data=="duration" && $this->config->text[1]["name"] == "duration")
|
||||
return $this->config->text[1]["name"];
|
||||
if ($data=="end_date" && $this->config->text[1]["name"] == "end_date")
|
||||
return $this->config->text[1]["name"];
|
||||
if ($data=="text")
|
||||
return $this->config->text[2]["name"];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONGanttDataItem extends GanttDataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$obj = array();
|
||||
$obj['id'] = $this->get_id();
|
||||
$obj['start_date'] = $this->data[$this->config->text[0]["name"]];
|
||||
$obj[$this->config->text[1]["name"]] = $this->data[$this->config->text[1]["name"]];
|
||||
$obj['text'] = $this->data[$this->config->text[2]["name"]];
|
||||
for ($i=3; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
$obj[$extra]=$this->data[$extra];
|
||||
}
|
||||
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$obj[$key]=$value;
|
||||
|
||||
return $obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONGanttConnector extends GanttConnector {
|
||||
|
||||
protected $data_separator = ",";
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="JSONGanttDataItem";
|
||||
if (!$data_type) $data_type="GanttDataProcessor";
|
||||
if (!$render_type) $render_type="JSONRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
protected function xml_start() {
|
||||
return '{ "data":';
|
||||
}
|
||||
|
||||
protected function xml_end() {
|
||||
$this->fill_collections();
|
||||
$end = (!empty($this->extra_output)) ? ', "collections": {'.$this->extra_output.'}' : '';
|
||||
foreach ($this->attributes as $k => $v)
|
||||
$end.=", \"".$k."\":\"".$v."\"";
|
||||
$end .= '}';
|
||||
return $end;
|
||||
}
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str=array();
|
||||
foreach($options as $k => $v)
|
||||
$str[]='{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
|
||||
$options=implode(",",$str);
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
|
||||
/*! generates xml description for options collections
|
||||
|
||||
@param list
|
||||
comma separated list of column names, for which options need to be generated
|
||||
*/
|
||||
protected function fill_collections($list=""){
|
||||
$options = array();
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
$option="\"{$name}\":[";
|
||||
if (!is_string($this->options[$name])){
|
||||
$data = json_encode($this->options[$name]->render());
|
||||
$option.=substr($data,1,-1);
|
||||
} else
|
||||
$option.=$this->options[$name];
|
||||
$option.="]";
|
||||
$options[] = $option;
|
||||
}
|
||||
$this->extra_output .= implode($this->data_separator, $options);
|
||||
}
|
||||
|
||||
|
||||
/*! output fetched data as XML
|
||||
@param res
|
||||
DB resultset
|
||||
*/
|
||||
protected function output_as_xml($res){
|
||||
$result = $this->render_set($res);
|
||||
if ($this->simple) return $result;
|
||||
|
||||
$data=$this->xml_start().json_encode($result).$this->xml_end();
|
||||
|
||||
if ($this->as_string) return $data;
|
||||
|
||||
$out = new OutputWriter($data, "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
|
||||
public function render_links($table,$id="",$fields=false,$extra=false,$relation_id=false) {
|
||||
$links = new JSONGanttLinksConnector($this->get_connection(),$this->names["db_class"]);
|
||||
$links->render_table($table,$id,$fields,$extra);
|
||||
$this->set_options("links", $links);
|
||||
}
|
||||
|
||||
|
||||
/*! render self
|
||||
process commands, output requested data as XML
|
||||
*/
|
||||
public function render(){
|
||||
$this->event->trigger("onInit", $this);
|
||||
EventMaster::trigger_static("connectorInit",$this);
|
||||
|
||||
if (!$this->as_string)
|
||||
$this->parse_request();
|
||||
$this->set_relation();
|
||||
|
||||
if ($this->live_update !== false && $this->updating!==false) {
|
||||
$this->live_update->get_updates();
|
||||
} else {
|
||||
if ($this->editing){
|
||||
if ($this->links_mode && isset($this->options["links"])) {
|
||||
$this->options["links"]->save();
|
||||
} else {
|
||||
$dp = new $this->names["data_class"]($this,$this->config,$this->request);
|
||||
$dp->process($this->config,$this->request);
|
||||
}
|
||||
} else {
|
||||
if (!$this->access->check("read")){
|
||||
LogMaster::log("Access control: read operation blocked");
|
||||
echo "Access denied";
|
||||
die();
|
||||
}
|
||||
$wrap = new SortInterface($this->request);
|
||||
$this->apply_sorts($wrap);
|
||||
$this->event->trigger("beforeSort",$wrap);
|
||||
$wrap->store();
|
||||
|
||||
$wrap = new FilterInterface($this->request);
|
||||
$this->apply_filters($wrap);
|
||||
$this->event->trigger("beforeFilter",$wrap);
|
||||
$wrap->store();
|
||||
|
||||
if ($this->model && method_exists($this->model, "get")){
|
||||
$this->sql = new ArrayDBDataWrapper();
|
||||
$result = new ArrayQueryWrapper(call_user_func(array($this->model, "get"), $this->request));
|
||||
$out = $this->output_as_xml($result);
|
||||
} else {
|
||||
$out = $this->output_as_xml($this->get_resource());
|
||||
|
||||
if ($out !== null) return $out;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$this->end_run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class GanttLinksConnector extends OptionsConnector {
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
|
||||
$res = $this->sql->select($this->request);
|
||||
return $this->render_set($res);
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$dp = new $this->names["data_class"]($this,$this->config,$this->request);
|
||||
$dp->process($this->config,$this->request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONGanttLinksConnector extends JSONOptionsConnector {
|
||||
public function render(){
|
||||
if (!$this->init_flag){
|
||||
$this->init_flag=true;
|
||||
return "";
|
||||
}
|
||||
|
||||
$res = $this->sql->select($this->request);
|
||||
return $this->render_set($res);
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$dp = new $this->names["data_class"]($this,$this->config,$this->request);
|
||||
$dp->process($this->config,$this->request);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
423
libraries/dhtmlxgantt/connector/grid_config.php
Normal file
423
libraries/dhtmlxgantt/connector/grid_config.php
Normal file
|
@ -0,0 +1,423 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
269
libraries/dhtmlxgantt/connector/grid_connector.php
Normal file
269
libraries/dhtmlxgantt/connector/grid_connector.php
Normal file
|
@ -0,0 +1,269 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("base_connector.php");
|
||||
require_once("grid_config.php");
|
||||
|
||||
//require_once("grid_dataprocessor.php");
|
||||
|
||||
/*! DataItem class for Grid component
|
||||
**/
|
||||
|
||||
class GridDataItem extends DataItem{
|
||||
protected $row_attrs;//!< hash of row attributes
|
||||
protected $cell_attrs;//!< hash of cell attributes
|
||||
|
||||
function __construct($data,$name,$index=0){
|
||||
parent::__construct($data,$name,$index);
|
||||
|
||||
$this->row_attrs=array();
|
||||
$this->cell_attrs=array();
|
||||
}
|
||||
/*! set color of row
|
||||
|
||||
@param color
|
||||
color of row
|
||||
*/
|
||||
function set_row_color($color){
|
||||
$this->row_attrs["bgColor"]=$color;
|
||||
}
|
||||
/*! set style of row
|
||||
|
||||
@param color
|
||||
color of row
|
||||
*/
|
||||
function set_row_style($color){
|
||||
$this->row_attrs["style"]=$color;
|
||||
}
|
||||
/*! assign custom style to the cell
|
||||
|
||||
@param name
|
||||
name of column
|
||||
@param value
|
||||
css style string
|
||||
*/
|
||||
function set_cell_style($name,$value){
|
||||
$this->set_cell_attribute($name,"style",$value);
|
||||
}
|
||||
/*! assign custom class to specific cell
|
||||
|
||||
@param name
|
||||
name of column
|
||||
@param value
|
||||
css class name
|
||||
*/
|
||||
function set_cell_class($name,$value){
|
||||
$this->set_cell_attribute($name,"class",$value);
|
||||
}
|
||||
/*! set custom cell attribute
|
||||
|
||||
@param name
|
||||
name of column
|
||||
@param attr
|
||||
name of attribute
|
||||
@param value
|
||||
value of attribute
|
||||
*/
|
||||
function set_cell_attribute($name,$attr,$value){
|
||||
if (!array_key_exists($name, $this->cell_attrs)) $this->cell_attrs[$name]=array();
|
||||
$this->cell_attrs[$name][$attr]=$value;
|
||||
}
|
||||
|
||||
/*! set custom row attribute
|
||||
|
||||
@param attr
|
||||
name of attribute
|
||||
@param value
|
||||
value of attribute
|
||||
*/
|
||||
function set_row_attribute($attr,$value){
|
||||
$this->row_attrs[$attr]=$value;
|
||||
}
|
||||
|
||||
/*! return self as XML string, starting part
|
||||
*/
|
||||
public function to_xml_start(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$str="<row id='".$this->xmlentities($this->get_id())."'";
|
||||
foreach ($this->row_attrs as $k=>$v)
|
||||
$str.=" ".$k."='".$v."'";
|
||||
$str.=">";
|
||||
for ($i=0; $i < sizeof($this->config->text); $i++){
|
||||
$str.="<cell";
|
||||
$name=$this->config->text[$i]["name"];
|
||||
$xmlcontent = false;
|
||||
if (isset($this->cell_attrs[$name])){
|
||||
$cattrs=$this->cell_attrs[$name];
|
||||
foreach ($cattrs as $k => $v){
|
||||
$str.=" ".$k."='".$this->xmlentities($v)."'";
|
||||
if ($k == "xmlcontent")
|
||||
$xmlcontent = true;
|
||||
}
|
||||
}
|
||||
$value = isset($this->data[$name]) ? $this->data[$name] : '';
|
||||
if (!$xmlcontent)
|
||||
$str.="><![CDATA[".$value."]]></cell>";
|
||||
else
|
||||
$str.=">".$value."</cell>";
|
||||
}
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$str.="<userdata name='".$key."'><![CDATA[".$value."]]></userdata>";
|
||||
|
||||
return $str;
|
||||
}
|
||||
/*! return self as XML string, ending part
|
||||
*/
|
||||
public function to_xml_end(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
return "</row>";
|
||||
}
|
||||
}
|
||||
/*! Connector for the dhtmlxgrid
|
||||
**/
|
||||
class GridConnector extends Connector{
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="GridDataItem";
|
||||
if (!$data_type) $data_type="GridDataProcessor";
|
||||
if (!$render_type) $render_type="RenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
|
||||
protected function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET["dhx_colls"]))
|
||||
$this->fill_collections($_GET["dhx_colls"]);
|
||||
}
|
||||
protected function resolve_parameter($name){
|
||||
if (intval($name).""==$name)
|
||||
return $this->config->text[intval($name)]["db_name"];
|
||||
return $name;
|
||||
}
|
||||
|
||||
/*! replace xml unsafe characters
|
||||
|
||||
@param string
|
||||
string to be escaped
|
||||
@return
|
||||
escaped string
|
||||
*/
|
||||
protected function xmlentities($string) {
|
||||
return str_replace( array( '&', '"', "'", '<', '>', '’' ), array( '&' , '"', ''' , '<' , '>', ''' ), $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;
|
||||
}
|
||||
}
|
||||
?>
|
48
libraries/dhtmlxgantt/connector/keygrid_connector.php
Normal file
48
libraries/dhtmlxgantt/connector/keygrid_connector.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
28
libraries/dhtmlxgantt/connector/mixed_connector.php
Normal file
28
libraries/dhtmlxgantt/connector/mixed_connector.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("base_connector.php");
|
||||
|
||||
class MixedConnector extends Connector {
|
||||
|
||||
protected $connectors = array();
|
||||
|
||||
public function add($name, $conn) {
|
||||
$this->connectors[$name] = $conn;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$result = "{";
|
||||
$parts = array();
|
||||
foreach($this->connectors as $name => $conn) {
|
||||
$conn->asString(true);
|
||||
$parts[] = "\"".$name."\":".($conn->render())."\n";
|
||||
}
|
||||
$result .= implode(",\n", $parts)."}";
|
||||
echo $result;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
45
libraries/dhtmlxgantt/connector/options_connector.php
Normal file
45
libraries/dhtmlxgantt/connector/options_connector.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
230
libraries/dhtmlxgantt/connector/scheduler_connector.php
Normal file
230
libraries/dhtmlxgantt/connector/scheduler_connector.php
Normal file
|
@ -0,0 +1,230 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("base_connector.php");
|
||||
require_once("data_connector.php");
|
||||
|
||||
/*! DataItem class for Scheduler component
|
||||
**/
|
||||
class SchedulerDataItem extends DataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$str="<event id='".$this->get_id()."' >";
|
||||
$str.="<start_date><![CDATA[".$this->data[$this->config->text[0]["name"]]."]]></start_date>";
|
||||
$str.="<end_date><![CDATA[".$this->data[$this->config->text[1]["name"]]."]]></end_date>";
|
||||
$str.="<text><![CDATA[".$this->data[$this->config->text[2]["name"]]."]]></text>";
|
||||
for ($i=3; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
$str.="<".$extra."><![CDATA[".$this->data[$extra]."]]></".$extra.">";
|
||||
}
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$str.="<".$key."><![CDATA[".$value."]]></".$key.">";
|
||||
|
||||
return $str."</event>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Connector class for dhtmlxScheduler
|
||||
**/
|
||||
class SchedulerConnector extends Connector{
|
||||
|
||||
protected $extra_output="";//!< extra info which need to be sent to client side
|
||||
protected $options=array();//!< hash of OptionsConnector
|
||||
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str="";
|
||||
foreach($options as $k => $v)
|
||||
$str.="<item value='".$this->xmlentities($k)."' label='".$this->xmlentities($v)."' />";
|
||||
$options=$str;
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
* @param render_type
|
||||
name of class which will be used for rendering.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="SchedulerDataItem";
|
||||
if (!$data_type) $data_type="SchedulerDataProcessor";
|
||||
if (!$render_type) $render_type="RenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
function parse_request(){
|
||||
parent::parse_request();
|
||||
if (count($this->config->text)){
|
||||
if (isset($_GET["to"]))
|
||||
$this->request->set_filter($this->config->text[0]["name"],$_GET["to"],"<");
|
||||
if (isset($_GET["from"]))
|
||||
$this->request->set_filter($this->config->text[1]["name"],$_GET["from"],">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! DataProcessor class for Scheduler component
|
||||
**/
|
||||
class SchedulerDataProcessor extends DataProcessor{
|
||||
function name_data($data){
|
||||
if ($data=="start_date")
|
||||
return $this->config->text[0]["db_name"];
|
||||
if ($data=="id")
|
||||
return $this->config->id["db_name"];
|
||||
if ($data=="end_date")
|
||||
return $this->config->text[1]["db_name"];
|
||||
if ($data=="text")
|
||||
return $this->config->text[2]["db_name"];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONSchedulerDataItem extends SchedulerDataItem{
|
||||
/*! return self as XML string
|
||||
*/
|
||||
function to_xml(){
|
||||
if ($this->skip) return "";
|
||||
|
||||
$obj = array();
|
||||
$obj['id'] = $this->get_id();
|
||||
$obj['start_date'] = $this->data[$this->config->text[0]["name"]];
|
||||
$obj['end_date'] = $this->data[$this->config->text[1]["name"]];
|
||||
$obj['text'] = $this->data[$this->config->text[2]["name"]];
|
||||
for ($i=3; $i<sizeof($this->config->text); $i++){
|
||||
$extra = $this->config->text[$i]["name"];
|
||||
$obj[$extra]=$this->data[$extra];
|
||||
}
|
||||
|
||||
if ($this->userdata !== false)
|
||||
foreach ($this->userdata as $key => $value)
|
||||
$obj[$key]=$value;
|
||||
|
||||
return $obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class JSONSchedulerConnector extends SchedulerConnector {
|
||||
|
||||
protected $data_separator = ",";
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="JSONSchedulerDataItem";
|
||||
if (!$data_type) $data_type="SchedulerDataProcessor";
|
||||
if (!$render_type) $render_type="JSONRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
protected function xml_start() {
|
||||
return '{ "data":';
|
||||
}
|
||||
|
||||
protected function xml_end() {
|
||||
$this->fill_collections();
|
||||
$end = (!empty($this->extra_output)) ? ', "collections": {'.$this->extra_output.'}' : '';
|
||||
foreach ($this->attributes as $k => $v)
|
||||
$end.=", \"".$k."\":\"".$v."\"";
|
||||
$end .= '}';
|
||||
return $end;
|
||||
}
|
||||
|
||||
/*! assign options collection to the column
|
||||
|
||||
@param name
|
||||
name of the column
|
||||
@param options
|
||||
array or connector object
|
||||
*/
|
||||
public function set_options($name,$options){
|
||||
if (is_array($options)){
|
||||
$str=array();
|
||||
foreach($options as $k => $v)
|
||||
$str[]='{"id":"'.$this->xmlentities($k).'", "value":"'.$this->xmlentities($v).'"}';
|
||||
$options=implode(",",$str);
|
||||
}
|
||||
$this->options[$name]=$options;
|
||||
}
|
||||
|
||||
|
||||
/*! generates xml description for options collections
|
||||
|
||||
@param list
|
||||
comma separated list of column names, for which options need to be generated
|
||||
*/
|
||||
protected function fill_collections($list=""){
|
||||
$options = array();
|
||||
foreach ($this->options as $k=>$v) {
|
||||
$name = $k;
|
||||
$option="\"{$name}\":[";
|
||||
if (!is_string($this->options[$name])){
|
||||
$data = json_encode($this->options[$name]->render());
|
||||
$option.=substr($data,1,-1);
|
||||
} else
|
||||
$option.=$this->options[$name];
|
||||
$option.="]";
|
||||
$options[] = $option;
|
||||
}
|
||||
$this->extra_output .= implode($this->data_separator, $options);
|
||||
}
|
||||
|
||||
|
||||
/*! output fetched data as XML
|
||||
@param res
|
||||
DB resultset
|
||||
*/
|
||||
protected function output_as_xml($res){
|
||||
$result = $this->render_set($res);
|
||||
if ($this->simple) return $result;
|
||||
|
||||
$data=$this->xml_start().json_encode($result).$this->xml_end();
|
||||
|
||||
if ($this->as_string) return $data;
|
||||
|
||||
$out = new OutputWriter($data, "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
}
|
||||
?>
|
508
libraries/dhtmlxgantt/connector/strategy.php
Normal file
508
libraries/dhtmlxgantt/connector/strategy.php
Normal file
|
@ -0,0 +1,508 @@
|
|||
<?php
|
||||
|
||||
class RenderStrategy {
|
||||
|
||||
protected $conn = null;
|
||||
|
||||
public function __construct($conn) {
|
||||
$this->conn = $conn;
|
||||
}
|
||||
|
||||
/*! adds mix fields into DataConfig
|
||||
* @param config
|
||||
* DataConfig object
|
||||
* @param mix
|
||||
* mix structure
|
||||
*/
|
||||
protected function mix($config, $mix) {
|
||||
for ($i = 0; $i < count($mix); $i++) {
|
||||
if ($config->is_field($mix[$i]['name'])===-1) {
|
||||
$config->add_field($mix[$i]['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! remove mix fields from DataConfig
|
||||
* @param config
|
||||
* DataConfig object
|
||||
* @param mix
|
||||
* mix structure
|
||||
*/
|
||||
protected function unmix($config, $mix) {
|
||||
for ($i = 0; $i < count($mix); $i++) {
|
||||
if ($config->is_field($mix[$i]['name'])!==-1) {
|
||||
$config->remove_field_full($mix[$i]['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! adds mix fields in item
|
||||
* simple mix adds only strings specified by user
|
||||
* @param mix
|
||||
* mix structure
|
||||
* @param data
|
||||
* array of selected data
|
||||
*/
|
||||
protected function simple_mix($mix, $data) {
|
||||
// get mix details
|
||||
for ($i = 0; $i < count($mix); $i++)
|
||||
$data[$mix[$i]["name"]] = is_object($mix[$i]["value"]) ? "" : $mix[$i]["value"];
|
||||
return $data;
|
||||
}
|
||||
|
||||
/*! adds mix fields in item
|
||||
* complex mix adds strings specified by user and results of subrequests
|
||||
* @param mix
|
||||
* mix structure
|
||||
* @param data
|
||||
* array of selected data
|
||||
*/
|
||||
protected function complex_mix($mix, $data) {
|
||||
// get mix details
|
||||
for ($i = 0; $i < count($mix); $i++) {
|
||||
$mixname = $mix[$i]["name"];
|
||||
if ($mix[$i]['filter'] !== false) {
|
||||
$subconn = $mix[$i]["value"];
|
||||
$filter = $mix[$i]["filter"];
|
||||
|
||||
// setting relationships
|
||||
$subconn->clear_filter();
|
||||
foreach ($filter as $k => $v)
|
||||
if (isset($data[$v]))
|
||||
$subconn->filter($k, $data[$v], "=");
|
||||
else
|
||||
throw new Exception('There was no such data field registered as: '.$k);
|
||||
|
||||
$subconn->asString(true);
|
||||
$data[$mixname]=$subconn->simple_render();
|
||||
if (is_array($data[$mixname]) && count($data[$mixname]) == 1)
|
||||
$data[$mixname] = $data[$mixname][0];
|
||||
} else {
|
||||
$data[$mixname] = $mix[$i]["value"];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/*! render from DB resultset
|
||||
@param res
|
||||
DB resultset
|
||||
process commands, output requested data as XML
|
||||
*/
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$this->mix($config, $mix);
|
||||
$conn->event->trigger("beforeRenderSet",$conn,$res,$config);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$data = $this->simple_mix($mix, $data);
|
||||
|
||||
$data = new $name($data,$config,$index);
|
||||
if ($data->get_id()===false)
|
||||
$data->set_id($conn->uuid());
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
$output.=$data->to_xml().$sep;
|
||||
$index++;
|
||||
}
|
||||
$this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class JSONRenderStrategy extends RenderStrategy {
|
||||
|
||||
/*! render from DB resultset
|
||||
@param res
|
||||
DB resultset
|
||||
process commands, output requested data as json
|
||||
*/
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$this->mix($config, $mix);
|
||||
$conn->event->trigger("beforeRenderSet",$conn,$res,$config);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$data = $this->complex_mix($mix, $data);
|
||||
$data = new $name($data,$config,$index);
|
||||
if ($data->get_id()===false)
|
||||
$data->set_id($conn->uuid());
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
$item = $data->to_xml();
|
||||
if ($item !== false)
|
||||
$output[]=$item;
|
||||
$index++;
|
||||
}
|
||||
$this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TreeRenderStrategy extends RenderStrategy {
|
||||
|
||||
protected $id_swap = array();
|
||||
|
||||
public function __construct($conn) {
|
||||
parent::__construct($conn);
|
||||
$conn->event->attach("afterInsert",array($this,"parent_id_correction_a"));
|
||||
$conn->event->attach("beforeProcessing",array($this,"parent_id_correction_b"));
|
||||
}
|
||||
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$config_copy = new DataConfig($config);
|
||||
$this->mix($config, $mix);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$data = $this->simple_mix($mix, $data);
|
||||
$data = new $name($data,$config,$index);
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
//there is no info about child elements,
|
||||
//if we are using dyn. loading - assume that it has,
|
||||
//in normal mode juse exec sub-render routine
|
||||
if ($data->has_kids()===-1 && $dload)
|
||||
$data->set_kids(true);
|
||||
$output.=$data->to_xml_start();
|
||||
if ($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload)){
|
||||
$sub_request = new DataRequestConfig($conn->get_request());
|
||||
//$sub_request->set_fieldset(implode(",",$config_copy->db_names_list($conn->sql)));
|
||||
$sub_request->set_relation($data->get_id());
|
||||
$output.=$this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config_copy, $mix);
|
||||
}
|
||||
$output.=$data->to_xml_end();
|
||||
$index++;
|
||||
}
|
||||
$this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
/*! store info about ID changes during insert operation
|
||||
@param dataAction
|
||||
data action object during insert operation
|
||||
*/
|
||||
public function parent_id_correction_a($dataAction){
|
||||
$this->id_swap[$dataAction->get_id()]=$dataAction->get_new_id();
|
||||
}
|
||||
|
||||
/*! update ID if it was affected by previous operation
|
||||
@param dataAction
|
||||
data action object, before any processing operation
|
||||
*/
|
||||
public function parent_id_correction_b($dataAction){
|
||||
$relation = $this->conn->get_config()->relation_id["db_name"];
|
||||
$value = $dataAction->get_value($relation);
|
||||
|
||||
if (array_key_exists($value,$this->id_swap))
|
||||
$dataAction->set_value($relation,$this->id_swap[$value]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class JSONTreeRenderStrategy extends TreeRenderStrategy {
|
||||
|
||||
public function render_set($res, $name, $dload, $sep, $config,$mix){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$config_copy = new DataConfig($config);
|
||||
$this->mix($config, $mix);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$data = $this->complex_mix($mix, $data);
|
||||
$data = new $name($data,$config,$index);
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
//there is no info about child elements,
|
||||
//if we are using dyn. loading - assume that it has,
|
||||
//in normal mode just exec sub-render routine
|
||||
if ($data->has_kids()===-1 && $dload)
|
||||
$data->set_kids(true);
|
||||
$record = $data->to_xml_start();
|
||||
if ($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload)){
|
||||
$sub_request = new DataRequestConfig($conn->get_request());
|
||||
//$sub_request->set_fieldset(implode(",",$config_copy->db_names_list($conn->sql)));
|
||||
$sub_request->set_relation($data->get_id());
|
||||
//$sub_request->set_filters(array());
|
||||
$temp = $this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config_copy, $mix);
|
||||
if (sizeof($temp))
|
||||
$record["data"] = $temp;
|
||||
}
|
||||
if ($record !== false)
|
||||
$output[] = $record;
|
||||
$index++;
|
||||
}
|
||||
$this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MultitableTreeRenderStrategy extends TreeRenderStrategy {
|
||||
|
||||
private $level = 0;
|
||||
private $max_level = null;
|
||||
protected $sep = ",";
|
||||
|
||||
public function __construct($conn) {
|
||||
parent::__construct($conn);
|
||||
$conn->event->attach("beforeProcessing", Array($this, 'id_translate_before'));
|
||||
$conn->event->attach("afterProcessing", Array($this, 'id_translate_after'));
|
||||
}
|
||||
|
||||
public function set_separator($sep) {
|
||||
$this->sep = $sep;
|
||||
}
|
||||
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$this->mix($config, $mix);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$data = $this->simple_mix($mix, $data);
|
||||
$data[$config->id['name']] = $this->level_id($data[$config->id['name']]);
|
||||
$data = new $name($data,$config,$index);
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
if (($this->max_level !== null)&&($conn->get_level() == $this->max_level)) {
|
||||
$data->set_kids(false);
|
||||
} else {
|
||||
if ($data->has_kids()===-1)
|
||||
$data->set_kids(true);
|
||||
}
|
||||
$output.=$data->to_xml_start();
|
||||
$output.=$data->to_xml_end();
|
||||
$index++;
|
||||
}
|
||||
$this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
public function level_id($id, $level = null) {
|
||||
return ($level === null ? $this->level : $level).$this->sep.$id;
|
||||
}
|
||||
|
||||
|
||||
/*! remove level prefix from id, parent id and set new id before processing
|
||||
@param action
|
||||
DataAction object
|
||||
*/
|
||||
public function id_translate_before($action) {
|
||||
$id = $action->get_id();
|
||||
$id = $this->parse_id($id, false);
|
||||
$action->set_id($id);
|
||||
$action->set_value('tr_id', $id);
|
||||
$action->set_new_id($id);
|
||||
$pid = $action->get_value($this->conn->get_config()->relation_id['db_name']);
|
||||
$pid = $this->parse_id($pid, false);
|
||||
$action->set_value($this->conn->get_config()->relation_id['db_name'], $pid);
|
||||
}
|
||||
|
||||
|
||||
/*! add level prefix in id and new id after processing
|
||||
@param action
|
||||
DataAction object
|
||||
*/
|
||||
public function id_translate_after($action) {
|
||||
$id = $action->get_id();
|
||||
$action->set_id($this->level_id($id));
|
||||
$id = $action->get_new_id();
|
||||
$action->success($this->level_id($id));
|
||||
}
|
||||
|
||||
|
||||
public function get_level($parent_name) {
|
||||
if ($this->level) return $this->level;
|
||||
if (!isset($_GET[$parent_name])) {
|
||||
if (isset($_POST['ids'])) {
|
||||
$ids = explode(",",$_POST["ids"]);
|
||||
$id = $this->parse_id($ids[0]);
|
||||
$this->level--;
|
||||
}
|
||||
$this->conn->get_request()->set_relation(false);
|
||||
} else {
|
||||
$id = $this->parse_id($_GET[$parent_name]);
|
||||
$_GET[$parent_name] = $id;
|
||||
}
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
|
||||
public function is_max_level() {
|
||||
if (($this->max_level !== null) && ($this->level >= $this->max_level))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
public function set_max_level($max_level) {
|
||||
$this->max_level = $max_level;
|
||||
}
|
||||
public function parse_id($id, $set_level = true) {
|
||||
$parts = explode($this->sep, $id, 2);
|
||||
if (count($parts) === 2) {
|
||||
$level = $parts[0] + 1;
|
||||
$id = $parts[1];
|
||||
} else {
|
||||
$level = 0;
|
||||
$id = '';
|
||||
}
|
||||
if ($set_level) $this->level = $level;
|
||||
return $id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class JSONMultitableTreeRenderStrategy extends MultitableTreeRenderStrategy {
|
||||
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
$this->mix($config, $mix);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
$data = $this->complex_mix($mix, $data);
|
||||
$data[$config->id['name']] = $this->level_id($data[$config->id['name']]);
|
||||
$data = new $name($data,$config,$index);
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
|
||||
if ($this->is_max_level()) {
|
||||
$data->set_kids(false);
|
||||
} else {
|
||||
if ($data->has_kids()===-1)
|
||||
$data->set_kids(true);
|
||||
}
|
||||
$record = $data->to_xml_start($output);
|
||||
$output[] = $record;
|
||||
$index++;
|
||||
}
|
||||
$this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class GroupRenderStrategy extends RenderStrategy {
|
||||
|
||||
protected $id_postfix = '__{group_param}';
|
||||
|
||||
public function __construct($conn) {
|
||||
parent::__construct($conn);
|
||||
$conn->event->attach("beforeProcessing", Array($this, 'check_id'));
|
||||
$conn->event->attach("onInit", Array($this, 'replace_postfix'));
|
||||
}
|
||||
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix, $usemix = false){
|
||||
$output="";
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
if ($usemix) $this->mix($config, $mix);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
if (isset($data[$config->id['name']])) {
|
||||
$this->simple_mix($mix, $data);
|
||||
$has_kids = false;
|
||||
} else {
|
||||
$data[$config->id['name']] = $data['value'].$this->id_postfix;
|
||||
$data[$config->text[0]['name']] = $data['value'];
|
||||
$has_kids = true;
|
||||
}
|
||||
$data = new $name($data,$config,$index);
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
if ($has_kids === false) {
|
||||
$data->set_kids(false);
|
||||
}
|
||||
|
||||
if ($data->has_kids()===-1 && $dload)
|
||||
$data->set_kids(true);
|
||||
$output.=$data->to_xml_start();
|
||||
if (($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload))&&($has_kids == true)){
|
||||
$sub_request = new DataRequestConfig($conn->get_request());
|
||||
$sub_request->set_relation(str_replace($this->id_postfix, "", $data->get_id()));
|
||||
$output.=$this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config, $mix, true);
|
||||
}
|
||||
$output.=$data->to_xml_end();
|
||||
$index++;
|
||||
}
|
||||
if ($usemix) $this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function check_id($action) {
|
||||
if (isset($_GET['editing'])) {
|
||||
$config = $this->conn->get_config();
|
||||
$id = $action->get_id();
|
||||
$pid = $action->get_value($config->relation_id['name']);
|
||||
$pid = str_replace($this->id_postfix, "", $pid);
|
||||
$action->set_value($config->relation_id['name'], $pid);
|
||||
if (!empty($pid)) {
|
||||
return $action;
|
||||
} else {
|
||||
$action->error();
|
||||
$action->set_response_text("This record can't be updated!");
|
||||
return $action;
|
||||
}
|
||||
} else {
|
||||
return $action;
|
||||
}
|
||||
}
|
||||
|
||||
public function replace_postfix() {
|
||||
if (isset($_GET['id'])) {
|
||||
$_GET['id'] = str_replace($this->id_postfix, "", $_GET['id']);
|
||||
}
|
||||
}
|
||||
|
||||
public function get_postfix() {
|
||||
return $this->id_postfix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class JSONGroupRenderStrategy extends GroupRenderStrategy {
|
||||
|
||||
public function render_set($res, $name, $dload, $sep, $config, $mix, $usemix = false){
|
||||
$output=array();
|
||||
$index=0;
|
||||
$conn = $this->conn;
|
||||
if ($usemix) $this->mix($config, $mix);
|
||||
while ($data=$conn->sql->get_next($res)){
|
||||
if (isset($data[$config->id['name']])) {
|
||||
$data = $this->complex_mix($mix, $data);
|
||||
$has_kids = false;
|
||||
} else {
|
||||
$data[$config->id['name']] = $data['value'].$this->id_postfix;
|
||||
$data[$config->text[0]['name']] = $data['value'];
|
||||
$has_kids = true;
|
||||
}
|
||||
$data = new $name($data,$config,$index);
|
||||
$conn->event->trigger("beforeRender",$data);
|
||||
if ($has_kids === false) {
|
||||
$data->set_kids(false);
|
||||
}
|
||||
|
||||
if ($data->has_kids()===-1 && $dload)
|
||||
$data->set_kids(true);
|
||||
$record = $data->to_xml_start();
|
||||
if (($data->has_kids()===-1 || ( $data->has_kids()==true && !$dload))&&($has_kids == true)){
|
||||
$sub_request = new DataRequestConfig($conn->get_request());
|
||||
$sub_request->set_relation(str_replace($this->id_postfix, "", $data->get_id()));
|
||||
$temp = $this->render_set($conn->sql->select($sub_request), $name, $dload, $sep, $config, $mix, true);
|
||||
if (sizeof($temp))
|
||||
$record["data"] = $temp;
|
||||
}
|
||||
$output[] = $record;
|
||||
$index++;
|
||||
}
|
||||
if ($usemix) $this->unmix($config, $mix);
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
267
libraries/dhtmlxgantt/connector/tools.php
Normal file
267
libraries/dhtmlxgantt/connector/tools.php
Normal file
|
@ -0,0 +1,267 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
|
||||
/*! Class which allows to assign|fire events.
|
||||
*/
|
||||
class EventMaster{
|
||||
private $events;//!< hash of event handlers
|
||||
private $master;
|
||||
private static $eventsStatic=array();
|
||||
|
||||
/*! constructor
|
||||
*/
|
||||
function __construct(){
|
||||
$this->events=array();
|
||||
$this->master = false;
|
||||
}
|
||||
/*! Method check if event with such name already exists.
|
||||
@param name
|
||||
name of event, case non-sensitive
|
||||
@return
|
||||
true if event with such name registered, false otherwise
|
||||
*/
|
||||
public function exist($name){
|
||||
$name=strtolower($name);
|
||||
return (isset($this->events[$name]) && sizeof($this->events[$name]));
|
||||
}
|
||||
/*! Attach custom code to event.
|
||||
|
||||
Only on event handler can be attached in the same time. If new event handler attached - old will be detached.
|
||||
|
||||
@param name
|
||||
name of event, case non-sensitive
|
||||
@param method
|
||||
function which will be attached. You can use array(class, method) if you want to attach the method of the class.
|
||||
*/
|
||||
public function attach($name,$method=false){
|
||||
//use class for event handling
|
||||
if ($method === false){
|
||||
$this->master = $name;
|
||||
return;
|
||||
}
|
||||
//use separate functions
|
||||
$name=strtolower($name);
|
||||
if (!array_key_exists($name,$this->events))
|
||||
$this->events[$name]=array();
|
||||
$this->events[$name][]=$method;
|
||||
}
|
||||
|
||||
public static function attach_static($name, $method){
|
||||
$name=strtolower($name);
|
||||
if (!array_key_exists($name,EventMaster::$eventsStatic))
|
||||
EventMaster::$eventsStatic[$name]=array();
|
||||
EventMaster::$eventsStatic[$name][]=$method;
|
||||
}
|
||||
|
||||
public static function trigger_static($name, $method){
|
||||
$arg_list = func_get_args();
|
||||
$name=strtolower(array_shift($arg_list));
|
||||
|
||||
if (isset(EventMaster::$eventsStatic[$name]))
|
||||
foreach(EventMaster::$eventsStatic[$name] as $method){
|
||||
if (is_array($method) && !method_exists($method[0],$method[1]))
|
||||
throw new Exception("Incorrect method assigned to event: ".$method[0].":".$method[1]);
|
||||
if (!is_array($method) && !function_exists($method))
|
||||
throw new Exception("Incorrect function assigned to event: ".$method);
|
||||
call_user_func_array($method, $arg_list);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Detach code from event
|
||||
@param name
|
||||
name of event, case non-sensitive
|
||||
*/
|
||||
public function detach($name){
|
||||
$name=strtolower($name);
|
||||
unset($this->events[$name]);
|
||||
}
|
||||
/*! Trigger event.
|
||||
@param name
|
||||
name of event, case non-sensitive
|
||||
@param data
|
||||
value which will be provided as argument for event function,
|
||||
you can provide multiple data arguments, method accepts variable number of parameters
|
||||
@return
|
||||
true if event handler was not assigned , result of event hangler otherwise
|
||||
*/
|
||||
public function trigger($name,$data){
|
||||
$arg_list = func_get_args();
|
||||
$name=strtolower(array_shift($arg_list));
|
||||
|
||||
if (isset($this->events[$name]))
|
||||
foreach($this->events[$name] as $method){
|
||||
if (is_array($method) && !method_exists($method[0],$method[1]))
|
||||
throw new Exception("Incorrect method assigned to event: ".$method[0].":".$method[1]);
|
||||
if (!is_array($method) && !function_exists($method))
|
||||
throw new Exception("Incorrect function assigned to event: ".$method);
|
||||
call_user_func_array($method, $arg_list);
|
||||
}
|
||||
|
||||
if ($this->master !== false)
|
||||
if (method_exists($this->master, $name))
|
||||
call_user_func_array(array($this->master, $name), $arg_list);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Class which handles access rules.
|
||||
**/
|
||||
class AccessMaster{
|
||||
private $rules,$local;
|
||||
/*! constructor
|
||||
|
||||
Set next access right to "allowed" by default : read, insert, update, delete
|
||||
Basically - all common data operations allowed by default
|
||||
*/
|
||||
function __construct(){
|
||||
$this->rules=array("read" => true, "insert" => true, "update" => true, "delete" => true);
|
||||
$this->local=true;
|
||||
}
|
||||
/*! change access rule to "allow"
|
||||
@param name
|
||||
name of access right
|
||||
*/
|
||||
public function allow($name){
|
||||
$this->rules[$name]=true;
|
||||
}
|
||||
/*! change access rule to "deny"
|
||||
|
||||
@param name
|
||||
name of access right
|
||||
*/
|
||||
public function deny($name){
|
||||
$this->rules[$name]=false;
|
||||
}
|
||||
|
||||
/*! change all access rules to "deny"
|
||||
*/
|
||||
public function deny_all(){
|
||||
$this->rules=array();
|
||||
}
|
||||
|
||||
/*! check access rule
|
||||
|
||||
@param name
|
||||
name of access right
|
||||
@return
|
||||
true if access rule allowed, false otherwise
|
||||
*/
|
||||
public function check($name){
|
||||
if ($this->local){
|
||||
/*!
|
||||
todo
|
||||
add referrer check, to prevent access from remote points
|
||||
*/
|
||||
}
|
||||
if (!isset($this->rules[$name]) || !$this->rules[$name]){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Controls error and debug logging.
|
||||
Class designed to be used as static object.
|
||||
**/
|
||||
class LogMaster{
|
||||
private static $_log=false;//!< logging mode flag
|
||||
private static $_output=false;//!< output error infor to client flag
|
||||
private static $session="";//!< all messages generated for current request
|
||||
|
||||
/*! convert array to string representation ( it is a bit more readable than var_dump )
|
||||
|
||||
@param data
|
||||
data object
|
||||
@param pref
|
||||
prefix string, used for formating, optional
|
||||
@return
|
||||
string with array description
|
||||
*/
|
||||
private static function log_details($data,$pref=""){
|
||||
if (is_array($data)){
|
||||
$str=array("");
|
||||
foreach($data as $k=>$v)
|
||||
array_push($str,$pref.$k." => ".LogMaster::log_details($v,$pref."\t"));
|
||||
return implode("\n",$str);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
/*! put record in log
|
||||
|
||||
@param str
|
||||
string with log info, optional
|
||||
@param data
|
||||
data object, which will be added to log, optional
|
||||
*/
|
||||
public static function log($str="",$data=""){
|
||||
if (LogMaster::$_log){
|
||||
$message = $str.LogMaster::log_details($data)."\n\n";
|
||||
LogMaster::$session.=$message;
|
||||
error_log($message,3,LogMaster::$_log);
|
||||
}
|
||||
}
|
||||
|
||||
/*! get logs for current request
|
||||
@return
|
||||
string, which contains all log messages generated for current request
|
||||
*/
|
||||
public static function get_session_log(){
|
||||
return LogMaster::$session;
|
||||
}
|
||||
|
||||
/*! error handler, put normal php errors in log file
|
||||
|
||||
@param errn
|
||||
error number
|
||||
@param errstr
|
||||
error description
|
||||
@param file
|
||||
error file
|
||||
@param line
|
||||
error line
|
||||
@param context
|
||||
error cntext
|
||||
*/
|
||||
public static function error_log($errn,$errstr,$file,$line,$context){
|
||||
LogMaster::log($errstr." at ".$file." line ".$line);
|
||||
}
|
||||
|
||||
/*! exception handler, used as default reaction on any error - show execution log and stop processing
|
||||
|
||||
@param exception
|
||||
instance of Exception
|
||||
*/
|
||||
public static function exception_log($exception){
|
||||
LogMaster::log("!!!Uncaught Exception\nCode: " . $exception->getCode() . "\nMessage: " . $exception->getMessage());
|
||||
if (LogMaster::$_output){
|
||||
echo "<pre><xmp>\n";
|
||||
echo LogMaster::get_session_log();
|
||||
echo "\n</xmp></pre>";
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
/*! enable logging
|
||||
|
||||
@param name
|
||||
path to the log file, if boolean false provided as value - logging will be disabled
|
||||
@param output
|
||||
flag of client side output, if enabled - session log will be sent to client side in case of an error.
|
||||
*/
|
||||
public static function enable_log($name,$output=false){
|
||||
LogMaster::$_log=$name;
|
||||
LogMaster::$_output=$output;
|
||||
if ($name){
|
||||
set_error_handler(array("LogMaster","error_log"),E_ALL);
|
||||
set_exception_handler(array("LogMaster","exception_log"));
|
||||
LogMaster::log("\n\n====================================\nLog started, ".date("d/m/Y h:i:s")."\n====================================");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
231
libraries/dhtmlxgantt/connector/tree_connector.php
Normal file
231
libraries/dhtmlxgantt/connector/tree_connector.php
Normal file
|
@ -0,0 +1,231 @@
|
|||
<?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';
|
||||
public $rootId = "0";
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
* @param render_type
|
||||
* name of class which will provides data rendering
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false, $render_type=false){
|
||||
if (!$item_type) $item_type="TreeDataItem";
|
||||
if (!$data_type) $data_type="TreeDataProcessor";
|
||||
if (!$render_type) $render_type="TreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
//parse GET scoope, all operations with incoming request must be done here
|
||||
public function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET[$this->parent_name]))
|
||||
$this->request->set_relation($_GET[$this->parent_name]);
|
||||
else
|
||||
$this->request->set_relation($this->rootId);
|
||||
|
||||
$this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
public function xml_start(){
|
||||
$attributes = "";
|
||||
foreach($this->attributes as $k=>$v)
|
||||
$attributes .= " ".$k."='".$v."'";
|
||||
|
||||
return "<tree id='".$this->request->get_relation()."'".$attributes.">";
|
||||
}
|
||||
|
||||
/*! renders self as xml, ending part
|
||||
*/
|
||||
public function xml_end(){
|
||||
$this->fill_collections();
|
||||
return $this->extra_output."</tree>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TreeDataProcessor extends DataProcessor{
|
||||
|
||||
function __construct($connector,$config,$request){
|
||||
parent::__construct($connector,$config,$request);
|
||||
$request->set_relation(false);
|
||||
}
|
||||
|
||||
/*! convert incoming data name to valid db name
|
||||
converts c0..cN to valid field names
|
||||
@param data
|
||||
data name from incoming request
|
||||
@return
|
||||
related db_name
|
||||
*/
|
||||
function name_data($data){
|
||||
if ($data=="tr_pid")
|
||||
return $this->config->relation_id["db_name"];
|
||||
if ($data=="tr_text")
|
||||
return $this->config->text[0]["db_name"];
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
89
libraries/dhtmlxgantt/connector/treedatagroup_connector.php
Normal file
89
libraries/dhtmlxgantt/connector/treedatagroup_connector.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?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'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("data_connector.php");
|
||||
|
||||
class TreeDataMultitableConnector extends TreeDataConnector{
|
||||
|
||||
protected $parent_name = 'parent';
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$data_type) $data_type="TreeDataProcessor";
|
||||
if (!$render_type) $render_type="MultitableTreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
public function render(){
|
||||
$this->dload = true;
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/*! sets relation for rendering */
|
||||
protected function set_relation() {
|
||||
if (!isset($_GET[$this->parent_name]))
|
||||
$this->request->set_relation(false);
|
||||
}
|
||||
|
||||
public function xml_start(){
|
||||
if (isset($_GET[$this->parent_name])) {
|
||||
return "<data parent='".$this->xmlentities($this->render->level_id($_GET[$this->parent_name], $this->render->get_level() - 1))."'>";
|
||||
} else {
|
||||
return "<data parent='0'>";
|
||||
}
|
||||
}
|
||||
|
||||
/*! set maximum level of tree
|
||||
@param max_level
|
||||
maximum level
|
||||
*/
|
||||
public function setMaxLevel($max_level) {
|
||||
$this->render->set_max_level($max_level);
|
||||
}
|
||||
|
||||
public function get_level() {
|
||||
return $this->render->get_level($this->parent_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class JSONTreeDataMultitableConnector extends TreeDataMultitableConnector{
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="JSONTreeCommonDataItem";
|
||||
if (!$data_type) $data_type="CommonDataProcessor";
|
||||
if (!$render_type) $render_type="JSONMultitableTreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
protected function output_as_xml($res){
|
||||
$result = $this->render_set($res);
|
||||
if ($this->simple) return $result;
|
||||
|
||||
$data = array();
|
||||
if (isset($_GET['parent']))
|
||||
$data["parent"] = $this->render->level_id($_GET[$this->parent_name], $this->render->get_level() - 1);
|
||||
else
|
||||
$data["parent"] = "0";
|
||||
$data["data"] = $result;
|
||||
|
||||
$result = json_encode($data);
|
||||
if ($this->as_string) return $result;
|
||||
|
||||
$out = new OutputWriter($result, "");
|
||||
$out->set_type("json");
|
||||
$this->event->trigger("beforeOutput", $this, $out);
|
||||
$out->output("", true, $this->encoding);
|
||||
}
|
||||
|
||||
public function xml_start(){
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
121
libraries/dhtmlxgantt/connector/treegrid_connector.php
Normal file
121
libraries/dhtmlxgantt/connector/treegrid_connector.php
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("grid_connector.php");
|
||||
|
||||
/*! DataItem class for TreeGrid component
|
||||
**/
|
||||
class TreeGridDataItem extends GridDataItem{
|
||||
private $kids=-1;//!< checked state
|
||||
|
||||
function __construct($data,$config,$index){
|
||||
parent::__construct($data,$config,$index);
|
||||
$this->im0=false;
|
||||
}
|
||||
/*! return id of parent record
|
||||
|
||||
@return
|
||||
id of parent record
|
||||
*/
|
||||
function get_parent_id(){
|
||||
return $this->data[$this->config->relation_id["name"]];
|
||||
}
|
||||
/*! assign image to treegrid's item
|
||||
longer description
|
||||
@param img
|
||||
relative path to the image
|
||||
*/
|
||||
function set_image($img){
|
||||
$this->set_cell_attribute($this->config->text[0]["name"],"image",$img);
|
||||
}
|
||||
|
||||
/*! return count of child items
|
||||
-1 if there is no info about childs
|
||||
@return
|
||||
count of child items
|
||||
*/
|
||||
function has_kids(){
|
||||
return $this->kids;
|
||||
}
|
||||
/*! sets count of child items
|
||||
@param value
|
||||
count of child items
|
||||
*/
|
||||
function set_kids($value){
|
||||
$this->kids=$value;
|
||||
if ($value)
|
||||
$this->set_row_attribute("xmlkids",$value);
|
||||
}
|
||||
}
|
||||
/*! Connector for dhtmlxTreeGrid
|
||||
**/
|
||||
class TreeGridConnector extends GridConnector{
|
||||
protected $parent_name = 'id';
|
||||
protected $rootId = "0";
|
||||
|
||||
/*! constructor
|
||||
|
||||
Here initilization of all Masters occurs, execution timer initialized
|
||||
@param res
|
||||
db connection resource
|
||||
@param type
|
||||
string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
||||
@param item_type
|
||||
name of class, which will be used for item rendering, optional, DataItem will be used by default
|
||||
@param data_type
|
||||
name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
||||
* @param render_type
|
||||
* name of class which will provides data rendering
|
||||
*/
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$item_type) $item_type="TreeGridDataItem";
|
||||
if (!$data_type) $data_type="TreeGridDataProcessor";
|
||||
if (!$render_type) $render_type="TreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
/*! process treegrid specific options in incoming request */
|
||||
public function parse_request(){
|
||||
parent::parse_request();
|
||||
|
||||
if (isset($_GET[$this->parent_name]))
|
||||
$this->request->set_relation($_GET[$this->parent_name]);
|
||||
else
|
||||
$this->request->set_relation($this->rootId);
|
||||
|
||||
$this->request->set_limit(0,0); //netralize default reaction on dyn. loading mode
|
||||
}
|
||||
|
||||
/*! renders self as xml, starting part
|
||||
*/
|
||||
protected function xml_start(){
|
||||
return "<rows parent='".$this->xmlentities( $this->request->get_relation() )."'>";
|
||||
}
|
||||
}
|
||||
|
||||
/*! DataProcessor class for Grid component
|
||||
**/
|
||||
class TreeGridDataProcessor extends GridDataProcessor{
|
||||
|
||||
function __construct($connector,$config,$request){
|
||||
parent::__construct($connector,$config,$request);
|
||||
$request->set_relation(false);
|
||||
}
|
||||
|
||||
/*! convert incoming data name to valid db name
|
||||
converts c0..cN to valid field names
|
||||
@param data
|
||||
data name from incoming request
|
||||
@return
|
||||
related db_name
|
||||
*/
|
||||
function name_data($data){
|
||||
|
||||
if ($data=="gr_pid")
|
||||
return $this->config->relation_id["name"];
|
||||
else return parent::name_data($data);
|
||||
}
|
||||
}
|
||||
?>
|
46
libraries/dhtmlxgantt/connector/treegridgroup_connector.php
Normal file
46
libraries/dhtmlxgantt/connector/treegridgroup_connector.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?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'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("treegrid_connector.php");
|
||||
|
||||
class TreeGridMultitableConnector extends TreeGridConnector{
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
$data_type="TreeGridMultitableDataProcessor";
|
||||
if (!$render_type) $render_type="MultitableTreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
public function render(){
|
||||
$this->dload = true;
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/*! sets relation for rendering */
|
||||
protected function set_relation() {
|
||||
if (!isset($_GET['id']))
|
||||
$this->request->set_relation(false);
|
||||
}
|
||||
|
||||
public function xml_start(){
|
||||
if (isset($_GET['id'])) {
|
||||
return "<rows parent='".$this->xmlentities($this->render->level_id($_GET['id'], $this->get_level() - 1))."'>";
|
||||
} else {
|
||||
return "<rows parent='0'>";
|
||||
}
|
||||
}
|
||||
|
||||
/*! set maximum level of tree
|
||||
@param max_level
|
||||
maximum level
|
||||
*/
|
||||
public function setMaxLevel($max_level) {
|
||||
$this->render->set_max_level($max_level);
|
||||
}
|
||||
|
||||
public function get_level() {
|
||||
return $this->render->get_level($this->parent_name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class TreeGridMultitableDataProcessor extends DataProcessor {
|
||||
|
||||
function name_data($data){
|
||||
if ($data=="gr_pid")
|
||||
return $this->config->relation_id["name"];
|
||||
if ($data=="gr_id")
|
||||
return $this->config->id["name"];
|
||||
preg_match('/^c([%\d]+)$/', $data, $data_num);
|
||||
if (!isset($data_num[1])) return $data;
|
||||
$data_num = $data_num[1];
|
||||
if (isset($this->config->data[$data_num]["db_name"])) {
|
||||
return $this->config->data[$data_num]["db_name"];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
46
libraries/dhtmlxgantt/connector/treegroup_connector.php
Normal file
46
libraries/dhtmlxgantt/connector/treegroup_connector.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?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'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
51
libraries/dhtmlxgantt/connector/treemultitable_connector.php
Normal file
51
libraries/dhtmlxgantt/connector/treemultitable_connector.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/*
|
||||
@author dhtmlx.com
|
||||
@license GPL, see license.txt
|
||||
*/
|
||||
require_once("tree_connector.php");
|
||||
|
||||
class TreeMultitableConnector extends TreeConnector{
|
||||
|
||||
protected $parent_name = 'id';
|
||||
|
||||
public function __construct($res,$type=false,$item_type=false,$data_type=false,$render_type=false){
|
||||
if (!$data_type) $data_type="TreeDataProcessor";
|
||||
if (!$render_type) $render_type="MultitableTreeRenderStrategy";
|
||||
parent::__construct($res,$type,$item_type,$data_type,$render_type);
|
||||
}
|
||||
|
||||
public function render(){
|
||||
$this->dload = true;
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/*! sets relation for rendering */
|
||||
protected function set_relation() {
|
||||
if (!isset($_GET[$this->parent_name]))
|
||||
$this->request->set_relation(false);
|
||||
}
|
||||
|
||||
public function xml_start(){
|
||||
if (isset($_GET[$this->parent_name])) {
|
||||
return "<tree id='".$this->xmlentities($this->render->level_id($_GET[$this->parent_name], $this->get_level() - 1))."'>";
|
||||
} else {
|
||||
return "<tree id='0'>";
|
||||
}
|
||||
}
|
||||
|
||||
/*! set maximum level of tree
|
||||
@param max_level
|
||||
maximum level
|
||||
*/
|
||||
public function setMaxLevel($max_level) {
|
||||
$this->render->set_max_level($max_level);
|
||||
}
|
||||
|
||||
public function get_level() {
|
||||
return $this->render->get_level($this->parent_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
266
libraries/dhtmlxgantt/connector/update.php
Normal file
266
libraries/dhtmlxgantt/connector/update.php
Normal file
|
@ -0,0 +1,266 @@
|
|||
<?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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
199
libraries/dhtmlxgantt/connector/xss_filter.php
Normal file
199
libraries/dhtmlxgantt/connector/xss_filter.php
Normal file
|
@ -0,0 +1,199 @@
|
|||
<?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 public $security_var = "dhx_security";
|
||||
|
||||
static private $filterClass = null;
|
||||
static function filter($value, $mode = false){
|
||||
if ($mode === false)
|
||||
$mode = ConnectorSecurity::$xss;
|
||||
|
||||
if ($mode == DHX_SECURITY_TRUSTED)
|
||||
return $value;
|
||||
if ($mode == DHX_SECURITY_SAFETEXT)
|
||||
return filter_var($value, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
|
||||
if ($mode == DHX_SECURITY_SAFEHTML){
|
||||
if (ConnectorSecurity::$filterClass == null)
|
||||
ConnectorSecurity::$filterClass = new dhx_externalinput_clean();
|
||||
return ConnectorSecurity::$filterClass->basic($value);
|
||||
}
|
||||
throw new Error("Invalid security mode:"+$mode);
|
||||
}
|
||||
|
||||
static function CSRF_detected(){
|
||||
LogMaster::log("[SECURITY] Possible CSRF attack detected", array(
|
||||
"referer" => $_SERVER["HTTP_REFERER"],
|
||||
"remote" => $_SERVER["REMOTE_ADDR"]
|
||||
));
|
||||
LogMaster::log("Request data", $_POST);
|
||||
die();
|
||||
}
|
||||
static function checkCSRF($edit){
|
||||
if (ConnectorSecurity::$security_key){
|
||||
if (!isset($_SESSION))
|
||||
@session_start();
|
||||
|
||||
if ($edit=== true){
|
||||
if (!isset($_POST[ConnectorSecurity::$security_var]))
|
||||
return ConnectorSecurity::CSRF_detected();
|
||||
$master_key = $_SESSION[ConnectorSecurity::$security_var];
|
||||
$update_key = $_POST[ConnectorSecurity::$security_var];
|
||||
if ($master_key != $update_key)
|
||||
return ConnectorSecurity::CSRF_detected();
|
||||
|
||||
return "";
|
||||
}
|
||||
//data loading
|
||||
if (!array_key_exists(ConnectorSecurity::$security_var,$_SESSION)){
|
||||
$_SESSION[ConnectorSecurity::$security_var] = md5(uniqid());
|
||||
}
|
||||
|
||||
return $_SESSION[ConnectorSecurity::$security_var];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue