db/db_item.inc.php

Go to the documentation of this file.
00001 <?php if(!function_exists('startedIndexPhp')) { header("location:../index.php"); exit();}
00002 
00003 
00004 require_once(confGet('DIR_STREBER') . "db/db.inc.php");
00005 require_once(confGet('DIR_STREBER') . "render/render_fields.inc.php");
00006 
00033 class Field
00034 {
00035     public      $type;                      #field
00036     public      $download   =FDOWNLOAD_ALWAYS; #loaded by default, on demand
00037     public      $name       ='';
00038     public      $title      ='';            # label used in forms
00039     public      $default;
00040     public      $tooltip    ='';
00041     public      $invalid;                   # current value marked as invalid (use for rerendering forms with invalid data)
00042 
00043     public      $func_renderToForm;            # function name for rendering the field / automatically defined
00044     public      $func_parseForm;            # functino name for parse entered data / automatically defined
00045     public      $func_renderListHead;
00046     public      $func_renderListRow;
00047     public      $func_getFormElement;
00048     public      $view_in_forms;             # TODO: 1-alwayys, 2-details, etc.
00049     public      $view_in_lists;             # do we see this field in lists?
00050     public      $log_changes = true;        # by default all changes are logged
00051     public      $export      = true;        # may be exported as csv or xml (should be false for passwords, etc)
00052 
00053 
00054     public      $export_csv = false;
00060     public function __construct($args=NULL)
00061     {
00062         #--- set parameters ------
00063         if(!$args) {
00064             trigger_error("Can't construct a field without name parameters", E_USER_ERROR);
00065         }
00066         foreach($args as $key=>$value) {
00067             empty($this->$key);     # cause php-notification if undefined property
00068             $this->$key= $value;
00069         }
00070 
00071 
00072         #--- try to automatically assign functions for rendering...
00073         if($this->view_in_forms) {
00074             foreach(array(
00075             '_renderToForm',
00076             '_parseForm',
00077             '_getFormElement'
00078             ) as $fn_append) {
00079                 $fname= $this->type.$fn_append;
00080                 $fn= 'func'.$fn_append;
00081                 if(!$this->$fn) {
00082                     if(function_exists($fname)) {
00083                         $this->$fn= $fname;
00084                     }
00085                 }
00086             }
00087         }
00088         if($this->view_in_lists) {
00089             foreach(array('_renderListHead','_renderListRow') as $fn_append) {
00090                 $fname= $this->type.$fn_append;
00091                 $fn= 'func'.$fn_append;
00092                 if(!$this->$fn) {
00093                     if(function_exists($fname)) {
00094                         $this->$fn= $fname;
00095                     }
00096                 }
00097                 else {
00098                     trigger_error("'$fname' is not defined", E_USER_ERROR);
00099                 }
00100             }
00101         }
00102 
00103         #--- some checks ---
00104         if(!$this->name) {
00105             trigger_error("Can't construct a field without name parameters",E_USER_ERROR);
00106             return;
00107         }
00108         if($this->download != FDOWNLOAD_ALWAYS && $this->download != FDOWNLOAD_ONDEMAND && $this->download != FDOWNLOAD_NEVER) {
00109             trigger_error("invalid value for download: $this->download",E_USER_ERROR);
00110         }
00111 
00112         #--- try to figure title ----
00113         if(!$this->title) {
00114             $this->title= ucwords(str_replace('_',' ',$this->name));
00115         }
00116     }
00117 
00118     #---------------------------------------------------------------------
00119     # converts a string into a valid value for database
00120     #---------------------------------------------------------------------
00121     public function value2db($value=FALSE)
00122     {
00123         return $value;
00124     }
00125 
00126     #------------------------------------------------------------------------
00127     # converts values from db into meaningful string-formats
00128     #------------------------------------------------------------------------
00129     public function db2value($value=FALSE)
00130     {
00131         return $value;
00132     }
00133 
00134     public function render2form(&$obj)
00135     {
00136         if(isset($this->func_renderToForm)) {
00137             $fn= $this->func_renderToForm;
00138             return $fn(&$this,&$obj);
00139         }
00140         return false;                   # TODO: add warning
00141     }
00142 
00143     public function parseForm(&$obj)
00144     {
00145         if(isset($this->func_parseForm)) {
00146             $fn= $this->func_parseForm;
00147             return $fn(&$this, &$obj);
00148         }
00149         return false;                   # TODO: add warning
00150     }
00151 
00155     public function getFormElement(&$obj, $title=NULL)
00156     {
00157         if(isset($this->func_getFormElement)) {
00158             $fn= $this->func_getFormElement;
00159             return $fn(&$this, &$obj, $title);
00160         }
00161         else {
00162             return new Form_CustomHTML('');
00163         }
00164     }
00165 }
00166 
00167 #================================================================================================================
00168 class FieldHidden extends Field {
00169     public function __construct($args=NULL) {
00170         $this->type=__class__;
00171         $this->default= 0;
00172         $this->view_in_forms=true;
00173         parent::__construct($args);
00174     }
00175 }
00176 
00177 #================================================================================================================
00178 class FieldInternal extends Field {
00179     public function __construct($args=NULL) {
00180         $this->type=__class__;
00181         $this->default= 0;
00182         $this->log_changes= false;
00183         $this->view_in_forms=false;
00184         $this->view_in_lists=false;
00185         parent::__construct($args);
00186     }
00187 }
00188 
00189 #================================================================================================================
00190 class FieldString extends Field {
00191     public function __construct($args=NULL) {
00192         $this->default= '';
00193         $this->type=__class__;
00194         $this->view_in_forms=true;
00195         $this->view_in_lists=true;
00196         parent::__construct($args);
00197     }
00198 }
00199 
00200 #================================================================================================================
00201 class FieldPassword extends Field {
00202     public function __construct($args=NULL) {
00203         $this->type=__class__;
00204         $this->default= '';
00205         $this->view_in_forms=true;
00206         $this->view_in_lists=false;
00207         parent::__construct($args);
00208     }
00209 }
00210 
00211 #================================================================================================================
00212 class FieldBool extends Field {
00213     public function __construct($args=NULL) {
00214         $this->default= 0;
00215         $this->type=__class__;
00216         $this->view_in_forms=true;
00217         parent::__construct($args);
00218     }
00219 }
00220 
00221 #================================================================================================================
00222 class FieldDate extends Field {
00223     public function __construct($args=NULL)
00224     {
00225         $this->default= '0000-00-00';
00226         $this->type=__class__;
00227         $this->view_in_forms=true;
00228         $this->view_in_lists=true;
00229         parent::__construct($args);
00230     }
00231 
00232 }
00233 
00234 #================================================================================================================
00235 class FieldTime extends Field {
00236     public function __construct($args=NULL) {
00237         $this->type=__class__;
00238         $this->view_in_forms=true;
00239         $this->view_in_lists=true;
00240         parent::__construct($args);
00241     }
00242 }
00243 
00244 #================================================================================================================
00245 class FieldPercentage extends Field {
00246     public function __construct($args=NULL) {
00247         $this->default= 0;
00248         $this->type=__class__;
00249         $this->view_in_forms=true;
00250         $this->view_in_lists=true;
00251         parent::__construct($args);
00252     }
00253 }
00254 
00255 #================================================================================================================
00256 class FieldDatetime extends Field {
00257     public function __construct($args=NULL) {
00258         $this->default= '0000-00-00 00:00:00';
00259         $this->type=__class__;
00260         $this->view_in_forms=true;
00261         $this->view_in_lists=true;
00262         parent::__construct($args);
00263     }
00264 }
00265 
00266 #================================================================================================================
00267 class FieldInt extends Field {
00268     public function __construct($args=NULL) {
00269         $this->default= 0;
00270         $this->type=__class__;
00271         $this->view_in_forms=true;
00272         $this->view_in_lists=true;
00273         parent::__construct($args);
00274     }
00275 }
00276 
00277 #================================================================================================================
00278 class FieldOption extends Field {
00279     public $options;
00280     public function __construct($args=NULL) {
00281         $this->default= 0;
00282         $this->type=__class__;
00283         $this->view_in_forms=true;
00284         $this->view_in_lists=true;
00285         $this->options=array();
00286         parent::__construct($args);
00287     }
00288 }
00289 
00290 #================================================================================================================
00291 class FieldText extends Field {
00292     public function __construct($args=NULL) {
00293         $this->default= '';
00294         $this->type=__class__;
00295         $this->view_in_forms=true;
00296         parent::__construct($args);
00297     }
00298 }
00299 
00300 
00301 #================================================================================================================
00302 class FieldUser extends Field {
00303     public function __construct($args=NULL) {
00304         $this->type=__class__;
00305         parent::__construct($args);
00306     }
00307 }
00308 
00309 //====================================================================
00310 // DbItem
00311 // - handles connection of objects to database
00312 //====================================================================
00313 abstract class DbItem {
00314     public $id=-1;                 # all items need to have an id
00315     public $_type;              # name of table like "user", etc. Needed to be set by derived class
00316     public $fields;             # reference to global assoc. array of Field-Objects
00317     private $field_states;      # assoc. array of field-names and field states. Required for lazy loading.
00318     public static $fields_static;
00319 
00320 
00321     public function __construct($id = false)
00322     {
00323         if(!isset($this->_type)) {
00324             trigger_error("Constructing DbItem requires this->_type to be set", E_USER_ERROR);
00325         }
00326 
00327         #--- create members for all fields ---
00328         $this->field_states=array();
00329         foreach($this->fields as $f) {
00330             $this->field_states[$f->name]=FSTATE_UNKNOWN;
00331             $tmp_name=$f->name;
00332 
00333             #--- set default-values ---
00334             $def_value=$f->default;
00335             if($def_value === FINIT_NOW) {
00336                 $def_value= getGMTString();
00337             }
00338             else if($def_value === FINIT_TODAY) {
00339                 $def_value=gmdate("Y-m-d");
00340             }
00341             else if($def_value === FINIT_RAND_MD5) {
00342                  $def_value= md5(time().microtime(). rand(12312,123213). rand(234423,123213)); #@@@ those numbers don't look very nice
00343             }
00344             else if($def_value === FINIT_CUR_USER) {
00345                 global $auth;
00346                 if($auth->cur_user) {
00347                     $def_value= $auth->cur_user->id;
00348                 }
00349             }
00350             $this->$tmp_name=$def_value;
00351         }
00352 
00353         if($id === 0) {
00354             return NULL;    # this is probably a failure...
00355         }
00356 
00357         if($id === false) {
00358           return;
00359         }
00360 
00361         #--- if id given, querry important fields from db
00362         $dbh = new DB_Mysql;
00363         $download_fields="";
00364         $delimiter= '';
00365         $fields=$this->fields;
00366         foreach($fields as $f) {
00367             if($f->download==FDOWNLOAD_ALWAYS) {
00368                 $download_fields.= $delimiter.$f->name;
00369                 $delimiter=',';
00370             }
00371         }
00372         $prefix= confGet('DB_TABLE_PREFIX');
00373         $query = "SELECT $download_fields from {$prefix}$this->_type WHERE id = 1";
00374 
00375         $data = $dbh->prepare($query)->execute($id)->fetch_assoc();
00376         if($data) {
00377             foreach( $data as $attr => $value ) {
00378                 $this->$attr = stripslashes($value);
00379             }
00380         }
00381         else {
00382             unset($this);
00383             return NULL;     # returning false does not makes sense
00384         }
00385     }
00386 
00387     #-------------------------------------------------
00388     # delete
00389     #-------------------------------------------------
00390     public function deleteFull()
00391     {
00392         if(!$this->id) {
00393           trigger_error("Deleting requires id",E_USER_ERROR);
00394         }
00395         $prefix= confGet('DB_TABLE_PREFIX');
00396         $query = "DELETE FROM {$prefix}{$this->_type} WHERE id = {$this->id}";
00397         $dbh = new DB_Mysql;
00398         $dbh->prepare($query)->execute($this->id);
00399 
00400         #--- deleting yourself? ----
00401         unset($this);
00402         return true;
00403     }
00404 
00405     #-------------------------------------------------
00406     # mark_delete (sets object-state to -1)
00407     #-------------------------------------------------
00408     public function delete()
00409     {
00410         if(!$this->id) {
00411             trigger_error("Deleting requires id", E_USER_ERROR);
00412         }
00413         $prefix= confGet('DB_TABLE_PREFIX');
00414         $query= "update {$prefix}{$this->_type} SET state=-1 WHERE id= $this->id";
00415         $dbh = new DB_Mysql;
00416         $dbh->prepare($query)->execute();
00417 
00418         #--- deleting yourself? ----
00419         unset($this);
00420         return true;
00421     }
00422 
00423 
00424     #-------------------------------------------------
00425     # update()  / write to db
00426     #-------------------------------------------------
00427     public function update($args=NULL, $update_modifier=true)
00428     {
00429         if(!$this->id) {
00430           trigger_error("needs id to call update()", E_USER_ERROR);
00431         }
00432         if(!isset($this->_type) || !$this->_type || $this->_type=="") {
00433             trigger_error("need _type to call update()", E_USER_ERROR);
00434         }
00435         if(!$args || !sizeof($args)) {
00436             $args=$this->field_states;
00437         }
00438         if(!sizeof($args)) {
00439             trigger_error("need members to update to database. e.g. 'firstname,lastname,data'", E_USER_ERROR);
00440         }
00441 
00442         #--- build query-string like "update users SET firstname=:1, lastname=:2 where id=:3" --
00443         #--- build value-array ----
00444         $prefix= confGet('DB_TABLE_PREFIX');
00445         $query = "UPDATE {$prefix}{$this->_type} SET  ";
00446         $values=array();
00447         $counter=1;
00448         $delimiter="";
00449         $value_str="VALUES(";
00450 
00451         # TODO: filter changed fields before saving to db!
00452         foreach($this->field_states as $m_key => $m_state) {
00453             if(!isset($this->$m_key) && $this->$m_key!=NULL) {
00454                 trigger_error("$m_key is not a member of '".get_class($this)."' and can't be passed to db", E_USER_ERROR);
00455             }
00456             $values[]=  $this->$m_key;
00457             $query.=    $delimiter.$m_key .'=' .$counter;
00458             $value_str.=$delimiter." ".$counter;
00459             ++$counter;
00460             $delimiter=", ";
00461         }
00462         $query.= " WHERE id=".$counter++;
00463         $values[]=$this->id;
00464 
00465         $dbh = new DB_Mysql;
00466         $statement=$dbh->prepare($query);
00467         call_user_func_array(array($statement,'execute'),$values);
00468         return true;
00469     }
00470 
00471 
00472 
00478     public function insert()
00479     {
00480         if($this->id) {
00481           trigger_error("User object which already has an id, can't be inserted", E_USER_ERROR);
00482         }
00483         if(!sizeof($this->field_states)) {
00484             trigger_error("need members to update to database. e.g. 'firstname,lastname,data'",E_USER_ERROR);
00485         }
00486 
00487         #--- build query-string like "INSERT INTO users (firstname, lastname) VALUES(:1, :2)" --
00488         #--- build value-array ----
00489         $prefix= confGet('DB_TABLE_PREFIX');
00490         $t_values= array();
00491         $t_fields= array();
00492         foreach($this->field_states as $m_key => $m_state) {
00493             if(!isset($this->$m_key) && $this->$m_key!=NULL) {
00494                 trigger_error("$m_key is not a member of $this and can't be passed to db", E_USER_ERROR);
00495             }
00496 
00497             $t_fields[]= $m_key;
00498             $t_values[]="'".asSecureString($this->$m_key)."'";
00499         }
00500 
00501         $dbh = new DB_Mysql;
00502         #$statement=$dbh->prepare($query);
00503         #call_user_func_array(array($statement,'execute'),$values);
00504 
00505         $str_query = "INSERT INTO {$prefix}$this->_type "
00506                           . '(' . join(', ', $t_fields )   .')'
00507                     .' VALUES(' . join(', ', $t_values) .')';
00508 
00509         $sth= $dbh->prepare($str_query);
00510 
00511         $sth->execute("",1);
00512 
00513          #$statement->execute($values);
00514         $this->id =  $dbh->lastId();
00515         return true;
00516 
00517     }
00518 
00524     function getShort($length = false)
00525     {
00526         if(isset($this->short) && $this->short && $this->short !="") {
00527             return $this->short;
00528         }
00529         if(!$length) {
00530             $length= confGet('STRING_LENGTH_SHORT');
00531         }
00532         if(isset($this->name) && $this->name !="") {
00533             if(strlen($this->name) > $length) {
00534                 if(function_exists('mb_substr')) {
00535                     return mb_substr($this->name, 0 ,$length) . "...";
00536                 }
00537                 return substr($this->name, 0 ,$length) . "...";
00538             }
00539             return $this->name;
00540         }
00541         else {
00542             return __("unnamed");
00543         }
00544     }
00545 
00546 
00547 
00551     function getShortWithTitle()
00552     {
00553         if(isset($this->short) && $this->short && $this->short !="") {
00554             return "<span title='$this->name'>".asHtml($this->short)."</span>";
00555         }
00556         $length= confGet('STRING_LENGTH_SHORT');
00557         if(isset($this->name) && $this->name !="") {
00558             ereg("(.{0,$length})(.*)",asHtml($this->name),$matches);
00559             if(!$matches[2]) {
00560                 return $matches[1];
00561             }
00562             return "<span title='$this->name'>".$matches[1]."...</span>";
00563         }
00564         else {
00565             return __("unnamed");
00566         }
00567     }
00568 
00569 
00570 
00571     static function getItemType($id)
00572     {
00573         $prefix= confGet('DB_TABLE_PREFIX');
00574         $dbh = new DB_Mysql;
00575         $sth= $dbh->prepare("SELECT  type FROM {$prefix}item i
00576             WHERE
00577                   i.id = $id
00578             " );
00579         $sth->execute("",1);
00580         $tmp=$sth->fetchall_assoc();
00581         return $tmp[0]['type'];
00582     }
00583 
00584 
00585 
00586     static function getItemState($id)
00587     {
00588         $prefix= confGet('DB_TABLE_PREFIX');
00589         $dbh = new DB_Mysql;
00590         $sth= $dbh->prepare("SELECT state FROM {$prefix}item i
00591             WHERE
00592                   i.id = $id
00593             " );
00594         $sth->execute("",1);
00595         $tmp=$sth->fetchall_assoc();
00596         return $tmp[0]['state'];
00597     }
00598 
00599 
00603     public function nowViewedByUser($user=NULL)
00604     {
00605         global $auth;
00606 
00607         if(is_null($user)){
00608             if($auth->cur_user){
00609                 $user = $auth->cur_user;
00610             }
00611             else{
00612                 return NULL;
00613             }
00614         }
00615 
00616         require_once(confGet('DIR_STREBER') . 'db/db_itemperson.inc.php');
00617 
00618         if($view = ItemPerson::getAll(array('person'=>$user->id, 'item'=>$this->id))){
00619             $view[0]->viewed        = true;
00620             $view[0]->viewed_last   = getGMTString();
00621             $view[0]->update();
00622         }
00623         else{
00624             $new_view = new ItemPerson(array(
00625             'item'          =>$this->id,
00626             'person'        =>$user->id,
00627             'viewed'        =>1,
00628             'viewed_last'   =>getGMTString(),
00629             'is_bookmark'   =>0,
00630             'notify_on_change'=>0));
00631             $new_view->insert();
00632         }
00633     }
00634 
00635 
00636 
00641     public function isChangedForUser()
00642     {
00643         global $auth;
00644 
00645         ### ignore, if too old
00646         if($this->modified < $auth->cur_user->date_highlight_changes) {
00647             return false;
00648         }
00649 
00650         ### ignore self edited items ###
00651         if($this->modified_by == $auth->cur_user->id) {
00652             return false;
00653         }
00654 
00655         require_once(confGet('DIR_STREBER') . 'db/db_itemperson.inc.php');
00656         if($item_persons = ItemPerson::getAll(array('person'=>$auth->cur_user->id,'item' => $this->id))) {
00657             $ip= $item_persons[0];
00658             if($ip->viewed_last < $this->modified) {
00659                 return true;
00660             }
00661             else {
00662                 return false;
00663             }
00664         }
00665         return true;
00666     }
00667 
00668     public function nowChangedByUser()
00669     {
00670         require_once('std/mail.inc.php');
00671         require_once('db/db_itemperson.inc.php');
00672         ### if notify_if_unchanges is set ###
00673         if ($ip = ItemPerson::getAll(array('item'=>$this->id,'notify_if_unchanged_min'=>NOTIFY_1DAY))){
00674             if(isset($ip)){
00675                 $ip[0]->notify_date = date('Y-m-d H:i:s', time());
00676                 $ip[0]->update();
00677             }
00678         }
00679     }
00680 
00681 
00682 
00683 
00684     #--- set --------------------------------------
00685     function __set($name, $val)
00686     {
00687        if (isset($this->$name) || isset($this->field_states[$name])) {
00688            $this->$name = $val;
00689        }
00690        else {
00691             trigger_error("can't set dbItem->$name for object of type ".get_class($this),E_USER_ERROR);
00692        }
00693     }
00694 
00695     #--- get --------------------------------------
00696     function __get($name)
00697     {
00698        if(isset($this->$name)) {
00699            return $this->$name;
00700        }
00701        else if(isset($this->fields[$name])) {
00702             trigger_error("can't read '$name' from object of type ".get_class($this),E_USER_ERROR);
00703        }
00704        else {
00705             trigger_error("can't read '$name' from object of type '".get_class($this)."' ",E_USER_WARNING);
00706        }
00707    }
00708 }
00709 
00710 
00711 
00712 DbProjectItem::initItemFields();
00713 
00714 
00715 function addProjectItemFields(&$ref_fields) {
00716     global $g_item_fields;
00717     foreach($g_item_fields as $f) {
00718         $ref_fields[$f->name]=$f;
00719     }
00720 }
00721 
00737 class DbProjectItem extends DbItem {
00738 
00739     public $fields_project;
00740     private $_values_org=array();
00741     public $children= array();
00742 
00746     public function __construct($id_or_array=NULL)
00747     {
00748 
00754         $this->_type=strtolower(get_class($this));
00755 
00756 
00760         if(!$this->fields) {
00761             global $g_item_fields;
00762             $this->fields=&$g_item_fields;
00763         }
00764 
00768         if(is_array($id_or_array)) {
00769             parent::__construct();
00770             foreach($id_or_array as $key => $value) {
00771                 is_null($this->$key); ### cause E_NOTICE on undefined properties
00772                 $this->_values_org[$key]= $this->$key=$value;
00773             }
00774         }
00775 
00781         else if(is_int($id_or_array) || (is_string($id_or_array) and $id_or_array !== "0")){
00782 
00783             parent::__construct();  # call constructor to initialize members from field-array
00784             $id=intval($id_or_array);       # construction-param was an id
00785             if(!$id) {
00786                 return;
00787             }
00788 
00789             global $g_item_fields;
00790 
00791 
00792             #--- try to find in item-table ---
00793             {
00794                 $dbh = new DB_Mysql;
00795                 $str_download_fields="";
00796                 $str_delimiter= '';
00797                 foreach($g_item_fields as $f) {
00798                     $str_download_fields.= $str_delimiter . $f->name;
00799                     $str_delimiter=',';
00800                 }
00801                 $prefix= confGet('DB_TABLE_PREFIX');
00802                 $query = "SELECT $str_download_fields from {$prefix}item WHERE id = $id";
00803                 $data = $dbh->prepare($query)->execute()->fetch_assoc();
00804                 if($data) {
00805                     foreach( $data as $attr => $value ) {
00806 
00807                         is_null($this->$attr);   # cause E_NOTICE if member not defined
00808                         $this->_values_org[$attr]= $this->$attr = $value;
00809                     }
00810                 }
00811 
00812                 #--- not found in item-table ---
00813                 else {
00817                     #trigger_error("item id='$id' not found in table", E_USER_WARNING);
00818                     unset($this);                   #@@@ not sure if abort called construction like this works
00819                     return NULL;
00820                 }
00821             }
00822 
00823             #--- now find the other fields in the appropriate table ---
00824             if($this->_type && $this->_type != 'dbprojectitem') {
00825                 $dbh = new DB_Mysql;
00826                 $str_download_fields="";
00827                 $str_delimiter= '';
00828                 foreach($this->fields as $f) {
00829                     #--- ignore project item fields ---
00830                     if(!isset($g_item_fields[$f->name])) {
00831                         $str_download_fields.= $str_delimiter . $f->name;
00832                         $str_delimiter=',';
00833                     }
00834                 }
00835                 $prefix= confGet('DB_TABLE_PREFIX');
00836                 $query = "SELECT $str_download_fields from {$prefix}$this->_type WHERE id = $id";
00837                 $data = $dbh->prepare($query)->execute()->fetch_assoc();
00838                 if($data) {
00839                     foreach( $data as $attr => $value ) {
00840                         is_null($this->$attr);                                          # cause E_NOTICE if member not defined
00841                         #$this->_values_org[$attr]= $this->$attr = stripslashes(stripslashes(stripslashes($value))); #@@@ note this is a weird bug
00842 
00847                         #if(get_magic_quotes_gpc()) {
00848                         #    $this->_values_org[$attr]= $this->$attr = stripslashes($value);
00849                         #}
00850                         #else {
00851                         
00852                         $this->_values_org[$attr]= $this->$attr = $value;
00853                         #}
00854                     }
00855                 }
00856 
00857                 #--- not found in item-table ---
00858                 else {
00859                     trigger_error("item #$id not found in db-table '$this->_type'",E_USER_WARNING);
00860                     return NULL;
00861                 }
00862             }
00863 
00864         }
00865         #--- just empty ----
00866         else {
00870             #trigger_error("can't construct zero-id item",E_USER_WARNING);
00871             parent::__construct();
00872             return NULL;
00873         }
00874     }
00875     
00876     static function initItemFields() {
00877         global $g_item_fields;
00878         $g_item_fields=array();
00879         
00880         foreach(array(
00881                     ### internal fields ###
00882                     new FieldInternal  (array('name'=>'id',
00883                         'default'=>0,
00884                         'log_changes'=>false,
00885                     )),
00886                     new FieldInternal  (array('name'=>'type',
00887                         'default'=>0,
00888                         'log_changes'=>false,
00889                     )),
00890                     new FieldUser     (array('name'=>'created_by',
00891                         'default'=> FINIT_CUR_USER,
00892                         'view_in_forms'=>false,
00893                         'log_changes'=>false,
00894                     )),
00895                     new FieldDatetime( array('name'=>'created',
00896                         'default'=>FINIT_NOW,
00897                         'view_in_forms'=>false,
00898                         'log_changes'=>false,
00899                     )),
00900                     new FieldUser     (array('name'=>'modified_by',
00901                         'default'=> FINIT_CUR_USER,
00902                         'view_in_forms'=>false,
00903                         'log_changes'=>false,
00904                     )),
00905                     new FieldDate     (array('name'=>'modified',
00906                         'default'=>FINIT_NOW,
00907                         'view_in_forms'=>false,
00908                         'log_changes'=>false,
00909                     )),
00910                     new FieldUser     (array('name'=>'deleted_by',
00911                         'view_in_forms'=>false,
00912                         'log_changes'=>false,
00913                         'default'=>0,
00914                     )),
00915                     new FieldDate     (array('name'=>'deleted',
00916                         'default'=>FINIT_NEVER,
00917                         'view_in_forms'=>false,
00918                         'log_changes'=>false,
00919                     )),
00920                     new FieldInternal(array(    'name'=>'pub_level',
00921                         'view_in_forms'=>false,
00922                         'default'=>PUB_LEVEL_OPEN,
00923                         'log_changes'=>true,
00924         
00925                     )),
00926                     new FieldInternal  (array('name'=>'state',
00927                         'log_changes'=>true,
00928                         'default'=>1,
00929                     )),
00930                     new FieldInternal  (array('name'=>'project',
00931                         'default'=>0,
00932                         'log_changes'=>false,
00933                     )),
00934         
00935                ) as $f) {
00936                     $g_item_fields[$f->name]=$f;
00937                }
00938             }
00939         
00940 
00941     
00942 
00943 
00949     static function getById($id)
00950     {
00951         $i= new DbProjectItem($id);
00952         if($i->id) {
00953             return $i;
00954         }
00955         return NULL;
00956     }
00957 
00958 
00966     static function getVisibleById($id)
00967     {
00968         if($i= DbProjectItem::getById($id)) {
00969             if($i->type == ITEM_PROJECT) {
00970 
00974                 return $i;
00975             }
00976             else if($i->type == ITEM_PERSON) {
00977                 if($p= Person::getVisibleById($id)) {
00978                     return $i;
00979                 }
00980                 else {
00981                     return NULL;
00982                 }
00983 
00984             }
00985             else if($i->type == ITEM_COMPANY) {
00986                 require_once(confGet('DIR_STREBER') . 'db/class_company.inc.php');
00987 
00988                 if($c= Company::getVisibleById($id)) {
00989                     return $i;
00990                 }
00991                 else {
00992                     return NULL;
00993                 }
00994 
00995             }
00996             else {
00997                 if($p= Project::getById($i->project)) {
00998                     if($p->validateViewItem($i)) {
00999                         return $i;
01000                     }
01001                 }
01002                 else {
01003                     trigger_error("item #$id (type= $i->type) has no project?",E_USER_WARNING);
01004                 }
01005             }
01006 
01007         }
01008         return NULL;
01009     }
01010 
01014     static function getEditableById($id)
01015     {
01016         require_once(confGet('DIR_STREBER') . 'db/class_project.inc.php');
01017         if($i= DbProjectItem::getById($id)) {
01018             if($i->type == ITEM_PROJECT) {
01019                 global $auth;
01020                 if($auth->cur_user->user_rights & RIGHT_PROJECT_EDIT) {
01021                     return $i;
01022                 }
01023             }
01024             else if($p= Project::getById($i->project)) {
01025                 if($p->validateEditItem($i)) {
01026                     return $i;
01027                 }
01028             }
01029             else {
01030                 trigger_error("issue without project?",E_USER_WARNING);
01031             }
01032         }
01033         return NULL;
01034     }
01035 
01036 
01037     /***************************************************************
01038     * insert objects to database
01039     */
01040     public function insert()
01041     {
01042         global $g_item_fields;
01043 
01044         if($this->id) {
01045           trigger_error("User object which already has an id, can't be inserted", E_USER_WARNING);
01046         }
01047         if(!sizeof($this->field_states)) {
01048             trigger_error("need members to update to database. e.g. 'firstname,lastname,data'", E_USER_WARNING);
01049         }
01050 
01059         #--- first write item-fields ---
01060         #
01061         # build query-string like "INSERT INTO users (firstname, lastname) VALUES(tom, mann)"
01062         #
01063         {
01064             $dbh = new DB_Mysql;
01065 
01066             $t_fields=array();
01067             $t_values=array();
01068             foreach($g_item_fields as $f) {
01069                 $name= $f->name;
01070                 if(!isset($this->$name) && $this->$name!=NULL) {
01071                     trigger_error("$name is not a member of $this and can't be passed to db",E_USER_WARNING);
01072                 }
01073                 $t_fields[]=$name;
01074                 $t_values[]="'".asSecureString($this->$name)."'";
01075             }
01076             $prefix= confGet('DB_TABLE_PREFIX');
01077             $str_query= 'INSERT INTO '
01078                         .$prefix.'item '
01079                               . '(' . join(', ', $t_fields )   .')'
01080                         .' VALUES(' . join(', ', $t_values) .')';
01081 
01082             $sth= $dbh->prepare($str_query);
01083             $sth->execute("",1);
01084         }
01085 
01086         #--- extract the id of last inserted item ---
01087         $this->id =  $dbh->lastId();
01088 
01089         #--- now write non item-fields ---
01090         #
01091         # build query-string like "INSERT INTO users (firstname, lastname) VALUES(tom, mann)"
01092         #
01093         {
01094             $dbh = new DB_Mysql;
01095             $t_fields=array();
01096             $t_values=array();
01097 
01098             foreach($this->fields as $f) {
01099                 $name= $f->name;
01100 
01101                 ### skip project-item fields ###
01102                 if(isset($this->fields[$name]) && isset($this->fields[$name]->in_db_object) || !isset($g_item_fields[$name])) {
01103                     if(!isset($this->$name) && $this->$name!=NULL) {
01104                         trigger_error("$name is not a member of $this and can't be passed to db", E_USER_WARNING);
01105                     }
01106                     $t_fields[]=$name;
01107                     $t_values[]="'".asSecureString($this->$name)."'";
01108                 }
01109             }
01110             $str_query= 'INSERT INTO '
01111                         .$prefix.$this->_type
01112                               . '(' . join(',', $t_fields  ) .')'
01113                         .' VALUES(' . join(',', $t_values) .')';
01114 
01115 
01116             $sth= $dbh->prepare($str_query);
01117             $sth->execute("",1);
01118         }
01119         return true;
01120     }
01121 
01122     /***************************************************************
01123     * update objects in database
01124     */
01125     public function update($args=NULL, $update_modifier=true)
01126     {
01127         global $auth;
01128         global $g_item_fields;
01129         $dbh = new DB_Mysql;
01130 
01131         $update_fields=NULL;
01132 
01133         ### build hash to fast access ##
01134         if($args) {
01135             $update_fields=array();
01136             foreach($args as $a) {
01137                 $update_fields[$a]=true;
01138             }
01139         }
01140 
01141         if(!$this->id) {
01142           trigger_error("User object without id can't be updated", E_USER_WARNING);
01143         }
01144         if(!sizeof($this->field_states)) {
01145             trigger_error("need members to update to database. e.g. 'firstname,lastname,data'", E_USER_WARNING);
01146         }
01147 
01155         if($update_modifier && $auth->cur_user) {
01156             $this->modified_by= $auth->cur_user->id;
01157             $this->modified=  getGMTString();
01158             if($update_fields) {
01159                 $update_fields['modified_by']=true;
01160                 $update_fields['modified']=true;
01161             }
01162         }
01163 
01164 
01165         $log_changed_fields= array();
01166 
01167         #--- first write item-fields ---
01168         #
01169         #--- build query-string like "update users SET firstname=:1, lastname=:2 where id=:3" --
01170         {
01171             $t_pairs=array();
01172             foreach($g_item_fields as $f) {
01173                 $name= $f->name;
01174                 if($update_fields && !isset($update_fields[$name])) {
01175                     continue;
01176                 }
01177                 
01178                 if(isset($this->_values_org[$name])) {
01179                     if(!isset($this->$name) && $this->$name!=NULL) {
01180                         trigger_error("$name is not a member of $this and can't be passed to db", E_USER_WARNING);
01181                     }
01182 
01183                     if (  $this->_values_org[$name] == stripslashes($this->$name)) {
01184                         continue;
01185                     }
01186                     else if($this->fields[$name]->log_changes) {
01187                         $log_changed_fields[]=$name;
01188                     }
01189                 }
01190 
01191                 $t_pairs[]= $name."='".asSecureString($this->$name)."'";
01192             }
01193             $prefix= confGet('DB_TABLE_PREFIX');
01194             if(count($t_pairs)) {
01195                 $str_query= 'UPDATE '
01196                             .$prefix.'item '
01197                             .'SET ' . join(', ', $t_pairs)
01198                             .' WHERE id='.$this->id ;
01199 
01200                 $dbh = new DB_Mysql;
01201 
01202                 $sth= $dbh->prepare($str_query);
01203                 $sth->execute("",1);
01204             }
01205         }
01206 
01207         #--- now write non item-fields ---
01208         #
01209         #--- build query-string like "update users SET firstname=:1, lastname=:2 where id=:3" --
01210         #
01211         if($this->_type && $this->_type != 'dbprojectitem') {
01212 
01213             $t_pairs=array();          # the 'id' field is skipped later, because it's defined as project-item-field. so we have to add it here
01214             foreach($this->fields as $f) {
01215                 $name= $f->name;
01216 
01217                 ### selective updates ###
01218                 if($update_fields && !isset($update_fields[$name])) {
01219                     continue;
01220                 }
01221 
01222                 ### skip project-item fields ###
01223                 if(
01224                    (   isset($this->fields[$name])
01225                     && isset($this->fields[$name]->in_db_object)
01226                    )
01227                    || !isset($g_item_fields[$name])
01228                 ){
01229                     if(!isset($this->$name) && $this->$name!=NULL) {
01230                         trigger_error("$name is not a member of $this and can't be passed to db", E_USER_WARNING);
01231                         continue;
01232                     }
01233                     if(isset($this->_values_org[$name])) {
01234                         if (  $this->_values_org[$name] == stripslashes($this->$name)) {
01235                             continue;
01236                         }
01237                         else if($this->fields[$name]->log_changes) {
01238                             $log_changed_fields[]=$name;
01239                         }
01240                     }
01241                     global $sql_obj;
01242                     $t_pairs[]= $bla= $name.'='."'". asSecureString($this->$name)."'";
01243                 }
01244             }
01245             if(count($t_pairs)) {
01246                 $str_query= 'UPDATE '
01247                             .$prefix.$this->_type
01248                             .' SET ' . join(', ', $t_pairs)
01249                             .' WHERE id='.$this->id ;
01250 
01251                 $sth= $dbh->prepare($str_query);
01252                 $sth->execute("",1);
01253             }
01254 
01255             if($log_changed_fields) {
01256                 require_once(confGet('DIR_STREBER') . "db/db_itemchange.inc.php");
01257                 foreach($log_changed_fields as $name) {
01258 
01262                     $c= new ItemChange(array(
01263                         'item'=>    $this->id,
01264                         'field'=>   $name,
01265                         'value_old'=>$this->_values_org[$name],
01266                     ));
01267                     $c->insert();
01268                 }
01269             }
01270         }
01271         return true;
01272     }
01273 
01277     public function delete()
01278     {
01279         global $auth;
01280         if(!$this->id) {
01281           trigger_error("Deleting requires id", E_USER_WARNING);
01282         }
01283 
01284 
01285         ### check user-rights ###
01286         if($pp= $this->getProjectPerson()) {
01287 
01288 
01289             $pub_level=  $this->pub_level;
01290 
01291             ### owned ###
01292             if($this->created_by == $pp->person) {
01293                 $pub_level= PUB_LEVEL_OWNED;
01294             }
01295 
01296             ### is item editable ?
01297             if($pub_level >= $pp->level_delete
01298             ) {
01299                 ### AND below delete-level ###
01300                 if($pub_level >= $pp->level_delete
01301                 ) {
01302                     $this->state = -1;
01303                     $this->deleted_by= $auth->cur_user->id;
01304                     $this->deleted= getGMTString();
01305 
01306                     $this->update();
01307 
01308                     #--- deleting yourself? ----
01309                     return true;
01310 
01311                 }
01312             }
01313         }
01314         ### not a project-item? ###
01315         #
01316         #@@@  be sure that rights deleting project, companies and persons is validated somewhere else
01317         #
01318         else if($this->project == 0) {
01319 
01320             if($auth->cur_user) {
01321                 $this->state = -1;
01322                 $this->deleted_by= $auth->cur_user->id;
01323                 $this->deleted= getGMTString();
01324 
01325                 $this->update();
01326                 return true;
01327             }
01328             else {
01329                 return false;
01330             }
01331         }
01332         return true;
01333     }
01334 
01341     public function deleteFromDb()
01342     {
01343         if(!$this->id) {
01344           trigger_error("Deleting requires id",E_USER_ERROR);
01345         }
01346         $prefix= confGet('DB_TABLE_PREFIX');
01347 
01348         $query = "DELETE FROM {$prefix}{$this->_type} WHERE id = {$this->id}";
01349         $dbh = new DB_Mysql;
01350         $dbh->prepare($query)->execute($this->id);
01351 
01352 
01353         $query = "DELETE FROM {$prefix}item WHERE id = {$this->id}";
01354         $dbh = new DB_Mysql;
01355         $dbh->prepare($query)->execute($this->id);
01356 
01357         #--- deleting yourself? ----
01358         return true;
01359     }
01360 
01361 
01362 
01366     public function getProjectPerson() {
01367         global $auth;
01368 
01369         $prefix= confGet('DB_TABLE_PREFIX');
01370 
01371         #--- get the belonging project-person ---
01372         $dbh = new DB_Mysql;
01373 
01374         $sth= $dbh->prepare(
01375                 "SELECT i.*, upp.* from {$prefix}item i,  {$prefix}projectperson upp
01376                 WHERE
01377                         upp.person = {$auth->cur_user->id}
01378                     AND upp.state = 1
01379                     AND upp.project = $this->project
01380 
01381                     AND i.type = '".ITEM_PROJECTPERSON."'
01382                     AND i.id = upp.id
01383                 ");
01384         $sth->execute("",1);
01385         $tmp=$sth->fetchall_assoc();
01386 
01387         ### return nothing if no rights ###
01388         if(count($tmp) != 1) {
01389             return NULL;
01390         }
01391         require_once(confGet('DIR_STREBER') . 'db/class_projectperson.inc.php');
01392         $pp=new ProjectPerson($tmp[0]);
01393         return $pp;
01394     }
01395 
01402     public function getValidUserSetPublevel()
01403     {
01404         global $g_pub_level_names;
01405 
01406         ### get belonging project person ###
01407         if($pp= $this->getProjectPerson()) {
01408             ### can we edit this object ? ###
01409             if(
01410                 $pp->level_edit <= $this->pub_level
01411                 ||
01412                 $this->created_by ==