Skip to content
Snippets Groups Projects
ResController.php 56.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • <?php
    
    /**
    * Copyright Maarch since 2008 under licence GPLv3.
    * See LICENCE.txt file at the root folder for more details.
    * This file is part of Maarch software.
    *
    */
    
    /**
    * @brief Resource Controller
    * @author dev@maarch.org
    */
    
    
    Damien's avatar
    Damien committed
    namespace Resource\controllers;
    
    use AcknowledgementReceipt\models\AcknowledgementReceiptModel;
    
    use Attachment\models\AttachmentModel;
    
    use Basket\models\BasketModel;
    
    use Basket\models\GroupBasketModel;
    
    Damien's avatar
    Damien committed
    use Basket\models\RedirectBasketModel;
    
    use Convert\controllers\ConvertPdfController;
    
    Damien's avatar
    Damien committed
    use Convert\controllers\ConvertThumbnailController;
    use Convert\models\AdrModel;
    
    use Docserver\models\DocserverModel;
    
    Damien's avatar
    Damien committed
    use Docserver\models\DocserverTypeModel;
    
    use Email\models\EmailModel;
    
    use Entity\models\EntityModel;
    
    use Entity\models\ListInstanceModel;
    
    use Folder\models\FolderModel;
    
    use Folder\models\ResourceFolderModel;
    
    Damien's avatar
    Damien committed
    use Group\controllers\GroupController;
    
    use Group\controllers\PrivilegeController;
    
    Damien's avatar
    Damien committed
    use History\controllers\HistoryController;
    
    use IndexingModel\models\IndexingModelFieldModel;
    
    use MessageExchange\models\MessageExchangeModel;
    
    use Note\models\NoteModel;
    
    use Priority\models\PriorityModel;
    
    Damien's avatar
    Damien committed
    use Resource\models\ResModel;
    
    use Resource\models\ResourceContactModel;
    
    use Resource\models\UserFollowedResourceModel;
    
    use Respect\Validation\Validator;
    
    Damien's avatar
    Damien committed
    use Slim\Http\Request;
    use Slim\Http\Response;
    
    use SrcCore\controllers\PreparedClauseController;
    
    use SrcCore\models\CoreConfigModel;
    use SrcCore\models\ValidatorModel;
    use Status\models\StatusModel;
    
    use Tag\models\ResourceTagModel;
    
    Damien's avatar
    Damien committed
    use User\models\UserModel;
    
    class ResController extends ResourceControlController
    
    Damien's avatar
    Damien committed
        public function create(Request $request, Response $response)
    
            if (!PrivilegeController::canIndex(['userId' => $GLOBALS['id']])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
    
    Damien's avatar
    Damien committed
            $body = $request->getParsedBody();
    
    Giovannoni Laurent's avatar
    Giovannoni Laurent committed
    
    
            $control = ResourceControlController::controlResource(['body' => $body]);
    
            if (!empty($control['errors'])) {
                return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
    
    Damien's avatar
    Damien committed
            $resId = StoreController::storeResource($body);
    
    Damien's avatar
    Damien committed
            if (empty($resId) || !empty($resId['errors'])) {
                return $response->withStatus(500)->withJson(['errors' => '[ResController create] ' . $resId['errors']]);
            }
    
    
            ResController::createAdjacentData(['body' => $body, 'resId' => $resId]);
    
                UserFollowedResourceModel::create([
    
                    'userId'    => $GLOBALS['id'],
                    'resId'     => $resId
    
            if (!empty($body['encodedFile'])) {
                ConvertPdfController::convert([
                    'resId'     => $resId,
    
                    'collId'    => 'letterbox_coll',
    
                $customId = CoreConfigModel::getCustomId();
                $customId = empty($customId) ? 'null' : $customId;
    
                exec("php src/app/convert/scripts/FullTextScript.php --customId {$customId} --resId {$resId} --collId letterbox_coll --userId {$GLOBALS['id']} > /dev/null &");
    
    Damien's avatar
    Damien committed
            HistoryController::add([
                'tableName' => 'res_letterbox',
                'recordId'  => $resId,
                'eventType' => 'ADD',
                'info'      => _DOC_ADDED,
    
                'moduleId'  => 'resource',
    
                'eventId'   => 'resourceCreation',
    
    Damien's avatar
    Damien committed
            ]);
    
    
    Damien's avatar
    Damien committed
            return $response->withJson(['resId' => $resId]);
        }
    
    
        public function getById(Request $request, Response $response, array $args)
        {
            if (!Validator::intVal()->validate($args['resId']) || !ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
    
            $queryParams = $request->getQueryParams();
    
    
            $select = ['model_id', 'category_id', 'priority', 'status', 'subject', 'alt_identifier', 'process_limit_date', 'closing_date', 'creation_date', 'modification_date', 'integrations'];
    
            if (empty($queryParams['light'])) {
    
                $select = array_merge($select, ['type_id', 'typist', 'destination', 'initiator', 'confidentiality', 'doc_date', 'admission_date', 'departure_date', 'barcode', 'custom_fields']);
    
            $document = ResModel::getById([
    
                'select'    => $select,
                'resId'     => $args['resId']
    
            ]);
            if (empty($document)) {
                return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']);
            }
    
    
            $unchangeableData = [
    
                'resId'             => (int)$args['resId'],
                'modelId'           => $document['model_id'],
                'categoryId'        => $document['category_id'],
                'chrono'            => $document['alt_identifier'],
    
                'status'            => $document['status'],
    
                'closingDate'       => $document['closing_date'],
                'creationDate'      => $document['creation_date'],
                'modificationDate'  => $document['modification_date'],
                'integrations'      => json_decode($document['integrations'], true)
    
            $formattedData = [
    
                'subject'           => $document['subject'],
                'processLimitDate'  => $document['process_limit_date'],
                'priority'          => $document['priority']
    
            if (empty($queryParams['light'])) {
                $formattedData = array_merge($formattedData, [
    
                    'doctype'           => $document['type_id'],
                    'typist'            => $document['typist'],
                    'typistLabel'       => UserModel::getLabelledUserById(['id' => $document['typist']]),
                    'destination'       => $document['destination'],
                    'initiator'         => $document['initiator'],
                    'confidentiality'   => $document['confidentiality'] == 'Y',
                    'documentDate'      => $document['doc_date'],
                    'arrivalDate'       => $document['admission_date'],
                    'departureDate'     => $document['departure_date'],
                    'barcode'           => $document['barcode']
    
            $modelFields = IndexingModelFieldModel::get([
                'select'    => ['identifier'],
                'where'     => ['model_id = ?'],
                'data'      => [$document['model_id']]
            ]);
            $modelFields = array_column($modelFields, 'identifier');
    
            foreach ($formattedData as $key => $data) {
    
                if (!in_array($key, $modelFields)) {
    
                    unset($formattedData[$key]);
                }
            }
    
            $formattedData = array_merge($unchangeableData, $formattedData);
    
    
            if (!empty($formattedData['destination'])) {
    
                $entity = EntityModel::getByEntityId(['entityId' => $formattedData['destination'], 'select' => ['entity_label', 'id']]);
                $formattedData['destination'] = $entity['id'];
    
    Damien's avatar
    Damien committed
                $formattedData['destinationLabel'] = $entity['entity_label'];
    
            }
            if (!empty($formattedData['initiator'])) {
    
                $entity = EntityModel::getByEntityId(['entityId' => $formattedData['initiator'], 'select' => ['entity_label', 'id']]);
                $formattedData['initiator'] = $entity['id'];
    
    Damien's avatar
    Damien committed
                $formattedData['initiatorLabel'] = $entity['entity_label'];
    
            }
            if (!empty($formattedData['status'])) {
    
                $status = StatusModel::getById(['id' => $formattedData['status'], 'select' => ['label_status', 'can_be_modified']]);
    
    Damien's avatar
    Damien committed
                $formattedData['statusLabel'] = $status['label_status'];
    
                $formattedData['statusAlterable'] = $status['can_be_modified'] == 'Y';
    
            }
            if (!empty($formattedData['priority'])) {
    
                $priority = PriorityModel::getById(['id' => $formattedData['priority'], 'select' => ['label', 'color']]);
    
    Damien's avatar
    Damien committed
                $formattedData['priorityLabel'] = $priority['label'];
    
                $formattedData['priorityColor'] = $priority['color'];
    
            if (in_array('senders', $modelFields)) {
                $formattedData['senders'] = ResourceContactModel::get([
                    'select'    => ['item_id as id', 'type'],
                    'where'     => ['res_id = ?', 'mode = ?'],
                    'data'      => [$args['resId'], 'sender']
                ]);
            }
            if (in_array('recipients', $modelFields) && empty($queryParams['light'])) {
                $formattedData['recipients'] = ResourceContactModel::get([
                    'select'    => ['item_id as id', 'type'],
                    'where'     => ['res_id = ?', 'mode = ?'],
                    'data'      => [$args['resId'], 'recipient']
                ]);
            }
    
    
            if (empty($queryParams['light'])) {
    
                $formattedData['customFields'] = !empty($document['custom_fields']) ? json_decode($document['custom_fields'], true) : [];
    
    
                $entities = EntityModel::getWithUserEntities([
                    'select' => ['entities.id'],
                    'where'  => ['user_id = ?'],
                    'data'   => [$GLOBALS['userId']]
                ]);
                $entities = array_column($entities, 'id');
                $folders = FolderModel::getWithEntitiesAndResources([
    
                    'select'    => ['distinct(resources_folders.folder_id)'],
    
                    'where'     => ['resources_folders.res_id = ?', '(entities_folders.entity_id in (?) OR folders.user_id = ? OR keyword = ?)'],
                    'data'      => [$args['resId'], $entities, $GLOBALS['id'], 'ALL_ENTITIES']
    
                $formattedData['folders'] = array_column($folders, 'folder_id');
    
                $tags = ResourceTagModel::get(['select' => ['tag_id'], 'where' => ['res_id = ?'], 'data' => [$args['resId']]]);
    
                $formattedData['tags'] = array_column($tags, 'tag_id');
    
            } else {
                $followed = UserFollowedResourceModel::get([
    
                    'select'    => [1],
                    'where'     => ['user_id = ?', 'res_id = ?'],
                    'data'      => [$GLOBALS['id'], $args['resId']]
    
                ]);
                $formattedData['followed'] = !empty($followed);
            }
    
            return $response->withJson($formattedData);
        }
    
    
        public function update(Request $request, Response $response, array $args)
        {
    
            if (!Validator::intVal()->validate($args['resId'])) {
                return ['errors' => 'Route resId is not an integer'];
            } elseif (!PrivilegeController::canUpdateResource(['userId' => $GLOBALS['id'], 'resId' => $args['resId']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
    
            $body = $request->getParsedBody();
    
            $queryParams = $request->getQueryParams();
    
            $onlyDocument = !empty($queryParams['onlyDocument']);
    
    
            unset($body['destination']);
            unset($body['diffusionList']);
    
            $control = ResourceControlController::controlUpdateResource(['body' => $body, 'resId' => $args['resId'], 'onlyDocument' => $onlyDocument]);
    
            if (!empty($control['errors'])) {
                return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
            }
    
    
            $resource = ResModel::getById(['resId' => $args['resId'], 'select' => ['alt_identifier', 'filename', 'docserver_id', 'path', 'fingerprint', 'version']]);
    
            if (!empty($resource['filename']) && !empty($body['encodedFile'])) {
                AdrModel::createDocumentAdr([
                    'resId'         => $args['resId'],
                    'type'          => 'DOC',
                    'docserverId'   => $resource['docserver_id'],
                    'path'          => $resource['path'],
                    'filename'      => $resource['filename'],
    
                    'version'       => $resource['version'],
    
                    'fingerprint'   => $resource['fingerprint']
                ]);
            }
    
    
            if ($onlyDocument) {
                $body = [
                    'encodedFile'   => $body['encodedFile'],
                    'format'        => $body['format']
                ];
            }
    
            $body['resId'] = $args['resId'];
            $resId = StoreController::storeResource($body);
            if (empty($resId) || !empty($resId['errors'])) {
                return $response->withStatus(500)->withJson(['errors' => '[ResController update] ' . $resId['errors']]);
            }
    
    
            if (!$onlyDocument) {
                ResController::updateAdjacentData(['body' => $body, 'resId' => $args['resId']]);
            }
    
            if (!empty($body['encodedFile'])) {
    
                ConvertPdfController::convert([
                    'resId'     => $args['resId'],
    
                    'collId'    => 'letterbox_coll',
    
                    'version'   => $resource['version'] + 1
    
                ]);
    
                $customId = CoreConfigModel::getCustomId();
                $customId = empty($customId) ? 'null' : $customId;
                exec("php src/app/convert/scripts/FullTextScript.php --customId {$customId} --resId {$args['resId']} --collId letterbox_coll --userId {$GLOBALS['id']} > /dev/null &");
    
    
                HistoryController::add([
                    'tableName' => 'res_letterbox',
                    'recordId'  => $args['resId'],
                    'eventType' => 'UP',
    
                    'info'      => _FILE_UPDATED . " : {$resource['alt_identifier']}",
    
                    'moduleId'  => 'resource',
                    'eventId'   => 'fileModification'
                ]);
    
            if (!$onlyDocument) {
                HistoryController::add([
                    'tableName' => 'res_letterbox',
                    'recordId'  => $args['resId'],
                    'eventType' => 'UP',
                    'info'      => _DOC_UPDATED . " : {$resource['alt_identifier']}",
                    'moduleId'  => 'resource',
                    'eventId'   => 'resourceModification'
                ]);
            }
    
    
            return $response->withStatus(204);
        }
    
    
        public function updateStatus(Request $request, Response $response)
    
    Damien's avatar
    Damien committed
        {
            $data = $request->getParams();
    
            if (empty($data['status'])) {
                $data['status'] = 'COU';
            }
    
            if (empty(StatusModel::getById(['id' => $data['status']]))) {
    
                return $response->withStatus(400)->withJson(['errors' => _STATUS_NOT_FOUND]);
    
    Damien's avatar
    Damien committed
            if (empty($data['historyMessage'])) {
                $data['historyMessage'] = _UPDATE_STATUS;
            }
    
    
            $check = Validator::arrayType()->notEmpty()->validate($data['chrono']) || Validator::arrayType()->notEmpty()->validate($data['resId']);
    
            $check = $check && Validator::stringType()->notEmpty()->validate($data['status']);
    
    Damien's avatar
    Damien committed
            $check = $check && Validator::stringType()->notEmpty()->validate($data['historyMessage']);
            if (!$check) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    Damien's avatar
    Damien committed
    
            $identifiers = !empty($data['chrono']) ? $data['chrono'] : $data['resId'];
            foreach ($identifiers as $id) {
    
                if (!empty($data['chrono'])) {
    
                    $document = ResModel::getByAltIdentifier(['altIdentifier' => $id, 'select' => ['res_id']]);
    
                    $document = ResModel::getById(['resId' => $id, 'select' => ['res_id']]);
    
                }
                if (empty($document)) {
                    return $response->withStatus(400)->withJson(['errors' => _DOCUMENT_NOT_FOUND]);
                }
    
                if (!ResController::hasRightByResId(['resId' => [$document['res_id']], 'userId' => $GLOBALS['id']])) {
    
                    return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
                }
    
                ResModel::update(['set' => ['status' => $data['status']], 'where' => ['res_id = ?'], 'data' => [$document['res_id']]]);
    
                HistoryController::add([
                    'tableName' => 'res_letterbox',
                    'recordId'  => $document['res_id'],
                    'eventType' => 'UP',
                    'info'      => $data['historyMessage'],
                    'moduleId'  => 'apps',
                    'eventId'   => 'resup',
                ]);
    
    Damien's avatar
    Damien committed
    
    
            return $response->withJson(['success' => 'success']);
    
    Damien's avatar
    Damien committed
        }
    
    
        public function getFileContent(Request $request, Response $response, array $aArgs)
        {
    
            if (!Validator::intVal()->validate($aArgs['resId']) || !ResController::hasRightByResId(['resId' => [$aArgs['resId']], 'userId' => $GLOBALS['id']])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
    
            $document = ResModel::getById(['select' => ['filename', 'format', 'typist'], 'resId' => $aArgs['resId']]);
    
            if (empty($document)) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']);
    
            } elseif (empty($document['filename'])) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Document has no file']);
            }
    
            $originalFormat = $document['format'];
    
            $creatorId = $document['typist'];
    
            $convertedDocument = ConvertPdfController::getConvertedPdfById(['resId' => $aArgs['resId'], 'collId' => 'letterbox_coll']);
    
            if (!empty($convertedDocument['errors'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Conversion error : ' . $convertedDocument['errors']]);
    
            $document = $convertedDocument;
    
    
    Damien's avatar
    Damien committed
            $docserver = DocserverModel::getByDocserverId(['docserverId' => $document['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
    
            if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']);
            }
    
            $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $document['path']) . $document['filename'];
    
    Alex ORLUC's avatar
    Alex ORLUC committed
            if (!file_exists($pathToDocument)) {
                return $response->withStatus(404)->withJson(['errors' => 'Document not found on docserver']);
            }
    
    Damien's avatar
    Damien committed
    
            $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
            $fingerprint = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
            if (!empty($document['fingerprint']) && $document['fingerprint'] != $fingerprint) {
                return $response->withStatus(400)->withJson(['errors' => 'Fingerprints do not match']);
            }
    
    
            $fileContent = WatermarkController::watermarkResource(['resId' => $aArgs['resId'], 'path' => $pathToDocument]);
    
    
            if (empty($fileContent)) {
    
                $fileContent = file_get_contents($pathToDocument);
    
            if ($fileContent === false) {
                return $response->withStatus(404)->withJson(['errors' => 'Document not found on docserver']);
            }
    
    
    Damien's avatar
    Damien committed
            HistoryController::add([
                'tableName' => 'res_letterbox',
                'recordId'  => $aArgs['resId'],
                'eventType' => 'VIEW',
                'info'      => _DOC_DISPLAYING . " : {$aArgs['resId']}",
                'moduleId'  => 'res',
                'eventId'   => 'resview',
            ]);
    
    
            $data = $request->getQueryParams();
            if ($data['mode'] == 'base64') {
    
                return $response->withJson(['encodedDocument' => base64_encode($fileContent), 'originalFormat' => $originalFormat, 'originalCreatorId' => $creatorId]);
    
            } else {
                $finfo    = new \finfo(FILEINFO_MIME_TYPE);
                $mimeType = $finfo->buffer($fileContent);
                $pathInfo = pathinfo($pathToDocument);
    
                $response->write($fileContent);
    
                $contentDisposition = $data['mode'] == 'view' ? 'inline' : 'attachment';
                $response = $response->withAddedHeader('Content-Disposition', "{$contentDisposition}; filename=maarch.{$pathInfo['extension']}");
    
                return $response->withHeader('Content-Type', $mimeType);
            }
    
        public function getVersionsInformations(Request $request, Response $response, array $args)
    
        {
            if (!Validator::intVal()->validate($args['resId']) || !ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
    
            $pdfVersions = [];
            $signedVersions = [];
            $noteVersions = [];
    
            $resource = ResModel::getById(['resId' => $args['resId'], 'select' => ['version', 'filename', 'format']]);
    
            if (empty($resource['filename'])) {
    
                return $response->withJson(['DOC' => $docVersions, 'PDF' => $pdfVersions, 'SIGN' => $signedVersions, 'NOTE' => $noteVersions]);
    
            $canConvert = ConvertPdfController::canConvert(['extension' => $resource['format']]);
            
    
            $convertedDocuments = AdrModel::getDocuments([
    
                'select'    => ['type', 'version'],
                'where'     => ['res_id = ?', 'type in (?)'],
    
                'data'      => [$args['resId'], ['DOC', 'PDF', 'SIGN', 'NOTE']],
    
                'orderBy'   => ['version ASC']
    
            if (empty($convertedDocuments)) {
    
                return $response->withJson(['DOC' => [$resource['version']], 'PDF' => $pdfVersions, 'SIGN' => $signedVersions, 'NOTE' => $noteVersions, 'convert' => $canConvert]);
    
    
            foreach ($convertedDocuments as $convertedDocument) {
    
                if ($convertedDocument['type'] == 'DOC') {
                    $docVersions[] = $convertedDocument['version'];
                } elseif ($convertedDocument['type'] == 'PDF') {
    
                    $pdfVersions[] = $convertedDocument['version'];
                } elseif ($convertedDocument['type'] == 'SIGN') {
                    $signedVersions[] = $convertedDocument['version'];
                } elseif ($convertedDocument['type'] == 'NOTE') {
                    $noteVersions[] = $convertedDocument['version'];
    
            $docVersions[] = $resource['version'];
    
            return $response->withJson(['DOC' => $docVersions, 'PDF' => $pdfVersions, 'SIGN' => $signedVersions, 'NOTE' => $noteVersions, 'convert' => $canConvert]);
    
        public function getVersionFileContent(Request $request, Response $response, array $args)
        {
            if (!Validator::intVal()->validate($args['resId']) || !ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
            $resource = ResModel::getById(['resId' => $args['resId'], 'select' => ['version', 'filename']]);
            if (empty($resource['filename'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Document has no file']);
            } elseif (!Validator::intVal()->validate($args['version']) || $args['version'] > $resource['version'] || $args['version'] < 1) {
                return $response->withStatus(400)->withJson(['errors' => 'Incorrect version']);
            }
    
            $queryParams = $request->getQueryParams();
    
            $type = 'PDF';
            if (!empty($queryParams['type']) && in_array($queryParams['type'], ['PDF', 'SIGN', 'NOTE'])) {
                $type = $queryParams['type'];
            }
    
            if ($type == 'NOTE' && !PrivilegeController::hasPrivilege(['privilegeId' => 'view_documents_with_notes', 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
            $convertedDocument = AdrModel::getDocuments([
                'select'    => ['docserver_id', 'path', 'filename', 'fingerprint'],
                'where'     => ['res_id = ?', 'type = ?', 'version = ?'],
                'data'      => [$args['resId'], $type, $args['version']]
            ]);
    
            if (empty($convertedDocument[0])) {
                return $response->withStatus(400)->withJson(['errors' => 'Type has no file']);
            }
            $convertedDocument = $convertedDocument[0];
    
            $docserver = DocserverModel::getByDocserverId(['docserverId' => $convertedDocument['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
            if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']);
            }
    
            $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $convertedDocument['path']) . $convertedDocument['filename'];
            if (!file_exists($pathToDocument)) {
                return $response->withStatus(404)->withJson(['errors' => 'Document not found on docserver']);
            }
    
            $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
            $fingerprint = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
            if (!empty($document['fingerprint']) && $document['fingerprint'] != $fingerprint) {
                return $response->withStatus(400)->withJson(['errors' => 'Fingerprints do not match']);
            }
    
            $fileContent = WatermarkController::watermarkResource(['resId' => $args['resId'], 'path' => $pathToDocument]);
            if (empty($fileContent)) {
                $fileContent = file_get_contents($pathToDocument);
            }
            if ($fileContent === false) {
                return $response->withStatus(404)->withJson(['errors' => 'Document not found on docserver']);
    
            return $response->withJson(['encodedDocument' => base64_encode($fileContent)]);
    
    Damien's avatar
    Damien committed
        public function getOriginalFileContent(Request $request, Response $response, array $aArgs)
        {
    
            if (!Validator::intVal()->validate($aArgs['resId']) || !ResController::hasRightByResId(['resId' => [$aArgs['resId']], 'userId' => $GLOBALS['id']])) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
    
            $document = ResModel::getById(['select' => ['docserver_id', 'path', 'filename', 'category_id'], 'resId' => $aArgs['resId']]);
            if (empty($document)) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']);
            }
    
    
            if (empty($document['filename'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Document has no file']);
            }
    
    
    Damien's avatar
    Damien committed
            $docserver = DocserverModel::getByDocserverId(['docserverId' => $document['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
            if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']);
            }
    
            $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $document['path']) . $document['filename'];
            if (!file_exists($pathToDocument)) {
                return $response->withStatus(404)->withJson(['errors' => 'Document not found on docserver']);
            }
    
            $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
            $fingerprint = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
            if (!empty($document['fingerprint']) && $document['fingerprint'] != $fingerprint) {
                return $response->withStatus(400)->withJson(['errors' => 'Fingerprints do not match']);
            }
    
    
            $fileContent = file_get_contents($pathToDocument);
    
    Damien's avatar
    Damien committed
            if ($fileContent === false) {
                return $response->withStatus(404)->withJson(['errors' => 'Document not found on docserver']);
            }
    
            $finfo    = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->buffer($fileContent);
            $pathInfo = pathinfo($pathToDocument);
    
            $response->write($fileContent);
    
            $response = $response->withAddedHeader('Content-Disposition', "attachment; filename=maarch.{$pathInfo['extension']}");
    
            HistoryController::add([
                'tableName' => 'res_letterbox',
                'recordId'  => $aArgs['resId'],
                'eventType' => 'VIEW',
                'info'      => _DOC_DISPLAYING . " : {$aArgs['resId']}",
                'moduleId'  => 'res',
                'eventId'   => 'resview',
            ]);
    
    
            return $response->withHeader('Content-Type', $mimeType);
        }
    
    
        public function getThumbnailContent(Request $request, Response $response, array $args)
    
    Damien's avatar
    Damien committed
        {
    
            if (!Validator::intVal()->validate($args['resId'])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'resId param is not an integer']);
    
    Damien's avatar
    Damien committed
            }
    
    
            $pathToThumbnail = 'apps/maarch_entreprise/img/noThumbnail.png';
    
            $document = ResModel::getById(['select' => ['filename', 'version'], 'resId' => $args['resId']]);
    
            if (empty($document)) {
                return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']);
            }
    
    
            if (!empty($document['filename']) && ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
    
                $tnlAdr = AdrModel::getDocuments(['select' => ['docserver_id', 'path', 'filename'], 'where' => ['res_id = ?', 'type = ?', 'version = ?'], 'data' => [$args['resId'], 'TNL', $document['version']]]);
    
                if (empty($tnlAdr[0])) {
    
                    $control = ConvertThumbnailController::convert(['type' => 'resource', 'resId' => $args['resId']]);
                    if (!empty($control['errors'])) {
                        return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
                    }
                    $tnlAdr = AdrModel::getDocuments(['select' => ['docserver_id', 'path', 'filename'], 'where' => ['res_id = ?', 'type = ?', 'version = ?'], 'data' => [$args['resId'], 'TNL', $document['version']]]);
    
    Damien's avatar
    Damien committed
    
    
                if (!empty($tnlAdr[0])) {
                    $docserver = DocserverModel::getByDocserverId(['docserverId' => $tnlAdr[0]['docserver_id'], 'select' => ['path_template']]);
    
                    if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
                        return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']);
                    }
    
    
                    $pathToThumbnail = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $tnlAdr[0]['path']) . $tnlAdr[0]['filename'];
    
    Damien's avatar
    Damien committed
    
            $fileContent = file_get_contents($pathToThumbnail);
            if ($fileContent === false) {
                return $response->withStatus(404)->withJson(['errors' => 'Thumbnail not found on docserver']);
            }
    
            $finfo    = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->buffer($fileContent);
            $pathInfo = pathinfo($pathToThumbnail);
    
            $response->write($fileContent);
            $response = $response->withAddedHeader('Content-Disposition', "inline; filename=maarch.{$pathInfo['extension']}");
    
            return $response->withHeader('Content-Type', $mimeType);
        }
    
    
        public function getItems(Request $request, Response $response, array $args)
        {
            if (!Validator::intVal()->validate($args['resId']) || !ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
            $document = ResModel::getById([
                'select'    => ['linked_resources'],
                'resId'     => $args['resId']
            ]);
            if (empty($document)) {
                return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']);
            }
    
            $linkedResources = json_decode($document['linked_resources'], true);
    
            if (!empty($linkedResources)) {
                $linkedResources = ResController::getAuthorizedResources(['resources' => $linkedResources, 'userId' => $GLOBALS['id']]);
            }
    
            $formattedData['linkedResources'] = count($linkedResources);
    
            $attachments = AttachmentModel::get(['select' => ['count(1)'], 'where' => ['res_id_master = ?', 'status in (?)'], 'data' => [$args['resId'], ['TRA', 'A_TRA', 'FRZ']]]);
            $formattedData['attachments'] = $attachments[0]['count'];
    
            $formattedData['diffusionList'] = 0;
            $formattedData['visaCircuit'] = 0;
            $formattedData['opinionCircuit'] = 0;
            $listInstanceItems = ListInstanceModel::get(['select' => ['count(1)', 'difflist_type'], 'where' => ['res_id = ?'], 'data' => [$args['resId']], 'groupBy' => ['difflist_type']]);
            foreach ($listInstanceItems as $item) {
                $type = $item['difflist_type'] == 'entity_id' ? 'diffusionList' : ($item['difflist_type'] == 'VISA_CIRCUIT' ? 'visaCircuit' : 'opinionCircuit');
                $formattedData[$type] = $item['count'];
            }
    
            $formattedData['notes'] = NoteModel::countByResId(['resId' => $args['resId'], 'userId' => $GLOBALS['id'], 'login' => $GLOBALS['userId']]);
    
    
            $emails = EmailModel::get(['select' => ['count(1)'], 'where' => ["document->>'id' = ?", "(status != 'DRAFT' or (status = 'DRAFT' and user_id = ?))"], 'data' => [$args['resId'], $GLOBALS['id']]]);
    
            $acknowledgementReceipts = AcknowledgementReceiptModel::get([
                'select' => ['count(1)'],
                'where'  => ['res_id = ?'],
                'data'   => [$args['resId']]
            ]);
            $messageExchanges = MessageExchangeModel::get([
                'select' => ['count(1)'],
                'where'  => ['res_id_master = ?'],
                'data'   => [$args['resId']]
            ]);
            $attachments = AttachmentModel::get([
                'select' => ['res_id'],
                'where'  => ['res_id_master = ?'],
                'data'   => [$args['resId']]
            ]);
            $attachments = array_column($attachments, 'res_id');
    
            $where = '(document_id = ? and document_type = ?)';
            $data  = [$args['resId'], 'resource'];
            if (!empty($attachments)) {
                $where .= ' or (document_id in (?) and document_type = ?)';
                $data[] = $attachments;
                $data[] = 'attachment';
            }
            $shippings = ShippingModel::get([
                'select' => ['count(1)'],
                'where'  => [$where],
                'data'   => $data
            ]);
    
            $formattedData['emails'] = $emails[0]['count'] + $acknowledgementReceipts[0]['count'] + $messageExchanges[0]['count'] + $shippings[0]['count'];
    
    
            return $response->withJson($formattedData);
        }
    
        public function getCategories(Request $request, Response $response)
        {
            return $response->withJson(['categories' => ResModel::getCategories()]);
        }
    
        public function isAllowedForCurrentUser(Request $request, Response $response, array $aArgs)
        {
            if (!Validator::intVal()->validate($aArgs['resId']) || !ResController::hasRightByResId(['resId' => [$aArgs['resId']], 'userId' => $GLOBALS['id']])) {
                return $response->withJson(['isAllowed' => false]);
            }
    
            return $response->withJson(['isAllowed' => true]);
        }
    
    
        public function updateExternalInfos(Request $request, Response $response)
        {
    
    Damien's avatar
    Damien committed
            //TODO Revoir cette fonction
    
            $data = $request->getParams();
    
    
            if (empty($data['externalInfos'])) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request : externalInfos is empty']);
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request : status is empty']);
    
            foreach ($data['externalInfos'] as $mail) {
    
                if (!Validator::intType()->validate($mail['res_id'])) {
    
                    return $response->withStatus(400)->withJson(['errors' => 'Bad Request: invalid res_id']);
    
                if (!Validator::StringType()->notEmpty()->validate($mail['external_id'])) {
    
                    return $response->withStatus(400)->withJson(['errors' => 'Bad Request: invalid external_id for element : '.$mail['res_id']]);
                }
    
                if (!Validator::StringType()->notEmpty()->validate($mail['external_link'])) {
    
                    return $response->withStatus(400)->withJson(['errors' => 'Bad Request:  invalid external_link for element'.$mail['res_id']]);
    
            foreach ($data['externalInfos'] as $mail) {
    
    Damien's avatar
    Damien committed
                $document = ResModel::getById(['resId' => $mail['res_id'], 'select' => ['res_id', 'external_id']]);
    
                if (empty($document)) {
                    return $response->withStatus(400)->withJson(['errors' => _DOCUMENT_NOT_FOUND]);
                }
    
                if (!ResController::hasRightByResId(['resId' => [$document['res_id']], 'userId' => $GLOBALS['id']])) {
    
                    return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
                }
    
    Damien's avatar
    Damien committed
                $externalId = json_decode($document['external_id'], true);
                $externalId['publikId'] = $mail['external_id'];
                ResModel::update(['set' => ['external_id' => json_encode($externalId), 'external_link' => $mail['external_link'], 'status' => $data['status']], 'where' => ['res_id = ?'], 'data' => [$document['res_id']]]);
    
            return $response->withJson(['success' => 'success']);
    
        public static function setInIntegrations(Request $request, Response $response)
    
        {
            $body = $request->getParsedBody();
    
    
            if (empty($body['resources']) || !Validator::arrayType()->validate($body['resources'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Body param resources is missing']);
    
            if (!ResController::hasRightByResId(['resId' => $body['resources'], 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
    
            if (empty($body['integrations']) || !Validator::arrayType()->validate($body['integrations'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Body param integrations is missing or not an array']);
    
            if (isset($body['integrations']['inSignatureBook']) && Validator::boolType()->validate($body['integrations']['inSignatureBook'])) {
                $inSignatureBook = $body['integrations']['inSignatureBook'] ? 'true' : 'false';
    
                ResModel::update([
                    'postSet'   => [
                        'integrations' => "jsonb_set(integrations, '{inSignatureBook}', '".$inSignatureBook."')",
                    ],
                    'where' => ['res_id in (?)'],
                    'data'  => [$body['resources']]
                ]);
            }
    
            if (isset($body['integrations']['inShipping']) && Validator::boolType()->validate($body['integrations']['inShipping'])) {
                $inShipping = $body['integrations']['inShipping'] ? 'true' : 'false';
    
                    'postSet'   => [
                        'integrations' => "jsonb_set(integrations, '{inShipping}', '".$inShipping."')",
    
                    'where' => ['res_id in (?)'],
                    'data'  => [$body['resources']]
    
            return $response->withStatus(204);
        }
    
        public function getField(Request $request, Response $response, array $args)
        {
            if (!ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
                return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
            }
    
            $authorizedFields = ['destination', 'status'];
            if (!in_array($args['fieldId'], $authorizedFields)) {
                return $response->withStatus(403)->withJson(['errors' => 'Field out of perimeter']);
            }
    
            $resource = ResModel::getById([
                'select'    => [$args['fieldId']],
                'resId'     => $args['resId']
            ]);
            if (empty($resource)) {
                return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']);
            }
    
            return $response->withJson(['field' => $resource[$args['fieldId']]]);
        }
    
    
    Damien's avatar
    Damien committed
        public static function getEncodedDocument(array $aArgs)
        {
            ValidatorModel::notEmpty($aArgs, ['resId']);
            ValidatorModel::intVal($aArgs, ['resId']);
            ValidatorModel::boolType($aArgs, ['original']);
    
    
            $document = ResModel::getById(['select' => ['docserver_id', 'path', 'filename', 'subject'], 'resId' => $aArgs['resId']]);
    
    Damien's avatar
    Damien committed
    
            if (empty($aArgs['original'])) {
    
                $convertedDocument = ConvertPdfController::getConvertedPdfById(['resId' => $aArgs['resId'], 'collId' => 'letterbox_coll']);
    
                if (empty($convertedDocument['errors'])) {
                    $document['docserver_id'] = $convertedDocument['docserver_id'];
                    $document['path'] = $convertedDocument['path'];
                    $document['filename'] = $convertedDocument['filename'];
                    $document['fingerprint'] = $convertedDocument['fingerprint'];
    
    Damien's avatar
    Damien committed
                }
            }
    
            $docserver = DocserverModel::getByDocserverId(['docserverId' => $document['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
            if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
                return ['errors' => 'Docserver does not exist'];
            }
    
            $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $document['path']) . $document['filename'];
            if (!file_exists($pathToDocument)) {
                return ['errors' => 'Document not found on docserver'];
            }
    
            $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
            $fingerprint = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
            if (!empty($document['fingerprint']) && $document['fingerprint'] != $fingerprint) {
                ['errors' => 'Fingerprints do not match'];
            }
    
            $fileContent = file_get_contents($pathToDocument);
            if ($fileContent === false) {
                return ['errors' => 'Document not found on docserver'];
            }
    
            $encodedDocument = base64_encode($fileContent);
    
    
    Damien's avatar
    Damien committed
            if (!empty($document['subject'])) {
    
                $document['subject'] = preg_replace(utf8_decode('@[\\/:*?"<>|]@i'), '_', substr($document['subject'], 0, 30));
    
    Damien's avatar
    Damien committed
            $pathInfo = pathinfo($pathToDocument);
            $fileName = (empty($document['subject']) ? 'document' : $document['subject']) . ".{$pathInfo['extension']}";
    
            return ['encodedDocument' => $encodedDocument, 'fileName' => $fileName];
        }
    
    
        public static function hasRightByResId(array $args)
    
            ValidatorModel::notEmpty($args, ['resId', 'userId']);
            ValidatorModel::intVal($args, ['userId']);
            ValidatorModel::arrayType($args, ['resId']);
    
            $resources = array_unique($args['resId']);
    
            $authorizedResources = ResController::getAuthorizedResources(['resources' => $resources, 'userId' => $args['userId']]);
    
            return count($authorizedResources) == count($resources);
        }
    
        public static function getAuthorizedResources(array $args)
        {
            ValidatorModel::notEmpty($args, ['resources', 'userId']);
            ValidatorModel::intVal($args, ['userId']);
            ValidatorModel::arrayType($args, ['resources']);
    
    
            $user = UserModel::getById(['id' => $args['userId'], 'select' => ['user_id']]);
    
            if ($user['user_id'] == 'superadmin') {
    
                return $args['resources'];
    
            $whereClause = '(res_id in (select res_id from users_followed_resources where user_id = ?))';
    
            $entities = UserModel::getEntitiesByLogin(['login' => $user['user_id'], 'select' => ['id']]);
    
            $entities = array_column($entities, 'id');
    
            $foldersClause = 'res_id in (select res_id from folders LEFT JOIN entities_folders ON folders.id = entities_folders.folder_id LEFT JOIN resources_folders ON folders.id = resources_folders.folder_id ';
    
            $foldersClause .= "WHERE entities_folders.entity_id in (?) OR folders.user_id = ? OR keyword = 'ALL_ENTITIES')";
    
            $whereClause .= " OR ({$foldersClause})";
    
            $groups = UserModel::getGroupsByLogin(['login' => $user['user_id'], 'select' => ['where_clause']]);
    
            $groupsClause = '';
            foreach ($groups as $key => $group) {
                if (!empty($group['where_clause'])) {
    
                    $groupClause = PreparedClauseController::getPreparedClause(['clause' => $group['where_clause'], 'login' => $user['user_id']]);
    
                    if ($key > 0) {
                        $groupsClause .= ' or ';
                    }
                    $groupsClause .= "({$groupClause})";
                }
    
            if (!empty($groupsClause)) {
    
                $whereClause .= " OR ({$groupsClause})";
    
            $baskets = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
    
            $basketsClause = '';
    
    Damien's avatar
    Damien committed
            foreach ($baskets as $basket) {
    
                if (!empty($basket['basket_clause'])) {
    
                    $basketClause = PreparedClauseController::getPreparedClause(['clause' => $basket['basket_clause'], 'login' => $user['user_id']]);
    
    Damien's avatar
    Damien committed
                    if (!empty($basketsClause)) {
                        $basketsClause .= ' or ';
                    }
                    $basketsClause .= "({$basketClause})";
                }
            }
    
            $assignedBaskets = RedirectBasketModel::getAssignedBasketsByUserId(['userId' => $args['userId']]);
    
    Damien's avatar
    Damien committed
            foreach ($assignedBaskets as $basket) {
                if (!empty($basket['basket_clause'])) {
                    $basketOwner = UserModel::getById(['id' => $basket['owner_user_id'], 'select' => ['user_id']]);
                    $basketClause = PreparedClauseController::getPreparedClause(['clause' => $basket['basket_clause'], 'login' => $basketOwner['user_id']]);
                    if (!empty($basketsClause)) {
    
                        $basketsClause .= ' or ';
                    }
                    $basketsClause .= "({$basketClause})";
                }
    
            if (!empty($basketsClause)) {
    
                $whereClause .= " OR ({$basketsClause})";
    
                $res = ResModel::getOnView(['select' => ['res_id'], 'where' => ['res_id in (?)', "({$whereClause})"], 'data' => [$args['resources'], $args['userId'], $entities, $args['userId']]]);
    
                return array_column($res, 'res_id');
    
            } catch (\Exception $e) {
    
        private static function createAdjacentData(array $args)
    
            ValidatorModel::notEmpty($args, ['resId', 'body']);
            ValidatorModel::intVal($args, ['resId']);
            ValidatorModel::arrayType($args, ['body']);
    
            $body = $args['body'];
    
            if (!empty($body['diffusionList'])) {
                foreach ($body['diffusionList'] as $diffusion) {
    
                    if ($diffusion['type'] == 'user') {
                        $item = UserModel::getById(['id' => $diffusion['id'], 'select' => ['user_id']]);
                        $diffusion['id'] = $item['user_id'];
                    } else {
                        $item = EntityModel::getById(['id' => $diffusion['id'], 'select' => ['entity_id']]);
                        $diffusion['id'] = $item['entity_id'];
                    }
    
    
                    if ($diffusion['mode'] == 'dest') {
                        ResModel::update(['set' => ['dest_user' => $diffusion['id']], 'where' => ['res_id = ?'], 'data' => [$args['resId']]]);
                    }
    
                    ListInstanceModel::create([
                        'res_id'            => $args['resId'],
                        'sequence'          => 0,
    
                        'item_id'           => $diffusion['id'],
    
                        'item_type'         => $diffusion['type'] == 'user' ? 'user_id' : 'entity_id',