From 9027d581fb328f9634f54eb0604ba6f2d9fbf333 Mon Sep 17 00:00:00 2001
From: Laurent Giovannoni <laurent.giovannoni@maarch.org>
Date: Thu, 2 Mar 2017 14:29:06 +0100
Subject: [PATCH] FEAT docservers in MVC

---
 composer.json                                 |   1 +
 core/Controllers/DocserverController.php      | 692 ++++++++++++++++++
 core/Controllers/DocserverToolsController.php | 453 ++++++++++++
 core/Controllers/DocserverTypeController.php  | 266 +++++++
 core/Controllers/ResController.php            |  84 +++
 core/Controllers/StatusController.php         |  37 +-
 core/Models/DocserverModel.php                |  22 +
 core/Models/DocserverModelAbstract.php        | 120 +++
 core/Models/DocserverTypeModel.php            |  22 +
 core/Models/DocserverTypeModelAbstract.php    |  88 +++
 core/Models/StatusModel.php                   |   8 +-
 core/Models/StatusModelAbstract.php           |  10 +-
 core/Test/DocserverControllerTest.php         | 245 +++++++
 core/Test/DocserverToolsControllerTest.php    | 143 ++++
 core/Test/DocserverTypeControllerTest.php     | 142 ++++
 core/Test/StatusControllerTest.php            |   7 +
 core/Test/define.php                          |   7 +
 rest/index.php                                |  16 +
 18 files changed, 2342 insertions(+), 21 deletions(-)
 create mode 100644 core/Controllers/DocserverController.php
 create mode 100644 core/Controllers/DocserverToolsController.php
 create mode 100644 core/Controllers/DocserverTypeController.php
 create mode 100644 core/Controllers/ResController.php
 create mode 100644 core/Models/DocserverModel.php
 create mode 100644 core/Models/DocserverModelAbstract.php
 create mode 100644 core/Models/DocserverTypeModel.php
 create mode 100644 core/Models/DocserverTypeModelAbstract.php
 create mode 100644 core/Test/DocserverControllerTest.php
 create mode 100644 core/Test/DocserverToolsControllerTest.php
 create mode 100644 core/Test/DocserverTypeControllerTest.php

diff --git a/composer.json b/composer.json
index d26c3313e0c..ebad0f0a5c8 100644
--- a/composer.json
+++ b/composer.json
@@ -3,6 +3,7 @@
     	"psr-4": {
     		"Core\\": "core/",
     		"Apps\\": "apps/maarch_entreprise/",
+                "Attachments\\": "modules/attachments/",
     		"Visa\\": "modules/visa/"
     	}
     },
