html.formprojet.class.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. <?php
  2. /* Copyright (c) 2013 Florian Henry <florian.henry@open-concept.pro>
  3. * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
  4. * Copyright (C) 2018 Charlene Benke <charlie@patas-monkey.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * \file htdocs/core/class/html.formprojet.class.php
  21. * \ingroup core
  22. * \brief Class file for html component project
  23. */
  24. /**
  25. * Class to manage building of HTML components
  26. */
  27. class FormProjets
  28. {
  29. /**
  30. * @var DoliDB Database handler.
  31. */
  32. public $db;
  33. /**
  34. * @var string Error code (or message)
  35. */
  36. public $error = '';
  37. public $errors = array();
  38. public $nboftasks;
  39. /**
  40. * Constructor
  41. *
  42. * @param DoliDB $db Database handler
  43. */
  44. public function __construct($db)
  45. {
  46. $this->db = $db;
  47. }
  48. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  49. /**
  50. * Output a combo list with projects qualified for a third party / user
  51. *
  52. * @param int $socid Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id)
  53. * @param string|Project $selected Id of preselected project or Project (or ''). Note: If you know the ref, you can also provide it into $selected_input_value to save one request in some cases.
  54. * @param string $htmlname Name of HTML field
  55. * @param int $maxlength Maximum length of label
  56. * @param int $option_only Return only html options lines without the select tag
  57. * @param int $show_empty Add an empty line
  58. * @param int $discard_closed Discard closed projects (0=Keep, 1=hide completely, 2=Disable). Use a negative value to not show the "discarded" tooltip.
  59. * @param int $forcefocus Force focus on field (works with javascript only)
  60. * @param int $disabled Disabled
  61. * @param int $mode 0 for HTML mode and 1 for JSON mode
  62. * @param string $filterkey Key to filter on ref or title
  63. * @param int $nooutput No print output. Return it only.
  64. * @param int $forceaddid Force to add project id in list, event if not qualified
  65. * @param string $morecss More css
  66. * @param int $htmlid Html id to use instead of htmlname
  67. * @param string $morefilter More filters (Must be a sql sanitized string)
  68. * @return string Return html content
  69. */
  70. public function select_projects($socid = -1, $selected = '', $htmlname = 'projectid', $maxlength = 16, $option_only = 0, $show_empty = 1, $discard_closed = 0, $forcefocus = 0, $disabled = 0, $mode = 0, $filterkey = '', $nooutput = 0, $forceaddid = 0, $morecss = '', $htmlid = '', $morefilter = '')
  71. {
  72. // phpcs:enable
  73. global $langs, $conf, $form;
  74. $selected_input_value = '';
  75. if (is_object($selected)) {
  76. $selected_input_value = $selected->ref;
  77. $selected = $selected->id;
  78. }
  79. $out = '';
  80. if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PROJECT_USE_SEARCH_TO_SELECT)) {
  81. $placeholder = '';
  82. if ($selected && empty($selected_input_value)) {
  83. require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  84. $project = new Project($this->db);
  85. $project->fetch($selected);
  86. $selected_input_value = $project->ref;
  87. }
  88. $urloption = 'socid='.((int) $socid).'&htmlname='.urlencode($htmlname).'&discardclosed='.((int) $discard_closed);
  89. if ($morefilter == 'usage_organize_event=1') {
  90. $urloption .= '&usage_organize_event=1';
  91. }
  92. $out .= '<input type="text" class="minwidth200'.($morecss ? ' '.$morecss : '').'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' />';
  93. $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/projet/ajax/projects.php', $urloption, $conf->global->PROJECT_USE_SEARCH_TO_SELECT, 0, array());
  94. } else {
  95. $out .= $this->select_projects_list($socid, $selected, $htmlname, $maxlength, $option_only, $show_empty, abs($discard_closed), $forcefocus, $disabled, 0, $filterkey, 1, $forceaddid, $htmlid, $morecss, $morefilter);
  96. }
  97. if ($discard_closed > 0) {
  98. if (!empty($form)) {
  99. $out .= $form->textwithpicto('', $langs->trans("ClosedProjectsAreHidden"));
  100. }
  101. }
  102. if (empty($nooutput)) {
  103. print $out;
  104. return '';
  105. } else {
  106. return $out;
  107. }
  108. }
  109. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  110. /**
  111. * Returns an array with projects qualified for a third party
  112. *
  113. * @param int $socid Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id)
  114. * @param int $selected Id project preselected
  115. * @param string $htmlname Nom de la zone html
  116. * @param int $maxlength Maximum length of label
  117. * @param int $option_only Return only html options lines without the select tag
  118. * @param int $show_empty Add an empty line
  119. * @param int $discard_closed Discard closed projects (0=Keep,1=hide completely,2=Disable)
  120. * @param int $forcefocus Force focus on field (works with javascript only)
  121. * @param int $disabled Disabled
  122. * @param int $mode 0 for HTML mode and 1 for array return (to be used by json_encode for example)
  123. * @param string $filterkey Key to filter on title or ref
  124. * @param int $nooutput No print output. Return it only.
  125. * @param int $forceaddid Force to add project id in list, event if not qualified
  126. * @param int $htmlid Html id to use instead of htmlname
  127. * @param string $morecss More CSS
  128. * @param string $morefilter More filters (Must be a sql sanitized string)
  129. * @return int Nb of project if OK, <0 if KO
  130. */
  131. public function select_projects_list($socid = -1, $selected = '', $htmlname = 'projectid', $maxlength = 24, $option_only = 0, $show_empty = 1, $discard_closed = 0, $forcefocus = 0, $disabled = 0, $mode = 0, $filterkey = '', $nooutput = 0, $forceaddid = 0, $htmlid = '', $morecss = 'maxwidth500', $morefilter = '')
  132. {
  133. // phpcs:enable
  134. global $user, $conf, $langs;
  135. require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  136. if (empty($htmlid)) {
  137. $htmlid = $htmlname;
  138. }
  139. $out = '';
  140. $outarray = array();
  141. $hideunselectables = false;
  142. if (!empty($conf->global->PROJECT_HIDE_UNSELECTABLES)) {
  143. $hideunselectables = true;
  144. }
  145. $projectsListId = false;
  146. if (empty($user->rights->projet->all->lire)) {
  147. $projectstatic = new Project($this->db);
  148. $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
  149. }
  150. // Search all projects
  151. $sql = "SELECT p.rowid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, s.nom as name, s.name_alias";
  152. $sql .= " FROM ".$this->db->prefix()."projet as p LEFT JOIN ".$this->db->prefix()."societe as s ON s.rowid = p.fk_soc";
  153. $sql .= " WHERE p.entity IN (".getEntity('project').")";
  154. if ($projectsListId !== false) {
  155. $sql .= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
  156. }
  157. if ($socid == 0) {
  158. $sql .= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
  159. }
  160. if ($socid > 0) {
  161. if (empty($conf->global->PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY)) {
  162. $sql .= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
  163. } elseif ($conf->global->PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY != 'all') { // PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY is 'all' or a list of ids separated by coma.
  164. $sql .= " AND (p.fk_soc IN (".$this->db->sanitize(((int) $socid).", ".$conf->global->PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY).") OR p.fk_soc IS NULL)";
  165. }
  166. }
  167. if (!empty($filterkey)) {
  168. $sql .= natural_search(array('p.title', 'p.ref'), $filterkey);
  169. }
  170. if ($morefilter) {
  171. $sql .= ' AND ('.$this->db->sanitize($morefilter, 0, 1).')';
  172. }
  173. $sql .= " ORDER BY p.ref ASC";
  174. $resql = $this->db->query($sql);
  175. if ($resql) {
  176. if (!empty($conf->use_javascript_ajax)) {
  177. $morecss .= ' minwidth100';
  178. }
  179. if (empty($option_only)) {
  180. $out .= '<select class="flat'.($morecss ? ' '.$morecss : '').'"'.($disabled ? ' disabled="disabled"' : '').' id="'.$htmlid.'" name="'.$htmlname.'">';
  181. }
  182. if (!empty($show_empty)) {
  183. $out .= '<option value="0">&nbsp;</option>';
  184. }
  185. $num = $this->db->num_rows($resql);
  186. $i = 0;
  187. if ($num) {
  188. while ($i < $num) {
  189. $obj = $this->db->fetch_object($resql);
  190. // If we ask to filter on a company and user has no permission to see all companies and project is linked to another company, we hide project.
  191. if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$user->hasRight('societe', 'lire')) {
  192. // Do nothing
  193. } else {
  194. if ($discard_closed == 1 && $obj->fk_statut == 2 && $obj->rowid != $selected) { // We discard closed except if selected
  195. $i++;
  196. continue;
  197. }
  198. $labeltoshow = dol_trunc($obj->ref, 18);
  199. //if ($obj->public) $labeltoshow.=' ('.$langs->trans("SharedProject").')';
  200. //else $labeltoshow.=' ('.$langs->trans("Private").')';
  201. $labeltoshow .= ', '.dol_trunc($obj->title, $maxlength);
  202. if ($obj->name) {
  203. $labeltoshow .= ' - '.$obj->name;
  204. if ($obj->name_alias) {
  205. $labeltoshow .= ' ('.$obj->name_alias.')';
  206. }
  207. }
  208. $disabled = 0;
  209. if ($obj->fk_statut == 0) {
  210. $disabled = 1;
  211. $labeltoshow .= ' - '.$langs->trans("Draft");
  212. } elseif ($obj->fk_statut == 2) {
  213. if ($discard_closed == 2) {
  214. $disabled = 1;
  215. }
  216. $labeltoshow .= ' - '.$langs->trans("Closed");
  217. } elseif (empty($conf->global->PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY) && $socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
  218. $disabled = 1;
  219. $labeltoshow .= ' - '.$langs->trans("LinkedToAnotherCompany");
  220. }
  221. if (!empty($selected) && $selected == $obj->rowid) {
  222. $out .= '<option value="'.$obj->rowid.'" selected';
  223. //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
  224. $out .= '>'.$labeltoshow.'</option>';
  225. } else {
  226. if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
  227. $resultat = '';
  228. } else {
  229. $resultat = '<option value="'.$obj->rowid.'"';
  230. if ($disabled) {
  231. $resultat .= ' disabled';
  232. }
  233. //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
  234. //else $labeltoshow.=' ('.$langs->trans("Private").')';
  235. $resultat .= '>';
  236. $resultat .= $labeltoshow;
  237. $resultat .= '</option>';
  238. }
  239. $out .= $resultat;
  240. $outarray[] = array(
  241. 'key' => (int) $obj->rowid,
  242. 'value' => $obj->ref,
  243. 'ref' => $obj->ref,
  244. 'labelx' => $labeltoshow,
  245. 'label' => ((bool) $disabled) ? '<span class="opacitymedium">'.$labeltoshow.'</span>' : $labeltoshow,
  246. 'disabled' => (bool) $disabled
  247. );
  248. }
  249. }
  250. $i++;
  251. }
  252. }
  253. $this->db->free($resql);
  254. if (!$mode) {
  255. if (empty($option_only)) {
  256. $out .= '</select>';
  257. }
  258. // Use select2 selector
  259. if (!empty($conf->use_javascript_ajax)) {
  260. include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
  261. $comboenhancement = ajax_combobox($htmlid, array(), 0, $forcefocus);
  262. $out .= $comboenhancement;
  263. $morecss .= ' minwidth100';
  264. }
  265. if (empty($nooutput)) {
  266. print $out;
  267. return '';
  268. } else {
  269. return $out;
  270. }
  271. } else {
  272. return $outarray;
  273. }
  274. } else {
  275. dol_print_error($this->db);
  276. return -1;
  277. }
  278. }
  279. /**
  280. * Output a combo list with tasks qualified for a third party
  281. *
  282. * @param int $socid Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id)
  283. * @param int $selected Id task preselected
  284. * @param string $htmlname Name of HTML select
  285. * @param int $maxlength Maximum length of label
  286. * @param int $option_only Return only html options lines without the select tag
  287. * @param string $show_empty Add an empty line ('1' or string to show for empty line)
  288. * @param int $discard_closed Discard closed projects (0=Keep, 1=hide completely, 2=Disable)
  289. * @param int $forcefocus Force focus on field (works with javascript only)
  290. * @param int $disabled Disabled
  291. * @param string $morecss More css added to the select component
  292. * @param string $projectsListId ''=Automatic filter on project allowed. List of id=Filter on project ids.
  293. * @param string $showmore 'all' = Show project info, 'progress' = Show task progression, ''=Show nothing more
  294. * @param User $usertofilter User object to use for filtering
  295. * @return int Nbr of tasks if OK, <0 if KO
  296. */
  297. public function selectTasks($socid = -1, $selected = '', $htmlname = 'taskid', $maxlength = 24, $option_only = 0, $show_empty = '1', $discard_closed = 0, $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500', $projectsListId = '', $showmore = 'all', $usertofilter = null)
  298. {
  299. global $user, $conf, $langs;
  300. require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  301. if (is_null($usertofilter)) {
  302. $usertofilter = $user;
  303. }
  304. $out = '';
  305. $hideunselectables = false;
  306. if (!empty($conf->global->PROJECT_HIDE_UNSELECTABLES)) {
  307. $hideunselectables = true;
  308. }
  309. if (empty($projectsListId)) {
  310. if (empty($usertofilter->rights->projet->all->lire)) {
  311. $projectstatic = new Project($this->db);
  312. $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
  313. }
  314. }
  315. // Search all projects
  316. $sql = "SELECT t.rowid, t.ref as tref, t.label as tlabel, t.progress,";
  317. $sql .= " p.rowid as pid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, p.usage_task,";
  318. $sql .= " s.nom as name";
  319. $sql .= " FROM ".$this->db->prefix()."projet as p";
  320. $sql .= " LEFT JOIN ".$this->db->prefix()."societe as s ON s.rowid = p.fk_soc,";
  321. $sql .= " ".$this->db->prefix()."projet_task as t";
  322. $sql .= " WHERE p.entity IN (".getEntity('project').")";
  323. $sql .= " AND t.fk_projet = p.rowid";
  324. if ($projectsListId) {
  325. $sql .= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
  326. }
  327. if ($socid == 0) {
  328. $sql .= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
  329. }
  330. if ($socid > 0) {
  331. $sql .= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
  332. }
  333. $sql .= " ORDER BY p.ref, t.ref ASC";
  334. $resql = $this->db->query($sql);
  335. if ($resql) {
  336. // Use select2 selector
  337. if (empty($option_only) && !empty($conf->use_javascript_ajax)) {
  338. include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
  339. $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
  340. $out .= $comboenhancement;
  341. $morecss .= ' minwidth200 maxwidth500';
  342. }
  343. if (empty($option_only)) {
  344. $out .= '<select class="valignmiddle flat'.($morecss ? ' '.$morecss : '').'"'.($disabled ? ' disabled="disabled"' : '').' id="'.$htmlname.'" name="'.$htmlname.'">';
  345. }
  346. if (!empty($show_empty)) {
  347. $out .= '<option value="0" class="optiongrey">';
  348. if (!is_numeric($show_empty)) {
  349. //if (!empty($conf->use_javascript_ajax)) $out .= '<span class="opacitymedium">aaa';
  350. $out .= $show_empty;
  351. //if (!empty($conf->use_javascript_ajax)) $out .= '</span>';
  352. } else {
  353. $out .= '&nbsp;';
  354. }
  355. $out .= '</option>';
  356. }
  357. $num = $this->db->num_rows($resql);
  358. $i = 0;
  359. if ($num) {
  360. while ($i < $num) {
  361. $obj = $this->db->fetch_object($resql);
  362. // If we ask to filter on a company and user has no permission to see all companies and project is linked to another company, we hide project.
  363. if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && empty($usertofilter->rights->societe->lire)) {
  364. // Do nothing
  365. } else {
  366. if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
  367. $i++;
  368. continue;
  369. }
  370. $labeltoshow = '';
  371. $titletoshow = '';
  372. $disabled = 0;
  373. if ($obj->fk_statut == Project::STATUS_DRAFT) {
  374. $disabled = 1;
  375. } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
  376. if ($discard_closed == 2) {
  377. $disabled = 1;
  378. }
  379. } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
  380. $disabled = 1;
  381. }
  382. if (preg_match('/all/', $showmore)) {
  383. $labeltoshow .= dol_trunc($obj->ref, 18); // Project ref
  384. //if ($obj->public) $labeltoshow.=' ('.$langs->trans("SharedProject").')';
  385. //else $labeltoshow.=' ('.$langs->trans("Private").')';
  386. $labeltoshow .= ' '.dol_trunc($obj->title, $maxlength);
  387. $titletoshow = $labeltoshow;
  388. if ($obj->name) {
  389. $labeltoshow .= ' ('.$obj->name.')';
  390. $titletoshow .= ' <span class="opacitymedium">('.$obj->name.')</span>';
  391. }
  392. $disabled = 0;
  393. if ($obj->fk_statut == Project::STATUS_DRAFT) {
  394. $disabled = 1;
  395. $labeltoshow .= ' - '.$langs->trans("Draft");
  396. $titletoshow .= ' - <span class="opacitymedium">'.$langs->trans("Draft").'</span>';
  397. } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
  398. if ($discard_closed == 2) {
  399. $disabled = 1;
  400. }
  401. $labeltoshow .= ' - '.$langs->trans("Closed");
  402. $titletoshow .= ' - <span class="opacitymedium">'.$langs->trans("Closed").'</span>';
  403. } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
  404. $disabled = 1;
  405. $labeltoshow .= ' - '.$langs->trans("LinkedToAnotherCompany");
  406. $titletoshow .= ' - <span class="opacitymedium">'.$langs->trans("LinkedToAnotherCompany").'</span>';
  407. }
  408. $labeltoshow .= ' - ';
  409. $titletoshow .= ' - ';
  410. }
  411. // Label for task
  412. $labeltoshow .= $obj->tref.' '.dol_trunc($obj->tlabel, $maxlength);
  413. $titletoshow .= $obj->tref.' '.dol_trunc($obj->tlabel, $maxlength);
  414. if ($obj->usage_task && preg_match('/progress/', $showmore)) {
  415. $labeltoshow .= ' <span class="opacitymedium">('.$obj->progress.'%)</span>';
  416. $titletoshow .= ' <span class="opacitymedium">('.$obj->progress.'%)</span>';
  417. }
  418. if (!empty($selected) && $selected == $obj->rowid) {
  419. $out .= '<option value="'.$obj->rowid.'" selected';
  420. $out .= ' data-html="'.dol_escape_htmltag($titletoshow).'"';
  421. //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
  422. $out .= '>'.$labeltoshow.'</option>';
  423. } else {
  424. if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
  425. $resultat = '';
  426. } else {
  427. $resultat = '<option value="'.$obj->rowid.'"';
  428. if ($disabled) {
  429. $resultat .= ' disabled';
  430. }
  431. //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
  432. //else $labeltoshow.=' ('.$langs->trans("Private").')';
  433. $resultat .= ' data-html="'.dol_escape_htmltag($titletoshow).'"';
  434. $resultat .= '>';
  435. $resultat .= $labeltoshow;
  436. $resultat .= '</option>';
  437. }
  438. $out .= $resultat;
  439. }
  440. }
  441. $i++;
  442. }
  443. }
  444. if (empty($option_only)) {
  445. $out .= '</select>';
  446. }
  447. $this->nboftasks = $num;
  448. print $out;
  449. $this->db->free($resql);
  450. return $num;
  451. } else {
  452. dol_print_error($this->db);
  453. return -1;
  454. }
  455. }
  456. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  457. /**
  458. * Build a HTML select list of element of same thirdparty to suggest to link them to project
  459. *
  460. * @param string $table_element Table of the element to update
  461. * @param string $socid If of thirdparty to use as filter or 'id1,id2,...'
  462. * @param string $morecss More CSS
  463. * @param int $limitonstatus Add filters to limit length of list to opened status (for example to avoid ERR_RESPONSE_HEADERS_TOO_BIG on project/element.php page). TODO To implement
  464. * @param string $projectkey Equivalent key to fk_projet for actual table_element
  465. * @param string $placeholder Placeholder
  466. * @return int|string The HTML select list of element or '' if nothing or -1 if KO
  467. */
  468. public function select_element($table_element, $socid = 0, $morecss = '', $limitonstatus = -2, $projectkey = "fk_projet", $placeholder = '')
  469. {
  470. // phpcs:enable
  471. global $conf, $langs;
  472. if ($table_element == 'projet_task') {
  473. return ''; // Special cas of element we never link to a project (already always done)
  474. }
  475. $linkedtothirdparty = false;
  476. if (!in_array($table_element, array(
  477. 'don',
  478. 'expensereport_det',
  479. 'expensereport', 'loan',
  480. 'stock_mouvement',
  481. 'payment_salary',
  482. 'payment_various',
  483. 'salary',
  484. 'chargesociales',
  485. 'entrepot')
  486. )) {
  487. $linkedtothirdparty = true;
  488. }
  489. $sqlfilter = '';
  490. //print $table_element;
  491. switch ($table_element) {
  492. case "loan":
  493. $sql = "SELECT t.rowid, t.label as ref";
  494. break;
  495. case "facture":
  496. $sql = "SELECT t.rowid, t.ref as ref";
  497. break;
  498. case "facture_fourn":
  499. $sql = "SELECT t.rowid, t.ref, t.ref_supplier";
  500. break;
  501. case "commande_fourn":
  502. case "commande_fournisseur":
  503. $sql = "SELECT t.rowid, t.ref, t.ref_supplier";
  504. break;
  505. case "facture_rec":
  506. $sql = "SELECT t.rowid, t.titre as ref";
  507. break;
  508. case "actioncomm":
  509. $sql = "SELECT t.id as rowid, t.label as ref";
  510. $projectkey = "fk_project";
  511. break;
  512. case "expensereport":
  513. return '';
  514. case "expensereport_det":
  515. /*$sql = "SELECT rowid, '' as ref"; // table is llx_expensereport_det
  516. $projectkey="fk_projet";
  517. break;*/
  518. return '';
  519. case "commande":
  520. case "contrat":
  521. case "fichinter":
  522. $sql = "SELECT t.rowid, t.ref";
  523. break;
  524. case 'stock_mouvement':
  525. $sql = "SELECT t.rowid, t.label as ref";
  526. $projectkey = 'fk_origin';
  527. break;
  528. case "payment_salary":
  529. $sql = "SELECT t.rowid, t.num_payment as ref"; // TODO In a future fill and use real ref field
  530. break;
  531. case "payment_various":
  532. $sql = "SELECT t.rowid, t.num_payment as ref";
  533. break;
  534. case "chargesociales":
  535. default:
  536. $sql = "SELECT t.rowid, t.ref";
  537. break;
  538. }
  539. if ($linkedtothirdparty) {
  540. $sql .= ", s.nom as name";
  541. }
  542. $sql .= " FROM ".$this->db->prefix().$table_element." as t";
  543. if ($linkedtothirdparty) {
  544. $sql .= ", ".$this->db->prefix()."societe as s";
  545. }
  546. $sql .= " WHERE ".$projectkey." is null";
  547. if (!empty($socid) && $linkedtothirdparty) {
  548. if (is_numeric($socid)) {
  549. $sql .= " AND t.fk_soc = ".((int) $socid);
  550. } else {
  551. $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socid).")";
  552. }
  553. }
  554. if (!in_array($table_element, array('expensereport_det', 'stock_mouvement'))) {
  555. $sql .= ' AND t.entity IN ('.getEntity('project').')';
  556. }
  557. if ($linkedtothirdparty) {
  558. $sql .= " AND s.rowid = t.fk_soc";
  559. }
  560. if ($sqlfilter) {
  561. $sql .= " AND ".$sqlfilter;
  562. }
  563. $sql .= " ORDER BY ref DESC";
  564. dol_syslog(get_class($this).'::select_element', LOG_DEBUG);
  565. $resql = $this->db->query($sql);
  566. if ($resql) {
  567. $num = $this->db->num_rows($resql);
  568. $i = 0;
  569. $sellist = '';
  570. if ($num > 0) {
  571. $sellist = '<select class="flat elementselect css'.$table_element.($morecss ? ' '.$morecss : '').'" name="elementselect">';
  572. $sellist .= '<option value="-1"'.($placeholder ? ' class="optiongrey"' : '').'>'.$placeholder.'</option>';
  573. while ($i < $num) {
  574. $obj = $this->db->fetch_object($resql);
  575. $ref = $obj->ref ? $obj->ref : $obj->rowid;
  576. if (!empty($obj->ref_supplier)) {
  577. $ref .= ' ('.$obj->ref_supplier.')';
  578. }
  579. if (!empty($obj->name)) {
  580. $ref .= ' - '.$obj->name;
  581. }
  582. $sellist .= '<option value="'.$obj->rowid.'">'.$ref.'</option>';
  583. $i++;
  584. }
  585. $sellist .= '</select>';
  586. }
  587. /*else
  588. {
  589. $sellist = '<select class="flat" name="elementselect">';
  590. $sellist.= '<option value="0" disabled>'.$langs->trans("None").'</option>';
  591. $sellist.= '</select>';
  592. }*/
  593. $this->db->free($resql);
  594. return $sellist;
  595. } else {
  596. dol_print_error($this->db);
  597. $this->error = $this->db->lasterror();
  598. $this->errors[] = $this->db->lasterror();
  599. dol_syslog(get_class($this)."::select_element ".$this->error, LOG_ERR);
  600. return -1;
  601. }
  602. }
  603. /**
  604. * Build a HTML select list of element of same thirdparty to suggest to link them to project
  605. *
  606. * @param string $htmlname HTML name
  607. * @param string $preselected Preselected (int or 'all' or 'none')
  608. * @param int $showempty Add an empty line
  609. * @param int $useshortlabel Use short label
  610. * @param int $showallnone Add choice "All" and "None"
  611. * @param int $showpercent Show default probability for status
  612. * @param string $morecss Add more css
  613. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  614. * @param int $addcombojs 1=Add a js combo
  615. * @return int|string The HTML select list of element or '' if nothing or -1 if KO
  616. */
  617. public function selectOpportunityStatus($htmlname, $preselected = '-1', $showempty = 1, $useshortlabel = 0, $showallnone = 0, $showpercent = 0, $morecss = '', $noadmininfo = 0, $addcombojs = 0)
  618. {
  619. global $conf, $langs, $user;
  620. $sql = "SELECT rowid, code, label, percent";
  621. $sql .= " FROM ".$this->db->prefix().'c_lead_status';
  622. $sql .= " WHERE active = 1";
  623. $sql .= " ORDER BY position";
  624. $resql = $this->db->query($sql);
  625. if ($resql) {
  626. $num = $this->db->num_rows($resql);
  627. $i = 0;
  628. if ($num > 0) {
  629. $sellist = '<select class="flat oppstatus'.($morecss ? ' '.$morecss : '').'" id="'.$htmlname.'" name="'.$htmlname.'">';
  630. if ($showempty) {
  631. // Without &nbsp, strange move of screen when switching value
  632. $sellist .= '<option value="-1">&nbsp;</option>';
  633. }
  634. if ($showallnone) {
  635. $sellist .= '<option value="all"'.($preselected == 'all' ? ' selected="selected"' : '').'>-- '.$langs->trans("OnlyOpportunitiesShort").'</option>';
  636. $sellist .= '<option value="openedopp"'.($preselected == 'openedopp' ? ' selected="selected"' : '').'>-- '.$langs->trans("OpenedOpportunitiesShort").'</option>';
  637. $sellist .= '<option value="notopenedopp"'.($preselected == 'notopenedopp' ? ' selected="selected"' : '').'>-- '.$langs->trans("NotOpenedOpportunitiesShort").'</option>';
  638. $sellist .= '<option value="none"'.($preselected == 'none' ? ' selected="selected"' : '').'>-- '.$langs->trans("NotAnOpportunityShort").'</option>';
  639. }
  640. while ($i < $num) {
  641. $obj = $this->db->fetch_object($resql);
  642. $sellist .= '<option value="'.$obj->rowid.'" defaultpercent="'.$obj->percent.'" elemcode="'.$obj->code.'"';
  643. if ($obj->rowid == $preselected) {
  644. $sellist .= ' selected="selected"';
  645. }
  646. $sellist .= '>';
  647. if ($useshortlabel) {
  648. $finallabel = ($langs->transnoentitiesnoconv("OppStatus".$obj->code) != "OppStatus".$obj->code ? $langs->transnoentitiesnoconv("OppStatus".$obj->code) : $obj->label);
  649. } else {
  650. $finallabel = ($langs->transnoentitiesnoconv("OppStatus".$obj->code) != "OppStatus".$obj->code ? $langs->transnoentitiesnoconv("OppStatus".$obj->code) : $obj->label);
  651. if ($showpercent) {
  652. $finallabel .= ' ('.$obj->percent.'%)';
  653. }
  654. }
  655. $sellist .= $finallabel;
  656. $sellist .= '</option>';
  657. $i++;
  658. }
  659. $sellist .= '</select>';
  660. if ($user->admin && !$noadmininfo) {
  661. $sellist .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  662. }
  663. if ($addcombojs) {
  664. $sellist .= ajax_combobox($htmlname);
  665. }
  666. }
  667. /*else
  668. {
  669. $sellist = '<select class="flat" name="elementselect">';
  670. $sellist.= '<option value="0" disabled>'.$langs->trans("None").'</option>';
  671. $sellist.= '</select>';
  672. }*/
  673. $this->db->free($resql);
  674. return $sellist;
  675. } else {
  676. $this->error = $this->db->lasterror();
  677. $this->errors[] = $this->db->lasterror();
  678. dol_syslog(get_class($this)."::selectOpportunityStatus ".$this->error, LOG_ERR);
  679. return -1;
  680. }
  681. }
  682. }