archiveModificationTrait.php 30.3 KB
Newer Older
Prosper De Laure's avatar
Prosper De Laure committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

/*
 * Copyright (C) 2015 Maarch
 *
 * This file is part of bundle recordsManagement.
 *
 * Bundle recordsManagement is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Bundle recordsManagement is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with bundle recordsManagement.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace bundle\recordsManagement\Controller;

/**
 * Trait for archives modification
 */
trait archiveModificationTrait
{

    /**
     * Read the retention rule of an archive
     * @param string $archiveId The archive identifier
     *
34
     * @return recordsManagement/archiveRetentionRule The retention rule object
Prosper De Laure's avatar
Prosper De Laure committed
35
36
37
38
39
     */
    public function editArchiveRetentionRule($archiveId)
    {
        $archive = $this->sdoFactory->read('recordsManagement/archive', $archiveId);

40
        if ($archive->status !== 'preserved') {
Alexandre Morin's avatar
Alexandre Morin committed
41
            throw new \bundle\recordsManagement\Exception\retentionRuleException(
42
                "An archive that does not have the status 'preserved' can't be modified."
Alexandre Morin's avatar
Alexandre Morin committed
43
            );
44
45
        }

Prosper De Laure's avatar
Prosper De Laure committed
46
47
48
49
50
51
52
        return \laabs::castMessage($archive, 'recordsManagement/archiveRetentionRule');
    }

    /**
     * Read the access rule of an archive
     * @param string $archiveId The archive identifier
     *
53
     * @return recordsManagement/archiveAccessRule The access rule updated
Prosper De Laure's avatar
Prosper De Laure committed
54
55
56
57
58
     */
    public function editArchiveAccessRule($archiveId)
    {
        $archive = $this->sdoFactory->read('recordsManagement/archive', $archiveId);

59
        if ($archive->status !== 'preserved') {
60
61
62
            throw new \bundle\recordsManagement\Exception\accessRuleException(
                "An archive that does not have the status 'preserved' can't be modified."
            );
63
64
        }

Prosper De Laure's avatar
Prosper De Laure committed
65
66
67
68
69
70
        $this->getAccessRule($archive);

        return \laabs::castMessage($archive, 'recordsManagement/archiveAccessRule');
    }

