diff --git a/htdocs/core/actions_comments.inc.php b/htdocs/core/actions_comments.inc.php new file mode 100644 index 00000000000..185973cb258 --- /dev/null +++ b/htdocs/core/actions_comments.inc.php @@ -0,0 +1,76 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + * + * $elementype must be defined. + */ + +/** + * \file htdocs/core/actions_comments.inc.php + * \brief Code for actions on comments pages + */ + + +require_once DOL_DOCUMENT_ROOT.'/core/class/comment.class.php'; + +$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; +$comment = new Comment($db); + +/* + * Actions + */ + +if ($action == 'addcomment') +{ + $description = GETPOST('comment_description'); + if (!empty($description)) + { + $comment->description = $description; + $comment->datec = time(); + $comment->fk_element = GETPOST('id'); + $comment->element_type = GETPOST('comment_element_type'); + $comment->fk_user_author = $user->id; + $comment->entity = $conf->entity; + if ($comment->create($user) > 0) + { + setEventMessages($langs->trans("CommentAdded"), null, 'mesgs'); + header('Location: '.$varpage.'?id='.$id.($withproject?'&withproject=1':'')); + exit; + } + else + { + setEventMessages($comment->error, $comment->errors,'errors'); + $action=''; + } + } +} +if ($action == 'deletecomment') +{ + if ($comment->fetch($idcomment) >= 0) + { + if ($comment->delete($user) > 0) + { + setEventMessages($langs->trans("CommentDeleted"), null, 'mesgs'); + header('Location: '.$varpage.'?id='.$id.($withproject?'&withproject=1':'')); + exit; + } + else + { + setEventMessages($comment->error, $comment->errors,'errors'); + $action=''; + } + } +} \ No newline at end of file diff --git a/htdocs/core/class/comment.class.php b/htdocs/core/class/comment.class.php new file mode 100644 index 00000000000..0ec77405721 --- /dev/null +++ b/htdocs/core/class/comment.class.php @@ -0,0 +1,322 @@ +db = $db; + } + + + /** + * Create into database + * + * @param User $user User that create + * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + function create($user, $notrigger=0) + { + global $conf, $langs; + + $error=0; + + // Insert request + $sql = "INSERT INTO ".MAIN_DB_PREFIX."comment ("; + $sql.= "description"; + $sql.= ", datec"; + $sql.= ", fk_element"; + $sql.= ", element_type"; + $sql.= ", fk_user_author"; + $sql.= ", entity"; + $sql.= ", import_key"; + $sql.= ") VALUES ("; + $sql.= "'".$this->db->escape($this->description)."'"; + $sql.= ", ".($this->datec!=''?"'".$this->db->idate($this->datec)."'":'null'); + $sql.= ", '".(isset($this->fk_element)?$this->fk_element:"null")."'"; + $sql.= ", '".$this->db->escape($this->element_type)."'"; + $sql.= ", '".(isset($this->fk_user_author)?$this->fk_user_author:"null")."'"; + $sql.= ", ".(!empty($this->entity)?$this->entity:'1'); + $sql.= ", ".(!empty($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null"); + $sql.= ")"; + + //var_dump($this->db); + //echo $sql; + + $this->db->begin(); + + dol_syslog(get_class($this)."::create", LOG_DEBUG); + $resql=$this->db->query($sql); + if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } + + if (! $error) + { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet_task_comment"); + + if (! $notrigger) + { + // Call trigger + $result=$this->call_trigger('TASK_COMMENT_CREATE',$user); + if ($result < 0) { $error++; } + // End call triggers + } + } + + // Commit or rollback + if ($error) + { + foreach($this->errors as $errmsg) + { + dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR); + $this->error.=($this->error?', '.$errmsg:$errmsg); + } + $this->db->rollback(); + return -1*$error; + } + else + { + $this->db->commit(); + return $this->id; + } + } + + + /** + * Load object in memory from database + * + * @param int $id Id object + * @param int $ref ref object + * @return int <0 if KO, 0 if not found, >0 if OK + */ + function fetch($id, $ref='') + { + global $langs; + + $sql = "SELECT"; + $sql.= " c.rowid,"; + $sql.= " c.description,"; + $sql.= " c.datec,"; + $sql.= " c.tms,"; + $sql.= " c.fk_element,"; + $sql.= " c.element_type,"; + $sql.= " c.fk_user_author,"; + $sql.= " c.entity,"; + $sql.= " c.import_key"; + $sql.= " FROM ".MAIN_DB_PREFIX."comment as c"; + $sql.= " WHERE c.rowid = ".$id; + + dol_syslog(get_class($this)."::fetch", LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $num_rows = $this->db->num_rows($resql); + + if ($num_rows) + { + $obj = $this->db->fetch_object($resql); + + $this->id = $obj->rowid; + $this->description = $obj->description; + $this->element_type = $obj->element_type; + $this->datec = $this->db->jdate($obj->datec); + $this->tms = $obj->tms; + $this->fk_user_author = $obj->fk_user_author; + $this->fk_element = $obj->fk_element; + $this->entity = $obj->entity; + $this->import_key = $obj->import_key; + } + + $this->db->free($resql); + + if ($num_rows) return 1; + else return 0; + } + else + { + $this->error="Error ".$this->db->lasterror(); + return -1; + } + } + + + /** + * Update database + * + * @param User $user User that modify + * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @return int <=0 if KO, >0 if OK + */ + function update(User $user, $notrigger=0) + { + global $conf, $langs; + $error=0; + + // Clean parameters + if (isset($this->fk_element)) $this->fk_project=(int) trim($this->fk_element); + if (isset($this->fk_user_author)) $this->fk_user_author=(int) trim($this->fk_user_author); + if (isset($this->description)) $this->description=trim($this->description); + + + // Update request + $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_comment SET"; + $sql.= " description=".(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").","; + $sql.= " datec=".($this->datec!=''?"'".$this->db->idate($this->datec)."'":'null').","; + $sql.= " fk_element=".(isset($this->fk_element)?$this->fk_element:"null").","; + $sql.= " element_type='".$this->element_type."',"; + $sql.= " fk_user_author=".(isset($this->fk_user_author)?$this->fk_user_author:"null").","; + $sql.= " entity=".(!empty($this->entity)?$this->entity:'1').","; + $sql.= " import_key=".(!empty($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null"); + $sql.= " WHERE rowid=".$this->id; + + $this->db->begin(); + + dol_syslog(get_class($this)."::update", LOG_DEBUG); + $resql = $this->db->query($sql); + if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } + + if (! $error) + { + if (! $notrigger) + { + // Call trigger + $result=$this->call_trigger('TASK_COMMENT_MODIFY',$user); + if ($result < 0) { $error++; } + // End call triggers + } + } + + // Commit or rollback + if ($error) + { + foreach($this->errors as $errmsg) + { + dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR); + $this->error.=($this->error?', '.$errmsg:$errmsg); + } + $this->db->rollback(); + return -1*$error; + } + else + { + $this->db->commit(); + return 1; + } + } + + + /** + * Delete task from database + * + * @param User $user User that delete + * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @return int <0 if KO, >0 if OK + */ + function delete($user, $notrigger=0) + { + global $conf, $langs; + require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; + + $error=0; + + $this->db->begin(); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."comment"; + $sql.= " WHERE rowid=".$this->id; + + $resql = $this->db->query($sql); + if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } + + if (! $error) + { + if (! $notrigger) + { + // Call trigger + $result=$this->call_trigger('TASK_COMMENT_DELETE',$user); + if ($result < 0) { $error++; } + // End call triggers + } + } + + // Commit or rollback + if ($error) + { + foreach($this->errors as $errmsg) + { + dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); + $this->error.=($this->error?', '.$errmsg:$errmsg); + } + $this->db->rollback(); + return -1*$error; + }else{ + $this->db->commit(); + return 1; + } + } + + + /** + * Load comments linked with current task + * + * @return array Comment array + */ + public static function fetchAllFor($element_type, $fk_element) + { + global $db,$conf; + $TComments = array(); + if(!empty($element_type) && !empty($fk_element)) { + $sql = "SELECT"; + $sql.= " c.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."comment as c"; + $sql.= " WHERE c.fk_element = ".$fk_element; + $sql.= " AND c.element_type = '".$element_type."'"; + $sql.= " AND c.entity = ".$conf->entity; + $sql.= " ORDER BY c.tms DESC"; + + dol_syslog("Comment::fetchAllFor", LOG_DEBUG); + $resql=$db->query($sql); + if ($resql) + { + $num_rows = $db->num_rows($resql); + if ($num_rows > 0) + { + while($obj = $db->fetch_object($resql)) + { + $comment = new self($db); + $comment->fetch($obj->rowid); + $TComments[] = $comment; + } + } + $db->free($resql); + } + } + return $TComments; + } +} \ No newline at end of file diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ac2c1482682..b8f80c23c15 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -308,6 +308,12 @@ abstract class CommonObject * @var CommonObjectLine[] */ public $lines; + + /** + * @var mixed Contains comments + * @see fetchComments() + */ + public $comments=array(); /** * @var int @@ -5288,5 +5294,28 @@ abstract class CommonObject // TODO... } + + /** + * Load comments linked with current task + * @return boolean 1 if ok + */ + public function fetchComments() + { + require_once DOL_DOCUMENT_ROOT.'/core/class/comment.class.php'; + + $comment = new Comment($this->db); + $this->comments = Comment::fetchAllFor($this->element, $this->id); + return 1; + } + + /** + * Return nb comments already posted + * + * @return int + */ + public function getNbComments() + { + return count($this->comments); + } } diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index af49fa6b27d..7f809fadd77 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -66,7 +66,19 @@ function project_prepare_head($object) // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'project'); - + + + // Manage discussion + if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT)) + { + $nbComments = $object->getNbComments(); + $head[$h][0] = DOL_URL_ROOT.'/projet/comment.php?id='.$object->id; + $head[$h][1] = $langs->trans("CommentLink"); + if ($nbComments > 0) $head[$h][1].= ' '.$nbComments.''; + $head[$h][2] = 'project_comment'; + $h++; + } + if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $nbNote = 0; @@ -179,9 +191,9 @@ function task_prepare_head($object) // Manage discussion if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK)) { - $nbComments= $object->getNbComments(); + $nbComments = $object->getNbComments(); $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$object->id.(GETPOST('withproject')?'&withproject=1':''); - $head[$h][1] = $langs->trans("TaskCommentLinks"); + $head[$h][1] = $langs->trans("CommentLink"); if ($nbComments > 0) $head[$h][1].= ' '.$nbComments.''; $head[$h][2] = 'task_comment'; $h++; diff --git a/htdocs/core/tpl/bloc_comment.tpl.php b/htdocs/core/tpl/bloc_comment.tpl.php new file mode 100644 index 00000000000..b28699744d2 --- /dev/null +++ b/htdocs/core/tpl/bloc_comment.tpl.php @@ -0,0 +1,105 @@ +'; +print '
'; +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print "\n"; + +print ''; +print ''; + +// Description +print ''; + +print ''; +print '
'.$langs->trans("Comments").'
'; + +$desc = GETPOST('comment_description'); + +$doleditor = new DolEditor('comment_description', $desc, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '100%'); +print $doleditor->Create(1); + +print ''; +print ''; +print '
'; + +// List of comments +if(!empty($object->comments)) { + // Default color for current user + $TColors = array($user->id => array('bgcolor'=>'efefef','color'=>'555')); + $first = true; + foreach($object->comments as $comment) { + $fk_user = $comment->fk_user_author; + $userstatic->fetch($fk_user); + if(empty($TColors[$fk_user])) { + $bgcolor = random_color(180,240); + if(!empty($userstatic->color)) { + $bgcolor = $userstatic->color; + } + $color = (colorIsLight($bgcolor))?'555':'fff'; + $TColors[$fk_user] = array('bgcolor'=>$bgcolor,'color'=>$color); + } + print '
'; + if($fk_user == $user->id) { + print '
 
'; + } + + print '
'; + print '
'; + if (! empty($user->photo)) + { + print Form::showphoto('userphoto', $userstatic, 80, 0, 0, '', 'small', 0, 1).'
'; + } + print $langs->trans('User').' : '.$userstatic->getNomUrl().'
'; + print $langs->trans('Date').' : '.dol_print_date($comment->datec,'dayhoursec'); + print '
'; // End comment-info + + print '
'; + print '
'; + print '
'; + print $comment->description; + print '
'; // End comment-description + if(($first && $fk_user == $user->id) || $user->admin == 1) { + print ''; + print img_picto('', 'delete.png'); + print ''; + } + print '
'; // End comment-table + print '
'; // End comment-right + print '
'; // End comment + + if($fk_user != $user->id) { + print '
 
'; + } + print '
'; + print '
'; // end 100p + + $first = false; + } +} + +print '
'; +print '
'; diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index ff9f4e0a2f8..fb9e5f8749f 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -302,14 +302,15 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPOSAL_SUPPLIER_CLOSE_SIGNED','Price request closed signed','Executed when a customer proposal is closed signed','proposal_supplier',10); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPOSAL_SUPPLIER_CLOSE_REFUSED','Price request closed refused','Executed when a customer proposal is closed refused','proposal_supplier',10); - -CREATE TABLE llx_projet_task_comment ( +DROP TABLE `llx_projet_task_comment`; +CREATE TABLE IF NOT EXISTS llx_comment ( rowid integer AUTO_INCREMENT PRIMARY KEY, datec datetime DEFAULT NULL, tms timestamp, description text NOT NULL, - fk_user integer DEFAULT NULL, - fk_task integer DEFAULT NULL, + fk_user_author integer DEFAULT NULL, + fk_element integer DEFAULT NULL, + element_type varchar(50) DEFAULT NULL, entity integer DEFAULT 1, import_key varchar(125) DEFAULT NULL )ENGINE=innodb; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index bfcbb5a2010..fbbd8dbaabd 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -873,3 +873,8 @@ SearchIntoContracts=Contracts SearchIntoCustomerShipments=Customer shipments SearchIntoExpenseReports=Expense reports SearchIntoLeaves=Leaves +CommentLink=Comments +NbComments=Number of comments +CommentPage=Comments space +CommentAdded=Comment added +CommentDeleted=Comment deleted diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 408c3db5e7a..f9eb6c00477 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -210,8 +210,4 @@ OppStatusLOST=Lost Budget=Budget # Comments trans AllowCommentOnTask=Allow user comments on tasks -TaskCommentLinks=Comments -TaskNbComments=Number of comments -TaskComment=Task's comments space -CommentAdded=Comment added -CommentDeleted=Comment deleted +AllowCommentOnProject=Allow user comments on projects diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index 6a6c80a78bf..7a47c934a80 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -842,3 +842,8 @@ SearchIntoContracts=Contrats SearchIntoCustomerShipments=Expéditions clients SearchIntoExpenseReports=Notes de frais SearchIntoLeaves=Congés +CommentLink=Commentaires +NbComments=Nombre de commentaires +CommentPage=Espace commentaires +CommentAdded=Commentaire ajouté avec succès +CommentDeleted=Commentaire supprimé avec succès diff --git a/htdocs/langs/fr_FR/projects.lang b/htdocs/langs/fr_FR/projects.lang index 154c1138ab9..c235230eb2f 100644 --- a/htdocs/langs/fr_FR/projects.lang +++ b/htdocs/langs/fr_FR/projects.lang @@ -209,8 +209,4 @@ OppStatusLOST=Perdu Budget=Budget #Comments trans AllowCommentOnTask=Autoriser les commentaires entre utilisateurs sur les tâches -TaskCommentLinks=Commentaires -TaskNbComments=Nombre de commentaires -TaskComment=Tâches espace commentaires -CommentAdded=Commentaire ajouté avec succès -CommentDeleted=Commentaire supprimé avec succès +AllowCommentOnProject=Autoriser les commentaires entre utilisateurs sur les projets diff --git a/htdocs/projet/admin/project.php b/htdocs/projet/admin/project.php index 0c0da27457e..54e864e1bf6 100644 --- a/htdocs/projet/admin/project.php +++ b/htdocs/projet/admin/project.php @@ -918,6 +918,15 @@ print ''; print ' '; print ''; +print ''; +print ''.$langs->trans("AllowCommentOnProject").''; + +print ''; +echo ajax_constantonoff('PROJECT_ALLOW_COMMENT_ON_PROJECT'); +print ''; +print ' '; +print ''; + print ''; print ''.$langs->trans("AllowCommentOnTask").''; diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index af55063c66a..18aa3fe1f52 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -441,6 +441,7 @@ class Project extends CommonObject // Retreive all extrafield for thirdparty $this->fetch_optionals(); + $this->fetchComments(); return 1; } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 32ae678b016..0758dce2acb 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -1832,332 +1832,4 @@ class Task extends CommonObject return ($datetouse > 0 && ($datetouse < ($now - $conf->projet->task->warning_delay))); } - - /** - * Return nb comments already posted - * - * @return int - */ - public function getNbComments() - { - return count($this->comments); - } - - /** - * Load comments linked with current task - * - * @return int <0 if KO, 0 if not found, >0 if OK - */ - public function fetchComments() - { - $this->comments = array(); - $sql = "SELECT"; - $sql.= " c.rowid"; - $sql.= " FROM ".MAIN_DB_PREFIX."projet_task_comment as c"; - $sql.= " WHERE c.fk_task = ".$this->id; - $sql.= " ORDER BY c.tms DESC"; - - dol_syslog(get_class($this)."::fetchComments", LOG_DEBUG); - $resql=$this->db->query($sql); - if ($resql) - { - $num_rows = $this->db->num_rows($resql); - if ($num_rows > 0) - { - while($obj = $this->db->fetch_object($resql)) - { - $comment = new TaskComment($this->db); - $comment->fetch($obj->rowid); - $this->comments[] = $comment; - } - return $num_rows; - }else{ - return 0; - } - } - else - { - $this->error="Error ".$this->db->lasterror(); - return -1; - } - } -} - -/** - * Class to manage tasks - */ -class TaskComment extends CommonObject -{ - public $element='project_task_comment'; //!< Id that identify managed objects - public $table_element='projet_task_comment'; //!< Name of table without prefix where object is stored - public $fk_element='fk_task'; - public $picto = 'task'; - - var $fk_task; - - var $description; - - var $tms; - - var $datec; - - var $fk_user; - - var $entity; - - var $import_key; - - public $oldcopy; - - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - function __construct($db) - { - $this->db = $db; - } - - - /** - * Create into database - * - * @param User $user User that create - * @param int $notrigger 0=launch triggers after, 1=disable triggers - * @return int <0 if KO, Id of created object if OK - */ - function create($user, $notrigger=0) - { - global $conf, $langs; - - $error=0; - - // Insert request - $sql = "INSERT INTO ".MAIN_DB_PREFIX."projet_task_comment ("; - $sql.= "description"; - $sql.= ", datec"; - $sql.= ", fk_task"; - $sql.= ", fk_user"; - $sql.= ", entity"; - $sql.= ", import_key"; - $sql.= ") VALUES ("; - $sql.= "'".$this->db->escape($this->description)."'"; - $sql.= ", ".($this->datec!=''?"'".$this->db->idate($this->datec)."'":'null'); - $sql.= ", '".(isset($this->fk_task)?$this->fk_task:"null")."'"; - $sql.= ", '".(isset($this->fk_user)?$this->fk_user:"null")."'"; - $sql.= ", ".(!empty($this->entity)?$this->entity:'1'); - $sql.= ", ".(!empty($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null"); - $sql.= ")"; - - //var_dump($this->db); - //echo $sql; - - $this->db->begin(); - - dol_syslog(get_class($this)."::create", LOG_DEBUG); - $resql=$this->db->query($sql); - if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } - - if (! $error) - { - $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet_task_comment"); - - if (! $notrigger) - { - // Call trigger - $result=$this->call_trigger('TASK_COMMENT_CREATE',$user); - if ($result < 0) { $error++; } - // End call triggers - } - } - - // Commit or rollback - if ($error) - { - foreach($this->errors as $errmsg) - { - dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR); - $this->error.=($this->error?', '.$errmsg:$errmsg); - } - $this->db->rollback(); - return -1*$error; - } - else - { - $this->db->commit(); - return $this->id; - } - } - - - /** - * Load object in memory from database - * - * @param int $id Id object - * @param int $ref ref object - * @return int <0 if KO, 0 if not found, >0 if OK - */ - function fetch($id, $ref='') - { - global $langs; - - $sql = "SELECT"; - $sql.= " c.rowid,"; - $sql.= " c.description,"; - $sql.= " c.datec,"; - $sql.= " c.tms,"; - $sql.= " c.fk_task,"; - $sql.= " c.fk_user,"; - $sql.= " c.entity,"; - $sql.= " c.import_key"; - $sql.= " FROM ".MAIN_DB_PREFIX."projet_task_comment as c"; - $sql.= " WHERE c.rowid = ".$id; - - dol_syslog(get_class($this)."::fetch", LOG_DEBUG); - $resql=$this->db->query($sql); - if ($resql) - { - $num_rows = $this->db->num_rows($resql); - - if ($num_rows) - { - $obj = $this->db->fetch_object($resql); - - $this->id = $obj->rowid; - $this->description = $obj->description; - $this->datec = $this->db->jdate($obj->datec); - $this->tms = $obj->tms; - $this->fk_user = $obj->fk_user; - $this->fk_task = $obj->fk_task; - $this->entity = $obj->entity; - $this->import_key = $obj->import_key; - } - - $this->db->free($resql); - - if ($num_rows) return 1; - else return 0; - } - else - { - $this->error="Error ".$this->db->lasterror(); - return -1; - } - } - - - /** - * Update database - * - * @param User $user User that modify - * @param int $notrigger 0=launch triggers after, 1=disable triggers - * @return int <=0 if KO, >0 if OK - */ - function update(User $user, $notrigger=0) - { - global $conf, $langs; - $error=0; - - // Clean parameters - if (isset($this->fk_task)) $this->fk_project=(int) trim($this->fk_task); - if (isset($this->fk_user)) $this->fk_user=(int) trim($this->fk_user); - if (isset($this->description)) $this->description=trim($this->description); - - - // Update request - $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_comment SET"; - $sql.= " description=".(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").","; - $sql.= " datec=".($this->datec!=''?"'".$this->db->idate($this->datec)."'":'null').","; - $sql.= " fk_task=".(isset($this->fk_task)?$this->fk_task:"null").","; - $sql.= " fk_user=".(isset($this->fk_user)?$this->fk_user:"null").","; - $sql.= " entity=".(!empty($this->entity)?$this->entity:'1').","; - $sql.= " import_key=".(!empty($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null"); - $sql.= " WHERE rowid=".$this->id; - - $this->db->begin(); - - dol_syslog(get_class($this)."::update", LOG_DEBUG); - $resql = $this->db->query($sql); - if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } - - if (! $error) - { - if (! $notrigger) - { - // Call trigger - $result=$this->call_trigger('TASK_COMMENT_MODIFY',$user); - if ($result < 0) { $error++; } - // End call triggers - } - } - - // Commit or rollback - if ($error) - { - foreach($this->errors as $errmsg) - { - dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR); - $this->error.=($this->error?', '.$errmsg:$errmsg); - } - $this->db->rollback(); - return -1*$error; - } - else - { - $this->db->commit(); - return 1; - } - } - - - /** - * Delete task from database - * - * @param User $user User that delete - * @param int $notrigger 0=launch triggers after, 1=disable triggers - * @return int <0 if KO, >0 if OK - */ - function delete($user, $notrigger=0) - { - global $conf, $langs; - require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; - - $error=0; - - $this->db->begin(); - - $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_comment"; - $sql.= " WHERE rowid=".$this->id; - - $resql = $this->db->query($sql); - if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } - - if (! $error) - { - if (! $notrigger) - { - // Call trigger - $result=$this->call_trigger('TASK_COMMENT_DELETE',$user); - if ($result < 0) { $error++; } - // End call triggers - } - } - - // Commit or rollback - if ($error) - { - foreach($this->errors as $errmsg) - { - dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); - $this->error.=($this->error?', '.$errmsg:$errmsg); - } - $this->db->rollback(); - return -1*$error; - }else{ - $this->db->commit(); - return 1; - } - } } \ No newline at end of file diff --git a/htdocs/projet/comment.php b/htdocs/projet/comment.php new file mode 100644 index 00000000000..4e3d52a2f37 --- /dev/null +++ b/htdocs/projet/comment.php @@ -0,0 +1,189 @@ + + * Copyright (C) 2006-2017 Laurent Destailleur + * Copyright (C) 2010-2012 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/projet/tasks/task.php + * \ingroup project + * \brief Page of a project task + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; +require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + +$langs->load("projects"); +$langs->load("companies"); + +$id=GETPOST('id','int'); +$idcomment=GETPOST('idcomment','int'); +$ref=GETPOST("ref",'alpha',1); // task ref +$objectref=GETPOST("taskref",'alpha'); // task ref +$action=GETPOST('action','alpha'); +$confirm=GETPOST('confirm','alpha'); +$withproject=GETPOST('withproject','int'); +$project_ref=GETPOST('project_ref','alpha'); +$planned_workload=((GETPOST('planned_workloadhour','int')!='' || GETPOST('planned_workloadmin','int')!='') ? (GETPOST('planned_workloadhour','int')>0?GETPOST('planned_workloadhour','int')*3600:0) + (GETPOST('planned_workloadmin','int')>0?GETPOST('planned_workloadmin','int')*60:0) : ''); + +// Security check +$socid=0; +//if ($user->societe_id > 0) $socid = $user->societe_id; // For external user, no check is done on company because readability is managed by public status of project and assignement. +if (! $user->rights->projet->lire) accessforbidden(); + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('projectcard','globalcard')); + +$object = new Project($db); +$extrafields = new ExtraFields($db); +$object = new Project($db); + +// fetch optionals attributes and labels +$extralabels=$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +if ($id > 0 || ! empty($ref)) +{ + $ret = $object->fetch($id,$ref); // If we create project, ref may be defined into POST but record does not yet exists into database + if ($ret > 0) { + $object->fetch_thirdparty(); + $id=$object->id; + } +} + +// include comment actions +include DOL_DOCUMENT_ROOT . '/core/actions_comments.inc.php'; + +/* + * View +*/ + + +llxHeader('', $langs->trans("CommentPage")); + +$form = new Form($db); +$formother = new FormOther($db); +$formfile = new FormFile($db); + +// Tabs for project +$tab = 'project_comment'; +$head = project_prepare_head($object); +dol_fiche_head($head, $tab, $langs->trans("Project"), - 1, ($object->public ? 'projectpub' : 'project')); + +$param = ($mode == 'mine' ? '&mode=mine' : ''); + +// Project card + +$linkback = '' . $langs->trans("BackToList") . ''; + +$morehtmlref = '
'; +// Title +$morehtmlref .= $object->title; +// Thirdparty +if ($object->thirdparty->id > 0) { + $morehtmlref .= '
' . $langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1, 'project'); +} +$morehtmlref .= '
'; + +// Define a complementary filter for search of next/prev ref. +if (! $user->rights->projet->all->lire) { + $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0); + $object->next_prev_filter = " rowid in (" . (count($objectsListId) ? join(',', array_keys($objectsListId)) : '0') . ")"; +} + +dol_banner_tab($object, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + +print '
'; +print '
'; +print '
'; + +print ''; + +// Visibility +print ''; + +// Date start - end +print ''; + +// Budget +print ''; + +// Other attributes +$cols = 2; +// include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + +print '
' . $langs->trans("Visibility") . ''; +if ($object->public) print $langs->trans('SharedProject'); +else + print $langs->trans('PrivateProject'); +print '
' . $langs->trans("DateStart") . ' - ' . $langs->trans("DateEnd") . ''; +print dol_print_date($object->date_start, 'day'); +$end = dol_print_date($object->date_end, 'day'); +if ($end) print ' - ' . $end; +print '
' . $langs->trans("Budget") . ''; +if (strcmp($object->budget_amount, '')) print price($object->budget_amount, '', $langs, 1, 0, 0, $conf->currency); +print '
'; + +print '
'; +print '
'; +print '
'; +print '
'; + +print ''; + +// Description +print ''; + +// Categories +if ($conf->categorie->enabled) { + print '"; +} + +// Nb comments +print ''; + +print '
' . $langs->trans("Description") . ''; +print nl2br($object->description); +print '
' . $langs->trans("Categories") . ''; + print $form->showCategories($object->id, 'project', 1); + print "
'.$langs->trans("NbComments").''; +print $object->getNbComments(); +print '
'; + +print '
'; +print '
'; +print '
'; + +print '
'; + +dol_fiche_end(); + +print '
'; + +// Include comment tpl view +include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_comment.tpl.php'; + + +llxFooter(); +$db->close(); diff --git a/htdocs/projet/tasks/comment.php b/htdocs/projet/tasks/comment.php index a36337c324d..e4250bad062 100644 --- a/htdocs/projet/tasks/comment.php +++ b/htdocs/projet/tasks/comment.php @@ -33,7 +33,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $langs->load("projects"); $langs->load("companies"); @@ -41,7 +40,7 @@ $langs->load("companies"); $id=GETPOST('id','int'); $idcomment=GETPOST('idcomment','int'); $ref=GETPOST("ref",'alpha',1); // task ref -$taskref=GETPOST("taskref",'alpha'); // task ref +$objectref=GETPOST("taskref",'alpha'); // task ref $action=GETPOST('action','alpha'); $confirm=GETPOST('confirm','alpha'); $withproject=GETPOST('withproject','int'); @@ -56,69 +55,25 @@ if (! $user->rights->projet->lire) accessforbidden(); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('projecttaskcard','globalcard')); -$task = new Task($db); -$object = new TaskComment($db); +$object = new Task($db); $extrafields = new ExtraFields($db); $projectstatic = new Project($db); -$userstatic = new User($db); // fetch optionals attributes and labels -$extralabels=$extrafields->fetch_name_optionals_label($task->table_element); +$extralabels=$extrafields->fetch_name_optionals_label($object->table_element); - -/* - * Actions - */ - -if ($action == 'addcomment') -{ - if (!empty($_POST['comment_description'])) - { - $object->description = GETPOST('comment_description'); - $object->datec = time(); - $object->fk_task = $id; - $object->fk_user = $user->id; - $object->entity = $conf->entity; - if ($object->create($user) > 0) - { - setEventMessages($langs->trans("CommentAdded"), null, 'mesgs'); - header('Location: '.DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$id.($withproject?'&withproject=1':'')); - exit; - } - else - { - setEventMessages($task->error,$task->errors,'errors'); - $action=''; - } - } -} -if ($action == 'deletecomment') -{ - if ($object->fetch($idcomment) >= 0) - { - if ($object->delete($user) > 0) - { - setEventMessages($langs->trans("CommentDeleted"), null, 'mesgs'); - header('Location: '.DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$id.($withproject?'&withproject=1':'')); - exit; - } - else - { - setEventMessages($task->error,$task->errors,'errors'); - $action=''; - } - } -} +// include comment actions +include DOL_DOCUMENT_ROOT . '/core/actions_comments.inc.php'; // Retreive First Task ID of Project if withprojet is on to allow project prev next to work if (! empty($project_ref) && ! empty($withproject)) { if ($projectstatic->fetch('',$project_ref) > 0) { - $tasksarray=$task->getTasksArray(0, 0, $projectstatic->id, $socid, 0); - if (count($tasksarray) > 0) + $objectsarray=$object->getTasksArray(0, 0, $projectstatic->id, $socid, 0); + if (count($objectsarray) > 0) { - $id=$tasksarray[0]->id; + $id=$objectsarray[0]->id; } else { @@ -132,7 +87,7 @@ if (! empty($project_ref) && ! empty($withproject)) */ -llxHeader('', $langs->trans("TaskComment")); +llxHeader('', $langs->trans("CommentPage")); $form = new Form($db); $formother = new FormOther($db); @@ -140,14 +95,14 @@ $formfile = new FormFile($db); if ($id > 0 || ! empty($ref)) { - if ($task->fetch($id,$ref) > 0) + if ($object->fetch($id,$ref) > 0) { - $res=$task->fetch_optionals($task->id,$extralabels); + $res=$object->fetch_optionals($object->id,$extralabels); - $result=$projectstatic->fetch($task->fk_project); + $result=$projectstatic->fetch($object->fk_project); if (! empty($projectstatic->socid)) $projectstatic->fetch_thirdparty(); - $task->project = clone $projectstatic; + $object->project = clone $projectstatic; $userWrite = $projectstatic->restrictedProjectArea($user,'write'); @@ -177,8 +132,8 @@ if ($id > 0 || ! empty($ref)) // Define a complementary filter for search of next/prev ref. if (! $user->rights->projet->all->lire) { - $tasksListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0); - $projectstatic->next_prev_filter=" rowid in (".(count($tasksListId)?join(',',array_keys($tasksListId)):'0').")"; + $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,0); + $projectstatic->next_prev_filter=" rowid in (".(count($objectsListId)?join(',',array_keys($objectsListId)):'0').")"; } dol_banner_tab($projectstatic, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref); @@ -245,7 +200,7 @@ if ($id > 0 || ! empty($ref)) print '
'; } - $head=task_prepare_head($task); + $head=task_prepare_head($object); /* * Fiche tache en mode visu @@ -263,9 +218,9 @@ if ($id > 0 || ! empty($ref)) if (! GETPOST('withproject') || empty($projectstatic->id)) { $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user,0,1); - $task->next_prev_filter=" fk_projet in (".$projectsListId.")"; + $object->next_prev_filter=" fk_projet in (".$projectsListId.")"; } - else $task->next_prev_filter=" fk_projet = ".$projectstatic->id; + else $object->next_prev_filter=" fk_projet = ".$projectstatic->id; $morehtmlref=''; @@ -285,7 +240,7 @@ if ($id > 0 || ! empty($ref)) $morehtmlref.=''; } - dol_banner_tab($task, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param); + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param); print '
'; @@ -293,8 +248,8 @@ if ($id > 0 || ! empty($ref)) print ''; // Nb comments - print ''; // Other attributes @@ -308,102 +263,9 @@ if ($id > 0 || ! empty($ref)) dol_fiche_end(); - - print '
'; - print '
'; - - // Add comment - - print '
'; - print ''; - print ''; - print ''; - print ''; - - print '
'.$langs->trans("TaskNbComments").''; - print $task->getNbComments(); + print ''.$langs->trans("NbComments").''; + print $object->getNbComments(); print '
'; - - print ''; - print ''; - print ''; - print ''; - print ''; - print "\n"; - - print ''; - print ''; - - // Description - print ''; - - print ''; - print '
'.$langs->trans("Comments").'
'; - - $desc = ($_POST['comment_description']?$_POST['comment_description']:''); - - $doleditor = new DolEditor('comment_description', $desc, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '100%'); - print $doleditor->Create(1); - - print ''; - print ''; - print '
'; - - // List of comments - if(!empty($task->comments)) { - // Default color for current user - $TColors = array($user->id => array('bgcolor'=>'efefef','color'=>'555')); - $first = true; - foreach($task->comments as $comment) { - $fk_user = $comment->fk_user; - $userstatic->fetch($fk_user); - if(empty($TColors[$fk_user])) { - $bgcolor = random_color(180,240); - if(!empty($userstatic->color)) { - $bgcolor = $userstatic->color; - } - $color = (colorIsLight($bgcolor))?'555':'fff'; - $TColors[$fk_user] = array('bgcolor'=>$bgcolor,'color'=>$color); - } - print '
'; - if($comment->fk_user == $user->id) { - print '
 
'; - } - - print '
'; - print '
'; - if (! empty($user->photo)) - { - print Form::showphoto('userphoto', $userstatic, 80, 0, 0, '', 'small', 0, 1).'
'; - } - print $langs->trans('User').' : '.$userstatic->getNomUrl().'
'; - print $langs->trans('Date').' : '.dol_print_date($comment->datec,'dayhoursec'); - print '
'; // End comment-info - - print '
'; - print '
'; - print '
'; - print $comment->description; - print '
'; // End comment-description - if(($first && $fk_user == $user->id) || $user->admin == 1) { - print ''; - print img_picto('', 'delete.png'); - print ''; - } - print '
'; // End comment-table - print '
'; // End comment-right - print '
'; // End comment - - if($comment->fk_user != $user->id) { - print '
 
'; - } - print '
'; - print '
'; // end 100p - - $first = false; - } - } - - print '
'; - print '
'; + + // Include comment tpl view + include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_comment.tpl.php'; } }