Passed
Push — EXTRACT_CLASSES ( c25e41...9f3ede )
by Rafael
55:18
created

EcmDirectory::fetch()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 43
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 33
nc 5
nop 1
dl 0
loc 43
rs 9.392
c 0
b 0
f 0
1
<?php
2
3
/* Copyright (C) 2007-2012  Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2008-2012  Regis Houssin               <[email protected]>
5
 * Copyright (C) 2024       Frédéric France             <[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Dolibarr\Code\Ecm\Classes;
23
24
use Dolibarr\Core\Base\CommonObject;
25
26
/**
27
 *  \file       htdocs/ecm/class/ecmdirectory.class.php
28
 *  \ingroup    ecm
29
 *  \brief      This file is an example for a class file
30
 */
31
32
/**
33
 *  Class to manage ECM directories
34
 */
35
class EcmDirectory extends CommonObject
36
{
37
    /**
38
     * @var string ID to identify managed object
39
     */
40
    public $element = 'ecm_directories';
41
42
    /**
43
     * @var string Name of table without prefix where object is stored
44
     */
45
    public $table_element = 'ecm_directories';
46
47
    /**
48
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
49
     */
50
    public $picto = 'folder-open';
51
52
    /**
53
     * @var int ID
54
     */
55
    public $id;
56
57
    /**
58
     * @var string ECM directories label
59
     */
60
    public $label;
61
62
    /**
63
     * @var int ID
64
     */
65
    public $fk_parent;
66
67
    /**
68
     * @var string description
69
     */
70
    public $description;
71
72
    /**
73
     * @var int cache nb of doc
74
     */
75
    public $cachenbofdoc = -1; // By default cache initialized with value 'not calculated'
76
77
    /**
78
     * @var int date_c
79
     */
80
    public $date_c;
81
82
    /**
83
     * @var int date_m
84
     */
85
    public $date_m;
86
87
    /**
88
     * @var int ID
89
     */
90
    public $fk_user_m;
91
92
    /**
93
     * @var int ID
94
     */
95
    public $fk_user_c;
96
97
    /**
98
     * @var string Ref
99
     */
100
    public $ref;
101
102
    /**
103
     * @var array array of categories
104
     */
105
    public $cats = array();
106
107
    /**
108
     * @var array array of children categories
109
     */
110
    public $motherof = array();
111
112
    /**
113
     * @var array array of forbidden chars
114
     */
115
    public $forbiddenchars = array('<', '>', ':', '/', '\\', '?', '*', '|', '"');
116
117
    /**
118
     * @var array array of forbidden chars for dir
119
     */
120
    public $forbiddencharsdir = array('<', '>', ':', '?', '*', '|', '"');
121
122
    /**
123
     * @var int 1 if full arbo loaded
124
     */
125
    public $full_arbo_loaded;
126
127
    /**
128
     *  Constructor
129
     *
130
     *  @param      DoliDB      $db      Database handler
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Ecm\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
131
     */
132
    public function __construct($db)
133
    {
134
        $this->db = $db;
135
    }
136
137
138
    /**
139
     *  Create record into database
140
     *
141
     *  @param      User    $user       User that create
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Ecm\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
142
     *  @return     int                 Return integer <0 if KO, >0 if OK
143
     */
144
    public function create($user)
145
    {
146
        global $conf, $langs;
147
148
        $error = 0;
149
        $now = dol_now();
150
151
        // Clean parameters
152
        $this->label = dol_sanitizeFileName(trim($this->label));
153
        $this->description = trim($this->description);
154
        $this->date_c = $now;
155
        $this->fk_user_c = $user->id;
156
        if ($this->fk_parent <= 0) {
157
            $this->fk_parent = 0;
158
        }
159
160
161
        // Check if same directory does not exists with this name
162
        $relativepath = $this->label;
163
        if ($this->fk_parent > 0) {
164
            $parent = new EcmDirectory($this->db);
165
            $parent->fetch($this->fk_parent);
166
            $relativepath = $parent->getRelativePath() . $relativepath;
167
        }
168
        $relativepath = preg_replace('/([\/])+/i', '/', $relativepath); // Avoid duplicate / or \
169
        //print $relativepath.'<br>';
170
171
        $cat = new EcmDirectory($this->db);
172
        $cate_arbo = $cat->get_full_arbo(1);
173
        $pathfound = 0;
174
        foreach ($cate_arbo as $key => $categ) {
175
            $path = str_replace($this->forbiddencharsdir, '_', $categ['fullrelativename']);
176
            //print $relativepath.' - '.$path.'<br>';
177
            if ($path == $relativepath) {
178
                $pathfound = 1;
179
                break;
180
            }
181
        }
182
183
        if ($pathfound) {
184
            $this->error = "ErrorDirAlreadyExists";
185
            dol_syslog(get_class($this) . "::create " . $this->error, LOG_WARNING);
186
            return -1;
187
        } else {
188
            $this->db->begin();
189
190
            // Insert request
191
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "ecm_directories(";
192
            $sql .= "label,";
193
            $sql .= "entity,";
194
            $sql .= "fk_parent,";
195
            $sql .= "description,";
196
            $sql .= "cachenbofdoc,";
197
            $sql .= "date_c,";
198
            $sql .= "fk_user_c";
199
            $sql .= ") VALUES (";
200
            $sql .= " '" . $this->db->escape($this->label) . "',";
201
            $sql .= " '" . $this->db->escape($conf->entity) . "',";
202
            $sql .= " " . ($this->fk_parent > 0 ? ((int) $this->fk_parent) : "null") . ",";
203
            $sql .= " '" . $this->db->escape($this->description) . "',";
204
            $sql .= " " . ((int) $this->cachenbofdoc) . ",";
205
            $sql .= " '" . $this->db->idate($this->date_c) . "',";
206
            $sql .= " " . ($this->fk_user_c > 0 ? ((int) $this->fk_user_c) : "null");
207
            $sql .= ")";
208
209
            dol_syslog(get_class($this) . "::create", LOG_DEBUG);
210
            $resql = $this->db->query($sql);
211
            if ($resql) {
212
                $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "ecm_directories");
213
214
                $dir = $conf->ecm->dir_output . '/' . $this->getRelativePath();
215
                $result = dol_mkdir($dir);
216
                if ($result < 0) {
217
                    $error++;
218
                    $this->error = "ErrorFailedToCreateDir";
219
                }
220
221
                // Call trigger
222
                $result = $this->call_trigger('MYECMDIR_CREATE', $user);
223
                if ($result < 0) {
224
                    $error++;
225
                }
226
                // End call triggers
227
228
                if (!$error) {
229
                    $this->db->commit();
230
                    return $this->id;
231
                } else {
232
                    $this->db->rollback();
233
                    return -1;
234
                }
235
            } else {
236
                $this->error = "Error " . $this->db->lasterror();
237
                $this->db->rollback();
238
                return -1;
239
            }
240
        }
241
    }
