* @package projectmanager * @copyright (c) 2005 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @version $Id: class.soconstraints.inc.php 22355 2006-08-26 16:30:45Z ralfbecker $ */ include_once(PHPGW_INCLUDE_ROOT.'/etemplate/inc/class.so_sql.inc.php'); /** * Constraints storage object of the projectmanager * * There are 3 constraint-types: * - start: PE has to start after an other PE (own pe_id is in pe_id_start) * - end: PE has to end before the start an other PE (own pe_id is in pe_id_end) * - milestone: PE has to end before a milestone (own pe_id is in pe_id_end) * * Tables: phpgw_pm_constraints */ class soconstraints extends so_sql { /** * Constructor, calls the constructor of the extended class * * @param int $pm_id pm_id of the project to use, default null */ function soconstraints($pm_id=null) { $this->so_sql('projectmanager','phpgw_pm_constraints'); if ((int) $pm_id) { $this->pm_id = (int) $pm_id; } } /** * searches db for rows matching searchcriteria, reimplemented to automatic add $this->pm_id * * '*' and '?' are replaced with sql-wildcards '%' and '_' * * @param array/string $criteria array of key and data cols, OR a SQL query (content for WHERE), fully quoted (!) * @param boolean $only_keys=true True returns only keys, False returns all cols * @param string $order_by='' fieldnames + {ASC|DESC} separated by colons ',', can also contain a GROUP BY (if it contains ORDER BY) * @param string/array $extra_cols='' string or array of strings to be added to the SELECT, eg. "count(*) as num" * @param string $wildcard='' appended befor and after each criteria * @param boolean $empty=false False=empty criteria are ignored in query, True=empty have to be empty in row * @param string $op='AND' defaults to 'AND', can be set to 'OR' too, then criteria's are OR'ed together * @param mixed $start=false if != false, return only maxmatch rows begining with start, or array($start,$num) * @param array $filter=null if set (!=null) col-data pairs, to be and-ed (!) into the query without wildcards * @param string $join='' sql to do a join, added as is after the table-name, eg. ", table2 WHERE x=y" or * "LEFT JOIN table2 ON (x=y)", Note: there's no quoting done on $join! * @return array of matching rows (the row is an array of the cols) or False */ function &search($criteria,$only_keys=True,$order_by='',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter=null,$join='') { if (!$this->pm_id && !isset($criteria['pm_id']) && !isset($filter['pm_id'])) { $filter['pm_id'] = $this->pm_id; } if (isset($criteria['pe_id']) && (int)$criteria['pe_id']) { $pe_id = (int) $criteria['pe_id']; unset($criteria['pe_id']); } if (isset($filter['pe_id']) && (int)$filter['pe_id']) { $pe_id = (int) $filter['pe_id']; unset($filter['pe_id']); } if ($pe_id) { $filter[] = "(pe_id_end=$pe_id OR pe_id_start=$pe_id)"; if ($extra_cols && !is_array($extra_cols)) $extra_cols = explode(',',$extra_cols); // defines 3 constrain-types: milestone, start and end $extra_cols[] = "CASE WHEN ms_id != 0 THEN 'milestone' WHEN pe_id_start=$pe_id THEN 'start' ELSE 'end' END AS constraint_type"; if (!$order_by) $order_by = 'constraint_type'; } return parent::search($criteria,$only_keys,$order_by,$extra_cols,$wildcard,$empty,$op,$start,$filter,$join); } /** * reads all constraints of a milestone (ms_id given), an element (pe_id given) or a project (pm_id given) * * It calls allways search to retrive the data. The form of the data returned depends on the given keys! * * @param array $keys array with keys in form internalName => value, may be a scalar value if only one key * @param string/array $extra_cols string or array of strings to be added to the SELECT, eg. "count(*) as num" * @param string $join='' sql to do a join, added as is after the table-name, eg. ", table2 WHERE x=y" or * @return array/boolean milestones: array with pe_id's, element: array with subarrays for start, end, milestone, * or same as search($keys) would return */ function read($keys,$extra_cols='',$join='') { if (!$search =& $this->search($criteria,$only_keys=True,$order_by='',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$keys)) { return false; } $ret = array(); if ((int) $keys['ms_id']) { foreach($search as $row) { $ret[] = $row['pe_id_end']; } } elseif ((int) $keys['pe_id']) { foreach($search as $row) { switch($row['constraint_type']) { case 'milestone': $ret['milestone'][] = $row['ms_id']; break; case 'start': $ret['start'][] = $row['pe_id_end']; break; case 'end': $ret['end'][] = $row['pe_id_start']; break; } } } else { $ret =& $search; } if ($this->debug) { echo "

soconstraints::read(".print_r($keys,true).",'$extra_cols','$join')

\n"; _debug_array($ret); } return $ret; } /** * saves the given data to the db * * @param array $data with either data for one row or null, or * for the constraints of an elements the keys pe_id, start, end, milestone, or * for the constraints of a milestone the keys ms_id, pe_id (pm_id can be given or is taken from $this->pm_id) * @return int 0 on success and errno != 0 else */ function save($data=null) { if ($this->debug) { echo "

soconstraints::save:"; _debug_array($data); } // constraints of an element? if ($data['pe_id']) { $pm_id = $data['pm_id'] ? $data['pm_id'] : $this->pm_id; unset($data['pm_id']); $pe_id = $data['pe_id']; unset($data['pe_id']); $this->delete(array( 'pm_id' => $pm_id, 'pe_id' => $pe_id, )); foreach($data as $type => $ids) { foreach(is_array($ids) ? $ids : explode(',',$ids) as $id) { if (!$id) continue; switch($type) { case 'milestone': $row = array( 'pe_id_end' => $pe_id, 'pe_id_start' => 0, 'ms_id' => $id, ); break; case 'start': $row = array( 'pe_id_end' => $id, 'pe_id_start' => $pe_id, 'ms_id' => 0, ); break; case 'end': $row = array( 'pe_id_end' => $pe_id, 'pe_id_start' => $id, 'ms_id' => 0, ); break; } $row['pm_id'] = $pm_id; if (($err = parent::save($row))) { return $err; } } } return 0; } // constraints of a milestone if ($data['ms_id'] && is_array($data['pe_id'])) { $keys = array( 'pm_id' => $data['pm_id'] ? $data['pm_id'] : $this->pm_id, 'pe_id_start' => 0, 'ms_id' => $data['ms_id'], ); $this->delete($keys); foreach($data['pe_id'] as $pe_id); { $keys['pe_id_end'] = $pe_id; if (($err = parent::save($keys))) { return $err; } } return 0; } return parent::save($data); } /** * reimplented to delete all constraints from a project-element if a pe_id is given * * @param array/int $keys if given array with col => value pairs to characterise the rows to delete or pe_id * @return int affected rows, should be 1 if ok, 0 if an error */ function delete($keys=null) { if ($this->debug) echo "

soconstraints::delete(".print_r($keys,true).")

\n"; if (is_numeric($keys) || is_array($keys) && (int) $keys['pe_id']) { if (is_array($keys)) { $pe_id = (int) $keys['pe_id']; unset($keys['pe_id']); } else { $pe_id = (int) $keys; $keys = array(); } $keys[] = "(pe_id_end=$pe_id OR pe_id_start=$pe_id)"; return $this->db->delete($this->table_name,$keys,__LINE__,__FILE__); } return parent::delete($keys); } }