Passed
Push — dev ( f7d146...05f415 )
by Rafael
60:50
created

Partnership::createFromClone()   F

Complexity

Conditions 22
Paths 13824

Size

Total Lines 90
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 47
nc 13824
nop 2
dl 0
loc 90
rs 0
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
use DoliDB;
27
28
/**
29
 * \file        htdocs/partnership/class/partnership.class.php
30
 * \ingroup     partnership
31
 * \brief       This file is a CRUD class file for Partnership (Create/Read/Update/Delete)
32
 */
33
34
/**
35
 * Class for Partnership
36
 */
37
class Partnership extends CommonObject
38
{
39
    /**
40
     * @var string ID of module.
41
     */
42
    public $module = 'partnership';
43
44
    /**
45
     * @var string ID to identify managed object.
46
     */
47
    public $element = 'partnership';
48
49
    /**
50
     * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management.
51
     */
52
    public $table_element = 'partnership';
53
54
    /**
55
     * @var string String with name of icon for partnership. Must be the part after the 'object_' into object_partnership.png
56
     */
57
    public $picto = 'partnership';
58
59
    public $type_code;
60
    public $type_label;
61
62
63
    const STATUS_DRAFT = 0;
64
    const STATUS_VALIDATED = 1;     // Validate (no more draft)
65
    const STATUS_APPROVED = 2;      // Approved
66
    const STATUS_REFUSED = 3;       // Refused
67
    const STATUS_CANCELED = 9;
68
69
70
    /**
71
     *  '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')
72
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
73
     *  'label' the translation key.
74
     *  'picto' is code of a picto to show before value in forms
75
     *  'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalString("MY_SETUP_PARAM")'
76
     *  'position' is the sort order of field.
77
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
78
     *  '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)
79
     *  'noteditable' says if field is not editable (1 or 0)
80
     *  '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.
81
     *  'index' if we want an index in database.
82
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
83
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
84
     *  '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).
85
     *  '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'
86
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
87
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
88
     *  '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.
89
     *  'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
90
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
91
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
92
     *
93
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
94
     */
95
96
    // BEGIN MODULEBUILDER PROPERTIES
97
    /**
98
     * @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...
99
     */
100
    public $fields = array(
101
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
102
        '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'),
103
        'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 'isModEnabled("multicompany")', 'position' => 15, 'notnull' => 1, 'visible' => -2, 'default' => '1', 'index' => 1,),
104
        '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'),
105
        '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',),
106
        'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
107
        'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
108
        'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'csslist' => 'nowraponall'),
109
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'csslist' => 'nowraponall'),
110
        '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'),
111
        'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'csslist' => 'tdoverflowmax125'),
112
        'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
113
        'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
114
        'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
115
        'date_partnership_start' => array('type' => 'date', 'label' => 'DatePartnershipStart', 'enabled' => 1, 'position' => 52, 'notnull' => 1, 'visible' => 1,),
116
        'date_partnership_end' => array('type' => 'date', 'label' => 'DatePartnershipEnd', 'enabled' => 1, 'position' => 53, 'notnull' => 0, 'visible' => 1,),
117
        'url_to_check' => array('type' => 'url', 'label' => 'UrlToCheck', 'enabled' => 'getDolGlobalString("PARTNERSHIP_BACKLINKS_TO_CHECK")', 'position' => 70, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150'),
118
        'count_last_url_check_error' => array('type' => 'integer', 'label' => 'CountLastUrlCheckError', 'enabled' => 'getDolGlobalString("PARTNERSHIP_BACKLINKS_TO_CHECK")', 'position' => 71, 'notnull' => 0, 'visible' => -4, 'default' => '0',),
119
        'last_check_backlink' => array('type' => 'datetime', 'label' => 'LastCheckBacklink', 'enabled' => 'getDolGlobalString("PARTNERSHIP_BACKLINKS_TO_CHECK")', 'position' => 72, 'notnull' => 0, 'visible' => -4, 'csslist' => 'nowraponall'),
120
        'reason_decline_or_cancel' => array('type' => 'text', 'label' => 'ReasonDeclineOrCancel', 'enabled' => 1, 'position' => 73, 'notnull' => 0, 'visible' => -2,),
121
        'ip' => array('type' => 'ip', 'label' => 'IPOfApplicant', 'enabled' => 1, 'position' => 74, 'notnull' => 0, 'visible' => -2,),
122
        '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'),),