242
243
    /**
244
     *  Update database
245
     *
246
     *  @param  User    $user           User that modify
247
     *  @param  int     $notrigger      0=no, 1=yes (no update trigger)
248
     *  @return int                     Return integer <0 if KO, >0 if OK
249
     */
250
    public function update($user = null, $notrigger = 0)
251
    {
252
        global $conf, $langs;
253
254
        $error = 0;
255
256
        // Clean parameters
257
        $this->label = trim($this->label);
258
        $this->description = trim($this->description);
259
        if ($this->fk_parent <= 0) {
260
            $this->fk_parent = 0;
261
        }
262
263
        $this->db->begin();
264
265
        // Update request
266
        $sql = "UPDATE " . MAIN_DB_PREFIX . "ecm_directories SET";
267
        $sql .= " label = '" . $this->db->escape($this->label) . "',";
268
        $sql .= " fk_parent = " . ($this->fk_parent > 0 ? ((int) $this->fk_parent) : "null") . ",";
269
        $sql .= " description = '" . $this->db->escape($this->description) . "'";
270
        $sql .= " WHERE rowid = " . ((int) $this->id);
271
272
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
273
        $resql = $this->db->query($sql);
274
        if (!$resql) {
275
            $error++;
276
            $this->error = "Error " . $this->db->lasterror();
277
        }
278
279
        if (!$error && !$notrigger) {
280
            // Call trigger
281
            $result = $this->call_trigger('MYECMDIR_MODIFY', $user);
282
            if ($result < 0) {
283
                $error++;
284
            }
285
            // End call triggers
286
        }
287
288
        if (!$error) {
289
            $this->db->commit();
290
            return 1;
291
        } else {
292
            $this->db->rollback();
293
            return -1;
294
        }
295
    }
