Passed
Push — EXTRACT_CLASSES ( 0382f2...c25e41 )
by Rafael
52:18
created

FormProjets::selectOpportunityStatus()   F

Complexity

Conditions 19
Paths 274

Size

Total Lines 70
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 46
nc 274
nop 9
dl 0
loc 70
rs 2.7583
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (c) 2013       Florian Henry               <[email protected]>
4
 * Copyright (C) 2015       Marcos García               <[email protected]>
5
 * Copyright (C) 2018       Charlene Benke              <[email protected]>
6
 * Copyright (C) 2024		Frédéric France				<[email protected]>
7
 * Copyright (C) 2024		MDW							<[email protected]>
8
 * Copyright (C) 2024		Benjamin Falière			<[email protected]>
9
 * Copyright (C) 2024       Rafael San José             <[email protected]>
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23
 */
24
25
namespace Dolibarr\Code\Core\Classes;
26
27
use DoliDB;
28
29
/**
30
 *      \file       htdocs/core/class/html.formprojet.class.php
31
 *      \ingroup    core
32
 *      \brief      Class file for html component project
33
 */
34
35
require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/html.form.class.php';
36
37
/**
38
 *      Class to manage building of HTML components
39
 */
40
class FormProjets extends Form
41
{
42
    /**
43
     * @var DoliDB Database handler.
44
     */
45
    public $db;
46
47
    /**
48
     * @var string Error code (or message)
49
     */
50
    public $error = '';
51
52
    public $errors = array();
53
54
55
    public $nboftasks;
56
57
58
    /**
59
     *    Constructor
60
     *
61
     * @param DoliDB $db Database handler
62
     */
63
    public function __construct($db)
64
    {
65
        $this->db = $db;
66
    }
67
68
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
69
70
    /**
71
     * Output a combo list with projects qualified for a third party / user
72
     *
73
     * @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)
74
     * @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.
75
     * @param string    $htmlname       Name of HTML field
76
     * @param int       $maxlength      Maximum length of label
77
     * @param int       $option_only    Return only html options lines without the select tag
78
     * @param int|string    $show_empty     Add an empty line
79
     * @param int       $discard_closed Discard closed projects (0=Keep, 1=hide completely, 2=Disable). Use a negative value to not show the "discarded" tooltip.
80
     * @param int       $forcefocus     Force focus on field (works with javascript only)
81
     * @param int       $disabled       Disabled
82
     * @param int       $mode           0 for HTML mode and 1 for JSON mode
83
     * @param string    $filterkey      Key to filter on ref or title
84
     * @param int       $nooutput       No print output. Return it only.
85
     * @param int       $forceaddid     Force to add project id in list, event if not qualified
86
     * @param string    $morecss        More css
87
     * @param string    $htmlid         Html id to use instead of htmlname, by example id="htmlid"
88
     * @param string    $morefilter     More filters (Must be a sql sanitized string)
89
     * @return string                   Return html content
90
     */
91
    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 = '')
92
    {
93
		// phpcs:enable
94
        global $langs, $conf, $form;
95
96
        $selected_input_value = '';
97
        if (is_object($selected)) {
98
            $selected_input_value = $selected->ref;
99
            $selected = $selected->id;
100
        }
101
102
        $out = '';
103
104
        if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
105
            $placeholder = '';
106
107
            if ($selected && empty($selected_input_value)) {
108
                require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/project.class.php';
109
                $project = new Project($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Core\Classes\Project was not found. Did you mean Project? If so, make sure to prefix the type with \.
Loading history...
110
                $project->fetch($selected);
111
                $selected_input_value = $project->ref;
112
            }
113
            $urloption = 'socid=' . ((int) $socid) . '&htmlname=' . urlencode($htmlname) . '&discardclosed=' . ((int) $discard_closed);
114
            if ($morefilter == 'usage_organize_event=1') {
115
                $urloption .= '&usage_organize_event=1';
116
            }
117
            $out .= '<input type="text" class="minwidth200' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' />';
118
119
            $out .= ajax_autocompleter($selected, $htmlname, constant('BASE_URL') . '/projet/ajax/projects.php', $urloption, $conf->global->PROJECT_USE_SEARCH_TO_SELECT, 0, array());
120
        } else {
121
            $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);
122
        }
123
        if ($discard_closed > 0) {
124
            if (!empty($form)) {
125
                $out .= $form->textwithpicto('', $langs->trans("ClosedProjectsAreHidden"));
126
            }
127
        }
128
129
        if (empty($nooutput)) {
130
            print $out;
131
            return '';
132
        } else {
133
            return $out;
134
        }
135
    }
