2
0
forked from Wavyzz/dolibarr
Files
dolibarr-fork/htdocs/projet/class/project.class.php
Laurent Destailleur 41a74c62e2 Fix trigger to insert lines where called when inserting line but also
when cloning parent object, making no way to know when to use them or
not. I introduced a context to allow code to know that and do not
triggers twice.
2015-02-26 13:03:17 +01:00

1414 lines
44 KiB
PHP

<?php
/* Copyright (C) 2002-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2005-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2010 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/projet/class/project.class.php
* \ingroup projet
* \brief File of class to manage projects
*/
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
/**
* Class to manage projects
*/
class Project extends CommonObject
{
public $element = 'project'; //!< Id that identify managed objects
public $table_element = 'projet'; //!< Name of table without prefix where object is stored
public $table_element_line = 'projet_task';
public $fk_element = 'fk_projet';
protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
/**
* {@inheritdoc}
*/
protected $table_ref_field = 'ref';
var $id;
var $ref;
var $description;
var $statut;
var $title;
var $date_start;
var $date_end;
var $socid;
var $user_author_id; //!< Id of project creator. Not defined if shared project.
var $public; //!< Tell if this is a public or private project
var $note_private;
var $note_public;
var $statuts_short;
var $statuts; // 0=draft, 1=opened, 2=closed
var $oldcopy;
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
function __construct($db)
{
$this->db = $db;
$this->statuts_short = array(0 => 'Draft', 1 => 'Opened', 2 => 'Closed');
$this->statuts = array(0 => 'Draft', 1 => 'Opened', 2 => 'Closed');
}
/**
* Create a project into database
*
* @param User $user User making creation
* @param int $notrigger Disable triggers
* @return int <0 if KO, id of created project if OK
*/
function create($user, $notrigger=0)
{
global $conf, $langs;
$error = 0;
$ret = 0;
$now=dol_now();
// Check parameters
if (!trim($this->ref))
{
$this->error = 'ErrorFieldsRequired';
dol_syslog(get_class($this)."::create error -1 ref null", LOG_ERR);
return -1;
}
$this->db->begin();
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "projet (";
$sql.= "ref";
$sql.= ", title";
$sql.= ", description";
$sql.= ", fk_soc";
$sql.= ", fk_user_creat";
$sql.= ", fk_statut";
$sql.= ", public";
$sql.= ", datec";
$sql.= ", dateo";
$sql.= ", datee";
$sql.= ", entity";
$sql.= ") VALUES (";
$sql.= "'" . $this->db->escape($this->ref) . "'";
$sql.= ", '" . $this->db->escape($this->title) . "'";
$sql.= ", '" . $this->db->escape($this->description) . "'";
$sql.= ", " . ($this->socid > 0 ? $this->socid : "null");
$sql.= ", " . $user->id;
$sql.= ", 0";
$sql.= ", " . ($this->public ? 1 : 0);
$sql.= ", '".$this->db->idate($now)."'";
$sql.= ", " . ($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null');
$sql.= ", " . ($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null');
$sql.= ", ".$conf->entity;
$sql.= ")";
dol_syslog(get_class($this)."::create", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "projet");
$ret = $this->id;
if (!$notrigger)
{
// Call trigger
$result=$this->call_trigger('PROJECT_CREATE',$user);
if ($result < 0) { $error++; }
// End call triggers
}
}
else
{
$this->error = $this->db->lasterror();
$this->errno = $this->db->lasterrno();
$error++;
}
//Update extrafield
if (!$error) {
if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
{
$result=$this->insertExtraFields();
if ($result < 0)
{
$error++;
}
}
}
if (!$error && !empty($conf->global->MAIN_DISABLEDRAFTSTATUS))
{
$res = $this->setValid($user);
if ($res < 0) $error++;
}
if (!$error)
{
$this->db->commit();
return $ret;
}
else
{
$this->db->rollback();
return -1;
}
}
/**
* Update a project
*
* @param User $user User object of making update
* @param int $notrigger 1=Disable all triggers
* @return int
*/
function update($user, $notrigger=0)
{
global $langs, $conf;
$error=0;
// Clean parameters
$this->title = trim($this->title);
$this->description = trim($this->description);
if (dol_strlen(trim($this->ref)) > 0)
{
$this->db->begin();
$sql = "UPDATE " . MAIN_DB_PREFIX . "projet SET";
$sql.= " ref='" . $this->db->escape($this->ref) . "'";
$sql.= ", title = '" . $this->db->escape($this->title) . "'";
$sql.= ", description = '" . $this->db->escape($this->description) . "'";
$sql.= ", fk_soc = " . ($this->socid > 0 ? $this->socid : "null");
$sql.= ", fk_statut = " . $this->statut;
$sql.= ", public = " . ($this->public ? 1 : 0);
$sql.= ", datec=" . ($this->date_c != '' ? "'".$this->db->idate($this->date_c)."'" : 'null');
$sql.= ", dateo=" . ($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null');
$sql.= ", datee=" . ($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null');
$sql.= " WHERE rowid = " . $this->id;
dol_syslog(get_class($this)."::Update", LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
{
if (!$notrigger)
{
// Call trigger
$result=$this->call_trigger('PROJECT_MODIFY',$user);
if ($result < 0) { $error++; }
// End call triggers
}
//Update extrafield
if (!$error) {
if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
{
$result=$this->insertExtraFields();
if ($result < 0)
{
$error++;
}
}
}
if (! $error && (is_object($this->oldcopy) && $this->oldcopy->ref != $this->ref))
{
// We remove directory
if ($conf->projet->dir_output)
{
$olddir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($this->oldcopy->ref);
$newdir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($this->ref);
if (file_exists($olddir))
{
include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
$res=dol_move($olddir, $newdir);
if (! $res)
{
$this->error='ErrorFailToMoveDir';
$error++;
}
}
}
}
if (! $error )
{
$this->db->commit();
$result = 1;
}
else
{
$this->db->rollback();
$result = -1;
}
}
else
{
$this->error = $this->db->lasterror();
$this->errors[] = $this->error;
$this->db->rollback();
dol_syslog(get_class($this)."::Update error -2 " . $this->error, LOG_ERR);
$result = -2;
}
}
else
{
dol_syslog(get_class($this)."::Update ref null");
$result = -1;
}
return $result;
}
/**
* Get object and lines from database
*
* @param int $id Id of object to load
* @param string $ref Ref of project
* @return int >0 if OK, 0 if not found, <0 if KO
*/
function fetch($id, $ref='')
{
if (empty($id) && empty($ref)) return -1;
$sql = "SELECT rowid, ref, title, description, public, datec";
$sql.= ", tms, dateo, datee, fk_soc, fk_user_creat, fk_statut, note_private, note_public,model_pdf";
$sql.= " FROM " . MAIN_DB_PREFIX . "projet";
if (! empty($id))
{
$sql.= " WHERE rowid=".$id;
}
else if (! empty($ref))
{
$sql.= " WHERE ref='".$this->db->escape($ref)."'";
$sql.= " AND entity IN (".getEntity('project',1).")";
}
dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
if ($this->db->num_rows($resql))
{
$obj = $this->db->fetch_object($resql);
$this->id = $obj->rowid;
$this->ref = $obj->ref;
$this->title = $obj->title;
$this->titre = $obj->title; // TODO deprecated
$this->description = $obj->description;
$this->date_c = $this->db->jdate($obj->datec);
$this->datec = $this->db->jdate($obj->datec); // TODO deprecated
$this->date_m = $this->db->jdate($obj->tms);
$this->datem = $this->db->jdate($obj->tms); // TODO deprecated
$this->date_start = $this->db->jdate($obj->dateo);
$this->date_end = $this->db->jdate($obj->datee);
$this->note_private = $obj->note_private;
$this->note_public = $obj->note_public;
$this->socid = $obj->fk_soc;
$this->user_author_id = $obj->fk_user_creat;
$this->public = $obj->public;
$this->statut = $obj->fk_statut;
$this->modelpdf = $obj->model_pdf;
$this->db->free($resql);
return 1;
}
else
{
return 0;
}
}
else
{
$this->error = $this->db->lasterror();
return -1;
}
}
/**
* Return list of projects
*
* @param int $socid To filter on a particular third party
* @return array List of projects
*/
function liste_array($socid='')
{
global $conf;
$projects = array();
$sql = "SELECT rowid, title";
$sql.= " FROM " . MAIN_DB_PREFIX . "projet";
$sql.= " WHERE entity = " . $conf->entity;
if (! empty($socid)) $sql.= " AND fk_soc = " . $socid;
$resql = $this->db->query($sql);
if ($resql)
{
$nump = $this->db->num_rows($resql);
if ($nump)
{
$i = 0;
while ($i < $nump)
{
$obj = $this->db->fetch_object($resql);
$projects[$obj->rowid] = $obj->title;
$i++;
}
}
return $projects;
}
else
{
print $this->db->lasterror();
}
}
/**
* Return list of elements for type linked to project
*
* @param string $type 'propal','order','invoice','order_supplier','invoice_supplier'
* @param string $tablename name of table associated of the type
* @param string $datefieldname name of table associated of the type
* @param string $dates Start date (at 00:00:00)
* @param string $datee End date (at 23:00:00)
* @return mixed List of orders linked to project, < 0 or string if error
*/
function get_element_list($type, $tablename, $datefieldname='', $dates='', $datee='')
{
$elements = array();
if ($type == 'agenda')
{
$sql = "SELECT id as rowid FROM " . MAIN_DB_PREFIX . "actioncomm WHERE fk_project=" . $this->id;
}
else
{
$sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $tablename." WHERE fk_projet=" . $this->id;
}
if ($dates > 0)
{
if (empty($datefieldname) && ! empty($this->table_element_date)) $datefieldname=$this->table_element_date;
if (empty($datefieldname)) return 'Error this object has no date field defined';
$sql.=" AND (".$datefieldname." >= '".$this->db->idate($dates)."' OR ".$datefieldname." IS NULL)";
}
if ($datee > 0)
{
if (empty($datefieldname) && ! empty($this->table_element_date)) $datefieldname=$this->table_element_date;
if (empty($datefieldname)) return 'Error this object has no date field defined';
$sql.=" AND (".$datefieldname." <= '".$this->db->idate($datee)."' OR ".$datefieldname." IS NULL)";
}
if (! $sql) return -1;
//print $sql;
dol_syslog(get_class($this)."::get_element_list", LOG_DEBUG);
$result = $this->db->query($sql);
if ($result)
{
$nump = $this->db->num_rows($result);
if ($nump)
{
$i = 0;
while ($i < $nump)
{
$obj = $this->db->fetch_object($result);
$elements[$i] = $obj->rowid;
$i++;
}
$this->db->free($result);
/* Return array */
return $elements;
}
}
else
{
dol_print_error($this->db);
}
}
/**
* Delete a project from database
*
* @param User $user User
* @param int $notrigger Disable triggers
* @return int <0 if KO, 0 if not possible, >0 if OK
*/
function delete($user, $notrigger=0)
{
global $langs, $conf;
require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
$error = 0;
$this->db->begin();
if (!$error)
{
// Delete linked contacts
$res = $this->delete_linked_contact();
if ($res < 0)
{
$this->error = 'ErrorFailToDeleteLinkedContact';
//$error++;
$this->db->rollback();
return 0;
}
}
// Delete tasks
if (! $error)
{
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "projet_task_time";
$sql.= " WHERE fk_task IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "projet_task WHERE fk_projet=" . $this->id . ")";
$resql = $this->db->query($sql);
if (!$resql)
{
$this->errors[] = $this->db->lasterror();
$error++;
}
}
if (! $error)
{
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "projet_task_extrafields";
$sql.= " WHERE fk_object IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "projet_task WHERE fk_projet=" . $this->id . ")";
$resql = $this->db->query($sql);
if (!$resql)
{
$this->errors[] = $this->db->lasterror();
$error++;
}
}
if (! $error)
{
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "projet_task";
$sql.= " WHERE fk_projet=" . $this->id;
$resql = $this->db->query($sql);
if (!$resql)
{
$this->errors[] = $this->db->lasterror();
$error++;
}
}
// Delete project
if (! $error)
{
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "projet";
$sql.= " WHERE rowid=" . $this->id;
$resql = $this->db->query($sql);
if (!$resql)
{
$this->errors[] = $this->db->lasterror();
$error++;
}
}
if (! $error)
{
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "projet_extrafields";
$sql.= " WHERE fk_object=" . $this->id;
$resql = $this->db->query($sql);
if (! $resql)
{
$this->errors[] = $this->db->lasterror();
$error++;
}
}
if (empty($error))
{
// We remove directory
$projectref = dol_sanitizeFileName($this->ref);
if ($conf->projet->dir_output)
{
$dir = $conf->projet->dir_output . "/" . $projectref;
if (file_exists($dir))
{
$res = @dol_delete_dir_recursive($dir);
if (!$res)
{
$this->errors[] = 'ErrorFailToDeleteDir';
$error++;
}
}
}
if (!$notrigger)
{
// Call trigger
$result=$this->call_trigger('PROJECT_DELETE',$user);
if ($result < 0) {
$error++;
}
// End call triggers
}
}
if (empty($error))
{
$this->db->commit();
return 1;
}
else
{
foreach ( $this->errors as $errmsg )
{
dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
dol_syslog(get_class($this) . "::delete " . $this->error, LOG_ERR);
$this->db->rollback();
return -1;
}
}
/**
* Validate a project
*
* @param User $user User that validate
* @return int <0 if KO, >0 if OK
*/
function setValid($user)
{
global $langs, $conf;
$error=0;
if ($this->statut != 1)
{
$this->db->begin();
$sql = "UPDATE " . MAIN_DB_PREFIX . "projet";
$sql.= " SET fk_statut = 1";
$sql.= " WHERE rowid = " . $this->id;
$sql.= " AND entity = " . $conf->entity;
dol_syslog(get_class($this)."::setValid", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
// Call trigger
$result=$this->call_trigger('PROJECT_VALIDATE',$user);
if ($result < 0) { $error++; }
// End call triggers
if (!$error)
{
$this->statut=1;
$this->db->commit();
return 1;
}
else
{
$this->db->rollback();
$this->error = join(',', $this->errors);
dol_syslog(get_class($this)."::setValid " . $this->error, LOG_ERR);
return -1;
}
}
else
{
$this->db->rollback();
$this->error = $this->db->lasterror();
return -1;
}
}
}
/**
* Close a project
*
* @param User $user User that validate
* @return int <0 if KO, >0 if OK
*/
function setClose($user)
{
global $langs, $conf;
$error=0;
if ($this->statut != 2)
{
$this->db->begin();
$sql = "UPDATE " . MAIN_DB_PREFIX . "projet";
$sql.= " SET fk_statut = 2";
$sql.= " WHERE rowid = " . $this->id;
$sql.= " AND entity = " . $conf->entity;
$sql.= " AND fk_statut = 1";
dol_syslog(get_class($this)."::setClose", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
// Call trigger
$result=$this->call_trigger('PROJECT_CLOSE',$user);
if ($result < 0) { $error++; }
// End call triggers
if (!$error)
{
$this->statut = 2;
$this->db->commit();
return 1;
}
else
{
$this->db->rollback();
$this->error = join(',', $this->errors);
dol_syslog(get_class($this)."::setClose " . $this->error, LOG_ERR);
return -1;
}
}
else
{
$this->db->rollback();
$this->error = $this->db->lasterror();
return -1;
}
}
}
/**
* Return status label of object
*
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
* @return string Label
*/
function getLibStatut($mode=0)
{
return $this->LibStatut($this->statut, $mode);
}
/**
* Renvoi status label for a status
*
* @param int $statut id statut
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
* @return string Label
*/
function LibStatut($statut, $mode=0)
{
global $langs;
if ($mode == 0)
{
return $langs->trans($this->statuts[$statut]);
}
if ($mode == 1)
{
return $langs->trans($this->statuts_short[$statut]);
}
if ($mode == 2)
{
if ($statut == 0)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0') . ' ' . $langs->trans($this->statuts_short[$statut]);
if ($statut == 1)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4') . ' ' . $langs->trans($this->statuts_short[$statut]);
if ($statut == 2)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6') . ' ' . $langs->trans($this->statuts_short[$statut]);
}
if ($mode == 3)
{
if ($statut == 0)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0');
if ($statut == 1)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4');
if ($statut == 2)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6');
}
if ($mode == 4)
{
if ($statut == 0)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0') . ' ' . $langs->trans($this->statuts_short[$statut]);
if ($statut == 1)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4') . ' ' . $langs->trans($this->statuts_short[$statut]);
if ($statut == 2)
return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6') . ' ' . $langs->trans($this->statuts_short[$statut]);
}
if ($mode == 5)
{
if ($statut == 0)
return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut0');
if ($statut == 1)
return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut4');
if ($statut == 2)
return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut6');
}
}
/**
* Renvoie nom clicable (avec eventuellement le picto)
*
* @param int $withpicto 0=Pas de picto, 1=Inclut le picto dans le lien, 2=Picto seul
* @param string $option Variant ('', 'nolink')
* @param int $addlabel 0=Default, 1=Add label into string, >1=Add first chars into string
* @return string Chaine avec URL
*/
function getNomUrl($withpicto=0, $option='', $addlabel=0)
{
global $langs;
$result = '';
$lien = '';
$lienfin = '';
if ($option != 'nolink')
{
if (preg_match('/\.php$/',$option))
{
$lien = '<a href="' . dol_buildpath($option,1) . '?id=' . $this->id . '">';
$lienfin = '</a>';
}
else
{
$lien = '<a href="' . DOL_URL_ROOT . '/projet/card.php?id=' . $this->id . '">';
$lienfin = '</a>';
}
}
$picto = 'projectpub';
if (!$this->public) $picto = 'project';
$label = $langs->trans("ShowProject") . ': ' . $this->ref . ($this->title ? ' - ' . $this->title : '');
if ($withpicto) $result.=($lien . img_object($label, $picto) . $lienfin);
if ($withpicto && $withpicto != 2) $result.=' ';
if ($withpicto != 2) $result.=$lien . $this->ref . $lienfin . (($addlabel && $this->title) ? ' - ' . dol_trunc($this->title, ($addlabel > 1 ? $addlabel : 0)) : '');
return $result;
}
/**
* Initialise an instance with random values.
* Used to build previews or test instances.
* id must be 0 if object instance is a specimen.
*
* @return void
*/
function initAsSpecimen()
{
global $user, $langs, $conf;
$now=dol_now();
// Initialise parameters
$this->id = 0;
$this->ref = 'SPECIMEN';
$this->specimen = 1;
$this->socid = 1;
$this->date_c = $now;
$this->date_m = $now;
$this->date_start = $now;
$this->note_public = 'SPECIMEN';
/*
$nbp = rand(1, 9);
$xnbp = 0;
while ($xnbp < $nbp)
{
$line = new Task($this->db);
$line->fk_project = 0;
$line->label = $langs->trans("Label") . " " . $xnbp;
$line->description = $langs->trans("Description") . " " . $xnbp;
$this->lines[]=$line;
$xnbp++;
}
*/
}
/**
* Check if user has permission on current project
*
* @param User $user Object user to evaluate
* @param string $mode Type of permission we want to know: 'read', 'write'
* @return int >0 if user has permission, <0 if user has no permission
*/
function restrictedProjectArea($user, $mode='read')
{
// To verify role of users
$userAccess = 0;
if (($mode == 'read' && ! empty($user->rights->projet->all->lire)) || ($mode == 'write' && ! empty($user->rights->projet->all->creer)) || ($mode == 'delete' && ! empty($user->rights->projet->all->supprimer)))
{
$userAccess = 1;
}
else if ($this->public && (($mode == 'read' && ! empty($user->rights->projet->lire)) || ($mode == 'write' && ! empty($user->rights->projet->creer)) || ($mode == 'delete' && ! empty($user->rights->projet->supprimer))))
{
$userAccess = 1;
}
else
{
foreach (array('internal', 'external') as $source)
{
$userRole = $this->liste_contact(4, $source);
$num = count($userRole);
$nblinks = 0;
while ($nblinks < $num)
{
if ($source == 'internal' && preg_match('/^PROJECT/', $userRole[$nblinks]['code']) && $user->id == $userRole[$nblinks]['id'])
{
if ($mode == 'read' && $user->rights->projet->lire) $userAccess++;
if ($mode == 'write' && $user->rights->projet->creer) $userAccess++;
if ($mode == 'delete' && $user->rights->projet->supprimer) $userAccess++;
}
// Permission are supported on users only. To have an external thirdparty contact to see a project, its user must allowed to contacts of projects.
/*if ($source == 'external' && preg_match('/PROJECT/', $userRole[$nblinks]['code']) && $user->contact_id == $userRole[$nblinks]['id'])
{
if ($mode == 'read' && $user->rights->projet->lire) $userAccess++;
if ($mode == 'write' && $user->rights->projet->creer) $userAccess++;
if ($mode == 'delete' && $user->rights->projet->supprimer) $userAccess++;
}*/
$nblinks++;
}
}
//if (empty($nblinks)) // If nobody has permission, we grant creator
//{
// if ((!empty($this->user_author_id) && $this->user_author_id == $user->id))
// {
// $userAccess = 1;
// }
//}
}
return ($userAccess?$userAccess:-1);
}
/**
* Return array of projects a user has permission on, is affected to, or all projects
*
* @param User $user User object
* @param int $mode 0=All project I have permission on, 1=Projects affected to me only, 2=Will return list of all projects with no test on contacts
* @param int $list 0=Return array,1=Return string list
* @param int $socid 0=No filter on third party, id of third party
* @return array or string Array of projects id, or string with projects id separated with ","
*/
function getProjectsAuthorizedForUser($user, $mode=0, $list=0, $socid=0)
{
$projects = array();
$temp = array();
$sql = "SELECT ".(($mode == 0 || $mode == 1) ? "DISTINCT " : "")."p.rowid, p.ref";
$sql.= " FROM " . MAIN_DB_PREFIX . "projet as p";
if ($mode == 0 || $mode == 1)
{
$sql.= ", " . MAIN_DB_PREFIX . "element_contact as ec";
$sql.= ", " . MAIN_DB_PREFIX . "c_type_contact as ctc";
}
$sql.= " WHERE p.entity IN (".getEntity('project',1).")";
// Internal users must see project he is contact to even if project linked to a third party he can't see.
//if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
if ($socid > 0) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = " . $socid . ")";
if ($mode == 0)
{
$sql.= " AND ec.element_id = p.rowid";
$sql.= " AND ( p.public = 1";
//$sql.= " OR p.fk_user_creat = ".$user->id;
$sql.= " OR ( ctc.rowid = ec.fk_c_type_contact";
$sql.= " AND ctc.element = '" . $this->element . "'";
$sql.= " AND ( (ctc.source = 'internal' AND ec.fk_socpeople = ".$user->id.")";
//$sql.= " OR (ctc.source = 'external' AND ec.fk_socpeople = ".($user->contact_id?$user->contact_id:0).")"; // Permission are supported on users only. To have an external thirdparty contact to see a project, its user must allowed to contacts of projects.
$sql.= " )";
$sql.= " ))";
}
if ($mode == 1)
{
$sql.= " AND ec.element_id = p.rowid";
$sql.= " AND ctc.rowid = ec.fk_c_type_contact";
$sql.= " AND ctc.element = '" . $this->element . "'";
$sql.= " AND ( (ctc.source = 'internal' AND ec.fk_socpeople = ".$user->id.")";
//$sql.= " OR (ctc.source = 'external' AND ec.fk_socpeople = ".($user->contact_id?$user->contact_id:0).")"; // Permission are supported on users only. To have an external thirdparty contact to see a project, its user must allowed to contacts of projects.
$sql.= " )";
}
if ($mode == 2)
{
// No filter. Use this if user has permission to see all project
}
//print $sql;
$resql = $this->db->query($sql);
if ($resql)
{
$num = $this->db->num_rows($resql);
$i = 0;
while ($i < $num)
{
$row = $this->db->fetch_row($resql);
$projects[$row[0]] = $row[1];
$temp[] = $row[0];
$i++;
}
$this->db->free($resql);
if ($list)
{
if (empty($temp)) return '0';
$result = implode(',', $temp);
return $result;
}
}
else
{
dol_print_error($this->db);
}
return $projects;
}
/**
* Load an object from its id and create a new one in database
*
* @param int $fromid Id of object to clone
* @param bool $clone_contact clone contact of project
* @param bool $clone_task clone task of project
* @param bool $clone_project_file clone file of project
* @param bool $clone_task_file clone file of task (if task are copied)
* @param bool $clone_note clone note of project
* @param bool $notrigger no trigger flag
* @return int New id of clone
*/
function createFromClone($fromid,$clone_contact=false,$clone_task=true,$clone_project_file=false,$clone_task_file=false,$clone_note=true,$notrigger=0)
{
global $user,$langs,$conf;
$error=0;
dol_syslog("createFromClone clone_contact=".$clone_contact." clone_task=".$clone_task." clone_project_file=".$clone_project_file." clone_note=".$clone_note);
$now = dol_mktime(0,0,0,idate('m',dol_now()),idate('d',dol_now()),idate('Y',dol_now()));
$clone_project=new Project($this->db);
$clone_project->context['createfromclone']='createfromclone';
$this->db->begin();
// Load source object
$clone_project->fetch($fromid);
$clone_project->fetch_thirdparty();
$orign_dt_start=$clone_project->date_start;
$orign_project_ref=$clone_project->ref;
$clone_project->id=0;
$clone_project->date_start = $now;
if (!(empty($clone_project->date_end)))
{
$clone_project->date_end = $clone_project->date_end + ($now - $orign_dt_start);
}
$clone_project->datec = $now;
if (! $clone_note)
{
$clone_project->note_private='';
$clone_project->note_public='';
}
//Generate next ref
$defaultref='';
$obj = empty($conf->global->PROJECT_ADDON)?'mod_project_simple':$conf->global->PROJECT_ADDON;
if (! empty($conf->global->PROJECT_ADDON) && is_readable(DOL_DOCUMENT_ROOT ."/core/modules/project/".$conf->global->PROJECT_ADDON.".php"))
{
require_once DOL_DOCUMENT_ROOT ."/core/modules/project/".$conf->global->PROJECT_ADDON.'.php';
$modProject = new $obj;
$defaultref = $modProject->getNextValue(is_object($clone_project->thirdparty)?$clone_project->thirdparty->id:0,$clone_project);
}
if (is_numeric($defaultref) && $defaultref <= 0) $defaultref='';
$clone_project->ref=$defaultref;
// Create clone
$result=$clone_project->create($user,$notrigger);
// Other options
if ($result < 0)
{
$this->error.=$clone_project->error;
$error++;
}
if (! $error)
{
//Get the new project id
$clone_project_id=$clone_project->id;
//Note Update
if (!$clone_note)
{
$clone_project->note_private='';
$clone_project->note_public='';
}
else
{
$this->db->begin();
$res=$clone_project->update_note(dol_html_entity_decode($clone_project->note_public, ENT_QUOTES),'_public');
if ($res < 0)
{
$this->error.=$clone_project->error;
$error++;
$this->db->rollback();
}
else
{
$this->db->commit();
}
$this->db->begin();
$res=$clone_project->update_note(dol_html_entity_decode($clone_project->note_private, ENT_QUOTES), '_private');
if ($res < 0)
{
$this->error.=$clone_project->error;
$error++;
$this->db->rollback();
}
else
{
$this->db->commit();
}
}
//Duplicate contact
if ($clone_contact)
{
$origin_project = new Project($this->db);
$origin_project->fetch($fromid);
foreach(array('internal','external') as $source)
{
$tab = $origin_project->liste_contact(-1,$source);
foreach ($tab as $contacttoadd)
{
$clone_project->add_contact($contacttoadd['id'], $contacttoadd['code'], $contacttoadd['source'],$notrigger);
if ($clone_project->error == 'DB_ERROR_RECORD_ALREADY_EXISTS')
{
$langs->load("errors");
$this->error.=$langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType");
$error++;
}
else
{
if ($clone_project->error!='')
{
$this->error.=$clone_project->error;
$error++;
}
}
}
}
}
//Duplicate file
if ($clone_project_file)
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$clone_project_dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($defaultref);
$ori_project_dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($orign_project_ref);
if (dol_mkdir($clone_project_dir) >= 0)
{
$filearray=dol_dir_list($ori_project_dir,"files",0,'','(\.meta|_preview\.png)$','',SORT_ASC,1);
foreach($filearray as $key => $file)
{
$rescopy = dol_copy($ori_project_dir . '/' . $file['name'], $clone_project_dir . '/' . $file['name'],0,1);
if (is_numeric($rescopy) && $rescopy < 0)
{
$this->error.=$langs->trans("ErrorFailToCopyFile",$ori_project_dir . '/' . $file['name'],$clone_project_dir . '/' . $file['name']);
$error++;
}
}
}
else
{
$this->error.=$langs->trans('ErrorInternalErrorDetected').':dol_mkdir';
$error++;
}
}
//Duplicate task
if ($clone_task)
{
require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php';
$taskstatic = new Task($this->db);
// Security check
$socid=0;
if ($user->societe_id > 0) $socid = $user->societe_id;
$tasksarray=$taskstatic->getTasksArray(0, 0, $fromid, $socid, 0);
//manage new parent clone task id
$tab_conv_child_parent=array();
foreach ($tasksarray as $tasktoclone)
{
$result_clone = $taskstatic->createFromClone($tasktoclone->id,$clone_project_id,$tasktoclone->fk_parent,true,true,false,$clone_task_file,true,false);
if ($result_clone <= 0)
{
$this->error.=$result_clone->error;
$error++;
}
else
{
$new_task_id=$result_clone;
$taskstatic->fetch($tasktoclone->id);
//manage new parent clone task id
// if the current task has child we store the original task id and the equivalent clone task id
if (($taskstatic->hasChildren()) && !array_key_exists($tasktoclone->id,$tab_conv_child_parent))
{
$tab_conv_child_parent[$tasktoclone->id] = $new_task_id;
}
}
}
//Parse all clone node to be sure to update new parent
$tasksarray=$taskstatic->getTasksArray(0, 0, $clone_project_id, $socid, 0);
foreach ($tasksarray as $task_cloned)
{
$taskstatic->fetch($task_cloned->id);
if ($taskstatic->fk_task_parent!=0)
{
$taskstatic->fk_task_parent=$tab_conv_child_parent[$taskstatic->fk_task_parent];
}
$res=$taskstatic->update($user,$notrigger);
if ($result_clone <= 0)
{
$this->error.=$taskstatic->error;
$error++;
}
}
}
}
unset($clone_project->context['createfromclone']);
if (! $error)
{
$this->db->commit();
return $clone_project_id;
}
else
{
$this->db->rollback();
dol_syslog(get_class($this)."::createFromClone nbError: ".$error." error : " . $this->error, LOG_ERR);
return -1;
}
}
/**
* Shift project task date from current date to delta
*
* @param timestamp $old_project_dt_start old project start date
* @return int 1 if OK or < 0 if KO
*/
function shiftTaskDate($old_project_dt_start)
{
global $user,$langs,$conf;
$error=0;
$taskstatic = new Task($this->db);
// Security check
$socid=0;
if ($user->societe_id > 0) $socid = $user->societe_id;
$tasksarray=$taskstatic->getTasksArray(0, 0, $this->id, $socid, 0);
foreach ($tasksarray as $tasktoshiftdate)
{
$to_update=false;
// Fetch only if update of date will be made
if ((!empty($tasktoshiftdate->date_start)) || (!empty($tasktoshiftdate->date_end)))
{
//dol_syslog(get_class($this)."::shiftTaskDate to_update", LOG_DEBUG);
$to_update=true;
$task = new Task($this->db);
$result = $task->fetch($tasktoshiftdate->id);
if (!$result)
{
$error++;
$this->error.=$task->error;
}
}
//print "$this->date_start + $tasktoshiftdate->date_start - $old_project_dt_start";exit;
//Calcultate new task start date with difference between old proj start date and origin task start date
if (!empty($tasktoshiftdate->date_start))
{
$task->date_start = $this->date_start + ($tasktoshiftdate->date_start - $old_project_dt_start);
}
//Calcultate new task end date with difference between origin proj end date and origin task end date
if (!empty($tasktoshiftdate->date_end))
{
$task->date_end = $this->date_start + ($tasktoshiftdate->date_end - $old_project_dt_start);
}
if ($to_update)
{
$result = $task->update($user);
if (!$result)
{
$error++;
$this->error.=$task->error;
}
}
}
if ($error!=0)
{
return -1;
}
return $result;
}
/**
* Associate element to a project
*
* @param string $tableName Table of the element to update
* @param int $elementSelectId Key-rowid of the line of the element to update
* @return int 1 if OK or < 0 if KO
*/
function update_element($tableName, $elementSelectId)
{
$sql="UPDATE ".MAIN_DB_PREFIX.$tableName;
if ($TableName=="actioncomm")
{
$sql.= " SET fk_project=".$this->id;
$sql.= " WHERE id=".$elementSelectId;
}
else
{
$sql.= " SET fk_projet=".$this->id;
$sql.= " WHERE rowid=".$elementSelectId;
}
dol_syslog(get_class($this)."::update_element", LOG_DEBUG);
$resql=$this->db->query($sql);
if (!$resql) {
$this->error=$this->db->lasterror();
return -1;
}else {
return 1;
}
}
/**
* Associate element to a project
*
* @param string $tableName Table of the element to update
* @param int $elementSelectId Key-rowid of the line of the element to update
* @return int 1 if OK or < 0 if KO
*/
function remove_element($tableName, $elementSelectId)
{
$sql="UPDATE ".MAIN_DB_PREFIX.$tableName;
if ($TableName=="actioncomm")
{
$sql.= " SET fk_project=NULL";
$sql.= " WHERE id=".$elementSelectId;
}
else
{
$sql.= " SET fk_projet=NULL";
$sql.= " WHERE rowid=".$elementSelectId;
}
dol_syslog(get_class($this)."::remove_element", LOG_DEBUG);
$resql=$this->db->query($sql);
if (!$resql) {
$this->error=$this->db->lasterror();
return -1;
}else {
return 1;
}
}
/**
* Create an intervention document on disk using template defined into PROJECT_ADDON_PDF
*
* @param string $modele force le modele a utiliser ('' par defaut)
* @param Translate $outputlangs objet lang a utiliser pour traduction
* @param int $hidedetails Hide details of lines
* @param int $hidedesc Hide description
* @param int $hideref Hide ref
* @return int 0 if KO, 1 if OK
*/
public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
{
global $conf,$langs;
$langs->load("projects");
// Positionne modele sur le nom du modele de projet a utiliser
if (! dol_strlen($modele))
{
if (! empty($conf->global->PROJECT_ADDON_PDF))
{
$modele = $conf->global->PROJECT_ADDON_PDF;
}
else
{
$modele='baleine';
}
}
$modelpath = "core/modules/project/doc/";
return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
}
}