diff --git a/core/Controllers/DocserverController.php b/core/Controllers/DocserverController.php
new file mode 100644
index 00000000000..1ab0f72e8ad
--- /dev/null
+++ b/core/Controllers/DocserverController.php
@@ -0,0 +1,692 @@
+<?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 = [
+            [
+                'status' => $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 = [
+            [
+                'status' => $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 = [
+            [
+                'status' => $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 = [
+            [
+                'status' => $obj,
+            ]
+        ];
+
+        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 = [
+            [
+                'status' => $obj,
+            ]
+        ];
+
+        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 = [
+            'docserver' => $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['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 = [
+            'storeResourceOnDocserver' => 
+                [
+                    'path_template' => $docserver['path_template'],
+                    'destination_dir' => $destinationDir,
+                    'docserver_id' => $docserver['docserver_id'],
+                    'file_destination_name' => $fileDestinationName,
+                ]
+        ];
+
+        return $datas;
+    }
+
+}
\ No newline at end of file
diff --git a/core/Controllers/DocserverToolsController.php b/core/Controllers/DocserverToolsController.php
new file mode 100644
index 00000000000..7d883fd3cbc
--- /dev/null
+++ b/core/Controllers/DocserverToolsController.php
@@ -0,0 +1,453 @@
+<?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 tools 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 DocserverToolsController
+{
+
+    /**
+     * Compute the path in the docserver for a batch
+     * @param $docServer docservers path
+     * @return @return array Contains 2 items : subdirectory path and error
+     */
+    public function createPathOnDocServer($aArgs)
+    {
+        if (empty($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!is_dir($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        $pathOnDocserver = $aArgs['path'];
+
+        error_reporting(0);
+
+        umask(0022);
+
+        if (!is_dir($pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR)) {
+            mkdir($pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR, 0770);
+            $this->setRights(['path' => $pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR]);
+        }
+        if (!is_dir(
+            $pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR.date('m')
+            . DIRECTORY_SEPARATOR
+        )
+        ) {
+            mkdir(
+                $pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR.date('m')
+                . DIRECTORY_SEPARATOR,
+                0770
+            );
+            $this->setRights(
+                ['path' => $pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR.date('m') . DIRECTORY_SEPARATOR]
+            );
+        }
+        if (isset($GLOBALS['wb']) && $GLOBALS['wb'] <> '') {
+            $path = $pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR.date('m')
+                  . DIRECTORY_SEPARATOR . 'BATCH' . DIRECTORY_SEPARATOR 
+                  . $GLOBALS['wb'] . DIRECTORY_SEPARATOR;
+            if (!is_dir($path)) {
+                mkdir($path, 0770, true);
+                $this->setRights(['path' => $path]);
+            } else {
+                $datas = [
+                    'errors' => 'Folder alreay exists, workbatch already exist:' . $path,
+                ];
+
+                return $datas;
+            }
+        } else {
+            $path = $pathOnDocserver . date('Y') . DIRECTORY_SEPARATOR.date('m')
+                  . DIRECTORY_SEPARATOR;
+        }
+
+        $datas = 
+            [
+                'createPathOnDocServer' => 
+                    [
+                        'destinationDir' => $path
+                    ]
+            ];
+        
+        return $datas;
+    }
+
+     /**
+     * Set Rights on resources
+     * @param   string $dest path of the resource
+     * @return  nothing
+     */
+    public function setRights($aArgs)
+    {
+        if (empty($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!is_dir($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        if (
+            DIRECTORY_SEPARATOR == '/'
+            && (isset($GLOBALS['apacheUserAndGroup'])
+            && $GLOBALS['apacheUserAndGroup'] <> '')
+        ) {
+            exec('chown ' 
+                . escapeshellarg($GLOBALS['apacheUserAndGroup']) . ' ' 
+                . escapeshellarg($aArgs['path'])
+            );
+        }
+
+        umask(0022);
+        chmod($aArgs['path'], 0770);
+
+        $datas = [
+            'setRights' => true,
+        ];
+
+        return $datas;
+    }
+
+    /**
+     * copy doc in a docserver.
+     * @param   string $sourceFilePath collection resource
+     * @param   array $infoFileNameInTargetDocserver infos of the doc to store,
+     *          contains : subdirectory path and new filename
+     * @param   string $docserverSourceFingerprint
+     * @return  array of docserver data for res_x else return error
+     */
+    public function copyOnDocserver($aArgs)
+    {
+        if (empty($aArgs['destinationDir'])) {
+            $datas = [
+                'errors' => 'destinationDir ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (empty($aArgs['fileDestinationName'])) {
+            $datas = [
+                'errors' => 'fileDestinationName ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (file_exists(($aArgs['destinationDir'] . $aArgs['fileDestinationName']))) {
+            $datas = [
+                'errors' => '' . $aArgs['destinationDir'] 
+                    . $aArgs['fileDestinationName'] . ' ' . _FILE_ALREADY_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        if (empty($aArgs['sourceFilePath'])) {
+            $datas = [
+                'errors' => 'sourceFilePath ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!file_exists($aArgs['sourceFilePath'])) {
+            $datas = [
+                'errors' => 'sourceFilePath '  . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        $destinationDir = $aArgs['destinationDir'];
+        $fileDestinationName = $aArgs['fileDestinationName'];
+        $sourceFilePath = str_replace('\\\\', '\\', $aArgs['sourceFilePath']);
+        $docserverSourceFingerprint = $aArgs['docserverSourceFingerprint'];
+
+        error_reporting(0);
+
+        if (!is_dir($destinationDir)) {
+            mkdir($destinationDir, 0770, true);
+            $aArgs = [
+                'path'=> $destinationDir
+            ];
+
+            $this->setRights($aArgs);
+        }
+
+        if(!copy($sourceFilePath, $destinationDir . $fileDestinationName)) {
+            $datas = [
+                'errors' => _DOCSERVER_COPY_ERROR . ' source : ' . $sourceFilePath
+                    . ' dest : ' . $destinationDir . $fileDestinationName
+            ];
+
+            return $datas;
+        }
+        
+        $aArgs = [
+            'path'=> $destinationDir . $fileDestinationName
+        ];
+
+        $this->setRights($aArgs);
+
+        $fingerprintControl = array();
+
+        $aArgs = [
+            'pathInit'          => $sourceFilePath,
+            'pathTarget'        => $destinationDir . $fileDestinationName,
+            'fingerprintMode'   => $docserverSourceFingerprint,
+        ];
+
+        $fingerprintControl = $this->controlFingerprint($aArgs);
+
+        if (!empty($fingerprintControl['errors'])) {
+            $datas = [
+                'errors' => $fingerprintControl['errors'],
+            ];
+
+            return $datas;
+        }
+
+        //for batch like life cycle
+        if (isset($GLOBALS['currentStep'])) {
+            $destinationDir = str_replace(
+                $GLOBALS['docservers'][$GLOBALS['currentStep']]['docserver']
+                ['path_template'],
+                '',
+                $destinationDir
+            );
+        }
+
+        $destinationDir = str_replace(
+            DIRECTORY_SEPARATOR,
+            '#',
+            $destinationDir
+        );
+
+        $datas = [
+            'copyOnDocserver' =>  
+                [
+                    'destinationDir'        => $destinationDir,
+                    'fileDestinationName'   => $fileDestinationName,
+                    'fileSize'              => filesize($sourceFilePath),
+                ]
+        ];
+
+        if (isset($GLOBALS['TmpDirectory']) && $GLOBALS['TmpDirectory'] <> '') {
+            $aArgs = [
+                'path'        => $GLOBALS['TmpDirectory'],
+                'contentOnly' => true,
+            ];
+            $this->washTmp($aArgs);
+        }
+
+        return $datas;
+    }
+
+    /**
+     * Compute the fingerprint of a resource
+     * @param   string $path path of the resource
+     * @param   string $fingerprintMode (md5, sha512, ...)
+     * @return  string the fingerprint
+     */
+    public function doFingerprint($aArgs)
+    {
+        if (empty($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!file_exists($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        if (
+            $aArgs['fingerprintMode'] == 'NONE' || 
+            $aArgs['fingerprintMode'] == ''
+        ) {
+            $datas = [
+                'fingerprint' => '0',
+            ];
+
+            return $datas;
+        } else {
+            $fingerprint = hash_file(
+                strtolower($aArgs['fingerprintMode']), 
+                $aArgs['path']
+            );
+
+            $datas = [
+                'fingerprint' => $fingerprint,
+            ];
+            
+            return $datas;
+        }
+    }
+
+    /**
+     * Control fingerprint between two resources
+     * @param   string $pathInit path of the resource 1
+     * @param   string $pathTarget path of the resource 2
+     * @param   string $fingerprintMode (md5, sha512, ...)
+     * @return  array ok or ko with error
+     */
+    public function controlFingerprint($aArgs)
+    {
+        if (empty($aArgs['pathInit'])) {
+            $datas = [
+                    'errors' => 'pathInit ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!file_exists($aArgs['pathInit'])) {
+            $datas = [
+                    'errors' => 'pathInit ' . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        if (empty($aArgs['pathTarget'])) {
+            $datas = [
+                    'errors' => 'pathTarget ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!file_exists($aArgs['pathTarget'])) {
+            $datas = [
+                    'errors' => 'pathTarget ' . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        $aArgsSrc = [
+            'path'            => $aArgs['pathInit'],
+            'fingerprintMode' => $aArgs['fingerprintMode'],
+        ];
+
+        $aArgsTarget = [
+            'path'            => $aArgs['pathTarget'],
+            'fingerprintMode' => $aArgs['fingerprintMode'],
+        ];
+
+        if ($this->doFingerprint($aArgsSrc) <> $this->doFingerprint($aArgsTarget)) {
+            $datas = [
+                    'errors' => PB_WITH_FINGERPRINT_OF_DOCUMENT . ' ' . $aArgs['pathInit']
+                        . ' '. _AND . ' ' . $aArgs['pathTarget'],
+            ];
+        } else {
+            $datas = [
+                'controlFingerprint' => true,
+            ];
+        }
+
+        return $datas;
+    }
+
+    /**
+     * del tmp files
+     * @param   $path dir to wash
+     * @param   $contentOnly boolean true if only the content
+     * @return  boolean
+     */
+    public function washTmp($aArgs)
+    {
+        if (empty($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _EMPTY,
+            ];
+
+            return $datas;
+        }
+
+        if (!is_dir($aArgs['path'])) {
+            $datas = [
+                    'errors' => 'path ' . _NOT_EXISTS,
+            ];
+
+            return $datas;
+        }
+
+        if (!is_bool($aArgs['contentOnly'])) {
+            $datas = [
+                    'errors' => 'contentOnly ' . _NOT . ' ' . _VALID,
+            ];
+
+            return $datas;
+        }
+
+        $objects = scandir($aArgs['path']);
+        foreach ($objects as $object) {
+            if ($object != '.' && $object != '..') {
+                if (filetype($aArgs['path'] . DIRECTORY_SEPARATOR . $object) == 'dir') {
+                    $this->washTmp(
+                        ['path' => $aArgs['path'] . DIRECTORY_SEPARATOR . $object]
+                    );
+                } else {
+                    unlink($aArgs['path'] . DIRECTORY_SEPARATOR . $object);
+                }
+            }
+        }
+
+        reset($objects);
+        
+        if (!$aArgs['contentOnly']) {
+            rmdir($aArgs['path']);
+        }
+
+        $datas = [
+            'washTmp' => true,
+        ];
+
+        return $datas;
+    }
+
+}
\ No newline at end of file
diff --git a/core/Controllers/DocserverTypeController.php b/core/Controllers/DocserverTypeController.php
new file mode 100644
index 00000000000..f38e8aed85c
--- /dev/null
+++ b/core/Controllers/DocserverTypeController.php
@@ -0,0 +1,266 @@
+<?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 DocerverType 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\DocserverTypeModel;
+
+class DocserverTypeController
+{
+
+    public function getList(RequestInterface $request, ResponseInterface $response)
+    {
+        $obj = DocserverTypeModel::getList();
+        
+        $datas = [
+            [
+                'DocserverType' => $obj,
+            ]
+        ];
+        
+        return $response->withJson($datas);
+    }
+
+    public function getById(RequestInterface $request, ResponseInterface $response, $aArgs)
+    {
+        if (isset($aArgs['id'])) {
+            $id = $aArgs['id'];
+            $obj = DocserverTypeModel::getById([
+                'id' => $id
+            ]);
+        } else {
+
+            return $response
+                ->withStatus(500)
+                ->withJson(['errors' => _ID . ' ' . _IS_EMPTY]);
+        }
+        
+        $datas = [
+            [
+                'DocserverType' => $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 = DocserverTypeModel::create($aArgs);
+
+        if ($return) {
+            $id = $aArgs['id'];
+            $obj = DocserverTypeModel::getById([
+                'id' => $id
+            ]);
+        } else {
+
+            return $response
+                ->withStatus(500)
+                ->withJson(['errors' => _NOT_CREATE]);
+        }
+
+        $datas = [
+            [
+                'DocserverType' => $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 = DocserverTypeModel::update($aArgs);
+
+        if ($return) {
+            $id = $aArgs['id'];
+            $obj = DocserverTypeModel::getById([
+                'id' => $id
+            ]);
+        } else {
+
+            return $response
+                ->withStatus(500)
+                ->withJson(['errors' => _NOT_UPDATE]);
+        }
+
+        $datas = [
+            [
+                'DocserverType' => $obj,
+            ]
+        ];
+
+        return $response->withJson($datas);
+    }
+
+    public function delete(RequestInterface $request, ResponseInterface $response, $aArgs)
+    {
+        if (isset($aArgs['id'])) {
+            $id = $aArgs['id'];
+            $obj = DocserverTypeModel::delete([
+                'id' => $id
+            ]);
+        } else {
+            
+            return $response
+                ->withStatus(500)
+                ->withJson(['errors' => _NOT_DELETE]);
+        }
+        
+        $datas = [
+            [
+                'DocserverType' => $obj,
+            ]
+        ];
+
+        return $response->withJson($datas);
+    }
+
+    protected function control($request, $mode)
+    {
+        $errors = [];
+
+        if($mode == 'update') {
+            $obj = DocserverTypeModel::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 = DocserverTypeModel::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;
+    }
+
+}
\ No newline at end of file
diff --git a/core/Controllers/ResController.php b/core/Controllers/ResController.php
new file mode 100644
index 00000000000..40b916030f6
--- /dev/null
+++ b/core/Controllers/ResController.php
@@ -0,0 +1,84 @@
+<?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
+* @ingroup core
+*/
+
+namespace Core\Controllers;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Respect\Validation\Validator;
+use Core\Models\ResModel;
+
+class ResController
+{
+
+    /**
+     * Store resource on database.
+     * @param  $resTable  string 
+     * @param  $destinationDir string
+     * @param  $pathTemplate  string 
+     * @param  $docserverId  string 
+     * @param  $data  array  
+     * @return res_id
+     */
+    public function storeResourceOnDB($aArgs)
+    {
+
+        // storeResult['destination_dir'],
+        // $storeResult['file_destination_name'] ,
+        // $storeResult['path_template'],
+        // $storeResult['docserver_id'], $_SESSION['data'],
+        // $_SESSION['config']['databasetype']
+        if (empty($aArgs['resTable'])) {
+
+            return ['errors' => 'resTable ' . _EMPTY];
+        }
+
+        if (empty($aArgs['destinationDir'])) {
+
+            return ['errors' => 'destinationDir ' . _EMPTY];
+        }
+
+        if (empty($aArgs['pathTemplate'])) {
+
+            return ['errors' => 'pathTemplate ' . _EMPTY];
+        }
+
+        if (empty($aArgs['docserverId'])) {
+
+            return ['errors' => 'docserverId ' . _EMPTY];
+        }
+
+        if (empty($aArgs['data'])) {
+
+            return ['errors' => 'data ' . _EMPTY];
+        }
+
+        if (isset($aArgs['collId'])) {
+            $collId = $aArgs['collId'];
+            $obj = DocserverModel::getDocserverToInsert([
+                'collId' => $collId
+            ]);
+        } else {
+
+            return ['errors' => 'collId ' . _EMPTY];
+        }
+
+        $datas = [
+            'docserver' => $obj,
+        ];
+
+        return $datas;
+    }
+}
\ No newline at end of file
diff --git a/core/Controllers/StatusController.php b/core/Controllers/StatusController.php
index 06e3f193200..a025d74c451 100644
--- a/core/Controllers/StatusController.php
+++ b/core/Controllers/StatusController.php
@@ -18,19 +18,18 @@ namespace Core\Controllers;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use Respect\Validation\Validator;
-
-require_once 'core/Models/StatusModel.php';
+use Core\Models\StatusModel;
 
 class StatusController
 {
 
     public function getList(RequestInterface $request, ResponseInterface $response)
     {
-        $status = \StatusModel::getList();
+        $obj = StatusModel::getList();
         
         $datas = [
             [
-                'status' => $status,
+                'status' => $obj,
             ]
         ];
         
@@ -41,7 +40,7 @@ class StatusController
     {
         if (isset($aArgs['id'])) {
             $id = $aArgs['id'];
-            $status = \StatusModel::getById([
+            $obj = StatusModel::getById([
                 'id' => $id
             ]);
         } else {
@@ -53,7 +52,7 @@ class StatusController
         
         $datas = [
             [
-                'status' => $status,
+                'status' => $obj,
             ]
         ];
 
@@ -75,11 +74,11 @@ class StatusController
 
         $aArgs = $request->getQueryParams();
 
-        $return = \StatusModel::create($aArgs);
+        $return = StatusModel::create($aArgs);
 
         if ($return) {
             $id = $aArgs['id'];
-            $status = \StatusModel::getById([
+            $obj = StatusModel::getById([
                 'id' => $id
             ]);
         } else {
@@ -91,7 +90,7 @@ class StatusController
 
         $datas = [
             [
-                'status' => $status,
+                'status' => $obj,
             ]
         ];
 
@@ -113,11 +112,11 @@ class StatusController
 
         $aArgs = $request->getQueryParams();
 
-        $return = \StatusModel::update($aArgs);
+        $return = StatusModel::update($aArgs);
 
         if ($return) {
             $id = $aArgs['id'];
-            $status = \StatusModel::getById([
+            $obj = StatusModel::getById([
                 'id' => $id
             ]);
         } else {
@@ -129,7 +128,7 @@ class StatusController
 
         $datas = [
             [
-                'status' => $status,
+                'status' => $obj,
             ]
         ];
 
@@ -140,7 +139,7 @@ class StatusController
     {
         if (isset($aArgs['id'])) {
             $id = $aArgs['id'];
-            $status = \StatusModel::delete([
+            $obj = StatusModel::delete([
                 'id' => $id
             ]);
         } else {
@@ -152,7 +151,7 @@ class StatusController
         
         $datas = [
             [
-                'status' => $status,
+                'status' => $obj,
             ]
         ];
 
@@ -164,10 +163,10 @@ class StatusController
         $errors = [];
 
         if($mode == 'update') {
-            $status = \StatusModel::getById([
+            $obj = StatusModel::getById([
                 'id' => $request->getParam('id')
             ]);
-            if (empty($status)) {
+            if (empty($obj)) {
                 array_push(
                     $errors, 
                     _ID . ' ' . $request->getParam('id') . ' ' . _NOT_EXISTS
@@ -178,13 +177,13 @@ class StatusController
         if (!Validator::notEmpty()->validate($request->getParam('id'))) {
             array_push($errors, _ID . ' ' . _IS_EMPTY);
         } elseif($mode == 'create') {
-            $status = \StatusModel::getById([
+            $obj = StatusModel::getById([
                 'id' => $request->getParam('id')
             ]);
-            if (!empty($status)) {
+            if (!empty($obj)) {
                 array_push(
                     $errors, 
-                    _ID . ' ' . $status[0]['id'] . ' ' . _ALREADY_EXISTS
+                    _ID . ' ' . $obj[0]['id'] . ' ' . _ALREADY_EXISTS
                 );
             }
         }
diff --git a/core/Models/DocserverModel.php b/core/Models/DocserverModel.php
new file mode 100644
index 00000000000..666fec6c713
--- /dev/null
+++ b/core/Models/DocserverModel.php
@@ -0,0 +1,22 @@
+<?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 Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+namespace Core\Models;
+
+require_once 'core/Models/DocserverModelAbstract.php';
+
+class DocserverModel extends DocserverModelAbstract
+{
+    // Do your stuff in this class
+}
diff --git a/core/Models/DocserverModelAbstract.php b/core/Models/DocserverModelAbstract.php
new file mode 100644
index 00000000000..0f0e1d76242
--- /dev/null
+++ b/core/Models/DocserverModelAbstract.php
@@ -0,0 +1,120 @@
+<?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 Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+
+namespace Core\Models;
+
+require_once 'apps/maarch_entreprise/services/Table.php';
+
+class DocserverModelAbstract extends \Apps_Table_Service
+{
+
+    public static function getList()
+    {
+        $aReturn = static::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['docservers'],
+        ]);
+
+        return $aReturn;
+    }
+
+    public static function getById(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $aReturn = static::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['docservers'],
+            'where'     => ['docserver_id = ?'],
+            'data'      => [$aArgs['id']]
+        ]);
+
+        return $aReturn;
+    }
+
+    public static function create(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['docserver_id']);
+        static::checkString($aArgs, ['docserver_id']);
+
+        $aReturn = static::insertInto($aArgs, 'docservers');
+
+        return $aReturn;
+    }
+
+    public static function update(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['docserver_id']);
+        static::checkString($aArgs, ['docserver_id']);
+
+        $where['docserver_id'] = $aArgs['docserver_id'];
+
+        $aReturn = static::updateTable(
+            $aArgs, 
+            'docservers',
+            $where
+        );
+
+        return $aReturn;
+    }
+
+    public static function delete(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $aReturn = static::deleteFrom([
+                'table' => 'docservers',
+                'where' => ['id = ?'],
+                'data'  => [$aArgs['id']]
+            ]);
+
+        return $aReturn;
+    }
+
+    public static function getDocserverToInsert(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['collId']);
+        static::checkString($aArgs, ['collId']);
+
+        $aReturn = static::select([
+            'select'    => ['*'],
+            'table'     => ['docservers'],
+            'where'     => ["is_readonly = 'N' and enabled = 'Y' and coll_id = ?"],
+            'data'      => [$aArgs['collId']],
+            'order_by'  => ['priority_number'],
+            'limit'     => 1,
+        ]);
+
+        return $aReturn;
+    }
+
+    public static function setSize(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $where['id'] = $aArgs['id'];
+
+        $aReturn = static::updateTable(
+            $aArgs, 
+            'docservers',
+            $where
+        );
+
+        return $aReturn;
+    }
+}
diff --git a/core/Models/DocserverTypeModel.php b/core/Models/DocserverTypeModel.php
new file mode 100644
index 00000000000..d759c5803f3
--- /dev/null
+++ b/core/Models/DocserverTypeModel.php
@@ -0,0 +1,22 @@
+<?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 DocserverType Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+namespace Core\Models;
+
+require_once 'core/Models/DocserverTypeModelAbstract.php';
+
+class DocserverTypeModel extends DocserverTypeModelAbstract
+{
+    // Do your stuff in this class
+}
diff --git a/core/Models/DocserverTypeModelAbstract.php b/core/Models/DocserverTypeModelAbstract.php
new file mode 100644
index 00000000000..619815db26b
--- /dev/null
+++ b/core/Models/DocserverTypeModelAbstract.php
@@ -0,0 +1,88 @@
+<?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 DocserverType Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+
+namespace Core\Models;
+
+require_once 'apps/maarch_entreprise/services/Table.php';
+
+class DocserverTypeModelAbstract extends \Apps_Table_Service
+{
+
+    public static function getList()
+    {
+        $aReturn = static::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['docserver_types'],
+        ]);
+
+        return $aReturn;
+    }
+
+    public static function getById(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $aReturn = static::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['docserver_types'],
+            'where'     => ['docserver_type_id = ?'],
+            'data'      => [$aArgs['id']]
+        ]);
+
+        return $aReturn;
+    }
+
+    public static function create(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $aReturn = static::insertInto($aArgs, 'docserver_types');
+
+        return $aReturn;
+    }
+
+    public static function update(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $where['id'] = $aArgs['id'];
+
+        $aReturn = static::updateTable(
+            $aArgs, 
+            'docserver_types',
+            $where
+        );
+
+        return $aReturn;
+    }
+
+    public static function delete(array $aArgs = [])
+    {
+        static::checkRequired($aArgs, ['id']);
+        static::checkString($aArgs, ['id']);
+
+        $aReturn = static::deleteFrom([
+                'table' => 'docserver_types',
+                'where' => ['id = ?'],
+                'data'  => [$aArgs['id']]
+            ]);
+
+        return $aReturn;
+    }
+
+}
diff --git a/core/Models/StatusModel.php b/core/Models/StatusModel.php
index 8b6044bbcd2..eb02f938265 100644
--- a/core/Models/StatusModel.php
+++ b/core/Models/StatusModel.php
@@ -7,7 +7,13 @@
 *
 */
 
-require_once 'core/Models/StatusModelAbstract.php';
+/**
+* @brief Status Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+
+namespace Core\Models;
 
 class StatusModel extends StatusModelAbstract
 {
diff --git a/core/Models/StatusModelAbstract.php b/core/Models/StatusModelAbstract.php
index 53fe8da1720..daa132b7a2a 100644
--- a/core/Models/StatusModelAbstract.php
+++ b/core/Models/StatusModelAbstract.php
@@ -7,9 +7,17 @@
 *
 */
 
+/**
+* @brief Status Model
+* @author dev@maarch.org
+* @ingroup core
+*/
+
+namespace Core\Models;
+
 require_once 'apps/maarch_entreprise/services/Table.php';
 
-class StatusModelAbstract extends Apps_Table_Service
+class StatusModelAbstract extends \Apps_Table_Service
 {
 
     public static function getList()
diff --git a/core/Test/DocserverControllerTest.php b/core/Test/DocserverControllerTest.php
new file mode 100644
index 00000000000..197167189f9
--- /dev/null
+++ b/core/Test/DocserverControllerTest.php
@@ -0,0 +1,245 @@
+<?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.
+*
+*/
+
+require_once __DIR__.'/define.php';
+
+class DocserverControllerTest extends PHPUnit_Framework_TestCase
+{
+    // public function testGetList()
+    // {
+    //     $action = new \Core\Controllers\DocserverController();
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'GET',
+    //             //'REQUEST_URI' => '/status',
+    //             //'QUERY_STRING'=>'foo=bar',
+    //         ]
+    //     );
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->getList($request, $response, []);
+
+    //     $this->assertNotNull((string)$response->getBody());
+    // }
+
+    // public function testGetById()
+    // {
+    //     $action = new \Core\Controllers\DocserverController();
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'GET',
+    //         ]
+    //     );
+
+    //     $aArgs = [
+    //         'id'=> 'NEW'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->getById($request, $response, $aArgs);
+    //     $compare = '[{"status":[{"id":"NEW","label_status":"Nouveau",'
+    //         . '"is_system":"Y","is_folder_status":"N","img_filename":'
+    //         . '"fm-letter-status-new","maarch_module":"apps",'
+    //         . '"can_be_searched":"Y","can_be_modified":"Y"}]}]';
+
+    //     $this->assertSame((string)$response->getBody(), $compare);
+    // }
+
+    // public function testCreate()
+    // {
+    //     $action = new \Core\Controllers\DocserverController();
+
+    //     $query  = 'id=TEST&';
+    //     $query .= 'label_status=TEST';
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'POST',
+    //             'QUERY_STRING'=> $query,
+    //         ]
+    //     );
+        
+    //     $aArgs = [
+    //         'id'=> 'NEW'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->create($request, $response, $aArgs);
+
+    //     $compare = '[{"status":[{"id":"TEST","label_status":"TEST",'
+    //         . '"is_system":"Y","is_folder_status":"N","img_filename":null,'
+    //         . '"maarch_module":"apps","can_be_searched":"Y",'
+    //         . '"can_be_modified":"Y"}]}]';
+        
+    //     $this->assertSame((string)$response->getBody(), $compare);
+    // }
+
+    // public function testUpdate()
+    // {
+    //     $action = new \Core\Controllers\DocserverController();
+
+    //     $query  = 'id=TEST&';
+    //     $query .= 'label_status=TEST AFTER UP';
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'PUT',
+    //             'QUERY_STRING'=> $query,
+    //         ]
+    //     );
+        
+    //     $aArgs = [
+    //         'id'=> 'NEW'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->update($request, $response, $aArgs);
+
+    //     $compare = '[{"status":[{"id":"TEST","label_status":"TEST AFTER UP",'
+    //         . '"is_system":"Y","is_folder_status":"N","img_filename":null,'
+    //         . '"maarch_module":"apps","can_be_searched":"Y",'
+    //         . '"can_be_modified":"Y"}]}]';
+        
+    //     $this->assertSame((string)$response->getBody(), $compare);
+    // }
+
+    // public function testDelete()
+    // {
+    //     $action = new \Core\Controllers\DocserverController();
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'DELETE',
+    //         ]
+    //     );
+
+    //     $aArgs = [
+    //         'id'=> 'TEST'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->delete($request, $response, $aArgs);
+        
+    //     $this->assertSame((string)$response->getBody(), '[{"status":true}]');
+    // }
+
+    public function testGetDocserverToInsert()
+    {
+        $action = new \Core\Controllers\DocserverController();
+
+        $aArgs = [
+            'collId' => 'letterbox_coll'
+        ];
+
+        $response = $action->getDocserverToInsert($aArgs);
+
+        $this->assertSame(
+            $response['docserver'][0]['coll_id'], 
+            $aArgs['collId']
+        );
+    }
+
+    public function testCheckSize()
+    {
+        $action = new \Core\Controllers\DocserverController();
+
+        $aArgs = [
+            'collId' => 'letterbox_coll'
+        ];
+        
+        $ds = $action->getDocserverToInsert($aArgs);
+
+        $aArgs = [
+            'docserver' => $ds['docserver'][0],
+            'filesize'  => 1090900,
+        ];
+
+        $response = $action->checkSize($aArgs);
+        
+        $this->assertGreaterThan(0, $response['newDsSize']);
+    }
+
+    public function testSetSize()
+    {
+        $action = new \Core\Controllers\DocserverController();
+
+        $aArgs = [
+            'collId' => 'letterbox_coll'
+        ];
+        
+        $ds = $action->getDocserverToInsert($aArgs);
+
+        $aArgs = [
+            'docserver_id' => $ds['docserver'][0]['docserver_id'],
+            'actual_size_number'  => 1,
+        ];
+
+        $response = $action->setSize($aArgs);
+        
+        $this->assertTrue($response['setSize']);
+    }
+
+    public function testGetNextFileNameInDocserver()
+    {
+        $action = new \Core\Controllers\DocserverController();
+
+        $aArgs = [
+            'pathOnDocserver' => '/opt/maarch/new_docservers/MaarchCourrierGit/manual/2017/02/'
+        ];
+
+        $response = $action->getNextFileNameInDocserver($aArgs);
+
+        $this->assertNotNull($response['fileDestinationName']);
+    }
+
+    public function testStoreResourceOnDocserver()
+    {
+        $action = new \Core\Controllers\DocserverController();
+
+        $path = $_SESSION['config']['tmppath'] . '/test/';
+
+        if (!is_dir($path)) {
+            mkdir($path);    
+        }
+
+        $fileSource = 'test_source.txt';
+
+        $fp = fopen($path . $fileSource, 'a');
+        fwrite($fp, 'a unit test');
+        fclose($fp);
+
+        $aArgs = [
+            'collId' => 'letterbox_coll',
+            'fileInfos' => 
+                [
+                    'tmpDir' => $path,
+                    'size' => 122345,
+                    'format' => 'txt',
+                    'tmpFileName' => $fileSource,
+                ]
+        ];
+
+        $response = $action->storeResourceOnDocserver($aArgs);
+
+        //print_r($response);
+
+        $this->assertArrayHasKey(
+            'path_template', 
+            $response['storeResourceOnDocserver']
+        );
+    }
+
+}
\ No newline at end of file
diff --git a/core/Test/DocserverToolsControllerTest.php b/core/Test/DocserverToolsControllerTest.php
new file mode 100644
index 00000000000..2e8ba6a3126
--- /dev/null
+++ b/core/Test/DocserverToolsControllerTest.php
@@ -0,0 +1,143 @@
+<?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.
+*
+*/
+
+require_once __DIR__.'/define.php';
+
+class DocserverToolsControllerTest extends PHPUnit_Framework_TestCase
+{
+    public function testSetRights()
+    {
+        $action = new \Core\Controllers\DocserverToolsController();
+
+        $aArgs = [
+            'path' => '/opt/maarch/docservers/'
+        ];
+
+        $response = $action->setRights($aArgs);
+
+        $this->assertTrue($response['setRights']);
+    }
+
+    public function testDoFingerprint()
+    {
+        $action = new \Core\Controllers\DocserverToolsController();
+
+        $path = $_SESSION['config']['tmppath'] . '/test/';
+
+        if (!is_dir($path)) {
+            mkdir($path);    
+        }
+
+        $fileSource = 'test_source.txt';
+
+        //creates an empty file
+        $fp = fopen($path . $fileSource, 'a');
+        fwrite($fp, 'a unit test');
+        fclose($fp);
+
+        $aArgs = [
+            'path'            => $fileSource,
+            'fingerprintMode' => 'NONE',
+        ];
+
+        $response = $action->doFingerprint($aArgs);
+
+        $this->assertEquals($response['setRights'], 0);
+    }
+
+    public function testControlFingerprint()
+    {
+        $action = new \Core\Controllers\DocserverToolsController();
+
+        $path = $_SESSION['config']['tmppath'] . '/test/';
+
+        if (!is_dir($path)) {
+            mkdir($path);    
+        }
+
+        $fileSource = 'test_source.txt';
+
+        $fp = fopen($path . $fileSource, 'a');
+        fwrite($fp, 'a unit test');
+        fclose($fp);
+
+        $aArgs = [
+            'pathInit'        => $path . $fileSource,
+            'pathTarget'      => $path . $fileSource,
+            'fingerprintMode' => 'sha256',
+        ];
+
+        $response = $action->controlFingerprint($aArgs);
+
+        $this->assertTrue($response['controlFingerprint']);
+    }
+
+    public function testCopyOnDocserver()
+    {
+        $action = new \Core\Controllers\DocserverToolsController();
+
+        $path = $_SESSION['config']['tmppath'] . '/test/';
+
+        if (!is_dir($path)) {
+            mkdir($path);    
+        }
+
+        $fileSource = 'test_source.txt';
+        $fileDest = 'test_dest.txt'; 
+
+        $fp = fopen($path . $fileSource, 'a');
+        fwrite($fp, 'a unit test');
+        fclose($fp);
+
+        $aArgs = [
+            'sourceFilePath'             => $path . $fileSource,
+            'destinationDir'             => $path,
+            'fileDestinationName'        => $fileDest,
+            'docserverSourceFingerprint' => 'sha256',
+        ];
+
+        $response = $action->copyOnDocserver($aArgs);
+
+        $this->assertArrayHasKey('destinationDir', $response['copyOnDocserver']);
+    }
+
+    public function testWashTmp()
+    {
+        $action = new \Core\Controllers\DocserverToolsController();
+
+        $path = $_SESSION['config']['tmppath'] . '/test/';
+        
+        if (!is_dir($path)) {
+            mkdir($path);    
+        }
+
+        $aArgs = [
+            'path'        => $path,
+            'contentOnly' => false,
+        ];
+
+        $response = $action->washTmp($aArgs);
+
+        $this->assertTrue($response['washTmp']);
+    }
+
+    public function testCreatePathOnDocServer()
+    {
+        $action = new \Core\Controllers\DocserverToolsController();
+
+        $aArgs = [
+            'path' => '/opt/maarch/new_docservers/MaarchCourrierGit/manual/'
+        ];
+
+        $response = $action->createPathOnDocServer($aArgs);
+
+        $this->assertArrayHasKey('destinationDir', $response['createPathOnDocServer']);
+    }
+
+}
\ No newline at end of file
diff --git a/core/Test/DocserverTypeControllerTest.php b/core/Test/DocserverTypeControllerTest.php
new file mode 100644
index 00000000000..9b6e49c10fd
--- /dev/null
+++ b/core/Test/DocserverTypeControllerTest.php
@@ -0,0 +1,142 @@
+<?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.
+*
+*/
+
+require_once __DIR__.'/define.php';
+
+class DocserverTypeControllerTest extends PHPUnit_Framework_TestCase
+{
+    public function testGetList()
+    {
+        $action = new \Core\Controllers\DocserverTypeController();
+
+        $environment = \Slim\Http\Environment::mock(
+            [
+                'REQUEST_METHOD' => 'GET',
+                //'REQUEST_URI' => '/docserverType',
+                //'QUERY_STRING'=>'foo=bar',
+            ]
+        );
+
+        $request = \Slim\Http\Request::createFromEnvironment($environment);
+        $response = new \Slim\Http\Response();
+        $response = $action->getList($request, $response, []);
+
+        $this->assertNotNull((string)$response->getBody());
+    }
+
+    public function testGetById()
+    {
+        $action = new \Core\Controllers\DocserverTypeController();
+
+        $environment = \Slim\Http\Environment::mock(
+            [
+                'REQUEST_METHOD' => 'GET',
+            ]
+        );
+
+        $aArgs = [
+            'id'=> 'FASTHD'
+        ];
+
+        $request = \Slim\Http\Request::createFromEnvironment($environment);
+        $response = new \Slim\Http\Response();
+        $response = $action->getById($request, $response, $aArgs);
+        $compare = '[{"DocserverType":[{"docserver_type_id":"FASTHD",'
+            . '"docserver_type_label":"FASTHD","enabled":"Y",'
+            . '"is_container":"N","container_max_number":0,'
+            . '"is_compressed":"N","compression_mode":"NONE",'
+            . '"is_meta":"N","meta_template":"NONE",'
+            . '"is_logged":"N","log_template":"NONE",'
+            . '"is_signed":"Y","fingerprint_mode":"SHA256"}]}]';
+
+        $this->assertSame((string)$response->getBody(), $compare);
+    }
+
+    // public function testCreate()
+    // {
+    //     $action = new \Core\Controllers\DocserverTypeController();
+
+    //     $query  = 'id=TEST&';
+    //     $query .= 'label_status=TEST';
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'POST',
+    //             'QUERY_STRING'=> $query,
+    //         ]
+    //     );
+        
+    //     $aArgs = [
+    //         'id'=> 'NEW'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->create($request, $response, $aArgs);
+
+    //     $compare = '[{"docserverType":[{"id":"TEST","label_status":"TEST",'
+    //         . '"is_system":"Y","is_folder_status":"N","img_filename":null,'
+    //         . '"maarch_module":"apps","can_be_searched":"Y",'
+    //         . '"can_be_modified":"Y"}]}]';
+        
+    //     $this->assertSame((string)$response->getBody(), $compare);
+    // }
+
+    // public function testUpdate()
+    // {
+    //     $action = new \Core\Controllers\DocserverTypeController();
+
+    //     $query  = 'id=TEST&';
+    //     $query .= 'label_status=TEST AFTER UP';
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'PUT',
+    //             'QUERY_STRING'=> $query,
+    //         ]
+    //     );
+        
+    //     $aArgs = [
+    //         'id'=> 'NEW'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->update($request, $response, $aArgs);
+
+    //     $compare = '[{"docserverType":[{"id":"TEST","label_status":"TEST AFTER UP",'
+    //         . '"is_system":"Y","is_folder_status":"N","img_filename":null,'
+    //         . '"maarch_module":"apps","can_be_searched":"Y",'
+    //         . '"can_be_modified":"Y"}]}]';
+        
+    //     $this->assertSame((string)$response->getBody(), $compare);
+    // }
+
+    // public function testDelete()
+    // {
+    //     $action = new \Core\Controllers\DocserverTypeController();
+
+    //     $environment = \Slim\Http\Environment::mock(
+    //         [
+    //             'REQUEST_METHOD' => 'DELETE',
+    //         ]
+    //     );
+
+    //     $aArgs = [
+    //         'id'=> 'TEST'
+    //     ];
+
+    //     $request = \Slim\Http\Request::createFromEnvironment($environment);
+    //     $response = new \Slim\Http\Response();
+    //     $response = $action->delete($request, $response, $aArgs);
+        
+    //     $this->assertSame((string)$response->getBody(), '[{"docserverType":true}]');
+    // }
+
+}
\ No newline at end of file
diff --git a/core/Test/StatusControllerTest.php b/core/Test/StatusControllerTest.php
index 807f37550e2..e850aea0101 100644
--- a/core/Test/StatusControllerTest.php
+++ b/core/Test/StatusControllerTest.php
@@ -1,5 +1,12 @@
 <?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.
+*
+*/
+
 require_once __DIR__.'/define.php';
 
 class StatusControllerTest extends PHPUnit_Framework_TestCase
diff --git a/core/Test/define.php b/core/Test/define.php
index 5aea23a212e..bd182b801ab 100644
--- a/core/Test/define.php
+++ b/core/Test/define.php
@@ -1,5 +1,12 @@
 <?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.
+*
+*/
+
 require_once 'vendor/autoload.php';
 require_once 'core/class/class_functions.php';
 include_once('core/init.php');
diff --git a/rest/index.php b/rest/index.php
index a722e4f11d4..b7bf9c5aa53 100644
--- a/rest/index.php
+++ b/rest/index.php
@@ -102,6 +102,22 @@ $app->post('/status', \Core\Controllers\StatusController::class . ':create');
 $app->put('/status', \Core\Controllers\StatusController::class . ':update');
 $app->delete('/status/{id}', \Core\Controllers\StatusController::class . ':delete');
 
+//docserver
+$app->get('/docserver', \Core\Controllers\DocserverController::class . ':getList');
+$app->get('/docserver/{id}', \Core\Controllers\DocserverController::class . ':getById');
+
+//docserverType
+$app->get('/docserverType', \Core\Controllers\DocserverTypeController::class . ':getList');
+$app->get('/docserverType/{id}', \Core\Controllers\DocserverTypeController::class . ':getById');
+
+//attachments
+$app->get('/attachments', \Attachments\Controllers\AttachmentsController::class . ':getList');
+$app->get('/attachments/{id}', \Attachments\Controllers\AttachmentsController::class . ':getById');
+$app->post('/attachments', \Attachments\Controllers\AttachmentsController::class . ':create');
+
+//basket
 $app->get('/{basketId}/signatureBook/{resId}', \Visa\Controllers\VisaController::class . ':getSignatureBook');
 
+
+
 $app->run();
-- 
GitLab