136
137
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
138
139
    /**
140
     * Returns an array with projects qualified for a third party
141
     *
142
     * @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)
143
     * @param int       $selected       Id project preselected
144
     * @param string    $htmlname       Name of html component
145
     * @param int       $maxlength      Maximum length of label
146
     * @param int       $option_only    Return only html options lines without the select tag
147
     * @param int|string    $show_empty Add an empty line
148
     * @param int       $discard_closed Discard closed projects (0=Keep,1=hide completely,2=Disable)
149
     * @param int       $forcefocus     Force focus on field (works with javascript only)
150
     * @param int       $disabled       Disabled
151
     * @param int       $mode           0 for HTML mode and 1 for array return (to be used by json_encode for example)
152
     * @param string    $filterkey      Key to filter on title or ref
153
     * @param int       $nooutput       No print output. Return it only.
154
     * @param int       $forceaddid     Force to add project id in list, event if not qualified
155
     * @param string    $htmlid         Html id to use instead of htmlname
156
     * @param string    $morecss        More CSS
157
     * @param string    $morefilter     More filters (Must be a sql sanitized string)
158
     * @return int|string|array         HTML string or array of option or <0 if KO
159
     */
160
    public function select_projects_list($socid = -1, $selected = 0, $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 = '')
161
    {
162
		// phpcs:enable
163
        global $user, $conf, $langs;
164
165
        require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/project.class.php';
166
167
        if (empty($htmlid)) {
168
            $htmlid = $htmlname;
169
        }
170
171
        $out = '';
172
        $outarray = array();
173
174
        $hideunselectables = false;
175
        if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
176
            $hideunselectables = true;
177
        }
178
        if (getDolGlobalInt('PROJECT_ALWAYS_DISCARD_CLOSED_PROJECTS_IN_SELECT')) {
179
            $discard_closed = 1;
180
        }
181
182
        $projectsListId = false;
183
        if (!$user->hasRight('projet', 'all', 'lire')) {
184
            $projectstatic = new Project($this->db);
185
            $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
186
        }
187
188
        // Search all projects
189
        $sql = "SELECT p.rowid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, s.nom as name, s.name_alias";
190
        $sql .= " FROM " . $this->db->prefix() . "projet as p LEFT JOIN " . $this->db->prefix() . "societe as s ON s.rowid = p.fk_soc";
191
        $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
192
        if ($projectsListId !== false) {
193
            $sql .= " AND p.rowid IN (" . $this->db->sanitize($projectsListId) . ")";
194
        }
195
        if ($socid == 0) {
196
            $sql .= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
197
        }
198
        if ($socid > 0) {
199
            if (!getDolGlobalString('PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY')) {
200
                $sql .= " AND (p.fk_soc=" . ((int) $socid) . " OR p.fk_soc IS NULL)";
201
            } elseif (getDolGlobalString('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.
202
                $sql .= " AND (p.fk_soc IN (" . $this->db->sanitize(((int) $socid) . ", " . getDolGlobalString('PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY')) . ") OR p.fk_soc IS NULL)";
203
            }
204
        }
205
        if (!empty($filterkey)) {
206
            $sql .= natural_search(array('p.title', 'p.ref'), $filterkey);
207
        }
208
        if ($morefilter) {
209
            $sql .= ' AND (' . $this->db->sanitize($morefilter, 0, 1) . ')';
210
        }
211
        $sql .= " ORDER BY p.ref ASC";
212
213
        $resql = $this->db->query($sql);
214
        if ($resql) {
215
            if (!empty($conf->use_javascript_ajax)) {
216
                $morecss .= ' minwidth100';
217
            }
218
            if (empty($option_only)) {
219
                $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlid . '" name="' . $htmlname . '">';
220
            }
221
            if (!empty($show_empty)) {
222
                if (is_numeric($show_empty)) {
223
                    $out .= '<option value="0">&nbsp;</option>';
224
                } else {
225
                    $out .= '<option value="-1">' . $show_empty . '</option>';
226
                }
227
            }
228
            $num = $this->db->num_rows($resql);
229
            $i = 0;
230
            if ($num) {
231
                while ($i < $num) {
232
                    $obj = $this->db->fetch_object($resql);
233
                    // 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.
234
                    if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$user->hasRight('societe', 'lire')) {
235
                        // Do nothing
236
                    } else {
237
                        if ($discard_closed == 1 && $obj->fk_statut == 2 && $obj->rowid != $selected) { // We discard closed except if selected
238
                            $i++;
239
                            continue;
240
                        }
241
242
                        $labeltoshow = dol_trunc($obj->ref, 18);
243
                        //if ($obj->public) $labeltoshow.=' ('.$langs->trans("SharedProject").')';
244
                        //else $labeltoshow.=' ('.$langs->trans("Private").')';
245
                        $labeltoshow .= ', ' . dol_trunc($obj->title, $maxlength);
246
                        if ($obj->name) {
247
                            $labeltoshow .= ' - ' . $obj->name;
248
                            if ($obj->name_alias) {
249
                                $labeltoshow .= ' (' . $obj->name_alias . ')';
250
                            }
251
                        }
252
253
                        $disabled = 0;
254
                        if ($obj->fk_statut == 0) {
255
                            $disabled = 1;
256
                            $labeltoshow .= ' - ' . $langs->trans("Draft");
257
                        } elseif ($obj->fk_statut == 2) {
258
                            if ($discard_closed == 2) {
259
                                $disabled = 1;
260
                            }
261
                            $labeltoshow .= ' - ' . $langs->trans("Closed");
262
                        } elseif (!getDolGlobalString('PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY') && $socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
263
                            $disabled = 1;
264
                            $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
265
                        }
266
267
                        if (!empty($selected) && $selected == $obj->rowid) {
268
                            $out .= '<option value="' . $obj->rowid . '" selected';
269
                            //if ($disabled) $out.=' disabled';                     // with select2, field can't be preselected if disabled
270
                            $out .= '>' . $labeltoshow . '</option>';
271
                        } else {
272
                            if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
273
                                $resultat = '';
274
                            } else {
275
                                $resultat = '<option value="' . $obj->rowid . '"';
276
                                if ($disabled) {
277
                                    $resultat .= ' disabled';
278
                                }
279
                                //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
280
                                //else $labeltoshow.=' ('.$langs->trans("Private").')';
281
                                $resultat .= '>';
282
                                $resultat .= $labeltoshow;
283
                                $resultat .= '</option>';
284
                            }
285
                            $out .= $resultat;
286
287
                            $outarray[] = array(
288
                                'key' => (int) $obj->rowid,
289
                                'value' => $obj->ref,
290
                                'ref' => $obj->ref,
291
                                'labelx' => $labeltoshow,
292
                                'label' => ($disabled ? '<span class="opacitymedium">' . $labeltoshow . '</span>' : $labeltoshow),
293
                                'disabled' => (bool) $disabled
294
                            );
295
                        }
296
                    }
297
                    $i++;
298
                }
299
            }