296
297
298
    /**
299
     *  Update cache of nb of documents into database
300
     *
301
     *  @param  string  $value      '+' or '-' or new number
302
     *  @return int                 Return integer <0 if KO, >0 if OK
303
     */
304
    public function changeNbOfFiles($value)
305
    {
306
        // Update request
307
        $sql = "UPDATE " . MAIN_DB_PREFIX . "ecm_directories SET";
308
        if (preg_match('/[0-9]+/', $value)) {
309
            $sql .= " cachenbofdoc = " . (int) $value;
310
        } else {
311
            $sql .= " cachenbofdoc = cachenbofdoc " . $value . " 1";
312
        }
313
        $sql .= " WHERE rowid = " . ((int) $this->id);
314
315
        dol_syslog(get_class($this) . "::changeNbOfFiles", LOG_DEBUG);
316
        $resql = $this->db->query($sql);
317
        if (!$resql) {
318
            $this->error = "Error " . $this->db->lasterror();
319
            return -1;
320
        } else {
321
            if (preg_match('/[0-9]+/', $value)) {
322
                $this->cachenbofdoc = (int) $value;
323
            } elseif ($value == '+') {
324
                $this->cachenbofdoc++;
325
            } elseif ($value == '-') {
326
                $this->cachenbofdoc--;
327
            }
328
        }
329
330
        return 1;
331
    }
332
333
334
    /**
335
     *  Load object in memory from database
336
     *
337
     *  @param  int     $id         Id of object
338
     *  @return int                 Return integer <0 if KO, 0 if not found, >0 if OK
339
     */
340
    public function fetch($id)
341
    {
342
        $sql = "SELECT";
343
        $sql .= " t.rowid,";
344
        $sql .= " t.label,";
345
        $sql .= " t.fk_parent,";
346
        $sql .= " t.description,";
347
        $sql .= " t.cachenbofdoc,";
348
        $sql .= " t.fk_user_c,";
349
        $sql .= " t.fk_user_m,";
350
        $sql .= " t.date_c as date_c,";
351
        $sql .= " t.tms as date_m";
352
        $sql .= " FROM " . MAIN_DB_PREFIX . "ecm_directories as t";
353
        $sql .= " WHERE t.rowid = " . ((int) $id);
354
355
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
356
        $resql = $this->db->query($sql);
357
        if ($resql) {
358
            $obj = $this->db->fetch_object($resql);
359
            if ($obj) {
360
                $this->id    = $obj->rowid;
361
                $this->ref   = $obj->rowid;
362
363
                $this->label = $obj->label;
364
                $this->fk_parent = $obj->fk_parent;
365
                $this->description = $obj->description;
366
                $this->cachenbofdoc = $obj->cachenbofdoc;
367
                $this->fk_user_m = $obj->fk_user_m;
368
                $this->fk_user_c = $obj->fk_user_c;
369
                $this->date_c = $this->db->jdate($obj->date_c);
370
                $this->date_m = $this->db->jdate($obj->date_m);
371
            }
372
373
            // Retrieve all extrafields for ecm_files
374
            // fetch optionals attributes and labels
375
            $this->fetch_optionals();
376
377
            $this->db->free($resql);
378
379
            return $obj ? 1 : 0;
380
        } else {
381
            $this->error = "Error " . $this->db->lasterror();
382
            return -1;
383
        }
384
    }
385
386
387
    /**
388
     *  Delete object on database and/or on disk
389
     *
390
     *  @param  User    $user                   User that delete
391
     *  @param  string  $mode                   'all'=delete all, 'databaseonly'=only database entry, 'fileonly' (not implemented)
392
     *  @param  int     $deletedirrecursive     1=Agree to delete content recursiveley (otherwise an error will be returned when trying to delete)
393
     *  @return int                             Return integer <0 if KO, >0 if OK
394
     */
395
    public function delete($user, $mode = 'all', $deletedirrecursive = 0)