    /**
Alexis Ragot's avatar
Alexis Ragot committed
71
     * Modify the archive retention rule
Prosper De Laure's avatar
Prosper De Laure committed
72
     *
Alexandre Morin's avatar
Alexandre Morin committed
73
     * @param recordsManagement/archiveRetentionRule $retentionRule The retention rule object
74
     * @param mixed                                  $archiveIds    The archives ids
Alexandre Morin's avatar
Alexandre Morin committed
75
76
77
78
     * @param null $comment
     * @param null $identifier
     * @return array
     * @throws \Exception
Prosper De Laure's avatar
Prosper De Laure committed
79
     */
Alexandre Morin's avatar
Alexandre Morin committed
80
    public function modifyRetentionRule($retentionRule, $archiveIds, $comment = null, $identifier = null)
Prosper De Laure's avatar
Prosper De Laure committed
81
    {
82
        // #10629 Get finalDisposition and duration from ref when empty and code is received
83
84
85
86
        if ((empty($retentionRule->finalDisposition)
                || empty($retentionRule->retentionDuration))
            && !empty($retentionRule->retentionRuleCode)
        ) {
87
88
89
90
91
92
93
94
95
96
            $refRetentionRule = $this->retentionRuleController->read($retentionRule->retentionRuleCode);

            if (empty($retentionRule->finalDisposition)) {
                $retentionRule->finalDisposition = $refRetentionRule->finalDisposition;
            }

            if (empty($retentionRule->retentionDuration)) {
                $retentionRule->retentionDuration = $refRetentionRule->duration;
            }
        }
97
98
99

        $retentionRuleReceived = $retentionRule;

Prosper De Laure's avatar
Prosper De Laure committed
100
101
102
103
104
105
106
107
        if (!is_array($archiveIds)) {
            $archiveIds = array($archiveIds);
        }

        $res = array('success' => array(), 'error' => array());

        $archives = array();

Cyril Vazquez's avatar
Cyril Vazquez committed
108
        if (!\laabs::getToken("ORGANIZATION")) {
109
110
111
112
            throw \laabs::newException(
                'recordsManagement/noOrgUnitException',
                "Permission denied: You have to choose a working organization unit to proceed this action."
            );
Prosper De Laure's avatar
Prosper De Laure committed
113
114
115
        }

        foreach ($archiveIds as $archiveId) {
116
            $archive = $this->retrieve($archiveId);
Prosper De Laure's avatar
Prosper De Laure committed
117
118
            $this->checkRights($archive);

119
            if (!in_array($archive->status, array("preserved"))) {
Prosper De Laure's avatar
Prosper De Laure committed
120
121
122
123
                array_push($res['error'], $archiveId);

                $operationResult = false;
            } else {
124
125
                $retentionRule = clone($retentionRuleReceived);

Prosper De Laure's avatar
Prosper De Laure committed
126
                $retentionRule->archiveId = $archiveId;
Alexandre Morin's avatar
Alexandre Morin committed
127
128

                // Update current object for caller
129
                if ($retentionRule->changeStartDate === false) {
130
                    $retentionRule->retentionStartDate = $archive->retentionStartDate;
Alexandre Morin's avatar
Alexandre Morin committed
131
132
                }

Alexis Ragot's avatar
Alexis Ragot committed
133
134
135
                if (empty($retentionRule->retentionRuleCode)) {
                    $retentionRule->retentionRuleCode = $archive->retentionRuleCode;
                    $retentionRule->retentionDuration = $archive->retentionDuration;
Alexandre Morin's avatar
Alexandre Morin committed
136
137
                }

Alexandre Morin's avatar
Alexandre Morin committed
138
139
140
                if ($retentionRule->finalDisposition === null) {
                    $retentionRule->finalDisposition = $archive->finalDisposition;
                } elseif ($retentionRule->finalDisposition === '') {
141
                    $retentionRule->finalDisposition = null;
Alexandre Morin's avatar
Alexandre Morin committed
142
143
                }

144
145
146
                if ($retentionRule->retentionDuration === '') {
                    $retentionRule->retentionDuration = null;
                } elseif (!empty($retentionRule->retentionDuration) && $retentionRule->retentionDuration->y >= 9999) {
147
                    $retentionRule->disposalDate = null;
148
149
                } else {
                    if (!empty($retentionRule->retentionDuration) && !empty($retentionRule->retentionStartDate)) {
Alexandre Morin's avatar
Alexandre Morin committed
150
151
152
153
                        $retentionRule->disposalDate = $this->calculateDate(
                            $retentionRule->retentionStartDate,
                            $retentionRule->retentionDuration
                        );
154
                    }
Alexandre Morin's avatar
Alexandre Morin committed
155
                }
Prosper De Laure's avatar
Prosper De Laure committed
156

Prosper De Laure's avatar
Prosper De Laure committed
157
                $retentionRule->retentionRuleStatus = "current";
158

159
                $retentionRule->lastModificationDate = \laabs::newTimestamp();
Alexis Ragot's avatar
Alexis Ragot committed
160

Prosper De Laure's avatar
Prosper De Laure committed
161
162
163
164
165
166
                $this->sdoFactory->update($retentionRule, 'recordsManagement/archive');

                $retentionRule->previousStartDate = $archive->retentionStartDate;
                $retentionRule->previousDuration = $archive->retentionDuration;
                $retentionRule->previousFinalDisposition = $archive->finalDisposition;

167
168
169
170
                $archive->retentionStartDate = $retentionRule->retentionStartDate;
                $archive->retentionDuration = $retentionRule->retentionDuration;
                $archive->finalDisposition = $retentionRule->finalDisposition;

Prosper De Laure's avatar
Prosper De Laure committed
171
172
173
174
175
176
177
                array_push($res['success'], $archiveId);

                $operationResult = true;

                $archives[] = $archive;

                // Life cycle journal
178
                $this->logRetentionRuleModification($archive, $retentionRule, $operationResult);
Prosper De Laure's avatar
Prosper De Laure committed
179
180
181
            }
        }

182
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
183
184
            $this->sendModificationNotification($archives, $comment, $identifier);
        }
185

Prosper De Laure's avatar
Prosper De Laure committed
186
187
188
189
190
        return $res;
    }

    /**
     * Modify the archive access
Alexandre Morin's avatar
Alexandre Morin committed
191
     *
192
193
     * @param recordsManagement/archiveAccessCode $accessRule The access rule object
     * @param array                               $archiveIds The archives ids
Alexandre Morin's avatar
Alexandre Morin committed
194
195
196
     * @param null $comment
     * @param null $identifier
     * @return array
Prosper De Laure's avatar
Prosper De Laure committed
197
     */