300
301
            $this->db->free($resql);
302
303
            if (!$mode) {
304
                if (empty($option_only)) {
305
                    $out .= '</select>';
306
                }
307
308
                // Use select2 selector
309
                if (!empty($conf->use_javascript_ajax)) {
310
                    include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
311
                    $comboenhancement = ajax_combobox($htmlid, array(), 0, $forcefocus);
312
                    $out .= $comboenhancement;
313
                    $morecss .= ' minwidth100';
314
                }
315
316
                if (empty($nooutput)) {
317
                    print $out;
318
                    return '';
319
                } else {
320
                    return $out;
321
                }
322
            } else {
323
                return $outarray;
324
            }
325
        } else {
326
            dol_print_error($this->db);
327
            return -1;
328
        }
329
    }
330
331
    /**
332
     *  Output a combo list with tasks qualified for a third party
333
     *
334
     * @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)
335
     * @param int       $selected       Id task preselected
336
     * @param string    $htmlname       Name of HTML select
337
     * @param int       $maxlength      Maximum length of label
338
     * @param int       $option_only    Return only html options lines without the select tag
339
     * @param string    $show_empty     Add an empty line ('1' or string to show for empty line)
340
     * @param int       $discard_closed Discard closed projects (0=Keep, 1=hide completely, 2=Disable)
341
     * @param int       $forcefocus     Force focus on field (works with javascript only)
342
     * @param int       $disabled       Disabled
343
     * @param string    $morecss        More css added to the select component
344
     * @param string    $projectsListId ''=Automatic filter on project allowed. List of id=Filter on project ids.
345
     * @param string    $showmore       'all' = Show project info, 'progress' = Show task progression, ''=Show nothing more
346
     * @param User      $usertofilter   User object to use for filtering
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Core\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
347
     * @param int       $nooutput       1=Return string, do not send to output
348
     *
349
     * @return int|string                   Nbr of tasks if OK, <0 if KO. If nooutput=1: Return a HTML select string.
350
     */
