Passed
Push — EXTRACT_CLASSES ( ff35ec...a2ff75 )
by Rafael
48:13
created

Partnership::approve()   F

Complexity

Conditions 20
Paths 785

Size

Total Lines 122
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 20
eloc 67
nc 785
nop 2
dl 0
loc 122
rs 0.2985
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

1
<?php
2
3
/* Copyright (C) 2017       Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2021       NextGestion                 <[email protected]>
5
 * Copyright (C) 2024       Frédéric France             <[email protected]>
6
 * Copyright (C) 2024		MDW							<[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
namespace Dolibarr\Code\Partnerships\Classes;
24
25
use Dolibarr\Core\Base\CommonObject;
26
27
/**
28
 * \file        htdocs/partnership/class/partnership.class.php
29
 * \ingroup     partnership
30
 * \brief       This file is a CRUD class file for Partnership (Create/Read/Update/Delete)
31
 */
32
33
/**
34
 * Class for Partnership
35
 */
36
class Partnership extends CommonObject
37
{
38
    /**
39
     * @var string ID of module.
40
     */
41
    public $module = 'partnership';
42
43
    /**
44
     * @var string ID to identify managed object.
45
     */
46
    public $element = 'partnership';
47
48
    /**
49
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
50
     */
51
    public $table_element = 'partnership';
52
53
    /**
54
     * @var string String with name of icon for partnership. Must be the part after the 'object_' into object_partnership.png
55
     */
56
    public $picto = 'partnership';
57
58
    public $type_code;
59
    public $type_label;
60
61
62
    const STATUS_DRAFT = 0;
63
    const STATUS_VALIDATED = 1;     // Validate (no more draft)
64
    const STATUS_APPROVED = 2;      // Approved
65
    const STATUS_REFUSED = 3;       // Refused
66
    const STATUS_CANCELED = 9;
67
68
69
    /**
70
     *  'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
71
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
72
     *  'label' the translation key.
73
     *  'picto' is code of a picto to show before value in forms
74
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")'
75
     *  'position' is the sort order of field.
76
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
77
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
78
     *  'noteditable' says if field is not editable (1 or 0)
79
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
80
     *  'index' if we want an index in database.
81
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
82
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
83
     *  'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
84
     *  'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200'
85
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
86
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
87
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
88
     *  'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
89
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
90
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
91
     *
92
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
93
     */
94
95
    // BEGIN MODULEBUILDER PROPERTIES
96
    /**
97
     * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}>  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string,array{type:...ring>,comment?:string}> at position 16 could not be parsed: Expected '}' at position 16, but found 'int'.
Loading history...
98
     */
99
    public $fields = array(
100
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
101
        'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)', 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'comment' => "Reference of object", 'csslist' => 'tdoverflowmax150'),
102
        'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 'isModEnabled("multicompany")', 'position' => 15, 'notnull' => 1, 'visible' => -2, 'default' => '1', 'index' => 1,),
103
        'fk_type' => array('type' => 'integer:PartnershipType:partnership/class/partnership_type.class.php:0:(active:=:1)', 'label' => 'Type', 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'visible' => 1, 'csslist' => 'tdoverflowmax125'),
104
        'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label' => 'ThirdParty', 'picto' => 'company', 'enabled' => 1, 'position' => 50, 'notnull' => -1, 'visible' => 1, 'index' => 1, 'css' => 'maxwidth500', 'csslist' => 'tdoverflowmax125',),
105
        'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
106
        'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
107
        'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'csslist' => 'nowraponall'),
108
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'csslist' => 'nowraponall'),
109
        'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'position' => 510, 'notnull' => 1, 'visible' => -2, 'foreignkey' => 'user.rowid', 'csslist' => 'tdoverflowmax125'),
110
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'csslist' => 'tdoverflowmax125'),
111
        'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
112
        'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
113
        'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
114
        'date_partnership_start' => array('type' => 'date', 'label' => 'DatePartnershipStart', 'enabled' => 1, 'position' => 52, 'notnull' => 1, 'visible' => 1,),
115
        'date_partnership_end' => array('type' => 'date', 'label' => 'DatePartnershipEnd', 'enabled' => 1, 'position' => 53, 'notnull' => 0, 'visible' => 1,),
116
        'url_to_check' => array('type' => 'url', 'label' => 'UrlToCheck', 'enabled' => 'getDolGlobalString("PARTNERSHIP_BACKLINKS_TO_CHECK")', 'position' => 70, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150'),
117
        'count_last_url_check_error' => array('type' => 'integer', 'label' => 'CountLastUrlCheckError', 'enabled' => 'getDolGlobalString("PARTNERSHIP_BACKLINKS_TO_CHECK")', 'position' => 71, 'notnull' => 0, 'visible' => -4, 'default' => '0',),
118
        'last_check_backlink' => array('type' => 'datetime', 'label' => 'LastCheckBacklink', 'enabled' => 'getDolGlobalString("PARTNERSHIP_BACKLINKS_TO_CHECK")', 'position' => 72, 'notnull' => 0, 'visible' => -4, 'csslist' => 'nowraponall'),
119
        'reason_decline_or_cancel' => array('type' => 'text', 'label' => 'ReasonDeclineOrCancel', 'enabled' => 1, 'position' => 73, 'notnull' => 0, 'visible' => -2,),
120
        'ip' => array('type' => 'ip', 'label' => 'IPOfApplicant', 'enabled' => 1, 'position' => 74, 'notnull' => 0, 'visible' => -2,),
121
        'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => 1, 'position' => 2000, 'notnull' => 1, 'visible' => 2, 'default' => '0', 'index' => 1, 'arrayofkeyval' => array('0' => 'Draft', '1' => 'Validated', '2' => 'Approved', '3' => 'Refused', '9' => 'Terminated'),),
122
    );
123
    public $rowid;
124
    public $ref;
125
    public $entity;
126
    public $fk_type;
127
    public $note_public;