Alexandre Morin's avatar
Alexandre Morin committed
198
    public function modifyAccessRule($accessRule, $archiveIds, $comment = null, $identifier = null)
Prosper De Laure's avatar
Prosper De Laure committed
199
200
201
202
203
204
205
206
207
208
    {
        if (!is_array($archiveIds)) {
            $archiveIds = array($archiveIds);
        }

        $res = array('success' => array(), 'error' => array());

        $archives = array();
        $operationResult = null;

209
210
        // #10629 Get duration from ref when empty and code is received
        if (empty($accessRule->accessRuleDuration) && !empty($accessRule->accessRuleCode)) {
Cyril Vazquez's avatar
Cyril Vazquez committed
211
            $refAccessRule = $this->accessRuleController->edit($accessRule->accessRuleCode);
212
213
214
215

            $accessRule->accessRuleDuration = $refAccessRule->duration;
        }

216
        $accessRuleReceived = $accessRule;
Prosper De Laure's avatar
Prosper De Laure committed
217
218

        foreach ($archiveIds as $archiveId) {
219
            $archive = $this->retrieve($archiveId);
Prosper De Laure's avatar
Prosper De Laure committed
220
221
            $this->checkRights($archive);

222
            if (!in_array($archive->status, array("preserved"))) {
Prosper De Laure's avatar
Prosper De Laure committed
223
224
225
226
                array_push($res['error'], $archiveId);

                $operationResult = false;
            } else {
Alexis Ragot's avatar
Alexis Ragot committed
227
                $accessRule = clone($accessRuleReceived);
228

Prosper De Laure's avatar
Prosper De Laure committed
229
230
                $accessRule->archiveId = $archiveId;

Cyril Vazquez's avatar
Cyril Vazquez committed
231
                if ($accessRule->changeStartDate === false) {
232
233
                    $accessRule->accessRuleStartDate = $archive->accessRuleStartDate;
                }
234

Alexis Ragot's avatar
Alexis Ragot committed
235
236
237
238
239
                if (empty($accessRule->accessRuleCode)) {
                    $accessRule->accessRuleCode = $archive->accessRuleCode;
                    $accessRule->accessRuleDuration = $archive->accessRuleDuration;
                }

240
241
242
243
244
                if ($accessRule->accessRuleDuration === '') {
                    $accessRule->accessRuleDuration = null;
                } elseif (!empty($accessRule->accessRuleDuration) && $accessRule->accessRuleDuration->y >= 9999) {
                    $accessRule->accessRuleComDate = null;
                } elseif (!empty($accessRule->accessRuleDuration) && !empty($accessRule->accessRuleStartDate)) {
Alexandre Morin's avatar
Alexandre Morin committed
245
246
247
248
                    $accessRule->accessRuleComDate = $this->calculateDate(
                        $accessRule->accessRuleStartDate,
                        $accessRule->accessRuleDuration
                    );
Prosper De Laure's avatar
Prosper De Laure committed
249
250
                }

251
252
                $accessRule->lastModificationDate = \laabs::newTimestamp();

Prosper De Laure's avatar
Prosper De Laure committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
                $this->sdoFactory->update($accessRule, 'recordsManagement/archive');

                $accessRule->previousAccessRuleStartDate = $archive->accessRuleStartDate;
                $accessRule->previousAccessRuleDuration = $archive->accessRuleDuration;

                $archive->accessRuleStartDate = $accessRule->accessRuleStartDate;
                $archive->accessRuleDuration = $accessRule->accessRuleDuration;
                $archive->accessRuleComDate = $accessRule->accessRuleComDate;

                array_push($res['success'], $archiveId);

                $operationResult = true;

                $archives[] = $archive;

                // Life cycle journal
269
                $this->logAccessRuleModification($archive, $accessRule, $operationResult);
Prosper De Laure's avatar
Prosper De Laure committed
270
271
272
            }
        }

273
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
274
275
            $this->sendModificationNotification($archives, $comment, $identifier);
        }
276

Prosper De Laure's avatar
Prosper De Laure committed
277
278
279
280
281
        return $res;
    }

    /**
     * Suspend archives
282
     * @param mixed $archiveIds Array of archive identifier
Alexandre Morin's avatar
Alexandre Morin committed
283
284
     * @param null $comment
     * @param null $identifier
Prosper De Laure's avatar
Prosper De Laure committed
285
286
287
     *
     * @return array
     */
Alexandre Morin's avatar
Alexandre Morin committed
288
    public function freeze($archiveIds, $comment = null, $identifier = null)
