PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/projet/class/task.class.php

https://bitbucket.org/speedealing/speedealing
PHP | 1156 lines | 898 code | 115 blank | 143 comment | 89 complexity | d3b11150a88d16e34e8594595caae655 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2008-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@capnetworks.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /**
  19. * \file htdocs/projet/class/task.class.php
  20. * \ingroup project
  21. * \brief This file is a CRUD class file for Task (Create/Read/Update/Delete)
  22. */
  23. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  24. /**
  25. * Class to manage tasks
  26. * Initialy built by build_class_from_table on 2008-09-10 12:41
  27. */
  28. class Task extends CommonObject
  29. {
  30. public $element='project_task'; //!< Id that identify managed objects
  31. public $table_element='projet_task'; //!< Name of table without prefix where object is stored
  32. var $id;
  33. var $fk_project;
  34. var $fk_task_parent;
  35. var $label;
  36. var $description;
  37. var $duration_effective;
  38. var $date_c;
  39. var $date_start;
  40. var $date_end;
  41. var $progress;
  42. var $priority;
  43. var $fk_user_creat;
  44. var $fk_user_valid;
  45. var $statut;
  46. var $note_private;
  47. var $note_public;
  48. var $timespent_id;
  49. var $timespent_duration;
  50. var $timespent_old_duration;
  51. var $timespent_date;
  52. var $timespent_fk_user;
  53. var $timespent_note;
  54. /**
  55. * Constructor
  56. *
  57. * @param DoliDB $db Database handler
  58. */
  59. function __construct($db = '')
  60. {
  61. $this->db = $db;
  62. }
  63. /**
  64. * Create into database
  65. *
  66. * @param User $user User that create
  67. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  68. * @return int <0 if KO, Id of created object if OK
  69. */
  70. function create($user, $notrigger=0)
  71. {
  72. global $conf, $langs;
  73. $error=0;
  74. // Clean parameters
  75. $this->label = trim($this->label);
  76. $this->description = trim($this->description);
  77. // Check parameters
  78. // Put here code to add control on parameters values
  79. // Insert request
  80. $sql = "INSERT INTO ".MAIN_DB_PREFIX."projet_task (";
  81. $sql.= "fk_projet";
  82. $sql.= ", fk_task_parent";
  83. $sql.= ", label";
  84. $sql.= ", description";
  85. $sql.= ", datec";
  86. $sql.= ", fk_user_creat";
  87. $sql.= ", dateo";
  88. $sql.= ", datee";
  89. $sql.= ", progress";
  90. $sql.= ") VALUES (";
  91. $sql.= $this->fk_project;
  92. $sql.= ", ".$this->fk_task_parent;
  93. $sql.= ", '".$this->db->escape($this->label)."'";
  94. $sql.= ", '".$this->db->escape($this->description)."'";
  95. $sql.= ", '".$this->db->idate($this->date_c)."'";
  96. $sql.= ", ".$user->id;
  97. $sql.= ", ".($this->date_start!=''?"'".$this->db->idate($this->date_start)."'":'null');
  98. $sql.= ", ".($this->date_end!=''?"'".$this->db->idate($this->date_end)."'":'null');
  99. $sql.= ", ".($this->progress!=''?$this->progress:0);
  100. $sql.= ")";
  101. $this->db->begin();
  102. dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG);
  103. $resql=$this->db->query($sql);
  104. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  105. if (! $error)
  106. {
  107. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet_task");
  108. if (! $notrigger)
  109. {
  110. // Call triggers
  111. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  112. $interface=new Interfaces($this->db);
  113. $result=$interface->run_triggers('TASK_CREATE',$this,$user,$langs,$conf);
  114. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  115. // End call triggers
  116. }
  117. }
  118. // Commit or rollback
  119. if ($error)
  120. {
  121. foreach($this->errors as $errmsg)
  122. {
  123. dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
  124. $this->error.=($this->error?', '.$errmsg:$errmsg);
  125. }
  126. $this->db->rollback();
  127. return -1*$error;
  128. }
  129. else
  130. {
  131. $this->db->commit();
  132. return $this->id;
  133. }
  134. }
  135. /**
  136. * Load object in memory from database
  137. *
  138. * @param int $id Id object
  139. * @return int <0 if KO, >0 if OK
  140. */
  141. function fetch($id)
  142. {
  143. global $langs;
  144. $sql = "SELECT";
  145. $sql.= " t.rowid,";
  146. $sql.= " t.fk_projet,";
  147. $sql.= " t.fk_task_parent,";
  148. $sql.= " t.label,";
  149. $sql.= " t.description,";
  150. $sql.= " t.duration_effective,";
  151. $sql.= " t.dateo,";
  152. $sql.= " t.datee,";
  153. $sql.= " t.fk_user_creat,";
  154. $sql.= " t.fk_user_valid,";
  155. $sql.= " t.fk_statut,";
  156. $sql.= " t.progress,";
  157. $sql.= " t.priority,";
  158. $sql.= " t.note_private,";
  159. $sql.= " t.note_public";
  160. $sql.= " FROM ".MAIN_DB_PREFIX."projet_task as t";
  161. $sql.= " WHERE t.rowid = ".$id;
  162. dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
  163. $resql=$this->db->query($sql);
  164. if ($resql)
  165. {
  166. if ($this->db->num_rows($resql))
  167. {
  168. $obj = $this->db->fetch_object($resql);
  169. $this->id = $obj->rowid;
  170. $this->ref = $obj->rowid;
  171. $this->fk_project = $obj->fk_projet;
  172. $this->fk_task_parent = $obj->fk_task_parent;
  173. $this->label = $obj->label;
  174. $this->description = $obj->description;
  175. $this->duration_effective = $obj->duration_effective;
  176. $this->date_c = $this->db->jdate($obj->datec);
  177. $this->date_start = $this->db->jdate($obj->dateo);
  178. $this->date_end = $this->db->jdate($obj->datee);
  179. $this->fk_user_creat = $obj->fk_user_creat;
  180. $this->fk_user_valid = $obj->fk_user_valid;
  181. $this->fk_statut = $obj->fk_statut;
  182. $this->progress = $obj->progress;
  183. $this->priority = $obj->priority;
  184. $this->note_private = $obj->note_private;
  185. $this->note_public = $obj->note_public;
  186. }
  187. $this->db->free($resql);
  188. return 1;
  189. }
  190. else
  191. {
  192. $this->error="Error ".$this->db->lasterror();
  193. dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR);
  194. return -1;
  195. }
  196. }
  197. /**
  198. * Update database
  199. *
  200. * @param User $user User that modify
  201. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  202. * @return int <0 if KO, >0 if OK
  203. */
  204. function update($user=0, $notrigger=0)
  205. {
  206. global $conf, $langs;
  207. $error=0;
  208. // Clean parameters
  209. if (isset($this->fk_project)) $this->fk_project=trim($this->fk_project);
  210. if (isset($this->fk_task_parent)) $this->fk_task_parent=trim($this->fk_task_parent);
  211. if (isset($this->label)) $this->label=trim($this->label);
  212. if (isset($this->description)) $this->description=trim($this->description);
  213. if (isset($this->duration_effective)) $this->duration_effective=trim($this->duration_effective);
  214. // Check parameters
  215. // Put here code to add control on parameters values
  216. // Update request
  217. $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task SET";
  218. $sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
  219. $sql.= " fk_task_parent=".(isset($this->fk_task_parent)?$this->fk_task_parent:"null").",";
  220. $sql.= " label=".(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
  221. $sql.= " description=".(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").",";
  222. $sql.= " duration_effective=".(isset($this->duration_effective)?$this->duration_effective:"null").",";
  223. $sql.= " dateo=".($this->date_start!=''?$this->db->idate($this->date_start):'null').",";
  224. $sql.= " datee=".($this->date_end!=''?$this->db->idate($this->date_end):'null').",";
  225. $sql.= " progress=".$this->progress;
  226. $sql.= " WHERE rowid=".$this->id;
  227. $this->db->begin();
  228. dol_syslog(get_class($this)."::update sql=".$sql, LOG_DEBUG);
  229. $resql = $this->db->query($sql);
  230. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  231. if (! $error)
  232. {
  233. if (! $notrigger)
  234. {
  235. // Call triggers
  236. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  237. $interface=new Interfaces($this->db);
  238. $result=$interface->run_triggers('TASK_MODIFY',$this,$user,$langs,$conf);
  239. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  240. // End call triggers
  241. }
  242. }
  243. // Commit or rollback
  244. if ($error)
  245. {
  246. foreach($this->errors as $errmsg)
  247. {
  248. dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
  249. $this->error.=($this->error?', '.$errmsg:$errmsg);
  250. }
  251. $this->db->rollback();
  252. return -1*$error;
  253. }
  254. else
  255. {
  256. $this->db->commit();
  257. return 1;
  258. }
  259. }
  260. /**
  261. * Delete object in database
  262. *
  263. * @param User $user User that delete
  264. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  265. * @return int <0 if KO, >0 if OK
  266. */
  267. function delete($user, $notrigger=0)
  268. {
  269. global $conf, $langs;
  270. $error=0;
  271. $this->db->begin();
  272. if ($this->hasChildren() > 0)
  273. {
  274. dol_syslog(get_class($this)."::delete Can't delete record as it has some child", LOG_WARNING);
  275. $this->error='ErrorRecordHasChildren';
  276. $this->db->rollback();
  277. return 0;
  278. }
  279. if (! $error)
  280. {
  281. // Delete linked contacts
  282. $res = $this->delete_linked_contact();
  283. if ($res < 0)
  284. {
  285. $this->error='ErrorFailToDeleteLinkedContact';
  286. //$error++;
  287. $this->db->rollback();
  288. return 0;
  289. }
  290. }
  291. // Delete rang of line
  292. //$this->delRangOfLine($this->id, $this->element);
  293. $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task";
  294. $sql.= " WHERE rowid=".$this->id;
  295. dol_syslog(get_class($this)."::delete sql=".$sql);
  296. $resql = $this->db->query($sql);
  297. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  298. if (! $error)
  299. {
  300. if (! $notrigger)
  301. {
  302. // Call triggers
  303. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  304. $interface=new Interfaces($this->db);
  305. $result=$interface->run_triggers('TASK_DELETE',$this,$user,$langs,$conf);
  306. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  307. // End call triggers
  308. }
  309. }
  310. // Commit or rollback
  311. if ($error)
  312. {
  313. foreach($this->errors as $errmsg)
  314. {
  315. dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
  316. $this->error.=($this->error?', '.$errmsg:$errmsg);
  317. }
  318. $this->db->rollback();
  319. return -1*$error;
  320. }
  321. else
  322. {
  323. //Delete associated link file
  324. if ($conf->projet->dir_output)
  325. {
  326. $projectstatic=new Project($this->db);
  327. $projectstatic->fetch($this->fk_project);
  328. $dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($projectstatic->ref) . '/' . dol_sanitizeFileName($this->id);
  329. dol_syslog(get_class($this)."::delete dir=".$dir, LOG_DEBUG);
  330. if (file_exists($dir))
  331. {
  332. require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  333. $res = @dol_delete_dir_recursive($dir);
  334. if (!$res)
  335. {
  336. $this->error = 'ErrorFailToDeleteDir';
  337. $this->db->rollback();
  338. return 0;
  339. }
  340. }
  341. }
  342. $this->db->commit();
  343. return 1;
  344. }
  345. }
  346. /**
  347. * Return nb of children
  348. *
  349. * @return int <0 if KO, 0 if no children, >0 if OK
  350. */
  351. function hasChildren()
  352. {
  353. $error=0;
  354. $ret=0;
  355. $sql = "SELECT COUNT(*) as nb";
  356. $sql.= " FROM ".MAIN_DB_PREFIX."projet_task";
  357. $sql.= " WHERE fk_task_parent=".$this->id;
  358. dol_syslog(get_class($this)."::hasChildren sql=".$sql, LOG_DEBUG);
  359. $resql = $this->db->query($sql);
  360. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  361. else
  362. {
  363. $obj=$this->db->fetch_object($resql);
  364. if ($obj) $ret=$obj->nb;
  365. $this->db->free($resql);
  366. }
  367. if (! $error)
  368. {
  369. return $ret;
  370. }
  371. else
  372. {
  373. return -1;
  374. }
  375. }
  376. /**
  377. * Renvoie nom clicable (avec eventuellement le picto)
  378. *
  379. * @param int $withpicto 0=Pas de picto, 1=Inclut le picto dans le lien, 2=Picto seul
  380. * @param int $option Sur quoi pointe le lien
  381. * @return string Chaine avec URL
  382. */
  383. function getNomUrl($withpicto=0,$option='')
  384. {
  385. global $langs;
  386. $result='';
  387. $lien = '<a href="'.DOL_URL_ROOT.'/projet/tasks/task.php?id='.$this->id.($option=='withproject'?'&withproject=1':'').'">';
  388. $lienfin='</a>';
  389. $picto='projecttask';
  390. $label=$langs->trans("ShowTask").': '.$this->ref.($this->label?' - '.$this->label:'');
  391. if ($withpicto) $result.=($lien.img_object($label,$picto).$lienfin);
  392. if ($withpicto && $withpicto != 2) $result.=' ';
  393. if ($withpicto != 2) $result.=$lien.$this->ref.$lienfin;
  394. return $result;
  395. }
  396. /**
  397. * Initialise an instance with random values.
  398. * Used to build previews or test instances.
  399. * id must be 0 if object instance is a specimen.
  400. *
  401. * @return void
  402. */
  403. function initAsSpecimen()
  404. {
  405. $this->id=0;
  406. $this->fk_projet='';
  407. $this->fk_task_parent='';
  408. $this->title='';
  409. $this->duration_effective='';
  410. $this->fk_user_creat='';
  411. $this->statut='';
  412. $this->note='';
  413. }
  414. /**
  415. * Return list of tasks for all projects or for one particular project
  416. * Sort order is on project, then on position of task, and last on title of first level task
  417. *
  418. * @param User $usert Object user to limit tasks affected to a particular user
  419. * @param User $userp Object user to limit projects of a particular user and public projects
  420. * @param int $projectid Project id
  421. * @param int $socid Third party id
  422. * @param int $mode 0=Return list of tasks and their projects, 1=Return projects and tasks if exists
  423. * @param string $filteronprojref Filter on project ref
  424. * @return array Array of tasks
  425. */
  426. function getTasksArray($usert=0, $userp=0, $projectid=0, $socid=0, $mode=0, $filteronprojref='')
  427. {
  428. global $conf;
  429. $tasks = array();
  430. //print $usert.'-'.$userp.'-'.$projectid.'-'.$socid.'-'.$mode.'<br>';
  431. // List of tasks (does not care about permissions. Filtering will be done later)
  432. $sql = "SELECT p.rowid as projectid, p.ref, p.title as plabel, p.public,";
  433. $sql.= " t.rowid as taskid, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress,";
  434. $sql.= " t.dateo as date_start, t.datee as date_end";
  435. if ($mode == 0)
  436. {
  437. $sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
  438. $sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
  439. $sql.= " WHERE t.fk_projet = p.rowid";
  440. $sql.= " AND p.entity = ".$conf->entity;
  441. if ($socid) $sql.= " AND p.fk_soc = ".$socid;
  442. if ($projectid) $sql.= " AND p.rowid in (".$projectid.")";
  443. }
  444. if ($mode == 1)
  445. {
  446. $sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
  447. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t on t.fk_projet = p.rowid";
  448. $sql.= " WHERE p.entity = ".$conf->entity;
  449. if ($socid) $sql.= " AND p.fk_soc = ".$socid;
  450. if ($projectid) $sql.= " AND p.rowid in (".$projectid.")";
  451. }
  452. if ($filteronprojref) $sql.= " AND p.ref LIKE '%".$filteronprojref."%'";
  453. $sql.= " ORDER BY p.ref, t.rang, t.label";
  454. //print $sql;
  455. dol_syslog(get_class($this)."::getTasksArray sql=".$sql, LOG_DEBUG);
  456. $resql = $this->db->query($sql);
  457. if ($resql)
  458. {
  459. $num = $this->db->num_rows($resql);
  460. $i = 0;
  461. // Loop on each record found, so each couple (project id, task id)
  462. while ($i < $num)
  463. {
  464. $error=0;
  465. $obj = $this->db->fetch_object($resql);
  466. if ((! $obj->public) && (is_object($userp))) // If not public project and we ask a filter on project owned by a user
  467. {
  468. if (! $this->getUserRolesForProjectsOrTasks($userp, 0, $obj->projectid, 0))
  469. {
  470. $error++;
  471. }
  472. }
  473. if (is_object($usert)) // If we ask a filter on a user affected to a task
  474. {
  475. if (! $this->getUserRolesForProjectsOrTasks(0, $usert, $obj->projectid, $obj->taskid))
  476. {
  477. $error++;
  478. }
  479. }
  480. if (! $error)
  481. {
  482. $tasks[$i] = new stdClass();
  483. $tasks[$i]->id = $obj->taskid;
  484. $tasks[$i]->ref = $obj->taskid;
  485. $tasks[$i]->fk_project = $obj->projectid;
  486. $tasks[$i]->projectref = $obj->ref;
  487. $tasks[$i]->projectlabel = $obj->plabel;
  488. $tasks[$i]->label = $obj->label;
  489. $tasks[$i]->description = $obj->description;
  490. $tasks[$i]->fk_parent = $obj->fk_task_parent;
  491. $tasks[$i]->duration = $obj->duration_effective;
  492. $tasks[$i]->progress = $obj->progress;
  493. $tasks[$i]->public = $obj->public;
  494. $tasks[$i]->date_start = $this->db->jdate($obj->date_start);
  495. $tasks[$i]->date_end = $this->db->jdate($obj->date_end);
  496. }
  497. $i++;
  498. }
  499. $this->db->free($resql);
  500. }
  501. else
  502. {
  503. dol_print_error($this->db);
  504. }
  505. return $tasks;
  506. }
  507. /**
  508. * Return list of roles for a user for each projects or each tasks (or a particular project or task).
  509. *
  510. * @param User $userp Return roles on project for this internal user (task id can't be defined)
  511. * @param User $usert Return roles on task for this internal user
  512. * @param int $projectid Project id list separated with , to filter on project
  513. * @param int $taskid Task id to filter on a task
  514. * @return array Array (projectid => 'list of roles for project' or taskid => 'list of roles for task')
  515. */
  516. function getUserRolesForProjectsOrTasks($userp,$usert,$projectid='',$taskid=0)
  517. {
  518. $arrayroles = array();
  519. dol_syslog(get_class($this)."::getUserRolesForProjectsOrTasks userp=".is_object($userp)." usert=".is_object($usert)." projectid=".$projectid." taskid=".$taskid);
  520. // We want role of user for a projet or role of user for a task. Both are not possible.
  521. if (empty($userp) && empty($usert))
  522. {
  523. $this->error="CallWithWrongParameters";
  524. return -1;
  525. }
  526. if (! empty($userp) && ! empty($usert))
  527. {
  528. $this->error="CallWithWrongParameters";
  529. return -1;
  530. }
  531. /* Liste des taches et role sur les projets ou taches */
  532. $sql = "SELECT pt.rowid as pid, ec.element_id, ctc.code, ctc.source";
  533. if ($userp) $sql.= " FROM ".MAIN_DB_PREFIX."projet as pt";
  534. if ($usert) $sql.= " FROM ".MAIN_DB_PREFIX."projet_task as pt";
  535. $sql.= ", ".MAIN_DB_PREFIX."element_contact as ec";
  536. $sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
  537. $sql.= " WHERE pt.rowid = ec.element_id";
  538. if ($userp) $sql.= " AND ctc.element = 'project'";
  539. if ($usert) $sql.= " AND ctc.element = 'project_task'";
  540. $sql.= " AND ctc.rowid = ec.fk_c_type_contact";
  541. if ($userp) $sql.= " AND ec.fk_socpeople = ".$userp->id;
  542. if ($usert) $sql.= " AND ec.fk_socpeople = ".$usert->id;
  543. $sql.= " AND ec.statut = 4";
  544. $sql.= " AND ctc.source = 'internal'";
  545. if ($projectid)
  546. {
  547. if ($userp) $sql.= " AND pt.rowid in (".$projectid.")";
  548. if ($usert) $sql.= " AND pt.fk_projet in (".$projectid.")";
  549. }
  550. if ($taskid)
  551. {
  552. if ($userp) $sql.= " ERROR SHOULD NOT HAPPENS";
  553. if ($usert) $sql.= " AND pt.rowid = ".$taskid;
  554. }
  555. //print $sql;
  556. dol_syslog(get_class($this)."::getUserRolesForProjectsOrTasks sql=".$sql);
  557. $resql = $this->db->query($sql);
  558. if ($resql)
  559. {
  560. $num = $this->db->num_rows($resql);
  561. $i = 0;
  562. while ($i < $num)
  563. {
  564. $obj = $this->db->fetch_object($resql);
  565. if (empty($arrayroles[$obj->pid])) $arrayroles[$obj->pid] = $obj->code;
  566. else $arrayroles[$obj->pid].=','.$obj->code;
  567. $i++;
  568. }
  569. $this->db->free($resql);
  570. }
  571. else
  572. {
  573. dol_print_error($this->db);
  574. }
  575. return $arrayroles;
  576. }
  577. /**
  578. * Return list of id of contacts of task
  579. *
  580. * @param string $source Source
  581. * @return array Array of id of contacts
  582. */
  583. function getListContactId($source='internal')
  584. {
  585. $contactAlreadySelected = array();
  586. $tab = $this->liste_contact(-1,$source);
  587. //var_dump($tab);
  588. $num=count($tab);
  589. $i = 0;
  590. while ($i < $num)
  591. {
  592. if ($source == 'thirdparty') $contactAlreadySelected[$i] = $tab[$i]['socid'];
  593. else $contactAlreadySelected[$i] = $tab[$i]['id'];
  594. $i++;
  595. }
  596. return $contactAlreadySelected;
  597. }
  598. /**
  599. * Add time spent
  600. *
  601. * @param User $user user id
  602. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  603. * @return void
  604. */
  605. function addTimeSpent($user, $notrigger=0)
  606. {
  607. global $conf,$langs;
  608. $error=0;
  609. $ret = 0;
  610. // Clean parameters
  611. if (isset($this->timespent_note)) $this->timespent_note = trim($this->timespent_note);
  612. $sql = "INSERT INTO ".MAIN_DB_PREFIX."projet_task_time (";
  613. $sql.= "fk_task";
  614. $sql.= ", task_date";
  615. $sql.= ", task_duration";
  616. $sql.= ", fk_user";
  617. $sql.= ", note";
  618. $sql.= ") VALUES (";
  619. $sql.= $this->id;
  620. $sql.= ", '".$this->db->idate($this->timespent_date)."'";
  621. $sql.= ", ".$this->timespent_duration;
  622. $sql.= ", ".$this->timespent_fk_user;
  623. $sql.= ", ".(isset($this->timespent_note)?"'".$this->db->escape($this->timespent_note)."'":"null");
  624. $sql.= ")";
  625. dol_syslog(get_class($this)."::addTimeSpent sql=".$sql, LOG_DEBUG);
  626. if ($this->db->query($sql) )
  627. {
  628. $task_id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet_task_time");
  629. $ret = $task_id;
  630. if (! $notrigger)
  631. {
  632. // Call triggers
  633. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  634. $interface=new Interfaces($this->db);
  635. $result=$interface->run_triggers('TASK_TIMESPENT_CREATE',$this,$user,$langs,$conf);
  636. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  637. // End call triggers
  638. }
  639. }
  640. else
  641. {
  642. $this->error=$this->db->lasterror();
  643. dol_syslog(get_class($this)."::addTimeSpent error -1 ".$this->error,LOG_ERR);
  644. $ret = -1;
  645. }
  646. if ($ret >= 0)
  647. {
  648. $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
  649. $sql.= " SET duration_effective = duration_effective + '".price2num($this->timespent_duration)."'";
  650. $sql.= " WHERE rowid = ".$this->id;
  651. dol_syslog(get_class($this)."::addTimeSpent sql=".$sql, LOG_DEBUG);
  652. if (! $this->db->query($sql) )
  653. {
  654. $this->error=$this->db->lasterror();
  655. dol_syslog(get_class($this)."::addTimeSpent error -2 ".$this->error, LOG_ERR);
  656. $ret = -2;
  657. }
  658. }
  659. return $ret;
  660. }
  661. /**
  662. * Load object in memory from database
  663. *
  664. * @param int $id Id object
  665. * @return int <0 if KO, >0 if OK
  666. */
  667. function fetchTimeSpent($id)
  668. {
  669. global $langs;
  670. $sql = "SELECT";
  671. $sql.= " t.rowid,";
  672. $sql.= " t.fk_task,";
  673. $sql.= " t.task_date,";
  674. $sql.= " t.task_duration,";
  675. $sql.= " t.fk_user,";
  676. $sql.= " t.note";
  677. $sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
  678. $sql.= " WHERE t.rowid = ".$id;
  679. dol_syslog(get_class($this)."::fetchTimeSpent sql=".$sql, LOG_DEBUG);
  680. $resql=$this->db->query($sql);
  681. if ($resql)
  682. {
  683. if ($this->db->num_rows($resql))
  684. {
  685. $obj = $this->db->fetch_object($resql);
  686. $this->timespent_id = $obj->rowid;
  687. $this->id = $obj->fk_task;
  688. $this->timespent_date = $obj->task_date;
  689. $this->timespent_duration = $obj->task_duration;
  690. $this->timespent_user = $obj->fk_user;
  691. $this->timespent_note = $obj->note;
  692. }
  693. $this->db->free($resql);
  694. return 1;
  695. }
  696. else
  697. {
  698. $this->error="Error ".$this->db->lasterror();
  699. dol_syslog(get_class($this)."::fetchTimeSpent ".$this->error, LOG_ERR);
  700. return -1;
  701. }
  702. }
  703. /**
  704. * Update time spent
  705. *
  706. * @param User $user User id
  707. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  708. * @return int <0 if KO, >0 if OK
  709. */
  710. function updateTimeSpent($user, $notrigger=0)
  711. {
  712. global $conf,$langs;
  713. $error=0;
  714. $ret = 0;
  715. // Clean parameters
  716. if (isset($this->timespent_note)) $this->timespent_note = trim($this->timespent_note);
  717. $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time SET";
  718. $sql.= " task_date = '".$this->db->idate($this->timespent_date)."',";
  719. $sql.= " task_duration = ".$this->timespent_duration.",";
  720. $sql.= " fk_user = ".$this->timespent_fk_user.",";
  721. $sql.= " note = ".(isset($this->timespent_note)?"'".$this->db->escape($this->timespent_note)."'":"null");
  722. $sql.= " WHERE rowid = ".$this->timespent_id;
  723. dol_syslog(get_class($this)."::updateTimeSpent sql=".$sql, LOG_DEBUG);
  724. if ($this->db->query($sql) )
  725. {
  726. if (! $notrigger)
  727. {
  728. // Call triggers
  729. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  730. $interface=new Interfaces($this->db);
  731. $result=$interface->run_triggers('TASK_TIMESPENT_MODIFY',$this,$user,$langs,$conf);
  732. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  733. // End call triggers
  734. }
  735. $ret = 1;
  736. }
  737. else
  738. {
  739. $this->error=$this->db->lasterror();
  740. dol_syslog(get_class($this)."::updateTimeSpent error -1 ".$this->error,LOG_ERR);
  741. $ret = -1;
  742. }
  743. if ($ret == 1 && ($this->timespent_old_duration != $this->timespent_duration))
  744. {
  745. $newDuration = $this->timespent_duration - $this->timespent_old_duration;
  746. $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
  747. $sql.= " SET duration_effective = duration_effective + '".$newDuration."'";
  748. $sql.= " WHERE rowid = ".$this->id;
  749. dol_syslog(get_class($this)."::updateTimeSpent sql=".$sql, LOG_DEBUG);
  750. if (! $this->db->query($sql) )
  751. {
  752. $this->error=$this->db->lasterror();
  753. dol_syslog(get_class($this)."::addTimeSpent error -2 ".$this->error, LOG_ERR);
  754. $ret = -2;
  755. }
  756. }
  757. return $ret;
  758. }
  759. /**
  760. * Delete time spent
  761. *
  762. * @param User $user User that delete
  763. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  764. * @return int <0 if KO, >0 if OK
  765. */
  766. function delTimeSpent($user, $notrigger=0)
  767. {
  768. global $conf, $langs;
  769. $error=0;
  770. $this->db->begin();
  771. $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_time";
  772. $sql.= " WHERE rowid = ".$this->timespent_id;
  773. dol_syslog(get_class($this)."::delTimeSpent sql=".$sql);
  774. $resql = $this->db->query($sql);
  775. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  776. if (! $error)
  777. {
  778. if (! $notrigger)
  779. {
  780. // Call triggers
  781. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  782. $interface=new Interfaces($this->db);
  783. $result=$interface->run_triggers('TASK_TIMESPENT_DELETE',$this,$user,$langs,$conf);
  784. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  785. // End call triggers
  786. }
  787. }
  788. if (! $error)
  789. {
  790. $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
  791. $sql.= " SET duration_effective = duration_effective - '".$this->timespent_duration."'";
  792. $sql.= " WHERE rowid = ".$this->id;
  793. dol_syslog(get_class($this)."::delTimeSpent sql=".$sql, LOG_DEBUG);
  794. if ($this->db->query($sql) )
  795. {
  796. $result = 0;
  797. }
  798. else
  799. {
  800. $this->error=$this->db->lasterror();
  801. dol_syslog(get_class($this)."::addTimeSpent error -3 ".$this->error, LOG_ERR);
  802. $result = -2;
  803. }
  804. }
  805. // Commit or rollback
  806. if ($error)
  807. {
  808. foreach($this->errors as $errmsg)
  809. {
  810. dol_syslog(get_class($this)."::delTimeSpent ".$errmsg, LOG_ERR);
  811. $this->error.=($this->error?', '.$errmsg:$errmsg);
  812. }
  813. $this->db->rollback();
  814. return -1*$error;
  815. }
  816. else
  817. {
  818. $this->db->commit();
  819. return 1;
  820. }
  821. }
  822. /** Load an object from its id and create a new one in database
  823. *
  824. * @param int $fromid Id of object to clone
  825. * @param int $project_id Id of project to attach clone task
  826. * @param int $parent_task_id Id of task to attach clone task
  827. * @param bool $clone_change_dt recalculate date of task regarding new project start date
  828. * @param bool $clone_affectation clone affectation of project
  829. * @param bool $clone_time clone time of project
  830. * @param bool $clone_file clone file of project
  831. * @param bool $clone_note clone note of project
  832. * @param bool $clone_prog clone progress of project
  833. * @return int New id of clone
  834. */
  835. function createFromClone($fromid,$project_id,$parent_task_id,$clone_change_dt=false,$clone_affectation=false,$clone_time=false,$clone_file=false,$clone_note=false,$clone_prog=false)
  836. {
  837. global $user,$langs,$conf;
  838. $error=0;
  839. $now=dol_now();
  840. $datec = $now;
  841. $clone_task=new Task($this->db);
  842. $this->db->begin();
  843. // Load source object
  844. $clone_task->fetch($fromid);
  845. $ori_project_id = $clone_task->fk_project;
  846. $clone_task->id = 0;
  847. $clone_task->fk_project = $project_id;
  848. $clone_task->fk_task_parent = $parent_task_id;
  849. $clone_task->date_c = $datec;
  850. //Manage Task Date
  851. if ($clone_change_dt)
  852. {
  853. $projectstatic=new Project($this->db);
  854. $projectstatic->fetch($ori_project_id);
  855. //Origin project strat date
  856. $orign_project_dt_start = $projectstatic->date_start;
  857. //Calcultate new task start date with difference between origin proj start date and origin task start date
  858. if (!empty($clone_task->date_start))
  859. {
  860. $clone_task->date_start = $now + $clone_task->date_start - $orign_project_dt_start;
  861. }
  862. //Calcultate new task end date with difference between origin proj end date and origin task end date
  863. if (!empty($clone_task->date_end))
  864. {
  865. $clone_task->date_end = $now + $clone_task->date_end - $orign_project_dt_start;
  866. }
  867. }
  868. if (!$clone_prog)
  869. {
  870. $clone_task->progress=0;
  871. }
  872. // Create clone
  873. $result=$clone_task->create($user);
  874. // Other options
  875. if ($result < 0)
  876. {
  877. $this->error=$clone_task->error;
  878. $error++;
  879. }
  880. // End
  881. if (! $error)
  882. {
  883. $this->db->commit();
  884. $clone_task_id=$clone_task->id;
  885. //Note Update
  886. if (!$clone_note)
  887. {
  888. $clone_task->note_private='';
  889. $clone_task->note_public='';
  890. }
  891. else
  892. {
  893. $this->db->begin();
  894. $res=$clone_task->update_note_public(dol_html_entity_decode($clone_task->note_public, ENT_QUOTES));
  895. if ($res < 0)
  896. {
  897. $this->error.=$clone_task->error;
  898. $error++;
  899. $this->db->rollback();
  900. }
  901. else
  902. {
  903. $this->db->commit();
  904. }
  905. $this->db->begin();
  906. $res=$clone_task->update_note(dol_html_entity_decode($clone_task->note_private, ENT_QUOTES));
  907. if ($res < 0)
  908. {
  909. $this->error.=$clone_task->error;
  910. $error++;
  911. $this->db->rollback();
  912. }
  913. else
  914. {
  915. $this->db->commit();
  916. }
  917. }
  918. //Duplicate file
  919. if ($clone_file)
  920. {
  921. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  922. //retreive project origin ref to know folder to copy
  923. $projectstatic=new Project($this->db);
  924. $projectstatic->fetch($ori_project_id);
  925. $ori_project_ref=$projectstatic->ref;
  926. if ($ori_project_id!=$project_id)
  927. {
  928. $projectstatic->fetch($project_id);
  929. $clone_project_ref=$projectstatic->ref;
  930. }
  931. else
  932. {
  933. $clone_project_ref=$ori_project_ref;
  934. }
  935. $clone_task_dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($clone_project_ref). "/" . dol_sanitizeFileName($clone_task_id);
  936. $ori_task_dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($ori_project_ref). "/" . dol_sanitizeFileName($fromid);
  937. $filearray=dol_dir_list($ori_task_dir,"files",0,'','\.meta$','',SORT_ASC,1);
  938. foreach($filearray as $key => $file)
  939. {
  940. if (!file_exists($clone_task_dir))
  941. {
  942. if (dol_mkdir($clone_task_dir) < 0)
  943. {
  944. $this->error.=$langs->trans('ErrorInternalErrorDetected').':dol_mkdir';
  945. $error++;
  946. }
  947. }
  948. $rescopy = dol_copy($ori_task_dir . '/' . $file['name'], $clone_task_dir . '/' . $file['name'],0,1);
  949. if (is_numeric($rescopy) && $rescopy < 0)
  950. {
  951. $this->error.=$langs->trans("ErrorFailToCopyFile",$ori_task_dir . '/' . $file['name'],$clone_task_dir . '/' . $file['name']);
  952. $error++;
  953. }
  954. }
  955. }
  956. // clone affectation
  957. if ($clone_affectation)
  958. {
  959. $origin_task = new Task($this->db);
  960. $origin_task->fetch($fromid);
  961. foreach(array('internal','external') as $source)
  962. {
  963. $tab = $origin_task->liste_contact(-1,$source);
  964. $num=count($tab);
  965. $i = 0;
  966. while ($i < $num)
  967. {
  968. $clone_task->add_contact($tab[$i]['id'], $tab[$i]['code'], $tab[$i]['source']);
  969. if ($clone_task->error == 'DB_ERROR_RECORD_ALREADY_EXISTS')
  970. {
  971. $langs->load("errors");
  972. $this->error.=$langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType");
  973. $error++;
  974. }
  975. else
  976. {
  977. if ($clone_task->error!='')
  978. {
  979. $this->error.=$clone_task->error;
  980. $error++;
  981. }
  982. }
  983. $i++;
  984. }
  985. }
  986. }
  987. if($clone_time)
  988. {
  989. //TODO clone time of affectation
  990. }
  991. if (! $error)
  992. {
  993. return $clone_task_id;
  994. }
  995. else
  996. {
  997. dol_syslog(get_class($this)."::createFromClone nbError: ".$error." error : " . $this->error, LOG_ERR);
  998. return -1;
  999. }
  1000. }
  1001. else
  1002. {
  1003. $this->db->rollback();
  1004. return -1;
  1005. }
  1006. }
  1007. }
  1008. ?>