351
    public function selectTasks($socid = -1, $selected = 0, $htmlname = 'taskid', $maxlength = 24, $option_only = 0, $show_empty = '1', $discard_closed = 0, $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500', $projectsListId = '', $showmore = 'all', $usertofilter = null, $nooutput = 0)
352
    {
353
        global $user, $conf, $langs;
354
355
        require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/project.class.php';
356
357
        if (is_null($usertofilter)) {
358
            $usertofilter = $user;
359
        }
360
361
        $out = '';
362
363
        $hideunselectables = false;
364
        if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
365
            $hideunselectables = true;
366
        }
367
368
        if (empty($projectsListId)) {
369
            if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
0 ignored issues
show
Bug introduced by
The method hasRight() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

369
            if (!$usertofilter->/** @scrutinizer ignore-call */ hasRight('projet', 'all', 'lire')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
370
                $projectstatic = new Project($this->db);
371
                $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
372
            }
373
        }
374
375
        // Search all projects
376
        $sql = "SELECT t.rowid, t.ref as tref, t.label as tlabel, t.progress,";
377
        $sql .= " p.rowid as pid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, p.usage_task,";
378
        $sql .= " s.nom as name";
379
        $sql .= " FROM " . $this->db->prefix() . "projet as p";
380
        $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON s.rowid = p.fk_soc,";
381
        $sql .= " " . $this->db->prefix() . "projet_task as t";
382
        $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
383
        $sql .= " AND t.fk_projet = p.rowid";
384
        if ($projectsListId) {
385
            $sql .= " AND p.rowid IN (" . $this->db->sanitize($projectsListId) . ")";
386
        }
387
        if ($socid == 0) {
388
            $sql .= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
389
        }
390
        if ($socid > 0) {
391
            $sql .= " AND (p.fk_soc=" . ((int) $socid) . " OR p.fk_soc IS NULL)";
392
        }
393
        $sql .= " ORDER BY p.ref, t.ref ASC";
394
395
        $resql = $this->db->query($sql);
396
        if ($resql) {
397
            // Use select2 selector
398
            if (empty($option_only) && !empty($conf->use_javascript_ajax)) {
399
                include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
400
                $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
401
                $out .= $comboenhancement;
402
                $morecss .= ' minwidth150imp';
403
            }
404
405
            if (empty($option_only)) {
406
                $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
407
            }
408
            if (!empty($show_empty)) {
409
                $out .= '<option value="0" class="optiongrey">';
410
                if (!is_numeric($show_empty)) {
411
                    //if (!empty($conf->use_javascript_ajax)) $out .= '<span class="opacitymedium">aaa';
412
                    $out .= $show_empty;
413
                    //if (!empty($conf->use_javascript_ajax)) $out .= '</span>';
414
                } else {
415
                    $out .= '&nbsp;';
416
                }
417
                $out .= '</option>';
418
            }
419
420
            $num = $this->db->num_rows($resql);
421
            $i = 0;
422
            if ($num) {
423
                while ($i < $num) {
424
                    $obj = $this->db->fetch_object($resql);
425
                    // 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.
426
                    if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
427
                        // Do nothing
428
                    } else {
429
                        if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
430
                            $i++;
431
                            continue;
432
                        }
433
434
                        $labeltoshow = '';
435
                        $labeltoshowhtml = '';
436
437
                        $disabled = 0;
438
                        if ($obj->fk_statut == Project::STATUS_DRAFT) {
439
                            $disabled = 1;
440
                        } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
441
                            if ($discard_closed == 2) {
442
                                $disabled = 1;
443
                            }
444
                        } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
445
                            $disabled = 1;
446
                        }
447
448
                        if (preg_match('/all/', $showmore)) {
449
                            $labeltoshow .= dol_trunc($obj->ref, 18); // Project ref
450
                            //if ($obj->public) $labeltoshow.=' ('.$langs->trans("SharedProject").')';
451
                            //else $labeltoshow.=' ('.$langs->trans("Private").')';
452
                            $labeltoshow .= ' ' . dol_trunc($obj->title, $maxlength);
453
                            $labeltoshowhtml = $labeltoshow;
454
455
                            if ($obj->name) {
456
                                $labeltoshow .= ' (' . $obj->name . ')';
457
                                $labeltoshowhtml .= ' <span class="opacitymedium">(' . $obj->name . ')</span>';
458
                            }
459
460
                            $disabled = 0;
461
                            if ($obj->fk_statut == Project::STATUS_DRAFT) {
462
                                $disabled = 1;
463
                                $labeltoshow .= ' - ' . $langs->trans("Draft");
464
                                $labeltoshowhtml .= ' -  <span class="opacitymedium">' . $langs->trans("Draft") . '</span>';
465
                            } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
466
                                if ($discard_closed == 2) {
467
                                    $disabled = 1;
468
                                }
469
                                $labeltoshow .= ' - ' . $langs->trans("Closed");
470
                                $labeltoshowhtml .= ' - <span class="opacitymedium">' . $langs->trans("Closed") . '</span>';
471
                            } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
472
                                $disabled = 1;
473
                                $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
474
                                $labeltoshowhtml .= ' - <span class="opacitymedium">' . $langs->trans("LinkedToAnotherCompany") . '</span>';
475
                            }
476
                            $labeltoshow .= ' - ';
477
                            $labeltoshowhtml .= ' - ';
478
                        }
479
480
                        // Label for task
481
                        $labeltoshow .= $obj->tref . ' ' . dol_trunc($obj->tlabel, $maxlength);
482
                        $labeltoshowhtml .= $obj->tref . ' - ' . dol_trunc($obj->tlabel, $maxlength);
483
                        if ($obj->usage_task && preg_match('/progress/', $showmore)) {
484
                            $labeltoshow .= ' <span class="opacitymedium">(' . $obj->progress . '%)</span>';
485
                            $labeltoshowhtml .= ' <span class="opacitymedium">(' . $obj->progress . '%)</span>';
486
                        }
487
488
                        if (!empty($selected) && $selected == $obj->rowid) {
489
                            $out .= '<option value="' . $obj->rowid . '" selected';
490
                            $out .= ' data-html="' . dol_escape_htmltag($labeltoshowhtml) . '"';
491
                            //if ($disabled) $out.=' disabled';                     // with select2, field can't be preselected if disabled
492
                            $out .= '>' . $labeltoshow . '</option>';
493
                        } else {
494
                            if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
495
                                $resultat = '';
496
                            } else {
497
                                $resultat = '<option value="' . $obj->rowid . '"';
498
                                if ($disabled) {
499
                                    $resultat .= ' disabled';
500
                                }
501
                                //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
502
                                //else $labeltoshow.=' ('.$langs->trans("Private").')';
503
                                $resultat .= ' data-html="' . dol_escape_htmltag($labeltoshowhtml) . '"';
504
                                $resultat .= '>';
505
                                $resultat .= $labeltoshow;
506
                                $resultat .= '</option>';
507
                            }