Prosper De Laure's avatar
Prosper De Laure committed
289
290
291
292
293
294
295
296
    {
        if (!is_array($archiveIds)) {
            $archiveIds = array($archiveIds);
        }

        $archives = array();

        foreach ($archiveIds as $archiveId) {
297
            $archive = $this->retrieve($archiveId);
Prosper De Laure's avatar
Prosper De Laure committed
298
299
            $this->checkRights($archive);

300
301
302
303
            $archives[$archiveId] = $archive;
        }

        $res = $this->setStatus($archiveIds, 'frozen');
304
        $this->setStatus($archiveIds, 'preserved', false, false, true);
Prosper De Laure's avatar
Prosper De Laure committed
305
306


307
        for ($i = 0, $count = count($res['success']); $i < $count; $i++) {
308
309
310
311
312
            if (array_key_exists($res['success'][$i], $archives)) {
                $archive = $archives[$res['success'][$i]];
            } else {
                $archive = $this->retrieve($res['success'][$i]);
            }
313
314
315
316
317
318
            $this->logFreeze($archive, true);
        }

        for ($i = 0, $count = count($res['error']); $i < $count; $i++) {
            $archive = $archives[$res['error'][$i]];
            $this->logFreeze($archive, false);
Prosper De Laure's avatar
Prosper De Laure committed
319
320
        }

321
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
322
323
            $this->sendModificationNotification($archives, $comment, $identifier);
        }
324

Prosper De Laure's avatar
Prosper De Laure committed
325
326
327
328
329
330
        return $res;
    }

    /**
     * Liberate archives
     * @param mixed $archiveIds Array of archive identifier
Alexandre Morin's avatar
Alexandre Morin committed
331
332
     * @param null $comment
     * @param null $identifier
Prosper De Laure's avatar
Prosper De Laure committed
333
334
335
     *
     * @return array
     */
Alexandre Morin's avatar
Alexandre Morin committed
336
    public function unfreeze($archiveIds, $comment = null, $identifier = null)
Prosper De Laure's avatar
Prosper De Laure committed
337
338
339
340
341
342
    {
        if (!is_array($archiveIds)) {
            $archiveIds = array($archiveIds);
        }

        $archives = array();
343

Prosper De Laure's avatar
Prosper De Laure committed
344
        foreach ($archiveIds as $archiveId) {
345
            $archive = $this->retrieve($archiveId);
Prosper De Laure's avatar
Prosper De Laure committed
346
347
            $this->checkRights($archive);

348
349
350
            $archives[$archiveId] = $archive;
        }

351
        $res = $this->setStatus($archiveIds, 'preserved', true);
352

Prosper De Laure's avatar
Prosper De Laure committed
353

354
        for ($i = 0, $count = count($res['success']); $i < $count; $i++) {
355
356
357
358
359
            if (array_key_exists($res['success'][$i], $archives)) {
                $archive = $archives[$res['success'][$i]];
            } else {
                $archive = $this->retrieve($res['success'][$i]);
            }
360
361
            $this->logUnfreeze($archive, true);
        }
Prosper De Laure's avatar
Prosper De Laure committed
362

363
364
365
        for ($i = 0, $count = count($res['error']); $i < $count; $i++) {
            $archive = $archives[$res['error'][$i]];
            $this->logUnfreeze($archive, false);
Prosper De Laure's avatar
Prosper De Laure committed
366
367
        }

368
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
369
370
            $this->sendModificationNotification($archives, $comment, $identifier);
        }
371

Prosper De Laure's avatar
Prosper De Laure committed
372
373
        return $res;
    }
374

375
376
377
378
    /**
     * Update metadata of archive
     * @param string $archiveId
     * @param string $originatorArchiveId
Alexandre Morin's avatar
Alexandre Morin committed
379
     * @param string $archiverArchiveId
380
     * @param string $archiveName
381
     * @param object $description
382
     * @param date   $originatingDate
383
     *
384
385
     * @return boolean The result of the operation
     */