128
    public $note_private;
129
    public $date_creation;
130
    public $fk_user_creat;
131
    public $fk_user_modif;
132
    public $last_main_doc;
133
    public $import_key;
134
    public $model_pdf;
135
    public $date_partnership_start;
136
    public $date_partnership_end;
137
    public $url_to_check;
138
    public $count_last_url_check_error;
139
    public $last_check_backlink;
140
    public $reason_decline_or_cancel;
141
    public $fk_soc;
142
    public $fk_member;
143
    public $ip;
144
    public $status;
145
    // END MODULEBUILDER PROPERTIES
146
147
148
    /**
149
     * Constructor
150
     *
151
     * @param DoliDB $db Database handler
152
     */
153
    public function __construct(DoliDB $db)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Partnerships\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
154
    {
155
        global $conf, $langs;
156
157
        $this->db = $db;
158
159
        $this->ismultientitymanaged = 0;
160
        $this->isextrafieldmanaged = 1;
161
162
        if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') {
163
            $this->fields['fk_member'] = array('type' => 'integer:Adherent:adherents/class/adherent.class.php:1', 'label' => 'Member', 'enabled' => '1', 'position' => 50, 'notnull' => -1, 'visible' => 1, 'index' => 1, 'picto' => 'member', 'csslist' => 'tdoverflowmax150');
164
        } else {
165
            $this->fields['fk_soc'] = array('type' => 'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label' => 'ThirdParty', 'enabled' => '1', 'position' => 50, 'notnull' => -1, 'visible' => 1, 'index' => 1, 'picto' => 'company', 'css' => 'maxwidth500', 'csslist' => 'tdoverflowmax150');
166
        }
167
168
        if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
169
            $this->fields['rowid']['visible'] = 0;
170
        }
171
172
        // Unset fields that are disabled
173
        foreach ($this->fields as $key => $val) {
174
            if (isset($val['enabled']) && empty($val['enabled'])) {
175
                unset($this->fields[$key]);
176
            }
177
        }
178
179
        // Translate some data of arrayofkeyval
180
        if (is_object($langs)) {
181
            foreach ($this->fields as $key => $val) {
182
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
183
                    foreach ($val['arrayofkeyval'] as $key2 => $val2) {
184
                        $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
185
                    }
186
                }
187
            }
188
        }
189
    }
190
191
    /**
192
     * Create object into database
193
     *
194
     * @param  User $user      User that creates
195
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
196
     * @return int             Return integer <0 if KO, Id of created object if OK
197
     */
198
    public function create(User $user, $notrigger = 0)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Partnerships\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
199
    {
200
        if ($this->fk_soc <= 0 && $this->fk_member <= 0) {
201
            $this->errors[] = "ErrorThirpdartyOrMemberidIsMandatory";
202
            return -1;
203
        }
204
205
        $this->status = 0;
206
        return $this->createCommon($user, $notrigger);
207
    }
208
209
    /**
210
     * Clone an object into another one
211
     *
212
     * @param   User    $user       User that creates
213
     * @param   int     $fromid     Id of object to clone
214
     * @return  mixed               New object created, <0 if KO
215
     */
216
    public function createFromClone(User $user, $fromid)
217
    {
218
        global $langs, $extrafields;
219
        $error = 0;
220
221
        dol_syslog(__METHOD__, LOG_DEBUG);
222
223
        $object = new self($this->db);
224
225
        $this->db->begin();
226
227
        // Load source object
228
        $result = $object->fetchCommon($fromid);
229
        if ($result > 0 && !empty($object->table_element_line)) {
230
            $object->fetchLines();
231
        }
232
233
        // get lines so they will be clone
234
        //foreach($this->lines as $line)
235
        //  $line->fetch_optionals();
236
237
        // Reset some properties
238
        unset($object->id);
239
        unset($object->fk_user_creat);
240
        unset($object->import_key);
241
242
        // Clear fields
243
        if (property_exists($object, 'ref')) {
244
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
245
        }
246
        if (property_exists($object, 'label')) {
247
            $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default'];
248
        }
249
        if (property_exists($object, 'status')) {
250
            $object->status = self::STATUS_DRAFT;
251
        }
252
        if (property_exists($object, 'date_creation')) {
253
            $object->date_creation = dol_now();
254
        }
255
        if (property_exists($object, 'date_modification')) {
256
            $object->date_modification = null;
257
        }
258
        // ...
259
        // Clear extrafields that are unique
260
        if (is_array($object->array_options) && count($object->array_options) > 0) {
261
            $extrafields->fetch_name_optionals_label($this->table_element);
262
            foreach ($object->array_options as $key => $option) {
263
                $shortkey = preg_replace('/options_/', '', $key);
264
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
265
                    //var_dump($key);
266
                    //var_dump($clonedObj->array_options[$key]); exit;
267
                    unset($object->array_options[$key]);
268
                }
269
            }
270
        }
271
272
        // Create clone
273
        $object->context['createfromclone'] = 'createfromclone';
274
        $result = $object->createCommon($user);
275
        if ($result < 0) {
276
            $error++;
277
            $this->error = $object->error;
278
            $this->errors = $object->errors;
279
        }
280
281
        if (!$error) {
282
            // copy internal contacts
283
            if ($this->copy_linked_contact($object, 'internal') < 0) {
284
                $error++;
285
            }
286
        }
287
288
        if (!$error) {
289
            // copy external contacts if same company
290
            if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
291
                if ($this->copy_linked_contact($object, 'external') < 0) {
292
                    $error++;
293
                }
294
            }
295
        }
296
297
        unset($object->context['createfromclone']);
298
299
        // End
300
        if (!$error) {
301
            $this->db->commit();
302
            return $object;
303
        } else {
304
            $this->db->rollback();
305
            return -1;
306
        }
307
    }
