[4001] | 1 | <?php
|
---|
| 2 |
|
---|
| 3 | require_once("tools.php");
|
---|
| 4 | require_once("db_common.php");
|
---|
| 5 | require_once("dataprocessor.php");
|
---|
| 6 | require_once("update.php");
|
---|
| 7 |
|
---|
| 8 | //enable buffering to catch and ignore any custom output before XML generation
|
---|
| 9 | //because of this command, it strongly recommended to include connector's file before any other libs
|
---|
| 10 | //in such case it will handle any extra output from not well formed code of other libs
|
---|
| 11 | ini_set("output_buffering","On");
|
---|
| 12 | ob_start();
|
---|
| 13 |
|
---|
| 14 | class OutputWriter{
|
---|
| 15 | private $start;
|
---|
| 16 | private $end;
|
---|
| 17 | private $type;
|
---|
| 18 |
|
---|
| 19 | public function __construct($start, $end = ""){
|
---|
| 20 | $this->start = $start;
|
---|
| 21 | $this->end = $end;
|
---|
| 22 | $this->type = "xml";
|
---|
| 23 | }
|
---|
| 24 | public function add($add){
|
---|
| 25 | $this->start.=$add;
|
---|
| 26 | }
|
---|
| 27 | public function reset(){
|
---|
| 28 | $this->start="";
|
---|
| 29 | $this->end="";
|
---|
| 30 | }
|
---|
| 31 | public function set_type($add){
|
---|
| 32 | $this->type=$add;
|
---|
| 33 | }
|
---|
| 34 | public function output($name="", $inline=true){
|
---|
| 35 | ob_clean();
|
---|
| 36 | if ($this->type == "xml")
|
---|
| 37 | header("Content-type: text/xml");
|
---|
| 38 |
|
---|
| 39 | echo $this->__toString();
|
---|
| 40 | }
|
---|
| 41 | public function __toString(){
|
---|
| 42 | return $this->start.$this->end;
|
---|
| 43 | }
|
---|
| 44 | }
|
---|
| 45 |
|
---|
| 46 | /*! EventInterface
|
---|
| 47 | Base class , for iterable collections, which are used in event
|
---|
| 48 | **/
|
---|
| 49 | class EventInterface{
|
---|
| 50 | protected $request; ////!< DataRequestConfig instance
|
---|
| 51 | public $rules=array(); //!< array of sorting rules
|
---|
| 52 |
|
---|
| 53 | /*! constructor
|
---|
| 54 | creates a new interface based on existing request
|
---|
| 55 | @param request
|
---|
| 56 | DataRequestConfig object
|
---|
| 57 | */
|
---|
| 58 | public function __construct($request){
|
---|
| 59 | $this->request = $request;
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | /*! remove all elements from collection
|
---|
| 63 | */
|
---|
| 64 | public function clear(){
|
---|
| 65 | array_splice($rules,0);
|
---|
| 66 | }
|
---|
| 67 | /*! get index by name
|
---|
| 68 |
|
---|
| 69 | @param name
|
---|
| 70 | name of field
|
---|
| 71 | @return
|
---|
| 72 | index of named field
|
---|
| 73 | */
|
---|
| 74 | public function index($name){
|
---|
| 75 | $len = sizeof($this->rules);
|
---|
| 76 | for ($i=0; $i < $len; $i++) {
|
---|
| 77 | if ($this->rules[$i]["name"]==$name)
|
---|
| 78 | return $i;
|
---|
| 79 | }
|
---|
| 80 | return false;
|
---|
| 81 | }
|
---|
| 82 | }
|
---|
| 83 | /*! Wrapper for collection of sorting rules
|
---|
| 84 | **/
|
---|
| 85 | class SortInterface extends EventInterface{
|
---|
| 86 | /*! constructor
|
---|
| 87 | creates a new interface based on existing request
|
---|
| 88 | @param request
|
---|
| 89 | DataRequestConfig object
|
---|
| 90 | */
|
---|
| 91 | public function __construct($request){
|
---|
| 92 | parent::__construct($request);
|
---|
| 93 | $this->rules = &$request->get_sort_by_ref();
|
---|
| 94 | }
|
---|
| 95 | /*! add new sorting rule
|
---|
| 96 |
|
---|
| 97 | @param name
|
---|
| 98 | name of field
|
---|
| 99 | @param dir
|
---|
| 100 | direction of sorting
|
---|
| 101 | */
|
---|
| 102 | public function add($name,$dir){
|
---|
| 103 | $this->request->set_sort($name,$dir);
|
---|
| 104 | }
|
---|
| 105 | public function store(){
|
---|
| 106 | $this->request->set_sort_by($this->rules);
|
---|
| 107 | }
|
---|
| 108 | }
|
---|
| 109 | /*! Wrapper for collection of filtering rules
|
---|
| 110 | **/
|
---|
| 111 | class FilterInterface extends EventInterface{
|
---|
| 112 | /*! constructor
|
---|
| 113 | creates a new interface based on existing request
|
---|
| 114 | @param request
|
---|
| 115 | DataRequestConfig object
|
---|
| 116 | */
|
---|
| 117 | public function __construct($request){
|
---|
| 118 | $this->request = $request;
|
---|
| 119 | $this->rules = &$request->get_filters_ref();
|
---|
| 120 | }
|
---|
| 121 | /*! add new filatering rule
|
---|
| 122 |
|
---|
| 123 | @param name
|
---|
| 124 | name of field
|
---|
| 125 | @param value
|
---|
| 126 | value to filter by
|
---|
| 127 | @param rule
|
---|
| 128 | filtering rule
|
---|
| 129 | */
|
---|
| 130 | public function add($name,$value,$rule){
|
---|
| 131 | $this->request->set_filter($name,$value,$rule);
|
---|
| 132 | }
|
---|
| 133 | public function store(){
|
---|
| 134 | $this->request->set_filters($this->rules);
|
---|
| 135 | }
|
---|
| 136 | }
|
---|
| 137 |
|
---|
| 138 | /*! base class for component item representation
|
---|
| 139 | **/
|
---|
| 140 | class DataItem{
|
---|
| 141 | protected $data; //!< hash of data
|
---|
| 142 | protected $config;//!< DataConfig instance
|
---|
| 143 | protected $index;//!< index of element
|
---|
| 144 | protected $skip;//!< flag , which set if element need to be skiped during rendering
|
---|
| 145 | /*! constructor
|
---|
| 146 |
|
---|
| 147 | @param data
|
---|
| 148 | hash of data
|
---|
| 149 | @param config
|
---|
| 150 | DataConfig object
|
---|
| 151 | @param index
|
---|
| 152 | index of element
|
---|
| 153 | */
|
---|
| 154 | function __construct($data,$config,$index){
|
---|
| 155 | $this->config=$config;
|
---|
| 156 | $this->data=$data;
|
---|
| 157 | $this->index=$index;
|
---|
| 158 | $this->skip=false;
|
---|
| 159 | }
|
---|
| 160 | /*! get named value
|
---|
| 161 |
|
---|
| 162 | @param name
|
---|
| 163 | name or alias of field
|
---|
| 164 | @return
|
---|
| 165 | value from field with provided name or alias
|
---|
| 166 | */
|
---|
| 167 | public function get_value($name){
|
---|
| 168 | return $this->data[$name];
|
---|
| 169 | }
|
---|
| 170 | /*! set named value
|
---|
| 171 |
|
---|
| 172 | @param name
|
---|
| 173 | name or alias of field
|
---|
| 174 | @param value
|
---|
| 175 | value for field with provided name or alias
|
---|
| 176 | */
|
---|
| 177 | public function set_value($name,$value){
|
---|
| 178 | return $this->data[$name]=$value;
|
---|
| 179 | }
|
---|
| 180 | /*! get id of element
|
---|
| 181 | @return
|
---|
| 182 | id of element
|
---|
| 183 | */
|
---|
| 184 | public function get_id(){
|
---|
| 185 | $id = $this->config->id["name"];
|
---|
| 186 | if (array_key_exists($id,$this->data))
|
---|
| 187 | return $this->data[$id];
|
---|
| 188 | return false;
|
---|
| 189 | }
|
---|
| 190 | /*! change id of element
|
---|
| 191 |
|
---|
| 192 | @param value
|
---|
| 193 | new id value
|
---|
| 194 | */
|
---|
| 195 | public function set_id($value){
|
---|
| 196 | $this->data[$this->config->id["name"]]=$value;
|
---|
| 197 | }
|
---|
| 198 | /*! get index of element
|
---|
| 199 |
|
---|
| 200 | @return
|
---|
| 201 | index of element
|
---|
| 202 | */
|
---|
| 203 | public function get_index(){
|
---|
| 204 | return $this->index;
|
---|
| 205 | }
|
---|
| 206 | /*! mark element for skiping ( such element will not be rendered )
|
---|
| 207 | */
|
---|
| 208 | public function skip(){
|
---|
| 209 | $this->skip=true;
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | /*! return self as XML string
|
---|
| 213 | */
|
---|
| 214 | public function to_xml(){
|
---|
| 215 | return $this->to_xml_start().$this->to_xml_end();
|
---|
| 216 | }
|
---|
| 217 |
|
---|
| 218 | /*! replace xml unsafe characters
|
---|
| 219 |
|
---|
| 220 | @param string
|
---|
| 221 | string to be escaped
|
---|
| 222 | @return
|
---|
| 223 | escaped string
|
---|
| 224 | */
|
---|
| 225 | protected function xmlentities($string) {
|
---|
| 226 | return str_replace( array( '&', '"', "'", '<', '>', 'â' ), array( '&' , '"', ''' , '<' , '>', ''' ), $string);
|
---|
| 227 | }
|
---|
| 228 |
|
---|
| 229 | /*! return starting tag for self as XML string
|
---|
| 230 | */
|
---|
| 231 | public function to_xml_start(){
|
---|
| 232 | $str="<item";
|
---|
| 233 | for ($i=0; $i < sizeof($this->config->data); $i++){
|
---|
| 234 | $name=$this->config->data[$i]["name"];
|
---|
| 235 | $str.=" ".$name."='".$this->xmlentities($this->data[$name])."'";
|
---|
| 236 | }
|
---|
| 237 | return $str.">";
|
---|
| 238 | }
|
---|
| 239 | /*! return ending tag for XML string
|
---|
| 240 | */
|
---|
| 241 | public function to_xml_end(){
|
---|
| 242 | return "</item>";
|
---|
| 243 | }
|
---|
| 244 | }
|
---|
| 245 |
|
---|
| 246 |
|
---|
| 247 |
|
---|
| 248 |
|
---|
| 249 |
|
---|
| 250 | /*! Base connector class
|
---|
| 251 | This class used as a base for all component specific connectors.
|
---|
| 252 | Can be used on its own to provide raw data.
|
---|
| 253 | **/
|
---|
| 254 | class Connector {
|
---|
| 255 | protected $config;//DataConfig instance
|
---|
| 256 | protected $request;//DataRequestConfig instance
|
---|
| 257 | protected $names;//!< hash of names for used classes
|
---|
| 258 | private $encoding="utf-8";//!< assigned encoding (UTF-8 by default)
|
---|
| 259 | private $editing=false;//!< flag of edit mode ( response for dataprocessor )
|
---|
| 260 | private $updating=false;//!< flag of update mode ( response for data-update )
|
---|
| 261 | private $db; //!< db connection resource
|
---|
| 262 | protected $dload;//!< flag of dyn. loading mode
|
---|
| 263 | public $access; //!< AccessMaster instance
|
---|
| 264 |
|
---|
| 265 | public $sql; //DataWrapper instance
|
---|
| 266 | public $event; //EventMaster instance
|
---|
| 267 | public $limit=false;
|
---|
| 268 |
|
---|
| 269 | private $id_seed=0; //!< default value, used to generate auto-IDs
|
---|
| 270 | protected $live_update = false; // actions table name for autoupdating
|
---|
| 271 |
|
---|
| 272 | /*! constructor
|
---|
| 273 |
|
---|
| 274 | Here initilization of all Masters occurs, execution timer initialized
|
---|
| 275 | @param db
|
---|
| 276 | db connection resource
|
---|
| 277 | @param type
|
---|
| 278 | string , which hold type of database ( MySQL or Postgre ), optional, instead of short DB name, full name of DataWrapper-based class can be provided
|
---|
| 279 | @param item_type
|
---|
| 280 | name of class, which will be used for item rendering, optional, DataItem will be used by default
|
---|
| 281 | @param data_type
|
---|
| 282 | name of class which will be used for dataprocessor calls handling, optional, DataProcessor class will be used by default.
|
---|
| 283 | */
|
---|
| 284 | public function __construct($db,$type=false, $item_type=false, $data_type=false){
|
---|
| 285 | $this->exec_time=microtime(true);
|
---|
| 286 |
|
---|
| 287 | if (!$type) $type="MySQL";
|
---|
| 288 | if (class_exists($type."DBDataWrapper",false)) $type.="DBDataWrapper";
|
---|
| 289 | if (!$item_type) $item_type="DataItem";
|
---|
| 290 | if (!$data_type) $data_type="DataProcessor";
|
---|
| 291 |
|
---|
| 292 | $this->names=array(
|
---|
| 293 | "db_class"=>$type,
|
---|
| 294 | "item_class"=>$item_type,
|
---|
| 295 | "data_class"=>$data_type,
|
---|
| 296 | );
|
---|
| 297 |
|
---|
| 298 | $this->config = new DataConfig();
|
---|
| 299 | $this->request = new DataRequestConfig();
|
---|
| 300 | $this->event = new EventMaster();
|
---|
| 301 | $this->access = new AccessMaster();
|
---|
| 302 |
|
---|
| 303 | if (!class_exists($this->names["db_class"],false))
|
---|
| 304 | throw new Exception("DB class not found: ".$this->names["db_class"]);
|
---|
| 305 | $this->sql = new $this->names["db_class"]($db,$this->config);
|
---|
| 306 |
|
---|
| 307 | $this->db=$db;//saved for options connectors, if any
|
---|
| 308 |
|
---|
| 309 | EventMaster::trigger_static("connectorCreate",$this);
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | /*! return db connection resource
|
---|
| 313 | nested class may neeed to access live connection object
|
---|
| 314 | @return
|
---|
| 315 | DB connection resource
|
---|
| 316 | */
|
---|
| 317 | protected function get_connection(){
|
---|
| 318 | return $this->db;
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | public function get_config(){
|
---|
| 322 | return new DataConfig($this->config);
|
---|
| 323 | }
|
---|
| 324 |
|
---|
| 325 | public function get_request(){
|
---|
| 326 | return new DataRequestConfig($this->config);
|
---|
| 327 | }
|
---|
| 328 |
|
---|
| 329 |
|
---|
| 330 | /*! config connector based on table
|
---|
| 331 |
|
---|
| 332 | @param table
|
---|
| 333 | name of table in DB
|
---|
| 334 | @param id
|
---|
| 335 | name of id field
|
---|
| 336 | @param fields
|
---|
| 337 | list of fields names
|
---|
| 338 | @param extra
|
---|
| 339 | list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
|
---|
| 340 | @param relation_id
|
---|
| 341 | name of field used to define relations for hierarchical data organization, optional
|
---|
| 342 | */
|
---|
| 343 | public function render_table($table,$id="",$fields=false,$extra=false,$relation_id=false){
|
---|
| 344 | $this->configure($table,$id,$fields,$extra,$relation_id);
|
---|
| 345 | return $this->render();
|
---|
| 346 | }
|
---|
| 347 | public function configure($table,$id="",$fields=false,$extra=false,$relation_id=false){
|
---|
| 348 | if ($fields === false){
|
---|
| 349 | //auto-config
|
---|
| 350 | $info = $this->sql->fields_list($table);
|
---|
| 351 | $fields = implode(",",$info["fields"]);
|
---|
| 352 | if ($info["key"])
|
---|
| 353 | $id = $info["key"];
|
---|
| 354 | }
|
---|
| 355 | $this->config->init($id,$fields,$extra,$relation_id);
|
---|
| 356 | $this->request->set_source($table);
|
---|
| 357 | }
|
---|
| 358 |
|
---|
| 359 | protected function uuid(){
|
---|
| 360 | return time()."x".$this->id_seed++;
|
---|
| 361 | }
|
---|
| 362 |
|
---|
| 363 | /*! config connector based on sql
|
---|
| 364 |
|
---|
| 365 | @param sql
|
---|
| 366 | sql query used as base of configuration
|
---|
| 367 | @param id
|
---|
| 368 | name of id field
|
---|
| 369 | @param fields
|
---|
| 370 | list of fields names
|
---|
| 371 | @param extra
|
---|
| 372 | list of extra fields, optional, such fields will not be included in data rendering, but will be accessible in all inner events
|
---|
| 373 | @param relation_id
|
---|
| 374 | name of field used to define relations for hierarchical data organization, optional
|
---|
| 375 | */
|
---|
| 376 | public function render_sql($sql,$id,$fields,$extra=false,$relation_id=false){
|
---|
| 377 | $this->config->init($id,$fields,$extra,$relation_id);
|
---|
| 378 | $this->request->parse_sql($sql);
|
---|
| 379 | return $this->render();
|
---|
| 380 | }
|
---|
| 381 |
|
---|
| 382 | /*! render already configured connector
|
---|
| 383 |
|
---|
| 384 | @param config
|
---|
| 385 | configuration of data
|
---|
| 386 | @param request
|
---|
| 387 | configuraton of request
|
---|
| 388 | */
|
---|
| 389 | public function render_connector($config,$request){
|
---|
| 390 | $this->config->copy($config);
|
---|
| 391 | $this->request->copy($request);
|
---|
| 392 | return $this->render();
|
---|
| 393 | }
|
---|
| 394 |
|
---|
| 395 | /*! render self
|
---|
| 396 | process commands, output requested data as XML
|
---|
| 397 | */
|
---|
| 398 | public function render(){
|
---|
| 399 | EventMaster::trigger_static("connectorInit",$this);
|
---|
| 400 |
|
---|
| 401 | $this->parse_request();
|
---|
| 402 | if ($this->live_update !== false && $this->updating!==false) {
|
---|
| 403 | $this->live_update->get_updates();
|
---|
| 404 | } else {
|
---|
| 405 | if ($this->editing){
|
---|
| 406 | $dp = new $this->names["data_class"]($this,$this->config,$this->request);
|
---|
| 407 | $dp->process($this->config,$this->request);
|
---|
| 408 | }
|
---|
| 409 | else {
|
---|
| 410 | $wrap = new SortInterface($this->request);
|
---|
| 411 | $this->event->trigger("beforeSort",$wrap);
|
---|
| 412 | $wrap->store();
|
---|
| 413 |
|
---|
| 414 | $wrap = new FilterInterface($this->request);
|
---|
| 415 | $this->event->trigger("beforeFilter",$wrap);
|
---|
| 416 | $wrap->store();
|
---|
| 417 |
|
---|
| 418 | $this->output_as_xml( $this->sql->select($this->request) );
|
---|
| 419 | }
|
---|
| 420 | }
|
---|
| 421 | $this->end_run();
|
---|
| 422 | }
|
---|
| 423 |
|
---|
| 424 | /*! prevent SQL injection through column names
|
---|
| 425 | replace dangerous chars in field names
|
---|
| 426 | @param str
|
---|
| 427 | incoming field name
|
---|
| 428 | @return
|
---|
| 429 | safe field name
|
---|
| 430 | */
|
---|
| 431 | protected function safe_field_name($str){
|
---|
| 432 | return strtok($str, " \n\t;',");
|
---|
| 433 | }
|
---|
| 434 |
|
---|
| 435 | /*! limit max count of records
|
---|
| 436 | connector will ignore any records after outputing max count
|
---|
| 437 | @param limit
|
---|
| 438 | max count of records
|
---|
| 439 | @return
|
---|
| 440 | none
|
---|
| 441 | */
|
---|
| 442 | public function set_limit($limit){
|
---|
| 443 | $this->limit = $limit;
|
---|
| 444 | }
|
---|
| 445 |
|
---|
| 446 | protected function parse_request_mode(){
|
---|
| 447 | //detect edit mode
|
---|
| 448 | if (isset($_GET["editing"])){
|
---|
| 449 | $this->editing=true;
|
---|
| 450 | } else if (isset($_POST["ids"])){
|
---|
| 451 | $this->editing=true;
|
---|
| 452 | 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]');
|
---|
| 453 | } else if (isset($_GET['dhx_version'])){
|
---|
| 454 | $this->updating = true;
|
---|
| 455 | }
|
---|
| 456 | }
|
---|
| 457 |
|
---|
| 458 | /*! parse incoming request, detects commands and modes
|
---|
| 459 | */
|
---|
| 460 | protected function parse_request(){
|
---|
| 461 | //set default dyn. loading params, can be reset in child classes
|
---|
| 462 | if ($this->dload)
|
---|
| 463 | $this->request->set_limit(0,$this->dload);
|
---|
| 464 | else if ($this->limit)
|
---|
| 465 | $this->request->set_limit(0,$this->limit);
|
---|
| 466 |
|
---|
| 467 | $this->parse_request_mode();
|
---|
| 468 |
|
---|
| 469 | if ($this->live_update && ($this->updating || $this->editing)){
|
---|
| 470 | $this->request->set_version($_GET["dhx_version"]);
|
---|
| 471 | $this->request->set_user($_GET["dhx_user"]);
|
---|
| 472 | }
|
---|
| 473 |
|
---|
| 474 | if (isset($_GET["dhx_sort"]))
|
---|
| 475 | foreach($_GET["dhx_sort"] as $k => $v){
|
---|
| 476 | $k = $this->safe_field_name($k);
|
---|
| 477 | $this->request->set_sort($this->resolve_parameter($k),$v);
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | if (isset($_GET["dhx_filter"]))
|
---|
| 481 | foreach($_GET["dhx_filter"] as $k => $v){
|
---|
| 482 | $k = $this->safe_field_name($k);
|
---|
| 483 | $this->request->set_filter($this->resolve_parameter($k),$v);
|
---|
| 484 | }
|
---|
| 485 |
|
---|
| 486 |
|
---|
| 487 | }
|
---|
| 488 |
|
---|
| 489 | /*! convert incoming request name to the actual DB name
|
---|
| 490 | @param name
|
---|
| 491 | incoming parameter name
|
---|
| 492 | @return
|
---|
| 493 | name of related DB field
|
---|
| 494 | */
|
---|
| 495 | protected function resolve_parameter($name){
|
---|
| 496 | return $name;
|
---|
| 497 | }
|
---|
| 498 |
|
---|
| 499 |
|
---|
| 500 | /*! replace xml unsafe characters
|
---|
| 501 |
|
---|
| 502 | @param string
|
---|
| 503 | string to be escaped
|
---|
| 504 | @return
|
---|
| 505 | escaped string
|
---|
| 506 | */
|
---|
| 507 | private function xmlentities($string) {
|
---|
| 508 | return str_replace( array( '&', '"', "'", '<', '>', 'â' ), array( '&' , '"', ''' , '<' , '>', ''' ), $string);
|
---|
| 509 | }
|
---|
| 510 |
|
---|
| 511 | /*! render from DB resultset
|
---|
| 512 | @param res
|
---|
| 513 | DB resultset
|
---|
| 514 | process commands, output requested data as XML
|
---|
| 515 | */
|
---|
| 516 | protected function render_set($res){
|
---|
| 517 | $output="";
|
---|
| 518 | $index=0;
|
---|
| 519 | $this->event->trigger("beforeRenderSet",$this,$res,$this->config);
|
---|
| 520 | while ($data=$this->sql->get_next($res)){
|
---|
| 521 | $data = new $this->names["item_class"]($data,$this->config,$index);
|
---|
| 522 | if ($data->get_id()===false)
|
---|
| 523 | $data->set_id($this->uuid());
|
---|
| 524 | $this->event->trigger("beforeRender",$data);
|
---|
| 525 | $output.=$data->to_xml();
|
---|
| 526 | $index++;
|
---|
| 527 | }
|
---|
| 528 | return $output;
|
---|
| 529 | }
|
---|
| 530 |
|
---|
| 531 | /*! output fetched data as XML
|
---|
| 532 | @param res
|
---|
| 533 | DB resultset
|
---|
| 534 | */
|
---|
| 535 | protected function output_as_xml($res){
|
---|
| 536 | $start="<?xml version='1.0' encoding='".$this->encoding."' ?>".$this->xml_start();
|
---|
| 537 | $end=$this->render_set($res).$this->xml_end();
|
---|
| 538 |
|
---|
| 539 | $out = new OutputWriter($start, $end);
|
---|
| 540 | $this->event->trigger("beforeOutput", $this, $out);
|
---|
| 541 |
|
---|
| 542 | $out->output();
|
---|
| 543 | }
|
---|
| 544 |
|
---|
| 545 |
|
---|
| 546 | /*! end processing
|
---|
| 547 | stop execution timer, kill the process
|
---|
| 548 | */
|
---|
| 549 | protected function end_run(){
|
---|
| 550 | $time=microtime(true)-$this->exec_time;
|
---|
| 551 | LogMaster::log("Done in {$time}s");
|
---|
| 552 | flush();
|
---|
| 553 | die();
|
---|
| 554 | }
|
---|
| 555 |
|
---|
| 556 | /*! set xml encoding
|
---|
| 557 |
|
---|
| 558 | methods sets only attribute in XML, no real encoding conversion occurs
|
---|
| 559 | @param encoding
|
---|
| 560 | value which will be used as XML encoding
|
---|
| 561 | */
|
---|
| 562 | public function set_encoding($encoding){
|
---|
| 563 | $this->encoding=$encoding;
|
---|
| 564 | }
|
---|
| 565 |
|
---|
| 566 | /*! enable or disable dynamic loading mode
|
---|
| 567 |
|
---|
| 568 | @param count
|
---|
| 569 | count of rows loaded from server, actual only for grid-connector, can be skiped in other cases.
|
---|
| 570 | If value is a false or 0 - dyn. loading will be disabled
|
---|
| 571 | */
|
---|
| 572 | public function dynamic_loading($count){
|
---|
| 573 | $this->dload=$count;
|
---|
| 574 | }
|
---|
| 575 |
|
---|
| 576 | /*! enable logging
|
---|
| 577 |
|
---|
| 578 | @param path
|
---|
| 579 | path to the log file. If set as false or empty strig - logging will be disabled
|
---|
| 580 | @param client_log
|
---|
| 581 | enable output of log data to the client side
|
---|
| 582 | */
|
---|
| 583 | public function enable_log($path=true,$client_log=false){
|
---|
| 584 | LogMaster::enable_log($path,$client_log);
|
---|
| 585 | }
|
---|
| 586 |
|
---|
| 587 | /*! provides infor about current processing mode
|
---|
| 588 | @return
|
---|
| 589 | true if processing dataprocessor command, false otherwise
|
---|
| 590 | */
|
---|
| 591 | public function is_select_mode(){
|
---|
| 592 | $this->parse_request_mode();
|
---|
| 593 | return !$this->editing;
|
---|
| 594 | }
|
---|
| 595 |
|
---|
| 596 | public function is_first_call(){
|
---|
| 597 | $this->parse_request_mode();
|
---|
| 598 | return !($this->editing || $this->updating || $this->request->get_start() || sizeof($this->request->get_filters()) || sizeof($this->request->get_sort_by()));
|
---|
| 599 |
|
---|
| 600 | }
|
---|
| 601 |
|
---|
| 602 | /*! renders self as xml, starting part
|
---|
| 603 | */
|
---|
| 604 | protected function xml_start(){
|
---|
| 605 | return "<data>";
|
---|
| 606 | }
|
---|
| 607 | /*! renders self as xml, ending part
|
---|
| 608 | */
|
---|
| 609 | protected function xml_end(){
|
---|
| 610 | return "</data>";
|
---|
| 611 | }
|
---|
| 612 |
|
---|
| 613 |
|
---|
| 614 | public function insert($data) {
|
---|
| 615 | $action = new DataAction('inserted', false, $data);
|
---|
| 616 | $request = new DataRequestConfig();
|
---|
| 617 | $request->set_source($this->request->get_source());
|
---|
| 618 |
|
---|
| 619 | $this->config->limit_fields($data);
|
---|
| 620 | $this->sql->insert($action,$request);
|
---|
| 621 | $this->config->restore_fields($data);
|
---|
| 622 |
|
---|
| 623 | return $action->get_new_id();
|
---|
| 624 | }
|
---|
| 625 |
|
---|
| 626 | public function delete($id) {
|
---|
| 627 | $action = new DataAction('deleted', $id, array());
|
---|
| 628 | $request = new DataRequestConfig();
|
---|
| 629 | $request->set_source($this->request->get_source());
|
---|
| 630 |
|
---|
| 631 | $this->sql->delete($action,$request);
|
---|
| 632 | return $action->get_status();
|
---|
| 633 | }
|
---|
| 634 |
|
---|
| 635 | public function update($data) {
|
---|
| 636 | $action = new DataAction('updated', $data[$this->config->id["name"]], $data);
|
---|
| 637 | $request = new DataRequestConfig();
|
---|
| 638 | $request->set_source($this->request->get_source());
|
---|
| 639 |
|
---|
| 640 | $this->config->limit_fields($data);
|
---|
| 641 | $this->sql->update($action,$request);
|
---|
| 642 | $this->config->restore_fields($data);
|
---|
| 643 |
|
---|
| 644 | return $action->get_status();
|
---|
| 645 | }
|
---|
| 646 |
|
---|
| 647 | /*! sets actions_table for Optimistic concurrency control mode and start it
|
---|
| 648 | @param table_name
|
---|
| 649 | name of database table which will used for saving actions
|
---|
| 650 | @param url
|
---|
| 651 | url used for update notifications
|
---|
| 652 | */
|
---|
| 653 | public function enable_live_update($table, $url=false){
|
---|
| 654 | $this->live_update = new DataUpdate($this->sql, $this->config, $this->request, $table,$url);
|
---|
| 655 | $this->live_update->set_event($this->event,$this->names["item_class"]);
|
---|
| 656 | $this->event->attach("beforeOutput", Array($this->live_update, "version_output"));
|
---|
| 657 | $this->event->attach("beforeFiltering", Array($this->live_update, "get_updates"));
|
---|
| 658 | $this->event->attach("beforeProcessing", Array($this->live_update, "check_collision"));
|
---|
| 659 | $this->event->attach("afterProcessing", Array($this->live_update, "log_operations"));
|
---|
| 660 | }
|
---|
| 661 | }
|
---|
| 662 |
|
---|
| 663 |
|
---|
| 664 | /*! wrapper around options collection, used for comboboxes and filters
|
---|
| 665 | **/
|
---|
| 666 | class OptionsConnector extends Connector{
|
---|
| 667 | protected $init_flag=false;//!< used to prevent rendering while initialization
|
---|
| 668 | public function __construct($res,$type=false,$item_type=false,$data_type=false){
|
---|
| 669 | if (!$item_type) $item_type="DataItem";
|
---|
| 670 | if (!$data_type) $data_type=""; //has not sense, options not editable
|
---|
| 671 | parent::__construct($res,$type,$item_type,$data_type);
|
---|
| 672 | }
|
---|
| 673 | /*! render self
|
---|
| 674 | process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
|
---|
| 675 | @return
|
---|
| 676 | data as XML string
|
---|
| 677 | */
|
---|
| 678 | public function render(){
|
---|
| 679 | if (!$this->init_flag){
|
---|
| 680 | $this->init_flag=true;
|
---|
| 681 | return "";
|
---|
| 682 | }
|
---|
| 683 | $res = $this->sql->select($this->request);
|
---|
| 684 | return $this->render_set($res);
|
---|
| 685 | }
|
---|
| 686 | }
|
---|
| 687 |
|
---|
| 688 |
|
---|
| 689 |
|
---|
| 690 | class DistinctOptionsConnector extends OptionsConnector{
|
---|
| 691 | /*! render self
|
---|
| 692 | process commands, return data as XML, not output data to stdout, ignore parameters in incoming request
|
---|
| 693 | @return
|
---|
| 694 | data as XML string
|
---|
| 695 | */
|
---|
| 696 | public function render(){
|
---|
| 697 | if (!$this->init_flag){
|
---|
| 698 | $this->init_flag=true;
|
---|
| 699 | return "";
|
---|
| 700 | }
|
---|
| 701 | $res = $this->sql->get_variants($this->config->text[0]["db_name"],$this->request);
|
---|
| 702 | return $this->render_set($res);
|
---|
| 703 | }
|
---|
| 704 | }
|
---|
| 705 |
|
---|
| 706 | ?>
|
---|