123
    );
124
    public $rowid;
125
    public $ref;
126
    public $entity;
127
    public $fk_type;
128
    public $note_public;
129
    public $note_private;
130
    public $date_creation;
131
    public $fk_user_creat;
132
    public $fk_user_modif;
133
    public $last_main_doc;
134
    public $import_key;
135
    public $model_pdf;
136
    public $date_partnership_start;
137
    public $date_partnership_end;
138
    public $url_to_check;
139
    public $count_last_url_check_error;
140
    public $last_check_backlink;
141
    public $reason_decline_or_cancel;
142
    public $fk_soc;
143
    public $fk_member;
144
    public $ip;
145
    public $status;
146
    // END MODULEBUILDER PROPERTIES
147
148
149
    /**
150
     * Constructor
151
     *
152
     * @param DoliDB $db Database handler
153
     */
154
    public function __construct(DoliDB $db)
155
    {
156
        global $conf, $langs;
157
158
        $this->db = $db;
159
160
        $this->ismultientitymanaged = 0;
161
        $this->isextrafieldmanaged = 1;
162
163
        if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') {
164
            $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');
165
        } else {
166
            $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');
167
        }
168
169
        if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
170
            $this->fields['rowid']['visible'] = 0;
171
        }
172
173
        // Unset fields that are disabled
174
        foreach ($this->fields as $key => $val) {
175
            if (isset($val['enabled']) && empty($val['enabled'])) {
176
                unset($this->fields[$key]);
177
            }
178
        }
179
180
        // Translate some data of arrayofkeyval
181
        if (is_object($langs)) {
182
            foreach ($this->fields as $key => $val) {
183
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
184
                    foreach ($val['arrayofkeyval'] as $key2 => $val2) {
185
                        $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
186
                    }
187
                }
188
            }
189
        }
190
    }
191
192
    /**
193
     * Create object into database
194
     *
195
     * @param  User $user      User that creates
196
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
197
     * @return int             Return integer <0 if KO, Id of created object if OK
198
     */
199
    public function create(User $user, $notrigger = 0)
200
    {
201
        if ($this->fk_soc <= 0 && $this->fk_member <= 0) {
202
            $this->errors[] = "ErrorThirpdartyOrMemberidIsMandatory";
203
            return -1;
204
        }
205
206
        $this->status = 0;
207
        return $this->createCommon($user, $notrigger);
208
    }
209
210
    /**
211
     * Clone an object into another one
212
     *
213
     * @param   User    $user       User that creates
214
     * @param   int     $fromid     Id of object to clone
215
     * @return  mixed               New object created, <0 if KO
216
     */
217
    public function createFromClone(User $user, $fromid)
218
    {
219
        global $langs, $extrafields;
220
        $error = 0;
221
222
        dol_syslog(__METHOD__, LOG_DEBUG);
223
224
        $object = new self($this->db);
225
226
        $this->db->begin();
227
228
        // Load source object
229
        $result = $object->fetchCommon($fromid);
230
        if ($result > 0 && !empty($object->table_element_line)) {
231
            $object->fetchLines();
232
        }
233
234
        // get lines so they will be clone
235
        //foreach($this->lines as $line)
236
        //  $line->fetch_optionals();
237
238
        // Reset some properties
239
        unset($object->id);
240
        unset($object->fk_user_creat);
241
        unset($object->import_key);
242
243
        // Clear fields
244
        if (property_exists($object, 'ref')) {
245
            $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default'];
246
        }
247
        if (property_exists($object, 'label')) {
248
            $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default'];
249
        }
250
        if (property_exists($object, 'status')) {
251
            $object->status = self::STATUS_DRAFT;
252
        }
253
        if (property_exists($object, 'date_creation')) {
254
            $object->date_creation = dol_now();
255
        }
256
        if (property_exists($object, 'date_modification')) {
257
            $object->date_modification = null;
258
        }
259
        // ...
260
        // Clear extrafields that are unique
261
        if (is_array($object->array_options) && count($object->array_options) > 0) {
262
            $extrafields->fetch_name_optionals_label($this->table_element);
263
            foreach ($object->array_options as $key => $option) {
264
                $shortkey = preg_replace('/options_/', '', $key);
265
                if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
266
                    //var_dump($key);
267
                    //var_dump($clonedObj->array_options[$key]); exit;
268
                    unset($object->array_options[$key]);
269
                }
270
            }
271
        }