308
309
    /**
310
     * Load object in memory from the database
311
     * Get object from database. Get also lines.
312
     *
313
     *  @param      int         $id                     Id of object to load
314
     *  @param      string      $ref                    Ref of object
315
     *  @param      int         $fk_member              fk_member
316
     *  @param      int         $fk_soc                 fk_soc
317
     *  @return     int                                 >0 if OK, <0 if KO, 0 if not found
318
     */
319
    public function fetch($id, $ref = null, $fk_member = null, $fk_soc = null)
320
    {
321
        // Check parameters
322
        if (empty($id) && empty($ref) && empty($fk_member) && empty($fk_soc)) {
323
            return -1;
324
        }
325
326
        $sql = 'SELECT p.rowid, p.ref, p.fk_type, p.fk_soc, p.fk_member, p.status';
327
        $sql .= ', p.entity, p.date_partnership_start, p.date_partnership_end, p.date_creation';
328
        $sql .= ', p.fk_user_creat, p.tms, p.fk_user_modif, p.fk_user_modif';
329
        $sql .= ', p.note_private, p.note_public, p.url_to_check';
330
        $sql .= ', p.last_main_doc, p.count_last_url_check_error, p.last_check_backlink, p.reason_decline_or_cancel';
331
        $sql .= ', p.import_key, p.model_pdf';
332
        $sql .= ', pt.code as type_code, pt.label as type_label';
333
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'partnership as p';
334
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_partnership_type as pt ON p.fk_type = pt.rowid';
335
336
        if ($id) {
337
            $sql .= " WHERE p.rowid = " . ((int) $id);
338
        } else {
339
            $sql .= " WHERE p.entity IN (0," . getEntity('partnership') . ")"; // Don't use entity if you use rowid
340
        }
341
342
        if ($ref) {
343
            $sql .= " AND p.ref='" . $this->db->escape($ref) . "'";
344
        }
345
346
        if ($fk_member > 0) {
347
            $sql .= ' AND p.fk_member = ' . ((int) $fk_member);
348
        }
349
        if ($fk_soc > 0) {
350
            $sql .= ' AND p.fk_soc = ' . ((int) $fk_soc);
351
        }
352
        $sql .= ' ORDER BY p.date_partnership_end DESC';
353
354
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
355
        $result = $this->db->query($sql);
356
        if ($result) {
357
            $obj = $this->db->fetch_object($result);
358
            if ($obj) {
359
                $this->id                           = $obj->rowid;
360
                $this->entity                       = $obj->entity;
361
                $this->ref                          = $obj->ref;
362
363
                $this->fk_type                      = $obj->fk_type;
364
                $this->type_code                    = $obj->type_code;
365
                $this->type_label                   = $obj->type_label;
366
367
                $this->fk_soc                       = $obj->fk_soc;
368
                $this->fk_member                    = $obj->fk_member;
369
                $this->status                       = $obj->status;
370
                $this->date_partnership_start       = $this->db->jdate($obj->date_partnership_start);
371
                $this->date_partnership_end         = $this->db->jdate($obj->date_partnership_end);
372
                $this->date_creation                = $this->db->jdate($obj->date_creation);
373
                $this->fk_user_creat                = $obj->fk_user_creat;
374
                $this->tms                          = $obj->tms;
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$tms has been deprecated: Use $date_modification ( Ignorable by Annotation )

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

374
                /** @scrutinizer ignore-deprecated */ $this->tms                          = $obj->tms;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
375
                $this->fk_user_modif                = $obj->fk_user_modif;
376
                $this->note_private                 = $obj->note_private;
377
                $this->note_public                  = $obj->note_public;
378
                $this->last_main_doc                = $obj->last_main_doc;
379
                $this->count_last_url_check_error   = $obj->count_last_url_check_error;
380
                $this->last_check_backlink          = $this->db->jdate($obj->last_check_backlink);
381
                $this->reason_decline_or_cancel     = $obj->reason_decline_or_cancel;
382
                $this->import_key                   = $obj->import_key;
383
                $this->model_pdf                    = $obj->model_pdf;
384
                $this->url_to_check                 = $obj->url_to_check;
385
386
                // Retrieve all extrafield
387
                // fetch optionals attributes and labels
388
                $this->fetch_optionals();
389
390
                $this->db->free($result);
391
392
                return 1;
393
            } else {
394
                // $this->error = 'Partnership with id '.$id.' not found sql='.$sql;
395
                return 0;
396
            }
397
        } else {
398
            $this->error = $this->db->error();
399
            return -1;
400
        }
401
    }
402
403
404
    /**
405
     * Load object lines in memory from the database
406
     *
407
     * @return int         Return integer <0 if KO, 0 if not found, >0 if OK
408
     */
409
    public function fetchLines()
410
    {
411
        $this->lines = array();
412
413
        $result = $this->fetchLinesCommon();
414
        return $result;
415
    }
416
417
418
    /**
419
     * Load list of objects in memory from the database.
420
     *
421
     * @param  string           $sortorder      Sort Order
422
     * @param  string           $sortfield      Sort field
423
     * @param  int              $limit          Limit
424
     * @param  int              $offset         Offset page
425
     * @param  string|array     $filter         Filter USF.
426
     * @param  string           $filtermode     Filter mode (AND or OR)
427
     * @return array|int                        int <0 if KO, array of pages if OK
428
     */
429
    public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
430
    {
431
        dol_syslog(__METHOD__, LOG_DEBUG);
432
433
        $records = array();
434
435
        $sql = 'SELECT ';
436
        $sql .= $this->getFieldList('t');
437
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
438
        if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
439
            $sql .= ' WHERE t.entity IN (' . getEntity($this->element) . ')';
440
        } else {
441
            $sql .= ' WHERE 1 = 1';
442
        }
443
444
        // Manage filter
