Passed
Pull Request — dev (#8)
by Rafael
58:47
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 Dolibarr\Code\Projet\Classes\Project;
28
use Dolibarr\Code\User\Classes\User;
29
use DoliDB;
30
31
/**
32
 *      \file       htdocs/core/class/html.formprojet.class.php
33
 *      \ingroup    core
34
 *      \brief      Class file for html component project
35
 */
36
37
38
/**
39
 *      Class to manage building of HTML components
40
 */
41
class FormProjets extends Form
42
{
43
    /**
44
     * @var DoliDB Database handler.
45
     */
46
    public $db;
47
48
    /**
49
     * @var string Error code (or message)
50
     */
51
    public $error = '';
52
53
    public $errors = array();
54
55
56
    public $nboftasks;
57
58
59
    /**
60
     *    Constructor
61
     *
62
     * @param DoliDB $db Database handler
63
     */
64
    public function __construct($db)
65
    {
66
        $this->db = $db;
67
    }
68
69
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
70
71
    /**
72
     * Output a combo list with projects qualified for a third party / user
73
     *
74
     * @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)
75
     * @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.
76
     * @param string    $htmlname       Name of HTML field
77
     * @param int       $maxlength      Maximum length of label
78
     * @param int       $option_only    Return only html options lines without the select tag
79
     * @param int|string    $show_empty     Add an empty line
80
     * @param int       $discard_closed Discard closed projects (0=Keep, 1=hide completely, 2=Disable). Use a negative value to not show the "discarded" tooltip.
81
     * @param int       $forcefocus     Force focus on field (works with javascript only)
82
     * @param int       $disabled       Disabled
83
     * @param int       $mode           0 for HTML mode and 1 for JSON mode
84
     * @param string    $filterkey      Key to filter on ref or title
85
     * @param int       $nooutput       No print output. Return it only.
86
     * @param int       $forceaddid     Force to add project id in list, event if not qualified
87
     * @param string    $morecss        More css
88
     * @param string    $htmlid         Html id to use instead of htmlname, by example id="htmlid"
89
     * @param string    $morefilter     More filters (Must be a sql sanitized string)
90
     * @return string                   Return html content
91
     */
92
    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 = '')
93
    {
94
		// phpcs:enable
95
        global $langs, $conf, $form;
96
97
        $selected_input_value = '';
98
        if (is_object($selected)) {
99
            $selected_input_value = $selected->ref;
100
            $selected = $selected->id;
101
        }
102
103
        $out = '';
104
105
        if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
106
            $placeholder = '';
107
108
            if ($selected && empty($selected_input_value)) {
109
                $project = new Project($this->db);
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
166
        if (empty($htmlid)) {
167
            $htmlid = $htmlname;
168
        }
169
170
        $out = '';
171
        $outarray = array();
172
173
        $hideunselectables = false;
174
        if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
175
            $hideunselectables = true;
176
        }
177
        if (getDolGlobalInt('PROJECT_ALWAYS_DISCARD_CLOSED_PROJECTS_IN_SELECT')) {
178
            $discard_closed = 1;
179
        }
180
181
        $projectsListId = false;
182
        if (!$user->hasRight('projet', 'all', 'lire')) {
183
            $projectstatic = new Project($this->db);
184
            $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
185
        }
186
187
        // Search all projects
188
        $sql = "SELECT p.rowid, p.ref, p.title, p.fk_soc, p.fk_statut, p.public, s.nom as name, s.name_alias";
189
        $sql .= " FROM " . $this->db->prefix() . "projet as p LEFT JOIN " . $this->db->prefix() . "societe as s ON s.rowid = p.fk_soc";
190
        $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
191
        if ($projectsListId !== false) {
192
            $sql .= " AND p.rowid IN (" . $this->db->sanitize($projectsListId) . ")";
193
        }
194
        if ($socid == 0) {
195
            $sql .= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
196
        }
197
        if ($socid > 0) {
198
            if (!getDolGlobalString('PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY')) {
199
                $sql .= " AND (p.fk_soc=" . ((int) $socid) . " OR p.fk_soc IS NULL)";
200
            } 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.
201
                $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)";
202
            }
203
        }
204
        if (!empty($filterkey)) {
205
            $sql .= natural_search(array('p.title', 'p.ref'), $filterkey);
206
        }
207
        if ($morefilter) {
208
            $sql .= ' AND (' . $this->db->sanitize($morefilter, 0, 1) . ')';
209
        }
210
        $sql .= " ORDER BY p.ref ASC";
211
212
        $resql = $this->db->query($sql);
