1<?php 2 /** 3 * SQL Generator ENTITY - helps to construct queries statements 4 * @author Edgar Antonio Luna Diaz <eald@co.com.mx> 5 * @author Alejadro Borges 6 * @author Jonathan Alberto Rivera Gomez 7 * @copyright Copyright (C) 2003,2004 Free Software Foundation, Inc. http://www.fsf.org/ 8 * @license http://www.fsf.org/licenses/gpl.html GNU General Public License 9 * @package phpgwapi 10 * @subpackage database 11 * @version $Id: class.sql_entity.inc.php 21045 2010-03-25 22:41:38Z Caeies $ 12 * @internal Development of this application was funded by http://www.sogrp.com 13 * @link http://www.sogrp.com/ 14 */ 15 16 /** 17 * SQL entity alias substitution string EASS 18 */ 19 define (PHPGW_SQL_EASS, '|%-'); 20 /** 21 * SQL default method 22 */ 23 define (PHPGW_SQL_DEFAULT_METHOD, -1); 24 /** 25 * SQL lazy key 26 */ 27 define (PHPGW_SQL_LAZY_KEY, 1); 28 /** 29 * SQL required key 30 */ 31 define (PHPGW_SQL_REQUIRED_KEY, 2); 32 /** 33 * SQL all match 34 */ 35 define (PHPGW_SQL_ALL_MATCH, 1); 36 /** 37 * SQL exclusive match 38 */ 39 define (PHPGW_SQL_EXCLUSIVE_MATCH, 2); 40 /** 41 * SQL return records 42 */ 43 define (PHPGW_SQL_RETURN_RECORDS, 1); 44 /** 45 * SQL run SQL 46 */ 47 define (PHPGW_SQL_RUN_SQL, 1); 48 /** 49 * SQL return SQL 50 */ 51 define (PHPGW_SQL_RETURN_SQL, 2); 52 53 54 /** 55 * SQL Generator ENTITY - helps to construct queries statements 56 * 57 * This class provide common methods to create transaction sql queries. 58 * Isolates an entity. 59 * @package phpgwapi 60 * @subpackage database 61 */ 62 class sql_entity 63 { 64 /* List of fields to mantain in each query, it morph if select, 65 * if insert, if update. 66 */ 67 var $fields; 68 var $inserts; 69 var $insert_index; 70 var $operation; 71 var $criteria; 72 // need in list form, for easy search 73 var $field_list; 74 // var $field_array; 75 var $alias; 76 // Just INSERT (update?) 77 var $values; 78 // Imported links 79 var $ilink = array(); 80 // Exported links 81 var $elink = array(); 82 var $ondebug; 83 var $table; 84 85 function sql_entity() 86 { 87 } 88 89 /*************************************************************\ 90 * Entity, class and general section * 91 \*************************************************************/ 92 93 function _constructor($table='', $alias='') 94 { 95 $this->table = $table; 96 // Temp alias name, just if not empty 97 $this->alias = ($alias)? $alias: $alias; 98 $this->ldebug('_constructor', array('Table' => $table, 99 'Alias' => $alias)); 100 } 101 102 /** 103 * Set the alias for the table 104 * 105 * @param string $alias The alias name 106 * @return The alias name which will be used for SELECT. 107 */ 108 function set_identity($alias) 109 { 110 $this->alias = ($alias)? $alias : get_class($this); 111 $this->table = ($this->table)? $this->table : 112 get_class($this); 113 $this->ldebug('set_identity', array('Alias' => $this->alias, 114 'Table' => $this->table)); 115 } 116 117 function set_table_name($table) 118 { 119 $this->table = $table; 120 } 121 122 function set_alias($alias) 123 { 124 $this->alias = $alias; 125 } 126 127 /** 128 * Get the list of false fields from instance. 129 * 130 * @return Array List of false fields. 131 */ 132 133 function get_false_fields() 134 { 135 return array_keys($this->map); 136 } 137 138 /** 139 * Determines whether if operation must be changed or not. 140 * 141 * Operation is used to decide if alias is attached to fields names or not 142 * @param string $opertation Actual action that is proposed to be the operation. 143 */ 144 function set_operation($operation) 145 { 146 if (empty($this->operation) && $operation != 'criteria' && !empty($operation)) 147 { 148 $this->operation = $operation; 149 } 150 } 151 152 /** 153 * Forced change of actual operation 154 * 155 * Operation is used to decide if alias is attached to fields names or not 156 * @param string $operation action to be set. 157 */ 158 function change_operation($operation) 159 { 160 if (!empty($operation) && $operation != 'criteria') 161 { 162 $this->operation = $operation; 163 } 164 } 165 166 /*************************************************************\ 167 * Alias section * 168 \*************************************************************/ 169 /** 170 * Replace the alias string with the one true alias name 171 * 172 * @return Tow string, fields and criteria with the correct alias name. 173 */ 174 function run_alias() 175 { 176 if ($this->alias) 177 { 178 $this->field_alias(); 179 $this->fields = str_replace(PHPGW_SQL_EASS, $this->alias, 180 $this->fields); 181 $this->criteria = str_replace(PHPGW_SQL_EASS, $this->alias, 182 $this->criteria); 183 $this->ldebug('run_alias', 184 array('Fields' => $this->fields, 185 'Criteria' => $this->criteria, 186 'Alias' => $this->alias)); 187 } 188 } 189 190 /** 191 * Set a alias to the table if is required 192 * 193 * @return string with the table name, with alias if is required. 194 */ 195 function get_identity() 196 { 197 return ($this->alias != $this->table)? $this->table 198 .' AS '.$this->alias : $this->table; 199 } 200 201 function get_alias() 202 { 203 return $this->alias; 204 } 205 206 /** 207 * @param string $field Name of the field. 208 * @return the string ready for replace s/EASS/alias/ 209 */ 210 function put_alias($field) 211 { 212 return ($this->operation == 'select')? PHPGW_SQL_EASS.'.'.$field : $field; 213 } 214 215 /** 216 * Set the alias to a any field 217 * @param string $field Name of the field. 218 * @return the string ready for replace s/EASS/alias/ 219 */ 220 function put_real_alias($field) 221 { 222 return ($this->operation == 'select')? $this->alias.'.'.$field : $field; 223 } 224 /*************************************************************\ 225 * Select section * 226 \*************************************************************/ 227 228 /** 229 * Add the field to list, with alias $alias 230 * 231 * @param string $field Any sql instruction like count(field_name) 232 * @param string $alias Alias for $field 233 */ 234 function add_field($alias, $field) 235 { 236 $this->field_list[$alias] = $field; 237 } 238 239 /** 240 * Add the field to list 241 * 242 * @param array $element with real_field and false field (field) 243 * @access private 244 */ 245 function _add_field($element) 246 { 247 $this->add_field($element['field'], 248 $this->put_alias($element['real_field'])); 249 $this->ldebug('_add_field', 250 array('Field_list' => $this->field_list), 251 'dump'); 252 } 253 254 /** 255 * Set the alias for the select query 256 * 257 * @param string $real_field The real name of the field 258 * @param string $alias_field the alias that field will take 259 * @access private 260 */ 261 function set_field_alias($real_field, $alias_field) 262 { 263 $this->ldebug('set_field_alias', 264 array('Field list' => $this->field_list), 265 'dump'); 266 $this->fields .= ', '.$real_field.' AS '.$alias_field; 267 } 268 269 function field_alias() 270 { 271 $this->ldebug('field_alias', 272 array('Field list' => $this->field_list), 273 'dump'); 274 if($this->field_list) 275 { 276 $alias_field = key($this->field_list); 277 $field = array_shift($this->field_list); 278 $this->fields = $field.' AS '.$alias_field; 279 array_walk($this->field_list, array(&$this,'set_field_alias')); 280 } 281 } 282 283 /** 284 * local select, if I'm the only one? or for catalog entities? 285 * 286 * @return string A select easy to use. 287 */ 288 function select() 289 { 290 $this->run_alias(); 291 $sql_select = 'SELECT ' . $this->fields. 292 ' FROM ' . $this->get_identity() . 293 ($this->get_criteria()?' WHERE ' . $this->get_criteria():''); 294 return $sql_select; 295 } 296 297 /** 298 * @return array (field, identity, alias, criteria) for: 299 * SELECT <field> FROM <identity> WHERE <criteria> and <alias> for the on construction depending on identity 300 */ 301 function get_select() 302 { 303 $this->run_alias(); 304 $select_value = array($this->fields, 305 $this->get_identity(), 306 $this->alias, 307 $this->get_criteria()); 308 $this->ldebug('get_select', array('Criteria' => $select_value[4])); 309 return $select_value; 310 } 311 312 /*************************************************************\ 313 * Criteria section * 314 \*************************************************************/ 315 /** 316 * Get the criteria 317 * 318 * @return string with the criteria which was autogenerate. 319 */ 320 function get_criteria() 321 { 322 return $this->criteria; 323 } 324 325 /** 326 * When no special method defined for $elemnent['field'] this is the method that will run. And add to the criteria list 327 * 328 * @param string $element['real_field'] The associated field. 329 * @param string $element['value'] Criteria for this field. 330 */ 331 function default_criteria($element) 332 { 333 $this->ldebug('default_criteria', 334 array('Element' => $element), 'dump'); 335 $field = (($this->operation == 'select') ? 336 $this->put_alias($element['real_field']) : 337 $element['real_field']); 338 $this->ldebug('default_criteria', 339 array('Field' => $field)); 340 341 $new_criteria = sql_criteria::has($field, 342 $element['value']); 343 $this->ldebug('default_criteria', 344 array('New Criteria' => $new_criteria)); 345 $this->_add_criteria($new_criteria); 346 } 347 348 /** 349 * Add criteria to list 350 * 351 * @param string $new_criteria with the new criteria which was autegenerate. 352 * @return string with the criteria. 353 */ 354 function _add_criteria($new_criteria) 355 { 356 $this->ldebug('_add_criteria', 357 array('New Criteria' => $new_criteria, 358 'All Criteria Prev' => $this->criteria)); 359 $this->criteria = sql_criteria::append_and(array($new_criteria, 360 $this->criteria)); 361 $this->ldebug('_add_criteria', 362 array('All Criteria Post' => $this->criteria)); 363 } 364 365 /** 366 * Especial criteria for index or id, it decides if must call equal or in operator 367 * 368 * @param array $element with field, value, real_name 369 * @return string with a usefull criteria to use for many (a in clause) or just one id (equal). 370 */ 371 function index_criteria($element) 372 { 373 $field = $this->put_alias($element['real_field']); 374 if(is_array($element['value'])) 375 { 376 if(count($element['value']) == 1) 377 { 378 $value = $this->cast(current($element['value']), $element['field']); 379 return sql_criteria::equal($field, $value); 380 } 381 elseif(count($element['value']) > 1) 382 { 383 return sql_criteria::in($field, $element['value'], $this->get_datatype($field)); 384 } 385 } 386 else 387 { 388 $value = $this->cast($element['value'], $element['field']); 389 return sql_criteria::equal($field, $value); 390 } 391 } 392 393 /** 394 * Analize a criteria created by tokens and create a string that represent it, useful for any kind of operation that use criteria I guess. 395 * 396 * @param $token_criteria array Array with all the criteria in tokens, generated with sql_criteria 397 * @return string Criteria string (All that goes in WHERE clause) 398 * @see sql_criteria 399 */ 400 401 function entity_criteria($token_criteria) 402 { 403 /* 404 Things to care about: 405 - `_append_and', `_append_or' arrays have two elements: 1. array with criterias, 2. token 406 - `in' is a three element: 1. field name, 2. array with values, 3. token 407 */ 408 409 $num_elements = count($token_criteria); 410 switch($num_elements) 411 { 412 case 0: 413 case 1: 414 $local_criteria = $token_criteria; 415 break; 416 case 2: 417 case 3: 418 $operator = array_pop($token_criteria); 419 $left = array_shift($token_criteria); 420 $right = array_shift($token_criteria); 421 422 if(is_array($left) && $operator != 'in') 423 { 424 $left = $this->entity_criteria($left); 425 } 426 else 427 { 428 $left = $this->real_field($left); 429 } 430 if(is_array($right)) 431 { 432 $right = $this->entity_criteria($right); 433 } 434 $local_criteria = sql_criteria::operate($operator,$left,$right); 435 break; 436 default: 437 $operator = array_pop($token_criteria); 438 $local_criteria = sql_criteria::operate($operator,$token_criteria); 439 } 440 return $local_criteria; 441 } 442 443 /*************************************************************\ 444 * Insert (input data) section * 445 \*************************************************************/ 446 447 /** 448 * Wrapper for calling add_insert_element, when we have $element ready. 449 * 450 * @param array $element Form: ('field', 'real_field', 'value'). 451 */ 452 function set_insert_data($element) 453 { 454 $this->add_insert_element($element['field'],$element['real_field'],$element['value']); 455 } 456 457 /** 458 * Genarete two string with fields and values list 459 * 460 * @param string $false_field Field in map. 461 * @param string $field BD field and which use in insert. 462 * @param string $value Value for use in insert. 463 */ 464 function add_insert_element($false_field,$field,$value) 465 { 466 $this->inserts[$this->insert_index]['data'][$false_field] = array('field' => $field, 'value' => $value); 467 $this->ldebug('add_insert_element', 468 array('False Field' => $false_field, 469 'DB Field' => $field, 470 'Value' => $value_insert)); 471 } 472 473 /*************************************************************\ 474 * Insert (return data) section * 475 \*************************************************************/ 476 477 /** 478 * Definitive interfase for get the array of inserts sql queries 479 * 480 * @param array $entities with the list of entity that are present in the transaction 481 * @return Array with the sql insert, just with imported keys missing 482 */ 483 function get_multiple_insert($entities) 484 { 485 foreach ($entities as $entity_name) 486 { 487 $link = $this-get_ilink($entity_name); 488 $field = $this->real_field($link['lfield']); 489 $fields_to_prototype[$field] = '{'.$link['lfield'].'}'; 490 } 491 492 foreach ($this->inserts as $index => $insert) 493 { 494 // First element, the only one than don't begin with `,' 495 $false_field = key($this->inserts[$index]['data']); 496 $this->inserts[$index]['fields'] = $insert['data'][$false_field]['field']; 497 $this->inserts[$index]['values'] = $insert['data'][$false_field]['value']; 498 // Go for next elements 499 array_walk($this->inserts[$index]['data'],array(&$this,'set_fields_insert'),$index); 500 reset($this->inserts[$index]['data']); 501 array_walk($field_to_prototype,array(&$this,'set_field_inserts_prototyped'),$index); 502 $inserts[$index] = $this->insert($idx); 503 } 504 return $inserts; 505 } 506 507 function insert($data, $action=PHPGW_SQL_RETURN_SQL) 508 { 509 $this->_insert($data, 0); 510 $sql = $this->get_single_insert(0); 511 switch($action) 512 { 513 case PHPGW_SQL_RETURN_RECORDS: 514 case PHPGW_SQL_RUN_SQL: 515 $GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__); 516 $this->ldebug('insert', $sql, 'msg'); 517 break; 518 case PHPGW_SQL_RETURN_SQL: 519 return $sql; 520 } 521 } 522 523 function _insert($data, $index = 0) 524 { 525 foreach($data as $field => $value) 526 { 527 $this->add_insert($field, $value, $index); 528 } 529 } 530 531 /** 532 * Get the insert sql statement for one entry 533 * 534 * @param int $index with the index of data which we want to insert 535 * @return string Corresponding sql insert. 536 */ 537 function get_single_insert($index = 0) 538 { 539 // First element, the only one than don't begin with `,' 540 $false_field = key($this->inserts[$index]['data']); 541 $this->inserts[$index]['fields'] = $this->inserts[$index]['data'][$false_field]['field']; 542 $this->inserts[$index]['values'] = $this->cast($this->inserts[$index]['data'][$false_field]['value'], $false_field); 543 // Go for next elements 544 while(next($this->inserts[$index]['data'])) 545 { 546 $false_field = key($this->inserts[$index]['data']); 547 $this->ldebug('get_single_insert', array('data for index '.$index => $this->inserts[$index]['data']), 'dump'); 548 $this->inserts[$index]['fields'] .= ', '.$this->inserts[$index]['data'][$false_field]['field']; 549 $this->inserts[$index]['values'] .= ', '.$this->cast($this->inserts[$index]['data'][$false_field]['value'], $false_field); 550 } 551 return $this->_single_insert($index); 552 } 553 554 /** 555 * Get the right value for the datatype of the false field 556 * 557 * @param mixed $data value that want to cast. 558 * @param string $false_field Field for search datatype 559 * @return string Corresponding string with sql for datatype 560 */ 561 function cast($data, $false_field) 562 { 563 if(is_array($data)) 564 { 565 return $this->index_criteria($data); 566 567 } 568 $type = $this->get_datatype($false_field); 569 return ($data == sql::null())? sql::null() : sql::$type($data); 570 } 571 572 /** 573 * Genarete the insert string 574 * 575 * @return The string which will be use for insert query. 576 */ 577 function _single_insert($index) 578 { 579 $sql_insert = 'INSERT INTO ' . $this->table . 580 ' ('. $this->get_insert_fields($index). 581 ') VALUES ('.$this->get_insert_values($index).')'; 582 return $sql_insert; 583 } 584 585 function set_fields_insert_prototyped($field, $value, $index) 586 { 587 if(!array_key_exist($field, $this->inserts[$index]['data'])) 588 { 589 $this->inserts[$index]['fields'] .= ', '.$field; 590 $this->inserts[$index]['values'] .= ', '.$value; 591 } 592 } 593 594 function get_insert_fields($index) 595 { 596 return $this->inserts[$index]['fields']; 597 } 598 599 function get_insert_values($index) 600 { 601 return $this->inserts[$index]['values']; 602 } 603 604 /*************************************************************\ 605 * Update section * 606 \*************************************************************/ 607 608 /** 609 * Create an update query for this entity 610 * 611 * @param Array $data Fields that want change value and their values 612 * @param Array $criteria With criterias that set the rows to edit 613 * @param integer action 614 * @return string SQL update string 615 */ 616 function update($data,$criteria, $action=PHPGW_SQL_RETURN_SQL) 617 { 618 if(is_array($data) && count($data) > 0) 619 { 620 array_walk($data, array(&$this,'add_update')); 621 } 622 else 623 { 624 list($field,$value) = explode('=',$data); 625 $this->add_update($field, $value); 626 } 627 if (is_string($criteria)) 628 { 629 $this->set_criteria($criteria); 630 } 631 else 632 { 633 $this->set_criteria(sql_criteria::criteria($criteria)); 634 } 635 636 if(!empty($this->values)) 637 { 638 switch($action) 639 { 640 case PHPGW_SQL_RETURN_RECORDS: 641 case PHPGW_SQL_RUN_SQL: 642 $sql = $this->return_update(); 643 $GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__); 644 $this->ldebug('update', $sql, 'msg'); 645 return; 646 case PHPGW_SQL_RETURN_SQL: 647 return $this->return_update(); 648 } 649 } 650 } 651 652 function set_criteria($criteria) 653 { 654 $this->criteria = $criteria; 655 656 } 657 658 /** 659 * Genarete the update string 660 * 661 * @return The string which will be used for update query. 662 */ 663 function return_update() 664 { 665 $sql_update = 'UPDATE ' . $this->table . 666 ' SET ' . $this->values; 667 if ($this->criteria) 668 { 669 $sql_update .=' WHERE ' . $this->criteria; 670 } 671 $this->values = ''; 672 $this->criteria = ''; 673 return $sql_update; 674 } 675 676 function get_update() 677 { 678 return (array('fields' => $this->get_update_data(), 679 'criteria'=> $this->get_criteria(), 680 'identity'=> $this->get_identity())); 681 } 682 683 /** 684 * Genarete a string with field = value to use in update 685 * 686 * @param string $fields 687 * @param string $values 688 * @return string with field=value list. 689 */ 690 function set_update_data($element) 691 { 692 $value = ($element['value'] || $element['value'] == 0) ? $this->cast($element['value'], $element['field']) : sql::null(); 693 $this->values .= (($this->values)?', ':'').$element['real_field'].' = '.$value; 694 } 695 696 /** 697 * Get the complete field=value listo to use in the update 698 * 699 * @return string with field=value comma separate. 700 */ 701 function get_update_data() 702 { 703 return $this->values; 704 } 705 706 /** 707 * Genarete the delete string 708 * 709 * @param string $criteria the criteria for select the rows to delete 710 * @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL 711 * @return string which will be used for delete query. 712 */ 713 function delete($criteria, $action) 714 { 715 if($criteria) 716 { 717 $sql = 'DELETE FROM '.$this->table.' WHERE '.$criteria; 718 719 $this->set_criteria(''); 720 switch($action) 721 { 722 case PHPGW_SQL_RETURN_RECORDS: 723 case PHPGW_SQL_RUN_SQL: 724 $GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__); 725 return; 726 case PHPGW_SQL_RETURN_SQL: 727 return $sql; 728 } 729 } 730 } 731 732 /** 733 * Get the complete fields list to use in the insert or select 734 * 735 * @return string with fields comma separate. 736 */ 737 function get_fields() 738 { 739 return $this->fields; 740 } 741 742 /*************************************************************\ 743 * Links and keys section * 744 \*************************************************************/ 745 /** 746 * Genarete an array with all imported links 747 * 748 * @param string $fl with local field 749 * @param string $t with table 750 * @param string $ff with foreign field 751 * @param int $key_type PHPGW_SQL_LAZY_KEY if want that this link be joined via OUTER (LEFT o RIGHT); PHPGW_SQL_REQUIRED_KEY 752 * if want that be joined with INNER LINK. This is the setting by default, and could be changed per query execution. 753 */ 754 function set_ilinks($fl,$t,$ff,$key_type = PHPGW_SQL_LAZY_KEY) 755 { 756 $this->ilink[$t] = array('lfield' => $fl, 757 'ffield' => $ff, 758 'type' => $key_type); 759 } 760 761 /** 762 * Genarete an array with all exported links 763 * 764 * @param string $fl with local field 765 * @param string $t with table 766 * @param string $ff with foreign field 767 */ 768 function set_elinks($fl,$t,$ff) 769 { 770 $this->elink[$t] = array('lfield' => $fl, 771 'ffield' => $ff); 772 } 773 774 /** 775 * Get the lfield and ffield from any of elink or ilink according to $entity. 776 * 777 * @param string $entity Name of entity to search link with. 778 * @return Array $lfield that is the local field of the link, and $ffield that is the foreign field. 779 */ 780 function get_link($entity = '') 781 { 782 if ($entity != '') 783 { 784 if(array_key_exists($entity, (isset($this->ilink)? $this->ilink : array()))) 785 { 786 return $this->ilink[$entity]; 787 } 788 elseif (array_key_exists($entity, (isset($this->elink)? $this->elink : array()))) 789 { 790 return $this->elink[$entity]; 791 } 792 } 793 // Must raise error 794 return ''; 795 } 796 797 /** 798 * Get the lfield and ffield from any of ilink according to $entity. 799 * 800 * @param strnig $entity Name of entity to search link with. 801 * @return Array $lfield that is the local field of the link, and $ffield that is the foreign field. 802 803 */ 804 function get_ilink($entity = '') 805 { 806 $this->ldebug('get_ilink', array('entity' => $entity)); 807 $this->ldebug('get_ilink', array('ilinks' => $this->ilink), 'dump'); 808 if ($entity != '') 809 { 810 if(array_key_exists($entity, (isset($this->ilink)? $this->ilink : array()))) 811 { 812 return $this->ilink[$entity]; 813 } 814 } 815 // Must raise error 816 return ; 817 } 818 819 /** 820 * Get the lfield and ffield from any of elink according to $entity. 821 * 822 * @param string $entity Name of entity to search link with. 823 * @return Array $lfield that is the local field of the link, and $ffield that is the foreign field. 824 */ 825 function get_elink($entity = '') 826 { 827 if ($entity != '') 828 { 829 if (array_key_exists($entity, (isset($this->elink)? $this->elink : array()))) 830 { 831 return $this->elink[$entity]; 832 } 833 } 834 return ; 835 } 836 837 /** 838 * Set an array with all imported or exported links 839 * 840 * @return array with imported or exported links. 841 */ 842 function get_ilinks() 843 { 844 return $this->ilink; 845 } 846 847 /** 848 * Set an array with all exported links 849 * 850 * @return array with imported or exported links. 851 */ 852 function get_elinks() 853 { 854 return $this->elink; 855 } 856 857 function get_fields_links($entities) 858 { 859 foreach ($entities as $entity_name) 860 { 861 $link = get_ilink($entity_name); 862 $fields_return[] = $link['ffalse']; 863 } 864 return $fields_return; 865 } 866 867 /*************************************************************\ 868 * add_element `Sniper' section * 869 \*************************************************************/ 870 871 function add_element($action, $element) 872 { 873 $this->set_operation($action); 874 $method = $this->get_method($action,$element['field']); 875 $element['real_field'] = $this->real_field($element['field']); 876 switch($action) 877 { 878 case 'select': 879 $method_default = '_add_field'; 880 break; 881 case 'insert': 882 case 'delete': 883 case 'update': 884 $method_default = 'set_'.$action.'_data'; 885 break; 886 case 'criteria': 887 $method_default = 'default_criteria'; 888 break; 889 default: 890 $this->dont_exist($action); 891 } 892 $this->ldebug('add_element', array('Element' => $element), 893 'dump'); 894 if($method == PHPGW_SQL_DEFAULT_METHOD) 895 { 896 $this->ldebug('add_element', 897 array('Method_Default DEF' => $method_default, 898 'Method DEF' => $default)); 899 $this->$method_default($element); 900 } 901 elseif ($method) 902 { 903 $this->ldebug('add_element', 904 array('Method_Default' => $method_default, 905 'Method' => $default)); 906 $this->$method($element); 907 } 908 else 909 { 910 $this->ldebug('add_element', 'Never be here, hope', 'msg'); 911 $this->dont_exist($element); 912 } 913 } 914 915 function get_method($action, $field) 916 { 917 if(isset($this->map[$field])) 918 { 919 $method = $this->map[$field][$action]; 920 if(isset($this->map[$field][$action]) 921 && method_exists($this, $method)) 922 { 923 return $method; 924 } 925 elseif(method_exists($this, $action.'_'.$field)) 926 { 927 return $action.'_'.$field; 928 } 929 else 930 { 931 return PHPGW_SQL_DEFAULT_METHOD; 932 } 933 } 934 // this is an error :/ not $field in map 935 return; 936 } 937 938 function real_field($field) 939 { 940 if(isset($this->map[$field])) 941 { 942 if(isset($this->map[$field]['field']) 943 && !empty($this->map[$field]['field'])) 944 { 945 return $this->map[$field]['field']; 946 } 947 else 948 { 949 return $field; 950 } 951 } 952 // this is an error :/ not $field in map 953 return; 954 } 955 956 /** 957 * Get the real field name with alias of table. (Used in criteria). 958 * 959 * @param string $field False field name. 960 * @return string alias.real_name 961 */ 962 function alias_field($field) 963 { 964 return $this->get_alias().'.'.$this->real_field($field); 965 } 966 967 968 function get_datatype($field) 969 { 970 if(isset($this->map[$field])) 971 { 972 if(isset($this->map[$field]['type']) 973 && !empty($this->map[$field]['type'])) 974 { 975 return $this->map[$field]['type']; 976 } 977 else 978 { 979 return 'string'; 980 } 981 } 982 // this is an error :/ not $field in map 983 return; 984 } 985 986 function make_pair($field, $value) 987 { 988 return array('field' => $field, 989 'value' => $value); 990 } 991 992 /*************************************************************\ 993 * sql_builder API section * 994 \*************************************************************/ 995 996 function add_select($field) 997 { 998 $this->add_element('select',$this->make_pair($field,'')); 999 $this->ldebug('add_select', array('Field' => $field)); 1000 } 1001 1002 function add_criteria($field, $value) 1003 { 1004 $this->add_element('criteria',$this->make_pair($field, 1005 $value)); 1006 $this->ldebug('add_criteria', array('Field' => $field)); 1007 1008 } 1009 function add_update($value, $field) 1010 { 1011 $this->add_element('update',$this->make_pair($field, 1012 $value)); 1013 } 1014 1015 function add_delete($field, $value) 1016 { 1017 $this->add_element('delete',$this->make_pair($field, 1018 $value)); 1019 } 1020 1021 function add_insert($field, $value, $idx = 0) 1022 { 1023 $this->insert_index = $idx; 1024 $this->add_element('insert',$this->make_pair($field, 1025 $value)); 1026 } 1027 1028 /** 1029 * Must raise errors for this class, don't know if phpgw have anything already, if yes, net call it 1030 * 1031 * @param mixed $data What dont exist 1032 */ 1033 function dont_exist($data) 1034 { 1035 } 1036 1037 /** 1038 * Get the field name which correspond to sort 1039 * 1040 * @param strngi $field The field 1041 * @return The alias and real name for field. 1042 */ 1043 function get_order($field) 1044 { 1045 if($this->map[$field]['sort']) 1046 { 1047 return $this->alias.'.'.$this->map[$field]['sort']; 1048 } 1049 } 1050 1051 function ldebug($myfoo, $data, $type = 'string', $err = '') 1052 { 1053// if (!((($myfoo != '') xor 1054// ($myfoo != 'default_criteria')) xor 1055// ($myfoo == '')) xor 1056// ($myfoo == '')) 1057// { 1058 return; 1059// } 1060 1061 $classname = '<strong>Class: '.get_class($this)."<br />Function: $myfoo<br /></strong>"; 1062 1063 switch($type) 1064 { 1065 case 'string': 1066 foreach($data as $vari => $value) 1067 { 1068 if (is_array($value)) 1069 { 1070 $this->ldebug($myfoo.' recursivecall', 1071 array(' -$vari: ' => $value), 1072 'dump'); 1073 } 1074 else 1075 { 1076 $output .= " -$vari = $value <br />"; 1077 } 1078 } 1079 break; 1080 case 'dump': 1081 foreach($data as $vari => $value) 1082 { 1083 $output .= " -$vari = "; 1084 $output .= var_dump($value)."<br />"; 1085 } 1086 break; 1087 default: 1088 $output .= "<br />$data<br />"; 1089 } 1090 if ($err != '') 1091 { 1092 $output = $classname.'Error: '.$output.'<br />'; 1093 } 1094 else 1095 { 1096 $output = $classname.$output.'<br />'; 1097 } 1098 echo $output; 1099 } 1100 } 1101?> 1102