445
        if (is_array($filter)) {
446
            $sqlwhere = array();
447
            if (count($filter) > 0) {
448
                foreach ($filter as $key => $value) {
449
                    if ($key == 't.rowid') {
450
                        $sqlwhere[] = $this->db->sanitize($key) . " = " . ((int) $value);
451
                    } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) {
452
                        $sqlwhere[] = $this->db->sanitize($key) . " = '" . $this->db->idate($value) . "'";
453
                    } elseif (strpos($value, '%') === false) {
454
                        $sqlwhere[] = $this->db->sanitize($key) . " IN (" . $this->db->sanitize($this->db->escape($value)) . ")";
455
                    } else {
456
                        $sqlwhere[] = $this->db->sanitize($key) . " LIKE '%" . $this->db->escape($this->db->escapeforlike($value)) . "%'";
457
                    }
458
                }
459
            }
460
            if (count($sqlwhere) > 0) {
461
                $sql .= ' AND (' . implode(' ' . $this->db->escape($filtermode) . ' ', $sqlwhere) . ')';
462
            }
463
464
            $filter = '';
465
        }
466
467
        // Manage filter
468
        $errormessage = '';
469
        $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
470
        if ($errormessage) {
471
            $this->errors[] = $errormessage;
472
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
473
            return -1;
474
        }
475
476
        if (!empty($sortfield)) {
477
            $sql .= $this->db->order($sortfield, $sortorder);
478
        }
479
        if (!empty($limit)) {
480
            $sql .= $this->db->plimit($limit, $offset);
481
        }
482
483
        $resql = $this->db->query($sql);
484
        if ($resql) {
485
            $num = $this->db->num_rows($resql);
486
            $i = 0;
487
            while ($i < ($limit ? min($limit, $num) : $num)) {
488
                $obj = $this->db->fetch_object($resql);
489
490
                $record = new self($this->db);
491
                $record->setVarsFromFetchObj($obj);
492
493
                $records[$record->id] = $record;
494
495
                $i++;
496
            }
497
            $this->db->free($resql);
498
499
            return $records;
500
        } else {
501
            $this->errors[] = 'Error ' . $this->db->lasterror();
502
            dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
503
504
            return -1;
505
        }
506
    }
507
508
    /**
509
     * Update object into database
510
     *
511
     * @param  User $user      User that modifies
512
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
513
     * @return int             Return integer <0 if KO, >0 if OK
514
     */
515
    public function update(User $user, $notrigger = 0)
516
    {
517
        if ($this->fk_soc <= 0 && $this->fk_member <= 0) {
518
            $this->errors[] = "ErrorThirpdartyOrMemberidIsMandatory"; // Mistyping in key is in translations
519
            return -1;
520
        }
521
        if (empty($this->fk_user_creat)) {  // For the case the object was created with empty user (from public page).
522
            $this->fk_user_creat = $user->id;
523
        }
524
525
        return $this->updateCommon($user, $notrigger);
526
    }
527
528
    /**
529
     * Delete object in database
530
     *
531
     * @param User  $user       User that deletes
532
     * @param int   $notrigger  0=launch triggers after, 1=disable triggers
533
     * @return int              Return integer <0 if KO, >0 if OK
534
     */
535
    public function delete(User $user, $notrigger = 0)
536
    {
537
        return $this->deleteCommon($user, $notrigger);
538
        //return $this->deleteCommon($user, $notrigger, 1);
539
    }
540
541
    /**
542
     *  Delete a line of object in database
543
     *
544
     *  @param  User    $user       User that delete
545
     *  @param  int     $idline     Id of line to delete
546
     *  @param  int     $notrigger  0=launch triggers after, 1=disable triggers
547
     *  @return int                 >0 if OK, <0 if KO
548
     */
549
    public function deleteLine(User $user, $idline, $notrigger = 0)
550
    {
551
        if ($this->status < 0) {
552
            $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
553
            return -2;
554
        }
555
556
        return $this->deleteLineCommon($user, $idline, $notrigger);
557
    }
558
559
560
    /**
561
     *  Validate object
562
     *
563
     *  @param      User    $user           User making status change
564
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
565
     *  @return     int                     Return integer <=0 if OK, 0=Nothing done, >0 if KO
566
     */
567
    public function validate($user, $notrigger = 0)
568
    {
569
        global $conf;
570
571
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
572
573
        $error = 0;
574
575
        // Protection
576
        if ($this->status == self::STATUS_VALIDATED) {
577
            dol_syslog(get_class($this) . "::validate action abandoned: already validated", LOG_WARNING);
578
            return 0;
579
        }
580
581
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->write))
582
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->partnership_advance->validate))))
583
         {
584
         $this->error='NotEnoughPermissions';
585
         dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
586
         return -1;
587
         }*/
588
589
        $now = dol_now();
590
591
        $this->db->begin();
592
593
        // Define new ref
594
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
595
            $num = $this->getNextNumRef();
596
        } else {
597
            $num = $this->ref;
598
        }
599
        $this->newref = $num;
600
601
        if (!empty($num)) {
602
            // Validate
603
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
604
            $sql .= " SET ref = '" . $this->db->escape($num) . "',";
605
            $sql .= " status = " . self::STATUS_VALIDATED;
606
            if (!empty($this->fields['date_validation'])) {
607
                $sql .= ", date_validation = '" . $this->db->idate($now) . "'";
608
            }
609
            if (!empty($this->fields['fk_user_valid'])) {
610
                $sql .= ", fk_user_valid = " . $user->id;
611
            }
612
            $sql .= " WHERE rowid = " . ((int) $this->id);
613
614
            dol_syslog(get_class($this) . "::validate()", LOG_DEBUG);
615
            $resql = $this->db->query($sql);
616
            if (!$resql) {
617
                dol_print_error($this->db);
618
                $this->error = $this->db->lasterror();
619
                $error++;
620
            }
621
622
            if (!$error && !$notrigger) {
623
                // Call trigger
624
                $result = $this->call_trigger('PARTNERSHIP_VALIDATE', $user);
625
                if ($result < 0) {
626
                    $error++;
627
                }
628
                // End call triggers
629
            }
630
        }