272
273
        // Create clone
274
        $object->context['createfromclone'] = 'createfromclone';
275
        $result = $object->createCommon($user);
276
        if ($result < 0) {
277
            $error++;
278
            $this->error = $object->error;
279
            $this->errors = $object->errors;
280
        }
281
282
        if (!$error) {
283
            // copy internal contacts
284
            if ($this->copy_linked_contact($object, 'internal') < 0) {
285
                $error++;
286
            }
287
        }
288
289
        if (!$error) {
290
            // copy external contacts if same company
291
            if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
292
                if ($this->copy_linked_contact($object, 'external') < 0) {
293
                    $error++;
294
                }
295
            }
296
        }
297
298
        unset($object->context['createfromclone']);
299
300
        // End
301
        if (!$error) {
302
            $this->db->commit();
303
            return $object;
304
        } else {
305
            $this->db->rollback();
306
            return -1;
307
        }
308
    }
309
310
    /**
311
     * Load object in memory from the database
312
     * Get object from database. Get also lines.
313
     *
314
     *  @param      int         $id                     Id of object to load
315
     *  @param      string      $ref                    Ref of object
316
     *  @param      int         $fk_member              fk_member
317
     *  @param      int         $fk_soc                 fk_soc
318
     *  @return     int                                 >0 if OK, <0 if KO, 0 if not found
319
     */
320
    public function fetch($id, $ref = null, $fk_member = null, $fk_soc = null)
321
    {
322
        // Check parameters
323
        if (empty($id) && empty($ref) && empty($fk_member) && empty($fk_soc)) {
324
            return -1;
325
        }
326
327
        $sql = 'SELECT p.rowid, p.ref, p.fk_type, p.fk_soc, p.fk_member, p.status';
328
        $sql .= ', p.entity, p.date_partnership_start, p.date_partnership_end, p.date_creation';
329
        $sql .= ', p.fk_user_creat, p.tms, p.fk_user_modif, p.fk_user_modif';
330
        $sql .= ', p.note_private, p.note_public, p.url_to_check';
331
        $sql .= ', p.last_main_doc, p.count_last_url_check_error, p.last_check_backlink, p.reason_decline_or_cancel';
332
        $sql .= ', p.import_key, p.model_pdf';
333
        $sql .= ', pt.code as type_code, pt.label as type_label';
334
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'partnership as p';
335
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_partnership_type as pt ON p.fk_type = pt.rowid';
336
337
        if ($id) {
338
            $sql .= " WHERE p.rowid = " . ((int) $id);
339
        } else {
340
            $sql .= " WHERE p.entity IN (0," . getEntity('partnership') . ")"; // Don't use entity if you use rowid
341
        }
342
343
        if ($ref) {
344
            $sql .= " AND p.ref='" . $this->db->escape($ref) . "'";
345
        }
346
347
        if ($fk_member > 0) {
348
            $sql .= ' AND p.fk_member = ' . ((int) $fk_member);
349
        }
350
        if ($fk_soc > 0) {
351
            $sql .= ' AND p.fk_soc = ' . ((int) $fk_soc);
352
        }
353
        $sql .= ' ORDER BY p.date_partnership_end DESC';
354
355
        dol_syslog(get_only_class($this) . "::fetch", LOG_DEBUG);
356
        $result = $this->db->query($sql);
357
        if ($result) {
358
            $obj = $this->db->fetch_object($result);
359
            if ($obj) {
360
                $this->id                           = $obj->rowid;
361
                $this->entity                       = $obj->entity;
362
                $this->ref                          = $obj->ref;
363
364
                $this->fk_type                      = $obj->fk_type;
365
                $this->type_code                    = $obj->type_code;
366
                $this->type_label                   = $obj->type_label;
367
368
                $this->fk_soc                       = $obj->fk_soc;
369
                $this->fk_member                    = $obj->fk_member;
370
                $this->status                       = $obj->status;
371
                $this->date_partnership_start       = $this->db->jdate($obj->date_partnership_start);
372
                $this->date_partnership_end         = $this->db->jdate($obj->date_partnership_end);
373
                $this->date_creation                = $this->db->jdate($obj->date_creation);
374
                $this->fk_user_creat                = $obj->fk_user_creat;
375
                $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

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

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

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