Skip to content
Snippets Groups Projects
DocserverController.php 19.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 Docserver Controller
    * @author dev@maarch.org
    * @ingroup core
    */
    
    namespace Core\Controllers;
    
    use Psr\Http\Message\RequestInterface;
    use Psr\Http\Message\ResponseInterface;
    use Respect\Validation\Validator;
    use Core\Models\DocserverModel;
    
    class DocserverController
    {
    
        public function getList(RequestInterface $request, ResponseInterface $response)
        {
            $obj = DocserverModel::getList();
            
            $datas = [
    
                $obj,
    
            ];
            
            return $response->withJson($datas);
        }
    
        public function getById(RequestInterface $request, ResponseInterface $response, $aArgs)
        {
            if (isset($aArgs['id'])) {
                $id = $aArgs['id'];
                $obj = DocserverModel::getById([
                    'id' => $id
                ]);
            } else {
    
                return $response
                    ->withStatus(500)
                    ->withJson(['errors' => _ID . ' ' . _IS_EMPTY]);
            }
            
            $datas = [
    
                $obj,
    
            ];
    
            return $response->withJson($datas);
        }
    
        public function create(RequestInterface $request, ResponseInterface $response, $aArgs)
        {
            $errors = [];
    
            $errors = $this->control($request, 'create');
    
            if (!empty($errors)) {
    
                return $response
                    ->withStatus(500)
                    ->withJson(['errors' => $errors]);
            }
    
            $aArgs = $request->getQueryParams();
    
            $return = DocserverModel::create($aArgs);
    
            if ($return) {
                $id = $aArgs['id'];
                $obj = DocserverModel::getById([
                    'id' => $id
                ]);
            } else {
    
                return $response
                    ->withStatus(500)
                    ->withJson(['errors' => _NOT_CREATE]);
            }
    
            $datas = [
    
                $obj,
    
            ];
    
            return $response->withJson($datas);
        }
    
        public function update(RequestInterface $request, ResponseInterface $response, $aArgs)
        {
            $errors = [];
    
            $errors = $this->control($request, 'update');
    
            if (!empty($errors)) {
    
                return $response
                    ->withStatus(500)
                    ->withJson(['errors' => $errors]);
            }
    
            $aArgs = $request->getQueryParams();
    
            $return = DocserverModel::update($aArgs);
    
            if ($return) {
                $id = $aArgs['id'];
                $obj = DocserverModel::getById([
                    'id' => $id
                ]);
            } else {
    
                return $response
                    ->withStatus(500)
                    ->withJson(['errors' => _NOT_UPDATE]);
            }
    
            $datas = [
    
            ];
    
            return $response->withJson($datas);
        }
    
        public function delete(RequestInterface $request, ResponseInterface $response, $aArgs)
        {
            if (isset($aArgs['id'])) {
                $id = $aArgs['id'];
                $obj = DocserverModel::delete([
                    'id' => $id
                ]);
            } else {
                
                return $response
                    ->withStatus(500)
                    ->withJson(['errors' => _NOT_DELETE]);
            }
            
            $datas = [
    
            ];
    
            return $response->withJson($datas);
        }
    
        protected function control($request, $mode)
        {
            $errors = [];
    
            if($mode == 'update') {
                $obj = DocserverModel::getById([
                    'id' => $request->getParam('id')
                ]);
                if (empty($obj)) {
                    array_push(
                        $errors, 
                        _ID . ' ' . $request->getParam('id') . ' ' . _NOT_EXISTS
                    );
                }
            }
    
            if (!Validator::notEmpty()->validate($request->getParam('id'))) {
                array_push($errors, _ID . ' ' . _IS_EMPTY);
            } elseif($mode == 'create') {
                $obj = DocserverModel::getById([
                    'id' => $request->getParam('id')
                ]);
                if (!empty($obj)) {
                    array_push(
                        $errors, 
                        _ID . ' ' . $obj[0]['id'] . ' ' . _ALREADY_EXISTS
                    );
                }
            }
    
            if (!Validator::regex('/^[\w.-]*$/')->validate($request->getParam('id'))) {
                array_push($errors, _ID . ' ' . _NOT . ' ' . _VALID);
            }
    
            if (!Validator::notEmpty()->validate($request->getParam('label_status'))) {
                array_push($errors, _LABEL_STATUS . ' ' . _IS_EMPTY);
            }
    
            if (
                Validator::notEmpty()
                    ->validate($request->getParam('is_system')) &&
                !Validator::contains('Y')
                    ->validate($request->getParam('is_system')) &&
                !Validator::contains('N')
                    ->validate($request->getParam('is_system'))
            ) {
                array_push($errors, _IS_SYSTEM . ' ' . _NOT . ' ' . _VALID);
            }
    
            if (
                Validator::notEmpty()
                    ->validate($request->getParam('is_folder_status')) &&
                !Validator::contains('Y')
                    ->validate($request->getParam('is_folder_status')) &&
                !Validator::contains('N')
                    ->validate($request->getParam('is_folder_status'))
            ) {
                array_push($errors, _IS_FOLDER_STATUS . ' ' . _NOT . ' ' . _VALID);
            }
    
            if (
                Validator::notEmpty()
                    ->validate($request->getParam('img_filename')) &&
                (!Validator::regex('/^[\w-.]+$/')
                    ->validate($request->getParam('img_filename')) ||
                !Validator::length(null, 255)
                    ->validate($request->getParam('img_filename')))
            ) {
                array_push($errors, _IMG_FILENAME . ' ' . _NOT . ' ' . _VALID);
            }
    
            if (
                Validator::notEmpty()
                    ->validate($request->getParam('maarch_module')) &&
                !Validator::length(null, 255)
                    ->validate($request->getParam('maarch_module'))
            ) {
                array_push($errors, _MAARCH_MODULE . ' ' . _NOT . ' ' . _VALID);
            }
    
            if (
                Validator::notEmpty()
                    ->validate($request->getParam('can_be_searched')) &&
                !Validator::contains('Y')
                    ->validate($request->getParam('can_be_searched')) &&
                !Validator::contains('N')
                    ->validate($request->getParam('can_be_searched'))
            ) {
                array_push($errors, _CAN_BE_SEARCHED . ' ' . _NOT . ' ' . _VALID);
            }
    
            if (
                Validator::notEmpty()
                    ->validate($request->getParam('can_be_modified')) &&
                !Validator::contains('Y')
                    ->validate($request->getParam('can_be_modified')) &&
                !Validator::contains('N')
                    ->validate($request->getParam('can_be_modified'))
            ) {
                array_push($errors, _CAN_BE_MODIFIED . ' ' . _NOT . ' ' . _VALID);
            }
    
            return $errors;
        }
    
        /**
         * Get docservers to insert a new doc.
         * Can return null if no corresponding object.
         * @param  $coll_id  string Collection identifier
         * @return docservers
         */
        public function getDocserverToInsert($aArgs)
        {
            if (isset($aArgs['collId'])) {
                $collId = $aArgs['collId'];
                $obj = DocserverModel::getDocserverToInsert([
                    'collId' => $collId
                ]);
            } else {
    
                return ['errors' => 'collId ' . _EMPTY];
            }
    
    
            $datas = $obj;
    
    
            return $datas;
        }
    
        /**
        * Checks the size of the docserver plus a new file to see
        * if there is enough disk space
        *
        * @param  $docserver docservers object
        * @param  $filesize integer File size
        * @return integer New docserver size or 0 if not enough disk space available
        */
        public function checkSize($aArgs)
        {
    
            $newDsSize = $aArgs['docserver']['actual_size_number'] + $aArgs['filesize'];
    
            if (empty($aArgs['docserver']['actual_size_number'])) {
                $datas = [
                        'errors' => 'actual_size_number' . _EMPTY,
                ];
    
                return $datas;
            }
    
            if (empty($aArgs['filesize'])) {
                $datas = [
                        'errors' => 'filesize' . _EMPTY,
                ];
    
                return $datas;
            }
            
            if (
                $aArgs['docserver']['size_limit_number'] > 0 &&
                $newDsSize >= $aArgs['docserver']['size_limit_number']
            ) {
                $datas = [
                    'newDsSize' => 0,
                ];
            } else {
                $datas = [
                    'newDsSize' => $newDsSize,
                ];
            }
    
            return $datas;
        }
    
        /**
        * Sets the size of the docserver
        * @param $docserver docservers object
        * @param $newSize integer New size of the docserver
        */
        public function setSize($aArgs)
        {
            if (empty($aArgs['docserver_id'])) {
    
                return ['errors' => 'docserver_id ' . _EMPTY];
            }
    
            if (empty($aArgs['actual_size_number'])) {
    
                return ['errors' => 'actual_size_number ' . _EMPTY];
            }
    
            //$obj = DocserverModel::setSize($aArgs);
            $return = DocserverModel::update($aArgs);
            
            $datas = [
                'setSize' => true,
            ];
    
            return $datas;
        }
    
    
        /**
        * Calculates the next file name in the docserver
        * @param $pathOnDocserver docservers path
        * @return array Contains 3 items :
        * subdirectory path and new filename and error
        */
        public function getNextFileNameInDocserver($aArgs)
        {
            if (empty($aArgs['pathOnDocserver'])) {
                $datas = [
                        'errors' => 'pathOnDocserver ' . _EMPTY,
                ];
    
                return $datas;
            }
    
            if (!is_dir($aArgs['pathOnDocserver'])) {
                $datas = [
                        'errors' => 'pathOnDocserver ' . _NOT_EXISTS,
                ];
    
                return $datas;
            }
    
            $pathOnDocserver = $aArgs['pathOnDocserver'];
    
            $dsTools = new \Core\Controllers\DocserverToolsController();
    
            umask(0022);
            //Scans the docserver path
            $fileTab = scandir($pathOnDocserver);
            //Removes . and .. lines
            array_shift($fileTab);
            array_shift($fileTab);
    
            if (file_exists($pathOnDocserver . DIRECTORY_SEPARATOR . 'package_information')) {
                unset($fileTab[array_search('package_information', $fileTab)]);
            }
            
            if (is_dir($pathOnDocserver . DIRECTORY_SEPARATOR . 'BATCH')) {
                unset($fileTab[array_search('BATCH', $fileTab)]);
            }
    
            $nbFiles = count($fileTab);
            //Docserver is empty
            if ($nbFiles == 0 ) {
                //Creates the directory
                if (!mkdir($pathOnDocserver . '0001', 0770)) {
                    $datas = [
                        'errors' => 'Pb to create directory on the docserver:'
                            . $pathOnDocserver,
                    ];
    
                    return $datas;
                } else {
                    $dsTools->setRights(
                        ['path' => $pathOnDocserver . '0001' . DIRECTORY_SEPARATOR]
                    );
                    $destinationDir = $pathOnDocserver . '0001'
                                    . DIRECTORY_SEPARATOR;
                    $fileDestinationName = '0001';
                    $fileDestinationName = $fileDestinationName . '_' . mt_rand();
                    $datas = [
                        'destinationDir' => $destinationDir,
                        'fileDestinationName' => $fileDestinationName,
                    ];
    
                    return $datas;
                }
            } else {
                //Gets next usable subdirectory in the docserver
                $destinationDir = $pathOnDocserver
                    . str_pad(
                        count($fileTab),
                        4,
                        '0',
                        STR_PAD_LEFT
                    )
                    . DIRECTORY_SEPARATOR;
                $fileTabBis = scandir(
                    $pathOnDocserver
                    . strval(str_pad(count($fileTab), 4, '0', STR_PAD_LEFT))
                );
                //Removes . and .. lines
                array_shift($fileTabBis);
                array_shift($fileTabBis);
                $nbFilesBis = count($fileTabBis);
                //If number of files => 1000 then creates a new subdirectory
                if ($nbFilesBis >= 1000 ) {
                    $newDir = ($nbFiles) + 1;
                    if (!mkdir(
                        $pathOnDocserver
                        . str_pad($newDir, 4, '0', STR_PAD_LEFT), 0770
                    )
                    ) {
                        $datas = [
                            'errors' => 'Pb to create directory on the docserver:'
                            . $pathOnDocserver
                            . str_pad($newDir, 4, '0', STR_PAD_LEFT),
                        ];
    
                        return $datas;
                    } else {
                        $dsTools->setRights(
                            [
                                'path' => $pathOnDocserver
                                    . str_pad($newDir, 4, '0', STR_PAD_LEFT)
                                    . DIRECTORY_SEPARATOR
                            ]
                        );
                        $destinationDir = $pathOnDocserver
                            . str_pad($newDir, 4, '0', STR_PAD_LEFT)
                            . DIRECTORY_SEPARATOR;
                        $fileDestinationName = '0001';
                        $fileDestinationName = $fileDestinationName . '_' . mt_rand();
                        $datas = [
                            'destinationDir' => $destinationDir,
                            'fileDestinationName' => $fileDestinationName,
                        ];
    
                        return $datas;
                    }
                } else {
                    //Docserver contains less than 1000 files
                    $newFileName = $nbFilesBis + 1;
                    $greater = $newFileName;
                    for ($n = 0;$n < count($fileTabBis);$n++) {
                        $currentFileName = array();
                        $currentFileName = explode('.', $fileTabBis[$n]);
                        if ((int) $greater <= (int) $currentFileName[0]) {
                            if ((int) $greater == (int) $currentFileName[0]) {
                                $greater ++;
                            } else {
                                //$greater < current
                                $greater = (int) $currentFileName[0] + 1;
                            }
                        }
                    }
                    $fileDestinationName = str_pad($greater, 4, '0', STR_PAD_LEFT);
                    $fileDestinationName = $fileDestinationName . '_' . mt_rand();
                    $datas = [
                        'destinationDir' => $destinationDir,
                        'fileDestinationName' => $fileDestinationName,
                    ];
    
                    return $datas;
                }
            }
        }
    
        /**
         * Store a new doc in a docserver.
         * @param   $collId collection resource
         * @param   $fileInfos infos of the doc to store, contains :
         *          tmpDir : path to tmp directory
         *          size : size of the doc
         *          format : format of the doc
         *          tmpFileName : file name of the doc in Maarch tmp directory
         * @return  array of docserver data for res_x else return error
         */
        public function storeResourceOnDocserver($aArgs)
        {
            if (empty($aArgs['collId'])) {
                
                return ['errors' => 'collId ' . _EMPTY];
            }
    
            if (empty($aArgs['fileInfos'])) {
                
                return ['errors' => 'fileInfos ' . _EMPTY];
            }
    
            if (empty($aArgs['fileInfos']['tmpDir'])) {
                
                return ['errors' => 'fileInfos.tmpDir ' . _EMPTY];
            }
    
            if (empty($aArgs['fileInfos']['size'])) {
                
                return ['errors' => 'fileInfos.size ' . _EMPTY];
            }
    
            if (empty($aArgs['fileInfos']['format'])) {
                
                return ['errors' => 'fileInfos.format ' . _EMPTY];
            }
    
            if (empty($aArgs['fileInfos']['tmpFileName'])) {
                
                return ['errors' => 'fileInfos.tmpFileName ' . _EMPTY];
            }
    
            if (!is_dir($aArgs['fileInfos']['tmpDir'])) {
                
                return ['errors' => 'fileInfos.tmpDir ' . _NOT_EXISTS];
            }
    
            if (!file_exists($aArgs['fileInfos']['tmpDir'] . $aArgs['fileInfos']['tmpFileName'])) {
                
                return ['errors' => 'fileInfos.tmpDir fileInfos.tmpFileName' . _NOT_EXISTS];
            }
    
            $collId = $aArgs['collId'];
            $fileInfos = $aArgs['fileInfos'];
            $size = $aArgs['fileInfos']['size'];
            $tmpDir = $aArgs['fileInfos']['tmpDir'];
    
            $dsTools = new \Core\Controllers\DocserverToolsController();
    
            $docserver = $this->getDocserverToInsert(['collId' => $collId]);
    
            $docserver = $docserver[0];
    
    
            $tmpSourceCopy = '';
            
            if (empty($docserver)) {
                
                return [
                    'errors' => _DOCSERVER_ERROR . ' : '
                        . _NO_AVAILABLE_DOCSERVER . ' .  ' . _MORE_INFOS 
                ];
            }
    
            $newSize = $this->checkSize(
                [
                    'docserver' => $docserver, 
                    'filesize' => $size,
                ]
            );
    
            if ($newSize['newDsSize'] == 0) {
    
                return [
                    'errors' => _DOCSERVER_ERROR . ' : '
                    . _NOT_ENOUGH_DISK_SPACE . ' .  ' . _MORE_INFOS 
                ];
            }
    
            if ($tmpDir == '') {
                $tmp = $_SESSION['config']['tmppath'];
            } else {
                $tmp = $tmpDir;
            }
    
            $d = dir($tmp);
            $pathTmp = $d->path;
            while ($entry = $d->read()) {
                if ($entry == $fileInfos['tmpFileName']) {
                    $tmpSourceCopy = $pathTmp . $entry;
                    $theFile = $entry;
                    break;
                }
            }
            $d->close();
    
            $pathOnDocserver = array();
            $pathOnDocserver = $dsTools->createPathOnDocServer(
                ['path' => $docserver['path_template']]
            );
    
            $docinfo = $this->getNextFileNameInDocserver(
                ['pathOnDocserver' => $pathOnDocserver['createPathOnDocServer']['destinationDir']]
            );
    
            if ($docinfo['errors'] <> '') {
    
                return ['errors' => _FILE_SEND_ERROR];
            }
    
            $docserverTypeControler = new \Core\Models\DocserverTypeModel();
            $docserverTypeObject = $docserverTypeControler->getById(
                ['id' => $docserver['docserver_type_id']]
            );
    
            $docserverTypeObject = $docserverTypeObject[0];
    
            $pathInfoTmpSrc = pathinfo($tmpSourceCopy);
    
            $docinfo['fileDestinationName'] .= '.'
                . strtolower($pathInfoTmpSrc['extension']);
    
            $copyResult = $dsTools->copyOnDocserver(
                [
                    'sourceFilePath'             => $tmpSourceCopy,
                    'destinationDir'             => $docinfo['destinationDir'],
                    'fileDestinationName'        => $docinfo['fileDestinationName'],
                    'docserverSourceFingerprint' => $docserverTypeObject['fingerprint_mode'],
                ]
            );
    
            if (isset($copyResult['errors']) && $copyResult['errors'] <> '') {
    
                return ['errors' => $copyResult['errors']];
            }
    
            $destinationDir = $copyResult['copyOnDocserver']['destinationDir'];
            $fileDestinationName = $copyResult['copyOnDocserver']['fileDestinationName'];
            
            $destinationDir = substr(
                $destinationDir,
                strlen($docserver['path_template'])
            ) . DIRECTORY_SEPARATOR;
            
            $destinationDir = str_replace(
                DIRECTORY_SEPARATOR,
                '#',
                $destinationDir
            );
    
            $this->setSize(
                [
                    'docserver_id' => $docserver['docserver_id'], 
                    'actual_size_number' => $newSize['newDsSize']
                ]
            );
    
            $datas = [
    
                'path_template' => $docserver['path_template'],
                'destination_dir' => $destinationDir,
                'docserver_id' => $docserver['docserver_id'],
                'file_destination_name' => $fileDestinationName,