631
632
        if (!$error) {
633
            $this->oldref = $this->ref;
634
635
            // Rename directory if dir was a temporary ref
636
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
637
                // Now we rename also files into index
638
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'partnership/" . $this->db->escape($this->newref) . "'";
639
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'partnership/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
640
                $resql = $this->db->query($sql);
641
                if (!$resql) {
642
                    $error++;
643
                    $this->error = $this->db->lasterror();
644
                }
645
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'partnership/" . $this->db->escape($this->newref) . "'";
646
                $sql .= " WHERE filepath = 'partnership/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
647
                $resql = $this->db->query($sql);
648
                if (!$resql) {
649
                    $error++;
650
                    $this->error = $this->db->lasterror();
651
                }
652
653
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
654
                $oldref = dol_sanitizeFileName($this->ref);
655
                $newref = dol_sanitizeFileName($num);
656
                $dirsource = $conf->partnership->dir_output . '/partnership/' . $oldref;
657
                $dirdest = $conf->partnership->dir_output . '/partnership/' . $newref;
658
                if (!$error && file_exists($dirsource)) {
659
                    dol_syslog(get_class($this) . "::validate() rename dir " . $dirsource . " into " . $dirdest);
660
661
                    if (@rename($dirsource, $dirdest)) {
662
                        dol_syslog("Rename ok");
663
                        // Rename docs starting with $oldref with $newref
664
                        $listoffiles = dol_dir_list($conf->partnership->dir_output . '/partnership/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
665
                        foreach ($listoffiles as $fileentry) {
666
                            $dirsource = $fileentry['name'];
667
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
668
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
669
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
670
                            @rename($dirsource, $dirdest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

670
                            /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
671
                        }
672
                    }
673
                }
674
            }
675
        }
676
677
        // Set new ref and current status
678
        if (!$error) {
679
            $this->ref = $num;
680
            $this->status = self::STATUS_VALIDATED;
681
        }
682
683
        if (!$error) {
684
            $this->db->commit();
685
            return 1;
686
        } else {
687
            $this->db->rollback();
688
            return -1;
689
        }
690
    }
691
692
    /**
693
     *  Approve object
694
     *
695
     *  @param      User    $user           User making status change
696
     *  @param      int     $notrigger      1=Does not execute triggers, 0= execute triggers
697
     *  @return     int                     Return integer <=0 if OK, 0=Nothing done, >0 if KO
698
     */
699
    public function approve($user, $notrigger = 0)
700
    {
701
        global $conf;
702
703
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
704
705
        $error = 0;
706
707
        // Protection
708
        if ($this->status == self::STATUS_APPROVED) {
709
            dol_syslog(get_class($this) . "::accept action abandoned: already acceptd", LOG_WARNING);
710
            return 0;
711
        }
712
713
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->write))
714
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->partnership_advance->accept))))
715
         {
716
         $this->error='NotEnoughPermissions';
717
         dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
718
         return -1;
719
         }*/
720
721
        $now = dol_now();
722
723
        $this->db->begin();
724
725
        // Define new ref
726
        if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
727
            $num = $this->getNextNumRef();
728
        } else {
729
            $num = $this->ref;
730
        }
731
        $this->newref = $num;
732
733
        if (!empty($num)) {
734
            // Accept
735
            $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element;
736
            $sql .= " SET ref = '" . $this->db->escape($num) . "',";
737
            $sql .= " status = " . self::STATUS_APPROVED;
738
            // if (!empty($this->fields['date_validation'])) {
739
            //  $sql .= ", date_validation = '".$this->db->idate($now)."'";
740
            // }
741
            // if (!empty($this->fields['fk_user_valid'])) {
742
            //  $sql .= ", fk_user_valid = ".$user->id;
743
            // }
744
            $sql .= " WHERE rowid = " . ((int) $this->id);
745
746
            dol_syslog(get_class($this) . "::accept()", LOG_DEBUG);
747
            $resql = $this->db->query($sql);
748
            if (!$resql) {
749
                dol_print_error($this->db);
750
                $this->error = $this->db->lasterror();
751
                $error++;
752
            }
753
754
            if (!$error && !$notrigger) {
755
                // Call trigger
756
                $result = $this->call_trigger('PARTNERSHIP_ACCEPT', $user);
757
                if ($result < 0) {
758
                    $error++;
759
                }
760
                // End call triggers
761
            }
762
        }