508
                            $out .= $resultat;
509
                        }
510
                    }
511
                    $i++;
512
                }
513
            }
514
            if (empty($option_only)) {
515
                $out .= '</select>';
516
            }
517
518
            $this->nboftasks = $num;
519
            $this->db->free($resql);
520
521
            // Output or return
522
            if (empty($nooutput)) {
523
                print $out;
524
            } else {
525
                return $out;
526
            }
527
528
            return $num;
529
        } else {
530
            dol_print_error($this->db);
531
            return -1;
532
        }
533
    }
534
535
536
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
537
538
    /**
539
     *    Build a HTML select list of element of same thirdparty to suggest to link them to project
540
     *
541
     * @param string $table_element Table of the element to update
542
     * @param int|string $socid If of thirdparty to use as filter or 'id1,id2,...'
543
     * @param string $morecss More CSS
544
     * @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
545
     * @param string $projectkey Equivalent key  to fk_projet for actual table_element
546
     * @param string $placeholder Placeholder
547
     * @return    int|string                        The HTML select list of element or '' if nothing or -1 if KO
548
     */
549
    public function select_element($table_element, $socid = 0, $morecss = '', $limitonstatus = -2, $projectkey = "fk_projet", $placeholder = '')
550
    {
551
		// phpcs:enable
552
        global $conf, $langs;
553
554
        if ($table_element == 'projet_task') {
555
            return ''; // Special cas of element we never link to a project (already always done)
556
        }
557
558
        $linkedtothirdparty = false;
559
        if (
560
            !in_array(
561
            $table_element,
562
            array(
563
                'don',
564
                'expensereport_det',
565
                'expensereport', 'loan',
566
                'stock_mouvement',
567
                'payment_salary',
568
                'payment_various',
569
                'salary',
570
                'chargesociales',
571
                'entrepot')
572
            )
573
        ) {
574
            $linkedtothirdparty = true;
575
        }
576
577
        $sqlfilter = '';
578
579
        //print $table_element;
580
        switch ($table_element) {
581
            case "loan":
582
                $sql = "SELECT t.rowid, t.label as ref";
583
                break;
584
            case "facture":
585
                $sql = "SELECT t.rowid, t.ref as ref";
586
                break;
587
            case "facture_fourn":
588
                $sql = "SELECT t.rowid, t.ref, t.ref_supplier";
589
                break;
590
            case "commande_fourn":
591
            case "commande_fournisseur":
592
                $sql = "SELECT t.rowid, t.ref, t.ref_supplier";
593
                break;
594
            case "facture_rec":
595
                $sql = "SELECT t.rowid, t.titre as ref";
596
                break;
597
            case "actioncomm":
598
                $sql = "SELECT t.id as rowid, t.label as ref";
599
                $projectkey = "fk_project";
600
                break;
601
            case "expensereport":
602
                return '';
603
            case "expensereport_det":
604
                /*$sql = "SELECT rowid, '' as ref"; // table is llx_expensereport_det
605
                $projectkey="fk_projet";
606
                break;*/
607
                return '';
608
            case "commande":
609
            case "contrat":
610
            case "fichinter":
611
                $sql = "SELECT t.rowid, t.ref";
612
                break;
613
            case 'stock_mouvement':
614
                $sql = "SELECT t.rowid, t.label as ref";
615
                $projectkey = 'fk_origin';
616
                break;
617
            case "payment_salary":
618
                $sql = "SELECT t.rowid, t.num_payment as ref"; // TODO In a future fill and use real ref field
619
                break;
620
            case "payment_various":
621
                $sql = "SELECT t.rowid, t.num_payment as ref";
622
                break;
623
            case "chargesociales":
624
            default:
625
                $sql = "SELECT t.rowid, t.ref";
626
                break;
627
        }
628
        if ($linkedtothirdparty) {
629
            $sql .= ", s.nom as name";
630
        }
631
        $sql .= " FROM " . $this->db->prefix() . $table_element . " as t";
632
        if ($linkedtothirdparty) {
633
            $sql .= ", " . $this->db->prefix() . "societe as s";
634
        }
635
        $sql .= " WHERE " . $projectkey . " is null";
636
        if (!empty($socid) && $linkedtothirdparty) {
637
            if (is_numeric($socid)) {
638
                $sql .= " AND t.fk_soc = " . ((int) $socid);
639
            } else {
640
                $sql .= " AND t.fk_soc IN (" . $this->db->sanitize($socid) . ")";
641
            }
642
        }
643
        if (!in_array($table_element, array('expensereport_det', 'stock_mouvement'))) {
644
            $sql .= ' AND t.entity IN (' . getEntity('project') . ')';
645
        }
646
        if ($linkedtothirdparty) {
647
            $sql .= " AND s.rowid = t.fk_soc";
648
        }
649
        if ($sqlfilter) {
650
            $sql .= " AND " . $sqlfilter;
651
        }
652
        $sql .= " ORDER BY ref DESC";
653
654
        dol_syslog(get_class($this) . '::select_element', LOG_DEBUG);
655
        $resql = $this->db->query($sql);
656
        if ($resql) {
657
            $num = $this->db->num_rows($resql);
658
            $i = 0;
659
            $sellist = '';
660
661
            if ($num > 0) {
662
                $sellist = '<select class="flat elementselect css' . $table_element . ($morecss ? ' ' . $morecss : '') . '" name="elementselect">';
663
                $sellist .= '<option value="-1"' . ($placeholder ? ' class="optiongrey"' : '') . '>' . $placeholder . '</option>';
664
                while ($i < $num) {
665
                    $obj = $this->db->fetch_object($resql);
666
                    $ref = $obj->ref ? $obj->ref : $obj->rowid;
667
                    if (!empty($obj->ref_supplier)) {
668
                        $ref .= ' (' . $obj->ref_supplier . ')';
669
                    }
670
                    if (!empty($obj->name)) {
671
                        $ref .= ' - ' . $obj->name;
672
                    }
673
                    $sellist .= '<option value="' . $obj->rowid . '">' . $ref . '</option>';
674
                    $i++;
675
                }
676
                $sellist .= '</select>';
677
            }
678
            /*else
679
            {
680
                $sellist = '<select class="flat" name="elementselect">';
681
                $sellist.= '<option value="0" disabled>'.$langs->trans("None").'</option>';
682
                $sellist.= '</select>';
683
            }*/
684
            $this->db->free($resql);
685
686
            return $sellist;
687
        } else {
688
            dol_print_error($this->db);
689
            $this->error = $this->db->lasterror();
690
            $this->errors[] = $this->db->lasterror();
691
            dol_syslog(get_class($this) . "::select_element " . $this->error, LOG_ERR);
692
            return -1;
693
        }
694
    }