396
    {
397
        global $conf, $langs;
398
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
399
400
        $error = 0;
401
402
        if ($mode != 'databaseonly') {
403
            $relativepath = $this->getRelativePath(1); // Ex: dir1/dir2/dir3
404
        }
405
406
        dol_syslog(get_class($this) . "::delete remove directory id=" . $this->id . " mode=" . $mode . (($mode == 'databaseonly') ? '' : ' relativepath=' . $relativepath));
407
408
        $this->db->begin();
409
410
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "ecm_directories";
411
        $sql .= " WHERE rowid=" . ((int) $this->id);
412
413
        dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
414
        $resql = $this->db->query($sql);
415
        if (!$resql) {
416
            $this->db->rollback();
417
            $this->error = "Error " . $this->db->lasterror();
418
            return -2;
419
        } else {
420
            // Call trigger
421
            $result = $this->call_trigger('MYECMDIR_DELETE', $user);
422
            if ($result < 0) {
423
                $this->db->rollback();
424
                return -2;
425
            }
426
            // End call triggers
427
        }
428
429
        if ($mode != 'databaseonly') {
430
            $file = $conf->ecm->dir_output . "/" . $relativepath;
431
            if ($deletedirrecursive) {
432
                $result = @dol_delete_dir_recursive($file, 0, 0);
433
            } else {
434
                $result = @dol_delete_dir($file, 0);
435
            }
436
        }
437
438
        if ($result || !@is_dir(dol_osencode($file))) {
439
            $this->db->commit();
440
        } else {
441
            $this->error = 'ErrorFailToDeleteDir';
442
            dol_syslog(get_class($this) . "::delete " . $this->error, LOG_ERR);
443
            $this->db->rollback();
444
            $error++;
445
        }
446
447
        if (!$error) {
448
            return 1;
449
        } else {
450
            return -1;
451
        }
452
    }
453
454
455
    /**
456
     *  Initialise an instance with random values.
457
     *  Used to build previews or test instances.
458
     *  id must be 0 if object instance is a specimen.
459
     *
460
     *  @return int
461
     */
462
    public function initAsSpecimen()
463
    {
464
        $this->id = 0;
465
466
        $this->label = 'MyDirectory';
467
        $this->fk_parent = 0;
468
        $this->description = 'This is a directory';
469
470
        return 1;
471
    }
472
473
474
    /**
475
     *  Return directory name you can click (and picto)
476
     *
477
     *  @param  int     $withpicto      0=Pas de picto, 1=Include picto into link, 2=Only picto
478
     *  @param  string  $option         Sur quoi pointe le lien
479
     *  @param  int     $max            Max length
480
     *  @param  string  $more           Add more param on a link
481
     *  @param  int     $notooltip      1=Disable tooltip
482
     *  @return string                  Chaine avec URL
483
     */
484
    public function getNomUrl($withpicto = 0, $option = '', $max = 0, $more = '', $notooltip = 0)