386
387
388
389
390
391
392
393
394
    public function modifyMetadata(
        $archiveId,
        $originatorArchiveId = null,
        $archiverArchiveId = null,
        $archiveName = null,
        $originatingDate = null,
        $description = null,
        $checkAccess = true
    ) {
395
        $archive = $this->retrieve($archiveId, false, $checkAccess);
Alexandre Morin's avatar
Alexandre Morin committed
396

397
398
399
400
        if ($checkAccess) {
            $this->checkRights($archive);
        }

Alexandre Morin's avatar
Alexandre Morin committed
401
        if (!empty($archive->archivalProfileReference)) {
402
403
            $archivalProfileController = \laabs::newController('recordsManagement/archivalProfile');
            $archivalProfileDescription = $archivalProfileController->getByReference(
404
405
                $archive->archivalProfileReference
            )->archiveDescription;
Alexandre Morin's avatar
Alexandre Morin committed
406
        }
Dylan's avatar
Dylan committed
407

408
409
410
        if ($archiveName) {
            $archive->archiveName = $archiveName;
        }
411

412
        $archive->originatorArchiveId = $originatorArchiveId;
413

Alexandre Morin's avatar
Alexandre Morin committed
414
415
416
417
        if ($archiverArchiveId) {
            $archive->archiverArchiveId = $archiverArchiveId;
        }

418
        $archive->originatingDate = $originatingDate;
419

420
421
        $archive->lastModificationDate = \laabs::newTimestamp();

422
        if (!empty($description)) {
Alexandre Morin's avatar
Alexandre Morin committed
423
            $descriptionObject = $description;
Alexandre Morin's avatar
Alexandre Morin committed
424
425
426
427
428

            if (!empty($archivalProfileDescription)) {
                foreach ($archivalProfileDescription as $descriptionImmutable) {
                    if ($descriptionImmutable->isImmutable) {
                        $fieldName = (string)$descriptionImmutable->fieldName;
429
                        if (isset($descriptionObject->$fieldName)) {
430
                            if (is_array($descriptionObject->$fieldName)) {
431
432
433
434
                                $archiveNewField = $descriptionObject->$fieldName;
                                $archiveOldField = $archive->descriptionObject->$fieldName;
                                sort($archiveNewField);
                                sort($archiveOldField);
435
436
                                if (is_object($descriptionObject->$fieldName[0])) {
                                    foreach ($archiveNewField as $index => $object) {
437
                                        if ($archiveOldField[$index] != $object) {
438
439
440
                                            throw new \bundle\recordsManagement\Exception\invalidArchiveException(
                                                'Attempt to modify readonly field(s)'
                                            );
441
442
443
                                        }
                                    }
                                } else {
444
445
446
447
448
449
                                    if (count($archiveNewField) != count($archiveOldField)
                                        || array_diff($archiveNewField, $archiveOldField)
                                    ) {
                                        throw new \bundle\recordsManagement\Exception\invalidArchiveException(
                                            'Attempt to modify readonly field(s)'
                                        );
450
451
                                    }
                                }
452
453
454
455
456
457
458
459
                            } elseif (!isset($archive->descriptionObject->$fieldName)) {
                                throw new \bundle\recordsManagement\Exception\invalidArchiveException(
                                    'Attempt to modify readonly field(s)'
                                );
                            } elseif ($descriptionObject->$fieldName != $archive->descriptionObject->$fieldName) {
                                throw new \bundle\recordsManagement\Exception\invalidArchiveException(
                                    'Attempt to modify readonly field(s)'
                                );
460
                            }
Alexandre Morin's avatar
Alexandre Morin committed
461
                        }
Dylan's avatar
Dylan committed
462
                    }
Alexandre Morin's avatar
Alexandre Morin committed
463
                }
Dylan's avatar
Dylan committed
464
            }
465

466
            if (!empty($archive->archivalProfileReference) && is_object($descriptionObject)) {
467
                $this->useArchivalProfile($archive->archivalProfileReference);
468

469
                $this->validateDescriptionModel($descriptionObject, $this->currentArchivalProfile);
470
471
            }

472
            $descriptionController = $this->useDescriptionController($archive->descriptionClass);
473

474
            $archive->descriptionObject = $descriptionObject;
475

476
            $descriptionController->update($archive);
477
        }
Dylan's avatar
Dylan committed
478

479
        $this->sdoFactory->update($archive, 'recordsManagement/archive');
480

481
482
        $operationResult = true;
        $res = true;
483

484
        $this->logMetadataModification($archive, $operationResult);
485

486
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
487
488
            $this->sendModificationNotification([$archive]);
        }
489

490
491
        return $res;
    }
492