695
696
697
    /**
698
     *    Build a HTML select list of element of same thirdparty to suggest to link them to project
699
     *
700
     * @param string $htmlname HTML name
701
     * @param string $preselected Preselected (int or 'all' or 'none')
702
     * @param int $showempty Add an empty line
703
     * @param int $useshortlabel Use short label
704
     * @param int $showallnone Add choice "All" and "None"
705
     * @param int $showpercent Show default probability for status
706
     * @param string $morecss Add more css
707
     * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
708
     * @param int $addcombojs 1=Add a js combo
709
     * @return  int<-1,-1>|string                      The HTML select list of element or '' if nothing or -1 if KO
710
     */
711
    public function selectOpportunityStatus($htmlname, $preselected = '-1', $showempty = 1, $useshortlabel = 0, $showallnone = 0, $showpercent = 0, $morecss = '', $noadmininfo = 0, $addcombojs = 0)
712
    {
713
        global $conf, $langs, $user;
714
715
        $sql = "SELECT rowid, code, label, percent";
716
        $sql .= " FROM " . $this->db->prefix() . 'c_lead_status';
717
        $sql .= " WHERE active = 1";
718
        $sql .= " ORDER BY position";
719
720
        $resql = $this->db->query($sql);
721
        if ($resql) {
722
            $num = $this->db->num_rows($resql);
723
            $i = 0;
724
            $sellist = '';
725
            if ($num > 0) {
726
                $sellist = '<select class="flat oppstatus' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
727
                if ($showempty) {
728
                    // Without &nbsp, strange move of screen when switching value
729
                    $sellist .= '<option value="-1">&nbsp;</option>';
730
                }
731
                if ($showallnone) {
732
                    $sellist .= '<option value="all"' . ($preselected == 'all' ? ' selected="selected"' : '') . '>-- ' . $langs->trans("OnlyOpportunitiesShort") . '</option>';
733
                    $sellist .= '<option value="openedopp"' . ($preselected == 'openedopp' ? ' selected="selected"' : '') . '>-- ' . $langs->trans("OpenedOpportunitiesShort") . '</option>';
734
                    $sellist .= '<option value="notopenedopp"' . ($preselected == 'notopenedopp' ? ' selected="selected"' : '') . '>-- ' . $langs->trans("NotOpenedOpportunitiesShort") . '</option>';
735
                    $sellist .= '<option value="none"' . ($preselected == 'none' ? ' selected="selected"' : '') . '>-- ' . $langs->trans("NotAnOpportunityShort") . '</option>';
736
                }
737
                while ($i < $num) {
738
                    $obj = $this->db->fetch_object($resql);
739
740
                    $sellist .= '<option value="' . $obj->rowid . '" defaultpercent="' . $obj->percent . '" elemcode="' . $obj->code . '"';
741
                    if ($obj->rowid == $preselected) {
742
                        $sellist .= ' selected="selected"';
743
                    }
744
                    $sellist .= '>';
745
                    if ($useshortlabel) {
746
                        $finallabel = ($langs->transnoentitiesnoconv("OppStatus" . $obj->code) != "OppStatus" . $obj->code ? $langs->transnoentitiesnoconv("OppStatus" . $obj->code) : $obj->label);
747
                    } else {
748
                        $finallabel = ($langs->transnoentitiesnoconv("OppStatus" . $obj->code) != "OppStatus" . $obj->code ? $langs->transnoentitiesnoconv("OppStatus" . $obj->code) : $obj->label);
749
                        if ($showpercent) {
750
                            $finallabel .= ' (' . $obj->percent . '%)';
751
                        }
752
                    }
753
                    $sellist .= $finallabel;
754
                    $sellist .= '</option>';
755
                    $i++;
756
                }
757
                $sellist .= '</select>';
758
759
                if ($user->admin && !$noadmininfo) {
760
                    $sellist .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
761
                }
762
763
                if ($addcombojs) {
764
                    $sellist .= ajax_combobox($htmlname);
765
                }
766
            }
767
            /*else
768
            {
769
                $sellist = '<select class="flat" name="elementselect">';
770
                $sellist.= '<option value="0" disabled>'.$langs->trans("None").'</option>';
771
                $sellist.= '</select>';
772
            }*/
773
            $this->db->free($resql);
774
775
            return $sellist;
776
        } else {
777
            $this->error = $this->db->lasterror();
778
            $this->errors[] = $this->db->lasterror();
779
            dol_syslog(get_class($this) . "::selectOpportunityStatus " . $this->error, LOG_ERR);
780
            return -1;
781
        }
782
    }