213
        if ($resql) {
214
            if (!empty($conf->use_javascript_ajax)) {
215
                $morecss .= ' minwidth100';
216
            }
217
            if (empty($option_only)) {
218
                $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlid . '" name="' . $htmlname . '">';
219
            }
220
            if (!empty($show_empty)) {
221
                if (is_numeric($show_empty)) {
222
                    $out .= '<option value="0">&nbsp;</option>';
223
                } else {
224
                    $out .= '<option value="-1">' . $show_empty . '</option>';
225
                }
226
            }
227
            $num = $this->db->num_rows($resql);
228
            $i = 0;
229
            if ($num) {
230
                while ($i < $num) {
231
                    $obj = $this->db->fetch_object($resql);
232
                    // 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.
233
                    if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$user->hasRight('societe', 'lire')) {
234
                        // Do nothing
235
                    } else {
236
                        if ($discard_closed == 1 && $obj->fk_statut == 2 && $obj->rowid != $selected) { // We discard closed except if selected
237
                            $i++;
238
                            continue;
239
                        }
240
241
                        $labeltoshow = dol_trunc($obj->ref, 18);
242
                        //if ($obj->public) $labeltoshow.=' ('.$langs->trans("SharedProject").')';
243
                        //else $labeltoshow.=' ('.$langs->trans("Private").')';
244
                        $labeltoshow .= ', ' . dol_trunc($obj->title, $maxlength);
245
                        if ($obj->name) {
246
                            $labeltoshow .= ' - ' . $obj->name;
247
                            if ($obj->name_alias) {
248
                                $labeltoshow .= ' (' . $obj->name_alias . ')';
249
                            }
250
                        }
251
252
                        $disabled = 0;
253
                        if ($obj->fk_statut == 0) {
254
                            $disabled = 1;
255
                            $labeltoshow .= ' - ' . $langs->trans("Draft");
256
                        } elseif ($obj->fk_statut == 2) {
257
                            if ($discard_closed == 2) {
258
                                $disabled = 1;
259
                            }
260
                            $labeltoshow .= ' - ' . $langs->trans("Closed");
261
                        } elseif (!getDolGlobalString('PROJECT_ALLOW_TO_LINK_FROM_OTHER_COMPANY') && $socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
262
                            $disabled = 1;
263
                            $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
264
                        }
265
266
                        if (!empty($selected) && $selected == $obj->rowid) {
267
                            $out .= '<option value="' . $obj->rowid . '" selected';
268
                            //if ($disabled) $out.=' disabled';                     // with select2, field can't be preselected if disabled
269
                            $out .= '>' . $labeltoshow . '</option>';
270
                        } else {
271
                            if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
272
                                $resultat = '';
273
                            } else {
274
                                $resultat = '<option value="' . $obj->rowid . '"';
275
                                if ($disabled) {
276
                                    $resultat .= ' disabled';
277
                                }
278
                                //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
279
                                //else $labeltoshow.=' ('.$langs->trans("Private").')';
280
                                $resultat .= '>';
281
                                $resultat .= $labeltoshow;
282
                                $resultat .= '</option>';
283
                            }
284
                            $out .= $resultat;
285
286
                            $outarray[] = array(
287
                                'key' => (int) $obj->rowid,
288
                                'value' => $obj->ref,
289
                                'ref' => $obj->ref,
290
                                'labelx' => $labeltoshow,
291
                                'label' => ($disabled ? '<span class="opacitymedium">' . $labeltoshow . '</span>' : $labeltoshow),
292
                                'disabled' => (bool) $disabled
293
                            );
294
                        }
295
                    }
296
                    $i++;
297
                }
298
            }
299
300
            $this->db->free($resql);
301
302
            if (!$mode) {
303
                if (empty($option_only)) {
304
                    $out .= '</select>';
305
                }
306
307
                // Use select2 selector
308
                if (!empty($conf->use_javascript_ajax)) {
309
                    include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
310
                    $comboenhancement = ajax_combobox($htmlid, array(), 0, $forcefocus);
311
                    $out .= $comboenhancement;
312
                    $morecss .= ' minwidth100';
313
                }
314
315
                if (empty($nooutput)) {
316
                    print $out;
317
                    return '';
318
                } else {
319
                    return $out;
320
                }
321
            } else {
322
                return $outarray;
323
            }
324
        } else {
325
            dol_print_error($this->db);
326
            return -1;
327
        }
328
    }
329
330
    /**
331
     *  Output a combo list with tasks qualified for a third party
332
     *
333
     * @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)
334
     * @param int       $selected       Id task preselected
335
     * @param string    $htmlname       Name of HTML select
336
     * @param int       $maxlength      Maximum length of label
337
     * @param int       $option_only    Return only html options lines without the select tag
338
     * @param string    $show_empty     Add an empty line ('1' or string to show for empty line)
339
     * @param int       $discard_closed Discard closed projects (0=Keep, 1=hide completely, 2=Disable)
340
     * @param int       $forcefocus     Force focus on field (works with javascript only)
341
     * @param int       $disabled       Disabled
342
     * @param string    $morecss        More css added to the select component
343
     * @param string    $projectsListId ''=Automatic filter on project allowed. List of id=Filter on project ids.
344
     * @param string    $showmore       'all' = Show project info, 'progress' = Show task progression, ''=Show nothing more
345
     * @param User      $usertofilter   User object to use for filtering
346
     * @param int       $nooutput       1=Return string, do not send to output
347
     *
348
     * @return int|string                   Nbr of tasks if OK, <0 if KO. If nooutput=1: Return a HTML select string.
349
     */
350
    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)
351
    {
352
        global $user, $conf, $langs;
353
354
355
        if (is_null($usertofilter)) {
356
            $usertofilter = $user;
357
        }
358
359
        $out = '';
360
361
        $hideunselectables = false;
362
        if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
363
            $hideunselectables = true;
364
        }
365
366
        if (empty($projectsListId)) {
367
            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

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