Prosper De Laure's avatar
Prosper De Laure committed
493
494
495
496
497
498
499
500
    /**
     * Add a relationship to the archive
     * @param recordsManagement/archiveRelationship $archiveRelationship The relationship of the archive
     *
     * @return bool The result of the operation
     */
    public function addRelationship($archiveRelationship)
    {
501
        $this->archiveRelationshipController->create($archiveRelationship);
Prosper De Laure's avatar
Prosper De Laure committed
502

503
        $archive = $this->retrieve($archiveRelationship->archiveId, false, false);
Prosper De Laure's avatar
Prosper De Laure committed
504
505

        // Life cycle journal
506
        $this->logRelationshipAdding($archive, $archiveRelationship);
507

508
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
509
510
            $this->sendModificationNotification([$archive]);
        }
511

Prosper De Laure's avatar
Prosper De Laure committed
512
513
514
515
516
517
518
519
520
521
522
        return true;
    }

    /**
     * delete a relationship
     * @param recordsManagement/archiveRelationship $archiveRelationship The archive relationship object
     *
     * @return recordsManagement/archiveRelationship
     */
    public function deleteRelationship($archiveRelationship)
    {
523
        $this->archiveRelationshipController->delete($archiveRelationship);
Prosper De Laure's avatar
Prosper De Laure committed
524

525
        $archive = $this->retrieve($archiveRelationship->archiveId, $withBinary = false, $checkAccess = false);
Prosper De Laure's avatar
Prosper De Laure committed
526
527

        // Life cycle journal
528
        $this->logRelationshipDeleting($archive, $archiveRelationship);
Prosper De Laure's avatar
Prosper De Laure committed
529

530
        if (isset(\laabs::configuration("medona")['transaction']) && \laabs::configuration("medona")['transaction']) {
Alexandre Morin's avatar
Alexandre Morin committed
531
532
            $this->sendModificationNotification([$archive]);
        }
533

Prosper De Laure's avatar
Prosper De Laure committed
534
535
        return true;
    }
536
537

    /**
538
     * Index full text
539
540
541
542
     * @param int $limit The maximum number of archive to index
     *
     * @return array The result of the operation
     */
543
    public function indexFullText($limit = 200)
544
545
546
547
    {
        $res = [];
        $res['success'] = [];
        $res['fail'] = [];
Alexandre Morin's avatar
Alexandre Morin committed
548
549
550
551
552
553
554
555
556
        $archivesToIndex = $this->sdoFactory->find(
            'recordsManagement/archive',
            "fullTextIndexation='requested'",
            [],
            null,
            null,
            $limit
        );

557
558
559
        if (isset(\laabs::configuration('recordsManagement')['stopWordsFilePath'])) {
            $stopWords = \laabs::configuration('recordsManagement')['stopWordsFilePath'];
            $stopWords = utf8_encode(file_get_contents($stopWords));
560
            $stopWords = preg_replace('/[\r\n]/', " ", $stopWords);
561
562
563
564
565
566
567
            $stopWords = explode(" ", $stopWords);
        }

        if (count($archivesToIndex)) {
            $descriptionController = $this->useDescriptionController('recordsManagement/description');

            foreach ($archivesToIndex as $archive) {
568
                $archive = $this->retrieve($archive->archiveId);
569
570
571
572

                try {
                    $fullText = $this->digitalResourceController->getFullTextByArchiveId($archive->archiveId);
                    $fullText = strtolower($fullText);
573
                    $fullText = preg_replace('/[.,\/#!?$%\^&\*;:{}=\-_\'`~()\r\n]|\s+/', " ", $fullText);
574
575
576
577
578
579

                    if (isset($stopWords)) {
                        $fullTextArray = explode(" ", $fullText);
                        $fullTextArray = array_diff($fullTextArray, $stopWords);
                        $fullText = implode(" ", $fullTextArray);
                    } else {
580
                        $fullText = preg_replace('/\b[a-z]{1,2}\b/', "", $fullText);
581
582
583
                    }

                    $descriptionController->create($archive, $fullText);
584
585
                    $archive->fullTextIndexation = "indexed";
                    $this->sdoFactory->update($archive, 'recordsManagement/archiveIndexationStatus');
586
587
588

                    $operationResult = true;

589
                } catch (\Exception $e) {
590
591
                    $operationResult = false;
                    $archive->fullTextIndexation = "failed";
592
                    $this->sdoFactory->update($archive, 'recordsManagement/archiveIndexationStatus');
593
594
                }

595
                $this->logMetadataModification($archive, $operationResult);
596
597
598
599
600
601
602
603
604
605
606

                if ($operationResult) {
                    $res['success'][] = (string)$archive->archiveId;
                } else {
                    $res['error'][] = (string)$archive->archiveId;
                }
            }
        }

        return $res;
    }