485
    {
486
        global $langs, $hookmanager;
487
488
        $result = '';
489
        //$newref=str_replace('_',' ',$this->ref);
490
        $newref = $this->ref;
491
        $label = $langs->trans("ShowECMSection") . ': ' . $newref;
492
        $linkclose = '"' . ($more ? ' ' . $more : '') . ' title="' . dol_escape_htmltag($label, 1) . '" class="classfortooltip">';
493
494
        $linkstart = '<a href="' . constant('BASE_URL') . '/ecm/dir_card.php?section=' . $this->id . $linkclose;
495
        if ($option == 'index') {
496
            $linkstart = '<a href="' . constant('BASE_URL') . '/ecm/index.php?section=' . $this->id . '&amp;sectionexpand=true' . $linkclose;
497
        }
498
        if ($option == 'indexexpanded') {
499
            $linkstart = '<a href="' . constant('BASE_URL') . '/ecm/index.php?section=' . $this->id . '&amp;sectionexpand=false' . $linkclose;
500
        }
501
        if ($option == 'indexnotexpanded') {
502
            $linkstart = '<a href="' . constant('BASE_URL') . '/ecm/index.php?section=' . $this->id . '&amp;sectionexpand=true' . $linkclose;
503
        }
504
        $linkend = '</a>';
505
506
        //$picto=DOL_URL_ROOT.'/theme/common/treemenu/folder.gif';
507
        $picto = 'dir';
508
509
        $result .= $linkstart;
510
        if ($withpicto) {
511
            $result .= img_object(($notooltip ? '' : $label), $this->picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
512
        }
513
        if ($withpicto != 2) {
514
            $result .= ($max ? dol_trunc($newref, $max, 'middle') : $newref);
515
        }
516
        $result .= $linkend;
517
518
        global $action;
519
        $hookmanager->initHooks(array($this->element . 'dao'));
520
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
521
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
522
        if ($reshook > 0) {
523
            $result = $hookmanager->resPrint;
524
        } else {
525
            $result .= $hookmanager->resPrint;
526
        }
527
        return $result;
528
    }
529
530
    /**
531
     *  Return relative path of a directory on disk
532
     *
533
     *  @param  int     $force      Force reload of full arbo even if already loaded
534
     *  @return string              Relative physical path
535
     */
536
    public function getRelativePath($force = 0)
537
    {
538
        $this->get_full_arbo($force);
539
540
        $ret = '';
541
        $idtosearch = $this->id;
542
        $i = 0;
543
        do {
544
            // Get index cursor in this->cats for id_mere
545
            $cursorindex = -1;
546
            foreach ($this->cats as $key => $val) {
547
                if ($this->cats[$key]['id'] == $idtosearch) {
548
                    $cursorindex = $key;
549
                    break;
550
                }
551
            }
552
            //print "c=".$idtosearch."-".$cursorindex;
553
554
            if ($cursorindex >= 0) {
555
                // Path is label sanitized (no space and no special char) and concatenated
556
                $ret = dol_sanitizeFileName($this->cats[$cursorindex]['label']) . '/' . $ret;
557
558
                $idtosearch = $this->cats[$cursorindex]['id_mere'];
559
                $i++;
560
            }
561
        } while ($cursorindex >= 0 && !empty($idtosearch) && $i < 100); // i avoid infinite loop
562
563
        return $ret;
564
    }
565
566
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
567
    /**
568
     *  Load this->motherof that is array(id_son=>id_parent, ...)
569
     *
570
     *  @return     int     Return integer <0 if KO, >0 if OK
571
     */
572
    public function load_motherof()
573
    {
574
		// phpcs:enable
575
        global $conf;
576
577
        $this->motherof = array();
578
579
        // Load array[child]=parent
580
        $sql = "SELECT fk_parent as id_parent, rowid as id_son";
581
        $sql .= " FROM " . MAIN_DB_PREFIX . "ecm_directories";
582
        $sql .= " WHERE fk_parent != 0";
583
        $sql .= " AND entity = " . $conf->entity;
584
585
        dol_syslog(get_class($this) . "::load_motherof", LOG_DEBUG);
586
        $resql = $this->db->query($sql);
587
        if ($resql) {
588
            // This assignment in condition is not a bug. It allows walking the results.
589
            while ($obj = $this->db->fetch_object($resql)) {
590
                $this->motherof[$obj->id_son] = $obj->id_parent;
591
            }
592
            return 1;
593
        } else {
594
            dol_print_error($this->db);
595
            return -1;
596
        }
597
    }
598
599
600
    /**
601
     *  Return the label of the status
602
     *
603
     *  @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
604
     *  @return string                 Label of status
605
     */
606
    public function getLibStatut($mode = 0)
607
    {
608
        return $this->LibStatut($this->status, $mode);
609
    }
610
611
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
612
    /**
613
     *  Return the status
614
     *
615
     *  @param  int     $status         Id status
616
     *  @param  int     $mode           0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 5=Long label + Picto
617
     *  @return string                  Label of status
618
     */
619
    public static function LibStatut($status, $mode = 0)
620
    {
621
		// phpcs:enable
622
        global $langs;
623
        return '';
624
    }
625
626
627
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
628
    /**
629
     *  Reconstruit l'arborescence des categories sous la forme d'un tableau à partir de la base de donnée
630
     *  Renvoi un tableau de tableau('id','id_mere',...) trie selon arbre et avec:
631
     *              id                  Id de la categorie
632
     *              id_mere             Id de la categorie mere
633
     *              id_children         Tableau des id enfant
634
     *              label               Name of directory
635
     *              cachenbofdoc        Nb of documents
636
     *              date_c              Date creation
637
     *              fk_user_c           User creation
638
     *              login_c             Login creation
639
     *              fullpath            Full path of id (Added by buildPathFromId call)
640
     *              fullrelativename    Full path name (Added by buildPathFromId call)
641
     *              fulllabel           Full label (Added by buildPathFromId call)
642
     *              level               Level of line (Added by buildPathFromId call)
643
     *
644
     *  @param  int     $force          Force reload of full arbo even if already loaded in cache $this->cats
645
     *  @return array|int                   Tableau de array if OK, -1 if KO
646
     */
647
    public function get_full_arbo($force = 0)
648
    {
649
		// phpcs:enable
650
        global $conf;
651
652
        if (empty($force) && !empty($this->full_arbo_loaded)) {
653
            return $this->cats;
654
        }
655
656
        // Init this->motherof that is array(id_son=>id_parent, ...)
657
        $this->load_motherof();
658
659
        // Charge tableau des categories
660
        $sql = "SELECT c.rowid as rowid, c.label as label,";
661
        $sql .= " c.description as description, c.cachenbofdoc,";
662
        $sql .= " c.fk_user_c,";
663
        $sql .= " c.date_c,";
664
        $sql .= " u.login as login_c,";
665
        $sql .= " u.statut as statut_c,";
666
        $sql .= " ca.rowid as rowid_fille";
667
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u, " . MAIN_DB_PREFIX . "ecm_directories as c";
668
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "ecm_directories as ca";
669
        $sql .= " ON c.rowid = ca.fk_parent";
670
        $sql .= " WHERE c.fk_user_c = u.rowid";
671
        $sql .= " AND c.entity = " . $conf->entity;
672
        $sql .= " ORDER BY c.label, c.rowid";
673
674
        dol_syslog(get_class($this) . "::get_full_arbo", LOG_DEBUG);
675
        $resql = $this->db->query($sql);
676
        if ($resql) {
677
            $this->cats = array();
678
            $i = 0;
679
            // This assignment in condition is not a bug. It allows walking the results.
680
            while ($obj = $this->db->fetch_object($resql)) {
681
                $this->cats[$obj->rowid]['id'] = $obj->rowid;
682
                $this->cats[$obj->rowid]['id_mere'] = (isset($this->motherof[$obj->rowid]) ? $this->motherof[$obj->rowid] : '');
683
                $this->cats[$obj->rowid]['label'] = $obj->label;
684
                $this->cats[$obj->rowid]['description'] = $obj->description;
685
                $this->cats[$obj->rowid]['cachenbofdoc'] = $obj->cachenbofdoc;
686
                $this->cats[$obj->rowid]['date_c'] = $this->db->jdate($obj->date_c);
687
                $this->cats[$obj->rowid]['fk_user_c'] = (int) $obj->fk_user_c;
688
                $this->cats[$obj->rowid]['statut_c'] = (int) $obj->statut_c;
689
                $this->cats[$obj->rowid]['login_c'] = $obj->login_c;
690
691
                if (!empty($obj->rowid_fille)) {
692
                    if (isset($this->cats[$obj->rowid]['id_children']) && is_array($this->cats[$obj->rowid]['id_children'])) {
693
                        $newelempos = count($this->cats[$obj->rowid]['id_children']);
694
                        //print "this->cats[$i]['id_children'] est deja un tableau de $newelem elements<br>";
695
                        $this->cats[$obj->rowid]['id_children'][$newelempos] = $obj->rowid_fille;
696
                    } else {
697
                        //print "this->cats[".$obj->rowid."]['id_children'] n'est pas encore un tableau<br>";
698
                        $this->cats[$obj->rowid]['id_children'] = array($obj->rowid_fille);
699
                    }
700
                }
701
                $i++;
702
            }
703
        } else {
704
            dol_print_error($this->db);
705
            return -1;
706
        }
707
708
        // We add properties fullxxx to all elements
709
        foreach ($this->cats as $key => $val) {
710
            if (isset($this->motherof[$key])) {
711
                continue;
712
            }
713
            $this->buildPathFromId($key, 0);
714
        }
715
716
        $this->cats = dol_sort_array($this->cats, 'fulllabel', 'asc', true, false);
717
        $this->full_arbo_loaded = 1;
718
719
        return $this->cats;
720
    }
721
722
    /**
723
     *  Define properties fullpath, fullrelativename, fulllabel of a directory of array this->cats and all its children.
724
     *  Separator between directories is always '/', whatever is OS.
725
     *
726
     *  @param  int     $id_categ       id_categ entry to update
727
     *  @param  int     $protection     Deep counter to avoid infinite loop
728
     *  @return void
729
     */
730
    private function buildPathFromId($id_categ, $protection = 0)
731
    {
732
        // Define fullpath
733
        if (!empty($this->cats[$id_categ]['id_mere'])) {
734
            $this->cats[$id_categ]['fullpath'] = $this->cats[$this->cats[$id_categ]['id_mere']]['fullpath'];
735
            $this->cats[$id_categ]['fullpath'] .= '_' . $id_categ;
736
            $this->cats[$id_categ]['fullrelativename'] = $this->cats[$this->cats[$id_categ]['id_mere']]['fullrelativename'];
737
            $this->cats[$id_categ]['fullrelativename'] .= '/' . $this->cats[$id_categ]['label'];
738
            $this->cats[$id_categ]['fulllabel'] = $this->cats[$this->cats[$id_categ]['id_mere']]['fulllabel'];
739
            $this->cats[$id_categ]['fulllabel'] .= ' >> ' . $this->cats[$id_categ]['label'];
740
        } else {
741
            $this->cats[$id_categ]['fullpath'] = '_' . $id_categ;
742
            $this->cats[$id_categ]['fullrelativename'] = $this->cats[$id_categ]['label'];
743
            $this->cats[$id_categ]['fulllabel'] = $this->cats[$id_categ]['label'];
744
        }
745
        // We count number of _ to have level (we use strlen that is faster than dol_strlen)
746
        $this->cats[$id_categ]['level'] = strlen(preg_replace('/([^_])/i', '', $this->cats[$id_categ]['fullpath']));
747
748
        // Process children
749
        $protection++;
750
        if ($protection > 20) {
751
            return; // We never go more than 20 levels
752
        }
753
        if (isset($this->cats[$id_categ]['id_children']) && is_array($this->cats[$id_categ]['id_children'])) {
754
            foreach ($this->cats[$id_categ]['id_children'] as $key => $val) {
755
                $this->buildPathFromId($val, $protection);
756
            }
757
        }
758
    }
759
760
    /**
761
     *  Refresh value for cachenboffile. This scan and count files into directory.
762
     *
763
     *  @param      int     $all        0=refresh record using this->id , 1=refresh record using this->entity
764
     *  @return     int                 -1 if KO, Nb of files in directory if OK
765
     */
766
    public function refreshcachenboffile($all = 0)
767
    {
768
        global $conf;
769
        include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
770
771
        $dir = $conf->ecm->dir_output . '/' . $this->getRelativePath();
772
        $filelist = dol_dir_list($dir, 'files', 0, '', '(\.meta|_preview.*\.png)$');
773
774
        // Test if filelist is in database
775
776
777
        // Update request
778
        $sql = "UPDATE " . MAIN_DB_PREFIX . "ecm_directories SET";
779
        $sql .= " cachenbofdoc = '" . count($filelist) . "'";
780
        if (empty($all)) {  // By default
781
            $sql .= " WHERE rowid = " . ((int) $this->id);
782
        } else {
783
            $sql .= " WHERE entity = " . $conf->entity;
784
        }
785
786
        dol_syslog(get_class($this) . "::refreshcachenboffile", LOG_DEBUG);
787
        $resql = $this->db->query($sql);
788
        if ($resql) {
789
            $this->cachenbofdoc = count($filelist);
790
            return $this->cachenbofdoc;
791
        } else {
792
            $this->error = "Error " . $this->db->lasterror();
793
            return -1;
794
        }
795
    }
796
797
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
798
    /**
799
     * Call trigger based on this instance.
800
     * We implement it here because this class doe not extend CommonObject.
801
     *
802
     * NB1: Error from trigger are stacked in errors
803
     * NB2: if trigger fail, action should be canceled.
804
     * NB3: Should be deleted if EcmDirectory extend CommonObject
805
     *
806
     * @param   string    $triggerName   trigger's name to execute
807
     * @param   User      $user           Object user
808
     * @return  int                       Result of run_triggers
809
     */
810
    public function call_trigger($triggerName, $user)
811
    {
812
		// phpcs:enable
813
        global $langs, $conf;
814
815
        include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
816
        $interface = new Interfaces($this->db);
817
        $result = $interface->run_triggers($triggerName, $this, $user, $langs, $conf);
818
        if ($result < 0) {
819
            if (!empty($this->errors)) {
820
                $this->errors = array_merge($this->errors, $interface->errors);
821
            } else {
822
                $this->errors = $interface->errors;
823
            }
824
        }
825
        return $result;
826
    }
827
}
828