763
764
        if (!$error) {
765
            $this->oldref = $this->ref;
766
767
            // Rename directory if dir was a temporary ref
768
            if (preg_match('/^[\(]?PROV/i', $this->ref)) {
769
                // Now we rename also files into index
770
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filename = CONCAT('" . $this->db->escape($this->newref) . "', SUBSTR(filename, " . (strlen($this->ref) + 1) . ")), filepath = 'partnership/" . $this->db->escape($this->newref) . "'";
771
                $sql .= " WHERE filename LIKE '" . $this->db->escape($this->ref) . "%' AND filepath = 'partnership/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
772
                $resql = $this->db->query($sql);
773
                if (!$resql) {
774
                    $error++;
775
                    $this->error = $this->db->lasterror();
776
                }
777
                $sql = 'UPDATE ' . MAIN_DB_PREFIX . "ecm_files set filepath = 'partnership/" . $this->db->escape($this->newref) . "'";
778
                $sql .= " WHERE filepath = 'partnership/" . $this->db->escape($this->ref) . "' and entity = " . $conf->entity;
779
                $resql = $this->db->query($sql);
780
                if (!$resql) {
781
                    $error++;
782
                    $this->error = $this->db->lasterror();
783
                }
784
785
                // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
786
                $oldref = dol_sanitizeFileName($this->ref);
787
                $newref = dol_sanitizeFileName($num);
788
                $dirsource = $conf->partnership->dir_output . '/partnership/' . $oldref;
789
                $dirdest = $conf->partnership->dir_output . '/partnership/' . $newref;
790
                if (!$error && file_exists($dirsource)) {
791
                    dol_syslog(get_class($this) . "::accept() rename dir " . $dirsource . " into " . $dirdest);
792
793
                    if (@rename($dirsource, $dirdest)) {
794
                        dol_syslog("Rename ok");
795
                        // Rename docs starting with $oldref with $newref
796
                        $listoffiles = dol_dir_list($conf->partnership->dir_output . '/partnership/' . $newref, 'files', 1, '^' . preg_quote($oldref, '/'));
797
                        foreach ($listoffiles as $fileentry) {
798
                            $dirsource = $fileentry['name'];
799
                            $dirdest = preg_replace('/^' . preg_quote($oldref, '/') . '/', $newref, $dirsource);
800
                            $dirsource = $fileentry['path'] . '/' . $dirsource;
801
                            $dirdest = $fileentry['path'] . '/' . $dirdest;
802
                            @rename($dirsource, $dirdest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

802
                            /** @scrutinizer ignore-unhandled */ @rename($dirsource, $dirdest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
803
                        }
804
                    }
805
                }
806
            }
807
        }
808
809
        // Set new ref and current status
810
        if (!$error) {
811
            $this->ref = $num;
812
            $this->status = self::STATUS_APPROVED;
813
        }
814
815
        if (!$error) {
816
            $this->db->commit();
817
            return 1;
818
        } else {
819
            $this->db->rollback();
820
            return -1;
821
        }
822
    }
823
824
825
    /**
826
     *  Set draft status
827
     *
828
     *  @param  User    $user           Object user that modify
829
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
830
     *  @return int                     Return integer <0 if KO, >0 if OK
831
     */
832
    public function setDraft($user, $notrigger = 0)
833
    {
834
        // Protection
835
        if ($this->status <= self::STATUS_DRAFT) {
836
            return 0;
837
        }
838
839
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->write))
840
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership_advance->validate))))
841
         {
842
         $this->error='Permission denied';
843
         return -1;
844
         }*/
845
846
        return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'PARTNERSHIP_UNVALIDATE');
847
    }
848
849
    /**
850
     *  Set refused status
851
     *
852
     *  @param  User    $user               Object user that modify
853
     *  @param  string  $reasondeclinenote  Reason decline
854
     *  @param  int     $notrigger          1=Does not execute triggers, 0=Execute triggers
855
     *  @return int                         Return integer <0 if KO, 0=Nothing done, >0 if OK
856
     */
857
    public function refused($user, $reasondeclinenote = '', $notrigger = 0)
858
    {
859
        // Protection
860
        if ($this->status == self::STATUS_REFUSED) {
861
            return 0;
862
        }
863
864
        $this->status                   = self::STATUS_REFUSED;
865
        $this->reason_decline_or_cancel = $reasondeclinenote;
866
867
        $result = $this->update($user);
868
869
        if ($result) {
870
            $this->reason_decline_or_cancel = $reasondeclinenote;
871
            return 1;
872
        }
873
874
        return -1;
875
    }
876
877
    /**
878
     *  Set cancel status
879
     *
880
     *  @param  User    $user           Object user that modify
881
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
882
     *  @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
883
     */
884
    public function cancel($user, $notrigger = 0)
885
    {
886
        // Protection
887
        if ($this->status != self::STATUS_APPROVED) {
888
            return 0;
889
        }
890
891
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->write))
892
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership_advance->validate))))
893
         {
894
         $this->error='Permission denied';
895
         return -1;
896
         }*/
897
898
        return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'PARTNERSHIP_CANCEL');
899
    }
900
901
    /**
902
     *  Set back to validated status
903
     *
904
     *  @param  User    $user           Object user that modify
905
     *  @param  int     $notrigger      1=Does not execute triggers, 0=Execute triggers
906
     *  @return int                     Return integer <0 if KO, 0=Nothing done, >0 if OK
907
     */
908
    public function reopen($user, $notrigger = 0)
909
    {
910
        // Protection
911
        if ($this->status != self::STATUS_CANCELED && $this->status != self::STATUS_REFUSED) {
912
            return 0;
913
        }
914
915
        /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership->write))
916
         || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->partnership_advance->validate))))
917
         {
918
         $this->error='Permission denied';
919
         return -1;
920
         }*/
921
922
        return $this->setStatusCommon($user, self::STATUS_APPROVED, $notrigger, 'PARTNERSHIP_REOPEN');
923
    }
924
925
    /**
926
     * getTooltipContentArray
927
     *
928
     * @param array $params ex option, infologin
929
     * @since v18
930
     * @return array
931
     */
932
    public function getTooltipContentArray($params)
933
    {
934
        global $langs;
935
936
        $langs->load('partnership');
937
938
        $datas = [];
939
        $datas['picto'] = img_picto('', $this->picto) . ' <u>' . $langs->trans("Partnership") . '</u>';
940
        if (isset($this->status)) {
941
            $datas['picto'] .= ' ' . $this->getLibStatut(5);
942
        }
943
        $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
944
945
        return $datas;
946
    }
947
948
    /**
949
     *  Return a link to the object card (with optionally the picto)
950
     *
951
     *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
952
     *  @param  string  $option                     On what the link point to ('nolink', ...)
953
     *  @param  int     $notooltip                  1=Disable tooltip
954
     *  @param  string  $morecss                    Add more css on link
955
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
956
     *  @return string                              String with URL
957
     */
958
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
959
    {
960
        global $conf, $langs, $hookmanager;
961
962
        if (!empty($conf->dol_no_mouse_hover)) {
963
            $notooltip = 1; // Force disable tooltips
964
        }
965
966
        $result = '';
967
        $params = [
968
            'id' => $this->id,
969
            'objecttype' => $this->element,
970
            'option' => $option,
971
        ];
972
        $classfortooltip = 'classfortooltip';
973
        $dataparams = '';
974
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
975
            $classfortooltip = 'classforajaxtooltip';
976
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
977
            $label = '';
978
        } else {
979
            $label = implode($this->getTooltipContentArray($params));
980
        }