Prosper De Laure's avatar
Prosper De Laure committed
607
608
609
610
611

    /**
     * Update archive with changed retention rule
     * @param int $limit The maximum number of archive to update
     */
612
613
    public function updateArchiveRetentionRule($limit = 1000)
    {
Alexandre Morin's avatar
Alexandre Morin committed
614
615
616
617
618
619
620
621
        $archives = $this->sdoFactory->find(
            'recordsManagement/archive',
            'retentionRuleCode != null AND retentionStartDate != null AND retentionDuration !=null AND retentionRuleStatus = "changed"',
            null,
            null,
            null,
            $limit
        );
Prosper De Laure's avatar
Prosper De Laure committed
622
        $retentionRules = [];
Prosper De Laure's avatar
Prosper De Laure committed
623

624
        foreach ($archives as $archive) {
625
626
627
628
629
630
631
            // avoid parallel processing
            if ($this->sdoFactory->read('recordsManagement/archive')->retentionRuleStatus != "changed") {
                continue;
            }
            $archive->retentionRuleStatus = "processing";
            $this->sdoFactory->update($archive, 'recordsManagement/archiveRetentionRule');

632
633
634
635
636
            $retentionRule = new \stdClass();
            $retentionRule->archiveId = $archive->archiveId;
            $retentionRule->previousStartDate = $archive->retentionStartDate;
            $retentionRule->previousDuration = $archive->retentionDuration;
            $retentionRule->previousFinalDisposition = $archive->finalDisposition;
Prosper De Laure's avatar
Prosper De Laure committed
637

638
            if (!isset($retentionRules[$archive->retentionRuleCode])) {
639
640
                $retentionRules[$archive->retentionRuleCode] =
                    $this->retentionRuleController->read($archive->retentionRuleCode);
641
            }
Prosper De Laure's avatar
Prosper De Laure committed
642

643
644
            $archive->retentionDuration =  $retentionRules[$archive->retentionRuleCode]->duration;
            $archive->disposalDate = $this->calculateDate($archive->retentionStartDate, $archive->retentionDuration);
Prosper De Laure's avatar
Prosper De Laure committed
645

646
647
648
            $retentionRule->retentionStartDate = $archive->retentionStartDate;
            $retentionRule->retentionDuration = $archive->retentionDuration;
            $retentionRule->finalDisposition = $archive->finalDisposition;
Prosper De Laure's avatar
Prosper De Laure committed
649

650
651
            $archive->retentionRuleStatus = "current";
            $this->sdoFactory->update($archive, 'recordsManagement/archiveRetentionRule');
Prosper De Laure's avatar
Prosper De Laure committed
652

653
654
            // Life cycle journal
            $this->logRetentionRuleModification($archive, $retentionRule, true);
Prosper De Laure's avatar
Prosper De Laure committed
655
656
        }
    }
657
658
659
660

    /**
     * Convert and store the resource
     *
661
662
663
664
     * @param string $archiveId   The archive identifier
     * @param string $contents    The resource contents
     * @param string $filename    The optional filename
     * @param string $checkAccess Check access to archive. If false caller MUST check access before.
665
     *
666
667
     * @return The new resource identifier
     */
668
    public function addResource($archiveId, $contents, $filename = null, $checkAccess = true)
