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 | ?>
|
---|