981
982
        $url = constant('BASE_URL') . '/partnership/partnership_card.php?id=' . $this->id;
983
984
        if ($option != 'nolink') {
985
            // Add param to save lastsearch_values or not
986
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
987
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
988
                $add_save_lastsearch_values = 1;
989
            }
990
            if ($add_save_lastsearch_values) {
991
                $url .= '&save_lastsearch_values=1';
992
            }
993
        }
994
995
        $linkclose = '';
996
        if (empty($notooltip)) {
997
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
998
                $label = $langs->trans("ShowPartnership");
999
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1000
            }
1001
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
1002
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
1003
        } else {
1004
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1005
        }
1006
1007
        if ($option == 'nolink') {
1008
            $linkstart = '<span';
1009
        } else {
1010
            $linkstart = '<a href="' . $url . '"';
1011
        }
1012
        $linkstart .= $linkclose . '>';
1013
        if ($option == 'nolink') {
1014
            $linkend = '</span>';
1015
        } else {
1016
            $linkend = '</a>';
1017
        }
1018
1019
        $result .= $linkstart;
1020
1021
        if (empty($this->showphoto_on_popup)) {
1022
            if ($withpicto) {
1023
                $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams . ' class="' . (($withpicto != 2) ? 'paddingright ' : '') . $classfortooltip . '"'), 0, 0, $notooltip ? 0 : 1);
1024
            }
1025
        } else {
1026
            if ($withpicto) {
1027
                require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
1028
1029
                list($class, $module) = explode('@', $this->picto);
1030
                $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
1031
                $filearray = dol_dir_list($upload_dir, "files");
1032
                $filename = $filearray[0]['name'];
1033
                if (!empty($filename)) {
1034
                    $pospoint = strpos($filearray[0]['name'], '.');
1035
1036
                    $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
1037
                    if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
1038
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo' . $module . '" alt="No photo" border="0" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div></div>';
1039
                    } else {
1040
                        $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div>';
1041
                    }
1042
1043
                    $result .= '</div>';
1044
                } else {
1045
                    $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1046
                }
1047
            }
1048
        }
1049
1050
        if ($withpicto != 2) {
1051
            $result .= $this->ref;
1052
        }
1053
1054
        $result .= $linkend;
1055
        //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1056
1057
        global $action, $hookmanager;
1058
        $hookmanager->initHooks(array('partnershipdao'));
1059
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1060
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1061
        if ($reshook > 0) {
1062
            $result = $hookmanager->resPrint;
1063
        } else {
1064
            $result .= $hookmanager->resPrint;
1065
        }
1066
1067
        return $result;
1068
    }
1069
1070
    /**
1071
     * Function used to replace a thirdparty id with another one.
1072
     *
1073
     * @param DoliDB    $db             Database handler
1074
     * @param int       $origin_id      Old thirdparty id
1075
     * @param int       $dest_id        New thirdparty id
1076
     * @return bool
1077
     */
1078
    public static function replaceThirdparty($db, $origin_id, $dest_id)
1079
    {
1080
        $tables = array('partnership');
1081
1082
        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1083
    }
1084
1085
    /**
1086
     *  Return the label of the status
1087
     *
1088
     *  @param  int     $mode          0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
1089
     *  @return string                 Label of status
1090
     */
1091
    public function getLibStatut($mode = 0)
1092
    {
1093
        return $this->LibStatut($this->status, $mode);
1094
    }
1095
1096
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1097
    /**
1098
     *  Return the status
1099
     *
1100
     *  @param  int     $status        Id status
1101
     *  @param  int     $mode          0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
1102
     *  @return string                 Label of status
1103
     */
1104
    public function LibStatut($status, $mode = 0)
1105
    {
1106
		// phpcs:enable
1107
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1108
            global $langs;
1109
            //$langs->load("partnership");
1110
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1111
            $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
1112
            $this->labelStatus[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('Approved');
1113
            $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
1114
            $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Terminated');
1115
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1116
            $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated');
1117
            $this->labelStatusShort[self::STATUS_APPROVED] = $langs->transnoentitiesnoconv('Approved');
1118
            $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
1119
            $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Terminated');
1120
        }
1121
1122
        $statusType = 'status' . $status;
1123
        if ($status == self::STATUS_APPROVED) {
1124
            $statusType = 'status4';
1125
        }
1126
        if ($status == self::STATUS_REFUSED) {
1127
            $statusType = 'status9';
1128
        }
1129
        if ($status == self::STATUS_CANCELED) {
1130
            $statusType = 'status6';
1131
        }
1132
1133
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1134
    }
1135
1136
    /**
1137
     *  Load the info information in the object
1138
     *
1139
     *  @param  int     $id       Id of object
1140
     *  @return void
1141
     */
1142
    public function info($id)
1143
    {
1144
        $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
1145
        $sql .= ' fk_user_creat, fk_user_modif';
1146
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
1147
        $sql .= ' WHERE t.rowid = ' . ((int) $id);
1148
        $result = $this->db->query($sql);
1149
        if ($result) {
1150
            if ($this->db->num_rows($result)) {
1151
                $obj = $this->db->fetch_object($result);
1152
1153
                $this->id = $obj->rowid;
1154
1155
                $this->user_creation_id = $obj->fk_user_creat;
1156
                $this->user_modification_id = $obj->fk_user_modif;
1157
                $this->date_creation     = $this->db->jdate($obj->datec);
1158
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1159
            }
1160
1161
            $this->db->free($result);
1162
        } else {
1163
            dol_print_error($this->db);
1164
        }
1165
    }
1166
1167
    /**
1168
     * Initialise object with example values
1169
     * Id must be 0 if object instance is a specimen
1170
     *
1171
     * @return int
1172
     */
1173
    public function initAsSpecimen()
1174
    {
1175
        return $this->initAsSpecimenCommon();
1176
    }