783
784
    /**
785
     *  Return combo list of different statuses of orders
786
     *
787
     *  @param  string  $selected   Preselected value
788
     *  @param  int     $short      Use short labels
789
     *  @param  string  $hmlname    Name of HTML select element
790
     *  @return void
791
     */
792
    public function selectProjectsStatus($selected = '', $short = 0, $hmlname = 'order_status')
793
    {
794
        $options = array();
795
796
        // 7 is same label than 6. 8 does not exists (billed is another field)
797
        $statustohow = array(
798
            '0' => '0',
799
            '1' => '1',
800
            '2' => '2',
801
        );
802
803
        $tmpproject = new Project($this->db);
804
805
        foreach ($statustohow as $key => $value) {
806
            $tmpproject->statut = $key;
807
            $options[$value] = $tmpproject->getLibStatut($short);
808
        }
809
810
        if (is_array($selected)) {
811
            $selectedarray = $selected;
812
        } elseif ($selected == 99) {
813
            $selectedarray = array(0,1);
814
        } else {
815
            $selectedarray = explode(',', $selected);
816
        }
817
818
        print Form::multiselectarray($hmlname, $options, $selectedarray, 0, 0, 'minwidth100');
819
    }
820
821
    /**
822
     *  Output a combo list with invoices and lines qualified for a project
823
     *
824
     * @param int $selectedInvoiceId Id invoice preselected
825
     * @param int $selectedLineId Id invoice line preselected
826
     * @param string $htmlNameInvoice Name of HTML select for Invoice
827
     * @param string $htmlNameInvoiceLine Name of HTML select for Invoice Line
828
     * @param string $morecss More css added to the select component
829
     * @param array $filters Array of filters
830
     * @param int $lineOnly return only option for line
831
     * @return string                    HTML Select
832
     */
833
    public function selectInvoiceAndLine($selectedInvoiceId = 0, $selectedLineId = 0, $htmlNameInvoice = 'invoiceid', $htmlNameInvoiceLine = 'invoicelineid', $morecss = 'maxwidth500', $filters = array(), $lineOnly = 0)
