[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/projectmanager/inc/ -> class.bopricelist.inc.php (source)

   1  <?php
   2  /**************************************************************************\
   3  * eGroupWare - ProjectManager - Pricelist buisness object                  *
   4  * http://www.egroupware.org                                                *
   5  * Written and (c) 2005 by Ralf Becker <RalfBecker@outdoor-training.de>     *
   6  * --------------------------------------------                             *
   7  *  This program is free software; you can redistribute it and/or modify it *
   8  *  under the terms of the GNU General Public License as published by the   *
   9  *  Free Software Foundation; either version 2 of the License, or (at your  *
  10  *  option) any later version.                                              *
  11  \**************************************************************************/
  12  
  13  /* $Id: class.bopricelist.inc.php 23135 2006-12-27 11:12:45Z ralfbecker $ */
  14  
  15  include_once (EGW_INCLUDE_ROOT.'/projectmanager/inc/class.sopricelist.inc.php');
  16  
  17  /**
  18   * Pricelist buisness object of the projectmanager
  19   *
  20   * @package projectmanager
  21   * @author RalfBecker-AT-outdoor-training.de
  22   * @copyright (c) 2005 by RalfBecker-AT-outdoor-training.de
  23   * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
  24   */
  25  class bopricelist extends sopricelist
  26  {
  27      /**
  28       * @var array $timestamps timestaps that need to be adjusted to user-time on reading or saving
  29       */
  30      var $timestamps = array(
  31          'pl_modified','pl_validsince',
  32      );
  33      /**
  34       * @var int $tz_offset_s offset in secconds between user and server-time,
  35       *    it need to be add to a server-time to get the user-time or substracted from a user-time to get the server-time
  36       */
  37      var $tz_offset_s;
  38      /**
  39       * @var int $now actual USER time
  40       */
  41      var $now;
  42  
  43      /**
  44       * Constructor, calls the constructor of the extended class
  45       * 
  46       * @param int $pm_id=0 pm_id of the project to use, default 0 (project independent / standard prices)
  47       */
  48  	function bopricelist($pm_id=0)
  49      {
  50          $this->sopricelist($pm_id);
  51  
  52          if (!is_object($GLOBALS['egw']->datetime))
  53          {
  54              $GLOBALS['egw']->datetime =& CreateObject('phpgwapi.datetime');
  55          }
  56          $this->tz_offset_s = $GLOBALS['egw']->datetime->tz_offset;
  57          $this->now = time() + $this->tz_offset_s;
  58          
  59          if (!is_object($GLOBALS['boprojectmanager']))
  60          {
  61              CreateObject('projectmanager.boprojectmanager',$pm_id);
  62          }
  63          $this->project =& $GLOBALS['boprojectmanager'];
  64      }
  65      
  66      /**
  67       * saves the content of data to the db, also checks acl and deletes not longer set prices!
  68       *
  69       * @param array $keys=null if given $keys are copied to data before saveing => allows a save as
  70       * @return int/boolean 0 on success, true on missing acl-rights and errno != 0 else
  71       */
  72  	function save($keys=null)
  73      {
  74          if (is_array($keys) && count($keys)) $this->data_merge($keys);
  75          
  76          if ((int)$this->debug >= 2)
  77          {
  78              echo "<p>sopricelist::save(".print_r($keys,true).") data=";
  79              _debug_array($this->data);
  80          }
  81          if ($this->data['pl_id'])
  82          {
  83              $backup =& $this->data;        // would get overwritten by read
  84              unset($this->data);
  85              $old = $this->read(array(
  86                  'pl_id' => $backup['pl_id'],
  87                  'pm_id' => $backup['pm_id'] ? array($backup['pm_id'],0) : 0
  88              ));
  89              $this->data =& $backup;
  90              unset($backup);
  91          }
  92          $need_general = count($old['prices']) > 0 || count($this->data['prices']) > 0;
  93          if (!($pricelist_need_save = !$this->data['pl_id']))
  94          {
  95              $this->data['cat_id'] = (int) $this->data['cat_id'];
  96              foreach($this->db_cols as $col => $data)
  97              {
  98                  if (!$old || $this->data[$col] != $old[$col])
  99                  {
 100                      $pricelist_need_save = true;
 101                      break;
 102                  }
 103              }
 104          }
 105          if ($pricelist_need_save)
 106          {
 107              // check acl
 108              if (!$this->check_acl(EGW_ACL_EDIT,$need_general ? 0 : $this->data['pm_id']))
 109              {
 110                  return lang('permission denied !!!').' need_general='.(int)$need_general;
 111              }
 112              if (($err = parent::save($this->data)))
 113              {
 114                  return $err;
 115              }
 116          }
 117          $prices = array();
 118          foreach($this->data['prices'] as $key => $nul)
 119          {
 120              $price =& $this->data['prices'][$key];
 121              $price['pm_id'] = 0;
 122              $price['pl_billable'] = $price['pl_customertitle'] = null;
 123              if (count($this->data['prices']) == 1) $price['pl_validsince'] = 0;    // no date for first price
 124              $prices[] =& $price;
 125          }
 126          foreach($this->data['project_prices'] as $key => $nul)
 127          {
 128              $price =& $this->data['project_prices'][$key];
 129              foreach(array('pm_id','pl_billable','pl_customertitle') as $key)
 130              {
 131                  if (!isset($price[$key])) $price[$key] = $this->data[$key];
 132              }
 133              if (count($this->data['project_prices']) == 1) $price['pl_validsince'] = 0;    // no date for first price
 134              $prices[] =& $price;
 135          }
 136          
 137          // index prices in old by pm_id and date (!) of validsince
 138          $old_prices = array();
 139          if ($old)
 140          {
 141              foreach(array_merge($old['prices'],$old['project_prices']) as $old_price)
 142              {
 143                  $old_prices[(int)$old_price['pm_id']][date('Y-m-d',(int)$old_price['pl_validsince'])] = $old_price;
 144              }
 145          }
 146          foreach($prices as $key => $nul)
 147          {
 148              $price =& $prices[$key];
 149              if (!isset($price['pl_id'])) $price['pl_id'] = $this->data['pl_id'];
 150              $old_price = $old_prices[(int)$price['pm_id']][date('Y-m-d',(int)$price['pl_validsince'])];
 151              if (!$this->prices_equal($price,$old_price))
 152              {
 153                  // price needs saving, checking acl now
 154                  if (!$this->check_acl(EGW_ACL_EDIT,$price['pm_id']))
 155                  {
 156                      return lang('permission denied !!!').' check_acl(EGW_ACL_EDIT(pm_id='.(int)$price[pm_id].')';
 157                  }
 158                  // maintain time of old price, to not create doublets with different times by users operating in different TZ's
 159                  if ($old_price) $price['pl_validsince'] = $old_price['pl_validsince'];
 160  
 161                  if (($err = parent::save_price($price)))
 162                  {
 163                      return $err;
 164                  }
 165              }
 166              unset($old_prices[(int)$price['pm_id']][date('Y-m-d',(int)$old_price['pl_validsince'])]);
 167          }
 168          // check if there are old prices not longer set ==> delete them
 169          foreach($old_prices as $pm_id => $prices)
 170          {
 171              foreach($prices as $price)
 172              {
 173                  if (!$this->check_acl(EGW_ACL_DELETE,$price['pm_id']))
 174                  {
 175                      return lang('permission denied !!!').' check_acl(EGW_ACL_DELETE(pm_id='.(int)$price[pm_id].')';
 176                  }
 177                  if (!parent::delete($price))
 178                  {
 179                      return lang('Error: deleting price !!!');
 180                  }
 181              }
 182          }
 183          return 0;
 184      }
 185      
 186      /**
 187       * search elements, reimplemented to use $this->pm_id, if no pm_id given in criteria or filter and join with the prices table
 188       *
 189       * @param array/string $criteria array of key and data cols, OR a SQL query (content for WHERE), fully quoted (!)
 190       * @param boolean $only_keys True returns only keys, False returns all cols
 191       * @param string $order_by fieldnames + {ASC|DESC} separated by colons ','
 192       * @param string/array $extra_cols string or array of strings to be added to the SELECT, eg. "count(*) as num"
 193       * @param string $wildcard appended befor and after each criteria
 194       * @param boolean $empty False=empty criteria are ignored in query, True=empty have to be empty in row
 195       * @param string $op defaults to 'AND', can be set to 'OR' too, then criteria's are OR'ed together
 196       * @param int/boolean $start if != false, return only maxmatch rows begining with start
 197       * @param array $filter if set (!=null) col-data pairs, to be and-ed (!) into the query without wildcards
 198       * @param string/boolean $join=true default join with prices-table or string as in so_sql
 199       * @return array of matching rows (the row is an array of the cols) or False
 200       */
 201  	function search($criteria,$only_keys=false,$order_by='',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter=null,$join=true)
 202      {
 203          if (!$this->check_acl(EGW_ACL_READ,(int)($criteria['pm_id'] ? $criteria['pm_id'] : $this->pm_id)))
 204          {
 205              return false;
 206          }
 207          return parent::search($criteria,$only_keys,$order_by,$extra_cols,$wildcard,$empty,$op,$start,$filter,$join);
 208      }
 209      
 210      /**
 211       * return priceslist of a given project (only bookable or billable price, no general pricelist)
 212       *
 213       * @param int $pm_id project
 214       * @return array/boolean array with pl_id => pl_unit: pl_tiltle (pl_price) pairs or false on error (eg. no ACL)
 215       */
 216  	function pricelist($pm_id)
 217      {
 218          //echo "<p>bopricelist::pricelist($pm_id)</p>\n";
 219          if (!($prices =& $this->search(array('pm_id' => $pm_id))))
 220          {
 221              return false;
 222          }
 223          $options = array();
 224          foreach($prices as $price)
 225          {
 226              $options[$price['pl_id']] = $price['pl_unit'].' '.$price['pl_title'].' ('.$price['pl_price'].')';
 227          }
 228          return $options;
 229      }
 230  
 231      /**
 232       * reads one pricelist-itme specified by $keys, reimplemented to use $this->pm_id, if no pm_id given
 233       *
 234       * @param array $keys array with keys in form internalName => value, may be a scalar value if only one key
 235       * @param string/array $extra_cols string or array of strings to be added to the SELECT, eg. "count(*) as num"
 236       * @param string/boolean $join=true default join with links-table or string as in so_sql
 237       * @return array/boolean data if row could be retrived else False
 238      */
 239  	function read($keys,$extra_cols='',$join=true)
 240      {
 241          // check if we have the requested access to all given pricelists
 242          foreach(!is_array($keys) || !isset($keys['pm_id']) ? array($this->pm_id) : 
 243              (is_array($keys['pm_id']) ? $keys['pm_id'] : array($keys['pm_id'])) as $pm_id)
 244          {
 245              if (!$this->check_acl(EGW_ACL_READ,(int)$pm_id)) return false;
 246          }
 247          return parent::read($keys,$extra_cols,$join);
 248      }
 249  
 250      /**
 251       * delete pricelist-entries and price(s) specified by keys pl_id, pm_id and/or pl_validsince
 252       *
 253       * If the last price of a pricelist-entry gets deleted, the pricelist entry is automatic deleted too!
 254       *
 255       * @param array/int $keys array with keys pm_id, pl_id and/or pl_validsince to delete or integer pm_id
 256       * @return int/boolean number of deleted prices or false if permission denied
 257       */
 258  	function delete($keys)
 259      {
 260          if (!$this->check_acl(EGW_ACL_EDIT,(int)(is_array($keys) ? $keys['pm_id'] : $keys)))
 261          {
 262              return false;
 263          }
 264          return parent::delete($keys);
 265      }
 266  
 267      /**
 268       * checks if the user has sufficent rights for a certain action
 269       *
 270       * For project-spez. prices/data you need a EGW_ACL_BUDGET right of the project for read or 
 271       * EGW_ACL_EDIT_BUDGET for write or delete.
 272       * For general pricelist data you need atm. no extra read rights, but is_admin to write/delete.
 273       *
 274       * @param int $required EGW_ACL_{READ|WRITE|DELETE}
 275       * @param int $pm_id=0 project-id for project-spez. prices/data to check, default 0 = general pricelist
 276       * @param array/int $data=null data/id of pricelist-entry, default null = use $this->data ($pm_id is ignored)
 277       * @return boolean true if the user has the rights, false otherwise
 278       */
 279  	function check_acl($required,$pm_id=0,$data=null)
 280      {
 281  /*        not used atm.
 282          if (is_null($data))
 283          {
 284              $data =& $this->data;
 285          }
 286          elseif (!is_array($data))
 287          {
 288              if ((int) $data)
 289              {
 290                  $backup = $this->data;
 291                  $data = $this->read(array('pm_id'=>(int)$pm_id,'pl_id' => (int)$data));
 292                  $this->data = $backup;
 293              }
 294              else
 295              {
 296                  return false;
 297              }
 298          }
 299  */
 300          if (!$pm_id)
 301          {
 302              return $required == EGW_ACL_READ || $this->project->is_admin;
 303          }
 304          return $this->project->check_acl($required == EGW_ACL_READ ? EGW_ACL_BUDGET : EGW_ACL_EDIT_BUDGET,$pm_id);
 305      }
 306  
 307      /**
 308       * Compares two prices to check if they are equal
 309       *
 310       * The compared fields depend on the price being project-specific or not
 311       *
 312       * @param array $price
 313       * @param array $price2
 314       * @return boolean true if the two prices are identical, false otherwise or if they are no arrays!
 315       */
 316  	function prices_equal($price,$price2)
 317      {
 318          if (!is_array($price) || !is_array($price2)) return false;
 319          
 320          $to_compare = array('pl_id','pm_id','pl_price','pl_validsince','pl_modified','pl_modifier');
 321          
 322          if ($price['pm_id'])
 323          {
 324              $to_compare[] = 'pl_customertitle';
 325              $to_compare[] = 'pl_billable';
 326          }
 327          $equal = true;
 328          foreach($to_compare as $key)
 329          {
 330              switch($key)
 331              {
 332                  case 'pm_id':
 333                      $equal = (int) $price['pm_id'] == (int) $price2['pm_id'];
 334                      break;
 335                  case 'pl_validsince':
 336                      $equal = date('Y-m-d',(int)$price['pl_validsince']) == date('Y-m-d',(int)$price2['pl_validsince']);
 337                      break;
 338                  default:
 339                      $equal = $price[$key] == $price2[$key];
 340                      break;
 341              }
 342              if (!$equal) break;
 343          }
 344          if ((int)$this->debug >= 3) echo "<p>bopricelist::prices_equal(".print_r($price,true).','.print_r($price2,true).') = '.($equal ? 'true' : "differ in $key: {$price[$key]} != {$price2[$key]}")."</p>\n";
 345  
 346          return $equal;
 347      }
 348  
 349      /**
 350       * changes the data from the db-format to your work-format
 351       *
 352       * reimplemented to adjust the timezone of the timestamps (adding $this->tz_offset_s to get user-time)
 353       * Please note, we do NOT call the method of the parent or so_sql !!!
 354       *
 355       * @param array $data if given works on that array and returns result, else works on internal data-array
 356       * @return array with changed data
 357       */
 358  	function db2data($data=null)
 359      {
 360          if (!is_array($data))
 361          {
 362              $data = &$this->data;
 363          }
 364          foreach($this->timestamps as $name)
 365          {
 366              if (isset($data[$name]) && $data[$name]) $data[$name] += $this->tz_offset_s;
 367          }
 368          return $data;
 369      }
 370  
 371      /**
 372       * changes the data from your work-format to the db-format
 373       *
 374       * reimplemented to adjust the timezone of the timestamps (subtraction $this->tz_offset_s to get server-time)
 375       * Please note, we do NOT call the method of the parent or so_sql !!!
 376       *
 377       * @param array $data if given works on that array and returns result, else works on internal data-array
 378       * @return array with changed data
 379       */
 380  	function data2db($data=null)
 381      {
 382          if ($intern = !is_array($data))
 383          {
 384              $data = &$this->data;
 385          }
 386          foreach($this->timestamps as $name)
 387          {
 388              if (isset($data[$name]) && $data[$name]) $data[$name] -= $this->tz_offset_s;
 389          }
 390          return $data;
 391      }
 392  }


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7