1177
1178
    /**
1179
     *  Create an array of lines
1180
     *
1181
     *  @return array|int       array of lines if OK, <0 if KO
1182
     */
1183
    public function getLinesArray()
1184
    {
1185
        $this->lines = array();
1186
1187
        $objectline = new PartnershipLine($this->db);
1188
        $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_partnership:=:' . ((int) $this->id) . ')');
1189
1190
        if (is_numeric($result)) {
1191
            $this->error = $objectline->error;
1192
            $this->errors = $objectline->errors;
1193
            return $result;
1194
        } else {
1195
            $this->lines = $result;
1196
            return $this->lines;
1197
        }
1198
    }
1199
1200
    /**
1201
     *  Returns the reference to the following non used object depending on the active numbering module.
1202
     *
1203
     *  @return string              Object free reference
1204
     */
1205
    public function getNextNumRef()
1206
    {
1207
        global $langs, $conf;
1208
        $langs->load("partnership");
1209
1210
        if (!getDolGlobalString('PARTNERSHIP_ADDON')) {
1211
            $conf->global->PARTNERSHIP_ADDON = 'mod_partnership_standard';
1212
        }
1213
1214
        if (getDolGlobalString('PARTNERSHIP_ADDON')) {
1215
            $mybool = false;
1216
1217
            $file = getDolGlobalString('PARTNERSHIP_ADDON') . ".php";
1218
            $classname = getDolGlobalString('PARTNERSHIP_ADDON');
1219
1220
            // Include file with class
1221
            $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1222
            foreach ($dirmodels as $reldir) {
1223
                $dir = dol_buildpath($reldir . "core/modules/partnership/");
1224
1225
                // Load file with numbering class (if found)
1226
                $mybool = ((bool) @include_once $dir . $file) || $mybool;
1227
            }
1228
1229
            if ($mybool === false) {
1230
                dol_print_error(null, "Failed to include file " . $file);
1231
                return '';
1232
            }
1233
1234
            if (class_exists($classname)) {
1235
                $obj = new $classname();
1236
                $numref = $obj->getNextValue($this);
1237
1238
                if ($numref != '' && $numref != '-1') {
1239
                    return $numref;
1240
                } else {
1241
                    $this->error = $obj->error;
1242
                    //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1243
                    return "";
1244
                }
1245
            } else {
1246
                print $langs->trans("Error") . " " . $langs->trans("ClassNotFound") . ' ' . $classname;
1247
                return "";
1248
            }
1249
        } else {
1250
            print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1251
            return "";
1252
        }
1253
    }
1254
1255
    /**
1256
     *  Create a document onto disk according to template module.
1257
     *
1258
     *  @param      string      $modele         Force template to use ('' to not force)
1259
     *  @param      Translate   $outputlangs    object lang a utiliser pour traduction
1260
     *  @param      int         $hidedetails    Hide details of lines
1261
     *  @param      int         $hidedesc       Hide description
1262
     *  @param      int         $hideref        Hide ref
1263
     *  @param      null|array  $moreparams     Array to provide more information
1264
     *  @return     int                         0 if KO, 1 if OK
1265
     */
1266
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1267
    {
1268
        global $conf, $langs;
1269
1270
        $result = 0;
1271
        $includedocgeneration = 0;
1272
1273
        $langs->load("partnership");
1274
1275
        if (!dol_strlen($modele)) {
1276
            $modele = 'standard_partnership';
1277
1278
            if (!empty($this->model_pdf)) {
1279
                $modele = $this->model_pdf;
1280
            } elseif (getDolGlobalString('PARTNERSHIP_ADDON_PDF')) {
1281
                $modele = getDolGlobalString('PARTNERSHIP_ADDON_PDF');
1282
            }
1283
        }
1284
1285
        $modelpath = "core/modules/partnership/doc/";
1286
1287
        if ($includedocgeneration && !empty($modele)) {
1288
            $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1289
        }
1290
1291
        return $result;
1292
    }
1293
1294
    /**
1295
     * Action executed by scheduler
1296
     * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters'
1297
     * Use public function doScheduledJob($param1, $param2, ...) to get parameters
1298
     *
1299
     * @return  int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
1300
     */
1301
    public function doScheduledJob()
1302
    {
1303
        //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1304
1305
        $error = 0;
1306
        $this->output = '';
1307
        $this->error = '';
1308
1309
        dol_syslog(__METHOD__, LOG_DEBUG);
1310
1311
        //$now = dol_now();
1312
1313
        $this->db->begin();
1314
1315
        // ...
1316
1317
        $this->db->commit();
1318
1319
        return $error;
1320
    }
1321
1322
    /**
1323
     *  Return a thumb for kanban views
1324
     *
1325
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
1326
     *  @param      array       $arraydata              Array of data
1327
     *  @return     string                              HTML Code for Kanban thumb.
1328
     */
1329
    public function getKanbanView($option = '', $arraydata = null)
1330
    {
1331
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1332
1333
        $return = '<div class="box-flex-item box-flex-grow-zero">';
1334
        $return .= '<div class="info-box info-box-sm">';
1335
        $return .= '<span class="info-box-icon bg-infobox-action">';
1336
        $return .= img_picto('', $this->picto);
1337
        $return .= '</span>';
1338
        $return .= '<div class="info-box-content">';
1339
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref) . '</span>';
1340
        if ($selected >= 0) {
1341
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
1342
        }
1343
        if (property_exists($this, 'label')) {
1344
            $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">' . $this->label . '</div>';
1345
        }
1346
        if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
1347
            $return .= '<br><div class="info-box-ref tdoverflowmax150">' . $this->thirdparty->getNomUrl(1) . '</div>';
1348
        }
1349
        if (method_exists($this, 'getLibStatut')) {
1350
            $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
1351
        }
1352
        $return .= '</div>';
1353
        $return .= '</div>';
1354
        $return .= '</div>';
1355
1356
        return $return;
1357
    }
1358
}
1359