834
    {
835
        global $user, $conf, $langs;
836
837
        require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/project.class.php';
838
839
        $out = '';
840
        if (empty($lineOnly)) {
841
            // Search Invoice
842
            $sql = "SELECT f.rowid, f.ref as fref,";
843
            $sql .= ' s.nom as name';
844
            $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
845
            $sql .= ' INNER JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc';
846
            $sql .= ' INNER JOIN ' . $this->db->prefix() . 'facture as f ON f.fk_projet = p.rowid';
847
            $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
848
            if (!empty($filters)) {
849
                foreach ($filters as $key => $value) {
850
                    if ($key == 'p.rowid') {
851
                        $sql .= " AND p.rowid=" . (int) $value;
852
                    }
853
                    if ($key == 'f.rowid') {
854
                        $sql .= " AND f.rowid=" . (int) $value;
855
                    }
856
                }
857
            }
858
            $sql .= " ORDER BY p.ref, f.ref ASC";
859
860
            $resql = $this->db->query($sql);
861
            if ($resql) {
862
                // Use select2 selector
863
                if (!empty($conf->use_javascript_ajax)) {
864
                    include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
865
                    $comboenhancement = ajax_combobox($htmlNameInvoice, array(array('method' => 'getLines', 'url' => dol_buildpath('/core/ajax/ajaxinvoiceline.php', 1), 'htmlname' => $htmlNameInvoiceLine)), 0, 0);
866
                    $out .= $comboenhancement;
867
                    $morecss = 'minwidth200imp maxwidth500';
868
                }
869
870
                $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlNameInvoice . '" name="' . $htmlNameInvoice . '">';
871
                $num = $this->db->num_rows($resql);
872
                if ($num) {
873
                    while ($obj = $this->db->fetch_object($resql)) {
874
                        $labeltoshow = $obj->fref; // Invoice ref
875
                        if ($obj->name) {
876
                            $labeltoshow .= ' - ' . $obj->name;
877
                        }
878
879
                        $out .= '<option value="' . $obj->rowid . '" ';
880
                        if (!empty($selectedInvoiceId) && $selectedInvoiceId == $obj->rowid) {
881
                            $out .= ' selected ';
882
                        }
883
                        $out .= '>' . $labeltoshow . '</option>';
884
                    }
885
                }
886
                $out .= '</select>';
887
            } else {
888
                dol_print_error($this->db->lasterror);
889
                return '';
890
            }
891
        }
892
893
        // Search Invoice Line
894
        $sql = "SELECT fd.rowid, fd.label, fd.description";
895
        $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
896
        $sql .= ' INNER JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc';
897
        $sql .= ' INNER JOIN ' . $this->db->prefix() . 'facture as f ON f.fk_projet = p.rowid';
898
        $sql .= ' INNER JOIN ' . $this->db->prefix() . 'facturedet as fd ON fd.fk_facture = f.rowid';
899
        $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
900
        if (!empty($filters)) {
901
            foreach ($filters as $key => $value) {
902
                if ($key == 'p.rowid') {
903
                    $sql .= " AND p.rowid=" . (int) $value;
904
                }
905
            }
906
        }
907
        if (!empty($selectedInvoiceId)) {
908
            $sql .= " AND f.rowid=" . (int) $selectedInvoiceId;
909
        }
910
        $sql .= " ORDER BY p.ref, f.ref ASC";
911
        $resql = $this->db->query($sql);
912
        if ($resql) {
913
            // Use select2 selector
914
            if (empty($lineOnly)) {
915
                if (!empty($conf->use_javascript_ajax)) {
916
                    include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
917
                    $comboenhancement = ajax_combobox($htmlNameInvoiceLine, '', 0, 0);
918
                    $out .= $comboenhancement;
919
                    $morecss = 'minwidth200imp maxwidth500';
920
                }
921
922
                $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlNameInvoiceLine . '" name="' . $htmlNameInvoiceLine . '">';
923
            }
924
            $num = $this->db->num_rows($resql);
925
            if ($num) {
926
                while ($obj = $this->db->fetch_object($resql)) {
927
                    $labeltoshow .= $obj->description; // Invoice ref
928
929
                    $out .= '<option value="' . $obj->rowid . '" ';
930
                    if (!empty($selectedLineId) && $selectedLineId == $obj->rowid) {
931
                        $out .= ' selected ';
932
                    }
933
                    $out .= '>' . $labeltoshow . '</option>';
934
                }
935
            }
936
            if (empty($lineOnly)) {
937
                $out .= '</select>';
938
            }
939
        } else {
940
            dol_print_error($this->db->lasterror);
941
            return '';
942
        }
943
944
        return $out;
945
    }
946
947
    /**
948
     *  Output html select to select opportunity status
949
     *
950
     *  @param  string $page            Page
951
     *  @param  string $selected        Id preselected
952
     *  @param  int    $percent_value       percentage of the opportunity
953
     *  @param  string $htmlname_status name of HTML element for status select
954
     *  @param  string $htmlname_percent    name of HTML element for percent input
955
     *  @param  string $filter          optional filters criteras
956
     *  @param  int    $nooutput        No print output. Return it only.
957
     *  @return void|string
958
     */
959
    public function formOpportunityStatus($page, $selected = '', $percent_value = 0, $htmlname_status = 'none', $htmlname_percent = 'none', $filter = '', $nooutput = 0)
960
    {
961
        // phpcs:enable
962
        global $conf, $langs;
963
964
        $out = '';
965
        if ($htmlname_status != "none" && $htmlname_percent != 'none') {
966
            $out .= '<form method="post" action="' . $page . '">';
967
            $out .= '<input type="hidden" name="action" value="set_opp_status">';
968
            $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
969
            $out .= $this-> selectOpportunityStatus($htmlname_status, $selected, 1, 0, 0, 0, 'minwidth150 inline-block valignmiddle', 1, 1);
970
            $out .= ' / <span title="' . $langs->trans("OpportunityProbability") . '"> ';
971
            $out .= '<input class="width50 right" type="text" id="' . $htmlname_percent . '" name="' . $htmlname_percent . '" title="' . dol_escape_htmltag($langs->trans("OpportunityProbability")) . '" value="' . $percent_value . '"> %';
972
            $out .= '</span>';
973
            $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
974
            $out .= '</form>';
975
        } else {
976
            if ($selected > 0) {
977
                $code = dol_getIdFromCode($this->db, $selected, 'c_lead_status', 'rowid', 'code');
978
                $out .= $langs->trans("OppStatus" . $code);
979
980
                // Opportunity percent
981
                $out .= ' / <span title="' . $langs->trans("OpportunityProbability") . '"> ';
982
                $out .= price($percent_value, 0, $langs, 1, 0) . ' %';
983
                $out .= '</span>';
984
            } else {
985
                $out .= "&nbsp;";
986
            }
987
        }
988
989
        if ($nooutput) {
990
            return $out;
991
        } else {
992
            print $out;
993
        }
994
    }
995
}
996