669
    {
670
671
672
673
674
675
676
        switch (true) {
            case is_string($contents)
                && (filter_var(substr($contents, 0, 10), FILTER_VALIDATE_URL) || is_file($contents)):
                $handler = fopen($contents, 'r');
                break;

            case is_string($contents) &&
677
                preg_match('%^[a-zA-Z0-9\\\\/+]*={0,2}$%', $contents):
678
679
680
681
682
683
684
                $handler = \laabs::createTempStream(base64_decode($contents));
                break;
        
            case is_resource($contents):
                $handler = \core\Encoding\Base64::decode($contents);
        }
        
685
        $digitalResource = $this->digitalResourceController->createFromStream($handler, $filename);
686
687
688
689
690
        $digitalResource->archiveId = $archiveId;
        $digitalResource->resId = \laabs::newId();

        $archive = $this->sdoFactory->read("recordsManagement/archive", $archiveId);

691
692
693
694
        if ($archive->status !== 'preserved') {
            throw \laabs::newException('recordsManagement/accessDeniedException', "Permission denied");
        }

695
        // Check rights ?
696
697
698
        if ($checkAccess) {
            $this->checkRights($archive);
        }
699

700
        $this->useServiceLevel('deposit', $archive->serviceLevelReference);
701

702
        $this->validateDigitalResource($digitalResource);
703
    
704
705
706
707
708
709
710
        $transactionControl = !$this->sdoFactory->inTransaction();

        if ($transactionControl) {
            $this->sdoFactory->beginTransaction();
        }

        try {
Alexandre Morin's avatar
Alexandre Morin committed
711
712
713
714
            $this->digitalResourceController->openContainers(
                $this->currentServiceLevel->digitalResourceClusterId,
                $archive->storagePath
            );
715
716
            $this->digitalResourceController->store($digitalResource);

Cyril Vazquez's avatar
Cyril Vazquez committed
717
            $this->logAddResource($archive, $digitalResource, true);
718
719
720
721
722
        } catch (\Exception $e) {
            if ($transactionControl) {
                $this->sdoFactory->rollback();
            }

Cyril Vazquez's avatar
Cyril Vazquez committed
723
724
            $this->logAddResource($archive, $digitalResource, false);

725
726
727
728
729
730
731
            throw $e;
        }

        if ($transactionControl) {
            $this->sdoFactory->commit();
        }

732
733
        if (isset(\laabs::configuration("medona")['transaction'])
            && \laabs::configuration("medona")['transaction']) {
734
735
736
            $this->sendModificationNotification([$archive]);
        }

737
738
        return $digitalResource->resId;
    }
Prosper De Laure's avatar
Prosper De Laure committed
739

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
    /**
     * Update user access
     * @param string $archiveId         The archive unit identifier
     * @param array  $userOrgRegNumbers The user org registration numbers
     * @param string $checkAccess       Check access to archive. If false caller MUST check access before.
     *
     * @return bool
     */
    public function updateUserOrgRegNumbers($archiveId, array $userOrgRegNumbers, $checkAccess = true)
    {
        $archive = $this->sdoFactory->read("recordsManagement/archive", $archiveId);

        // Check rights ?
        if ($checkAccess) {
            $this->checkRights($archive);
        }

        $archiveUserOrgRegNumbers = \laabs::newInstance('recordsManagement/archiveUserOrgRegNumbers');
        $archiveUserOrgRegNumbers->archiveId = $archiveId;
        $archiveUserOrgRegNumbers->userOrgRegNumbers = \laabs::newTokenList($userOrgRegNumbers);
        $archiveUserOrgRegNumbers->lastModificationDate = \laabs::newTimestamp();

        $this->sdoFactory->update($archiveUserOrgRegNumbers);
    }
764

Alexandre Morin's avatar
Alexandre Morin committed
765
    protected function sendModificationNotification($archives, $comment = null, $identifier = null)
766
    {
Cyril Vazquez's avatar
WIP    
Cyril Vazquez committed
767
768
        $currentOrg = \laabs::getToken("ORGANIZATION");

769
770
        $archivesByOriginator = array();
        foreach ($archives as $archive) {
Cyril Vazquez's avatar
WIP    
Cyril Vazquez committed
771
772
773
774
775
            if ($currentOrg->registrationNumber != $archive->originatorOrgRegNumber) {
                if (!isset($archivesByOriginator[$archive->originatorOrgRegNumber])) {
                    $archivesByOriginator[$archive->originatorOrgRegNumber] = array();
                }
                $archivesByOriginator[$archive->originatorOrgRegNumber][] = $archive;
776
777
778
779
            }
        }

        $archiveModificationNotificationController = \laabs::newController("medona/ArchiveModificationNotification");
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
        if (!$identifier) {
            $identifier = "archiveModificationNotification_".date("Y-m-d-H-i-s");
        }

        $reference = $identifier;
        foreach ($archivesByOriginator as $originatorOrgRegNumber => $archives) {
            $i = 1;
            $senderOrg = $archives[0]->archiverOrgRegNumber;
            $recipientOrg = $originatorOrgRegNumber;

            $unique = array(
                'type' => 'ArchiveModificationNotification',
                'senderOrgRegNumber' => $senderOrg,
                'reference' => $reference,
            );

            while ($this->sdoFactory->exists("medona/message", $unique)) {
                $i++;
                $unique['reference'] = $reference = $identifier.'_'.$i;
            }
801

Alexandre Morin's avatar
Alexandre Morin committed
802
803
804
805
806
807
808
            $archiveModificationNotificationController->send(
                $reference,
                $archives,
                $senderOrg,
                $recipientOrg,
                $comment
            );
809
810
        }
    }
811
}