PageRenderTime 24ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/tine20/Timetracker/Controller/Timesheet.php

https://github.com/testruby/Tine-2.0-Open-Source-Groupware-and-CRM
PHP | 295 lines | 166 code | 34 blank | 95 comment | 46 complexity | 34db5a1a74db269b9d19f3a1db7bdfc1 MD5 | raw file
  1. <?php
  2. /**
  3. * Timesheet controller for Timetracker application
  4. *
  5. * @package Timetracker
  6. * @subpackage Controller
  7. * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
  8. * @author Philipp Schüle <p.schuele@metaways.de>
  9. * @copyright Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
  10. */
  11. /**
  12. * Timesheet controller class for Timetracker application
  13. *
  14. * @package Timetracker
  15. * @subpackage Controller
  16. */
  17. class Timetracker_Controller_Timesheet extends Tinebase_Controller_Record_Abstract
  18. {
  19. /**
  20. * the constructor
  21. *
  22. * don't use the constructor. use the singleton
  23. */
  24. private function __construct() {
  25. // config
  26. $this->_applicationName = 'Timetracker';
  27. $this->_backend = new Timetracker_Backend_Timesheet();
  28. $this->_modelName = 'Timetracker_Model_Timesheet';
  29. $this->_currentAccount = Tinebase_Core::getUser();
  30. $this->_resolveCustomFields = TRUE;
  31. // disable container ACL checks as we don't init the 'Shared Timesheets' grants in the setup
  32. $this->_doContainerACLChecks = FALSE;
  33. // use modlog and don't completely delete records
  34. $this->_purgeRecords = FALSE;
  35. }
  36. /**
  37. * field grants for specific timesheet fields
  38. *
  39. * @var array
  40. */
  41. protected $_fieldGrants = array(
  42. 'is_billable' => array('default' => 1, 'requiredGrant' => Timetracker_Model_TimeaccountGrants::MANAGE_BILLABLE),
  43. 'billed_in' => array('default' => '', 'requiredGrant' => Tinebase_Model_Grants::GRANT_ADMIN),
  44. 'is_cleared' => array('default' => 0, 'requiredGrant' => Tinebase_Model_Grants::GRANT_ADMIN),
  45. );
  46. /**
  47. * holds the instance of the singleton
  48. *
  49. * @var Timetracker_Controller_Timesheet
  50. */
  51. private static $_instance = NULL;
  52. /**
  53. * the singleton pattern
  54. *
  55. * @return Timetracker_Controller_Timesheet
  56. */
  57. public static function getInstance()
  58. {
  59. if (self::$_instance === NULL) {
  60. self::$_instance = new Timetracker_Controller_Timesheet();
  61. }
  62. return self::$_instance;
  63. }
  64. /****************************** functions ************************/
  65. /**
  66. * get all timesheets for a timeaccount
  67. *
  68. * @param string $_timeaccountId
  69. * @return Tinebase_Record_RecordSet of Timetracker_Model_Timesheet records
  70. */
  71. public function getTimesheetsByTimeaccountId($_timeaccountId)
  72. {
  73. $filter = new Timetracker_Model_TimesheetFilter(array(
  74. array('field' => 'timeaccount_id', 'operator' => 'AND', 'value' => array(
  75. array('field' => 'id', 'operator' => 'equals', 'value' => $_timeaccountId),
  76. ))
  77. ));
  78. $records = $this->search($filter);
  79. return $records;
  80. }
  81. /**
  82. * checks deadline of record
  83. *
  84. * @param Timetracker_Model_Timesheet $_record
  85. * @param boolean $_throwException
  86. * @return void
  87. * @throws Timetracker_Exception_Deadline
  88. */
  89. protected function _checkDeadline(Timetracker_Model_Timesheet $_record, $_throwException = TRUE)
  90. {
  91. // get timeaccount
  92. $timeaccount = Timetracker_Controller_Timeaccount::getInstance()->get($_record->timeaccount_id);
  93. if (isset($timeaccount->deadline) && $timeaccount->deadline == Timetracker_Model_Timeaccount::DEADLINE_LASTWEEK) {
  94. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Check if deadline is exceeded for timeaccount ' . $timeaccount->title);
  95. // it is only on monday allowed to add timesheets for last week
  96. $date = new Tinebase_DateTime();
  97. $date->setTime(0,0,0);
  98. $dayOfWeek = $date->get('w');
  99. if ($dayOfWeek >= 2) {
  100. // only allow to add ts for this week
  101. $date->sub($dayOfWeek, Tinebase_DateTime::MODIFIER_DAY);
  102. } else {
  103. // only allow to add ts for last week
  104. $date->sub($dayOfWeek+7, Tinebase_DateTime::MODIFIER_DAY);
  105. }
  106. // convert start date to Tinebase_DateTime
  107. $startDate = new Tinebase_DateTime($_record->start_date);
  108. if ($date->compare($startDate) >= 0) {
  109. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Deadline exceeded: ' . $startDate . ' < ' . $date);
  110. if ($this->checkRight(Timetracker_Acl_Rights::MANAGE_TIMEACCOUNTS, FALSE)
  111. || Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Tinebase_Model_Grants::GRANT_ADMIN)) {
  112. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
  113. . ' User with admin / manage all rights is allowed to save Timesheet even if it exceeds the deadline.'
  114. );
  115. } else if ($_throwException) {
  116. throw new Timetracker_Exception_Deadline();
  117. }
  118. } else {
  119. if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Valid date: ' . $startDate . ' >= ' . $date);
  120. }
  121. }
  122. }
  123. /****************************** overwritten functions ************************/
  124. /**
  125. * inspect creation of one record
  126. *
  127. * @param Tinebase_Record_Interface $_record
  128. * @return void
  129. */
  130. protected function _inspectBeforeCreate(Tinebase_Record_Interface $_record)
  131. {
  132. $this->_checkDeadline($_record);
  133. }
  134. /**
  135. * inspect update of one record
  136. *
  137. * @param Tinebase_Record_Interface $_record the update record
  138. * @param Tinebase_Record_Interface $_oldRecord the current persistent record
  139. * @return void
  140. */
  141. protected function _inspectBeforeUpdate($_record, $_oldRecord)
  142. {
  143. $this->_checkDeadline($_record);
  144. }
  145. /**
  146. * check grant for action
  147. *
  148. * @param Timetracker_Model_Timeaccount $_record
  149. * @param string $_action
  150. * @param boolean $_throw
  151. * @param string $_errorMessage
  152. * @param Timetracker_Model_Timesheet $_oldRecord
  153. * @return boolean
  154. * @throws Tinebase_Exception_AccessDenied
  155. *
  156. * @todo think about just setting the default values when user
  157. * hasn't the required grant to change the field (instead of throwing exception)
  158. */
  159. protected function _checkGrant($_record, $_action, $_throw = TRUE, $_errorMessage = 'No Permission.', $_oldRecord = NULL)
  160. {
  161. // users with MANAGE_TIMEACCOUNTS have all grants here
  162. if ( $this->checkRight(Timetracker_Acl_Rights::MANAGE_TIMEACCOUNTS, FALSE)
  163. || Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Tinebase_Model_Grants::GRANT_ADMIN)) {
  164. return TRUE;
  165. }
  166. // only TA managers are allowed to alter TS of closed TAs
  167. if ($_action != 'get') {
  168. $timeaccount = Timetracker_Controller_Timeaccount::getInstance()->get($_record->timeaccount_id);
  169. if (! $timeaccount->is_open) {
  170. return FALSE;
  171. }
  172. // check if timeaccount->is_billable is false => set default in fieldGrants to 0 and allow only managers to change it
  173. if (!$timeaccount->is_billable) {
  174. $this->_fieldGrants['is_billable']['default'] = 0;
  175. $this->_fieldGrants['is_billable']['requiredGrant'] = Tinebase_Model_Grants::GRANT_ADMIN;
  176. }
  177. }
  178. $hasGrant = FALSE;
  179. switch ($_action) {
  180. case 'get':
  181. $hasGrant = (
  182. Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, array(
  183. Timetracker_Model_TimeaccountGrants::VIEW_ALL,
  184. Timetracker_Model_TimeaccountGrants::BOOK_ALL
  185. ))
  186. || ($_record->account_id == $this->_currentAccount->getId() && Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_OWN))
  187. );
  188. break;
  189. case 'create':
  190. $hasGrant = (
  191. ($_record->account_id == $this->_currentAccount->getId() && Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_OWN))
  192. || Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_ALL)
  193. );
  194. if ($hasGrant) {
  195. foreach ($this->_fieldGrants as $field => $config) {
  196. if (isset($_record->$field) && $_record->$field != $config['default']) {
  197. $hasGrant &= Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, $config['requiredGrant']);
  198. }
  199. }
  200. }
  201. break;
  202. case 'update':
  203. $hasGrant = (
  204. ($_record->account_id == $this->_currentAccount->getId() && Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_OWN))
  205. || Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_ALL)
  206. );
  207. if ($hasGrant) {
  208. foreach ($this->_fieldGrants as $field => $config) {
  209. if (isset($_record->$field) && $_record->$field != $_oldRecord->$field) {
  210. $hasGrant &= Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, $config['requiredGrant']);
  211. }
  212. }
  213. }
  214. break;
  215. case 'delete':
  216. $hasGrant = (
  217. ($_record->account_id == $this->_currentAccount->getId() && Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_OWN))
  218. || Timetracker_Model_TimeaccountGrants::hasGrant($_record->timeaccount_id, Timetracker_Model_TimeaccountGrants::BOOK_ALL)
  219. );
  220. break;
  221. }
  222. if ($_throw && !$hasGrant) {
  223. throw new Tinebase_Exception_AccessDenied($_errorMessage);
  224. }
  225. return $hasGrant;
  226. }
  227. /**
  228. * Removes timeaccounts where current user has no access to
  229. *
  230. * @param Tinebase_Model_Filter_FilterGroup $_filter
  231. * @param string $_action get|update
  232. */
  233. public function checkFilterACL(Tinebase_Model_Filter_FilterGroup $_filter, $_action = 'get')
  234. {
  235. switch ($_action) {
  236. case 'get':
  237. $_filter->setRequiredGrants(array(
  238. Timetracker_Model_TimeaccountGrants::BOOK_OWN,
  239. Timetracker_Model_TimeaccountGrants::BOOK_ALL,
  240. Timetracker_Model_TimeaccountGrants::VIEW_ALL,
  241. Tinebase_Model_Grants::GRANT_ADMIN,
  242. ));
  243. break;
  244. case 'update':
  245. $_filter->setRequiredGrants(array(
  246. Timetracker_Model_TimeaccountGrants::BOOK_OWN,
  247. Timetracker_Model_TimeaccountGrants::BOOK_ALL,
  248. Tinebase_Model_Grants::GRANT_ADMIN,
  249. ));
  250. break;
  251. case 'export':
  252. $_filter->setRequiredGrants(array(
  253. Tinebase_Model_Grants::GRANT_EXPORT,
  254. Tinebase_Model_Grants::GRANT_ADMIN,
  255. ));
  256. break;
  257. default:
  258. throw new Timetracker_Exception_UnexpectedValue('Unknown action: ' . $_action);
  259. }
  260. }
  261. }