<?php

/**
 * OpenKM, Open Knowledge Management System S.L.  (http://www.openkm.com)
 * Copyright (c) 2006-2023
 *
 * No bytes were intentionally harmed during the development of this application.
 *
 * This program is commercial software; you can use it under the terms of the
 * EULA - OpenKM SDK End User License Agreement as published by OpenKM Knowledge Management System S.L.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * EULA - OpenKM SDK End User License Agreement for more details:
 * http://docs.openkm.com/kcenter/view/licenses/eula-openkm-sdk-end-user-license-agreement.html
 */

namespace openkm\impl;

use openkm\bean\Document;
use openkm\bean\TemplateParams;
use openkm\bean\UpdateTemplateParams;
use openkm\bean\Version;
use openkm\bean\LockInfo;
use openkm\definition\BaseDocument;
use openkm\util\UriHelper;
use Httpful\Request;
use Httpful\Mime;
use openkm\util\Status;
use openkm\util\BeanHelper;
use openkm\util\TypeException;
use openkm\exception\UnsupportMimeTypeException;
use openkm\exception\FileSizeExceededException;
use openkm\exception\VirusDetectedException;
use openkm\exception\AccessDeniedException;
use openkm\exception\PathNotFoundException;
use openkm\exception\RepositoryException;
use openkm\exception\DatabaseException;
use Httpful\Exception\ConnectionErrorException;
use openkm\exception\UnknowException;
use openkm\exception\ItemExistsException;
use openkm\exception\ExtensionException;
use openkm\exception\AutomationException;
use openkm\exception\LockException;
use openkm\exception\UserQuotaExceededException;
use openkm\exception\IOException;
use openkm\exception\VersionException;
use openkm\exception\ConversionException;
use openkm\exception\PrincipalAdapterException;
use openkm\exception\DocumentException;
use openkm\exception\TemplateException;
use openkm\exception\DocumentTemplateException;
use openkm\exception\ParseException;
use openkm\exception\NoSuchGroupException;
use openkm\exception\NoSuchPropertyException;
use openkm\exception\InterruptedException;
use openkm\util\FormatUtils;

/**
 * DocumentImpl
 *
 * @author sochoa
 */
class DocumentImpl extends ClientImpl implements BaseDocument {

    /**
     * Create a new document
     *
     * @param string $uuid The destination uuid of the Folder o Record
     * @param string $name The name document
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return Document Return as a result an object Document with the properties of the created document.
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws IOException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws UserQuotaExceededException
     * @throws VirusDetectedException
     * @throws ItemExistsException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function createDocument($uuid, $name, $content) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_POST_CREATE, ['uuid' => $uuid]));

            $params = [];

            $param1 = [];
            $param1['name'] = 'nodeClass';
            $param1['body'] = 0;
            $params[] = $param1;

            $files = [];
            $file = [];
            $file['name'] = 'content';
            $file['body'] = $content;
            $file['fileName'] = $name;
            $files[] = $file;

            $body = [];
            $body['params'] = $params;
            $body['files'] = $files;

            $client = Request::post($uri);
            $client->setCurlPostFile(true);
            $client->sends(Mime::UPLOAD);
            $client->body($body);
            $client->addHeader('Authorization', $this->authorizationToken);
            $client->expects(Mime::JSON);

            $response = $client->send();
            if ($response->code == Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                        throw new UnsupportMimeTypeException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                        throw new FileSizeExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                        throw new UserQuotaExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::VIRUS_DETECTED_EXCEPTION) {
                        throw new VirusDetectedException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException($restException->getMessage());
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Delete a document.
     *
     * When a document is deleted is automatically moved to /okm:trash/userId folder.
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws ExtensionException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function deleteDocument($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_PUT_DELETE, ['uuid' => $uuid]));
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException($restException->getMessage());
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get document properties
     *
     * @param string $uuid The uuid or path of the Document
     * @return Document Return the document properties.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getDocumentProperties($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_PROPERTIES, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get content
     *
     * @param string $uuid The uuid or path of the Document
     * @return string Retrieve document content - binary data - of the actual document version
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getContent($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_CONTENT, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClientWithUploadResponse($client);
            if ($response->code == Status::OK) {
                return $response->body;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get content by version
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $versionId The number version of the document
     * @return string Retrieve document content - binary data - of the actual document version
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws IOException
     * @throws UnknowException
     */
    public function getContentByVersion($uuid, $versionId) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_CONTENT_BY_VERSION, ['uuid' => $uuid, 'versionId' => $versionId]));
            $client = Request::get($uri);
            $response = $this->getClientWithUploadResponse($client);
            if ($response->code == Status::OK) {
                return $response->body;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get extracted text
     *
     * @param string $uuid The uuid or path of the Document
     * @return string Return an String with the extracted text by text extractor process.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws IOException
     * @throws UnknowException
     */
    public function getExtractedText($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_EXTRACTED_TEXT, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClientWithPlainResponse($client);
            if ($response->code == Status::OK) {
                return (string)$response->body;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Thumbnail
     *
     * @param string $uuid The uuid or path of the Document
     * Each thumbnail type has its own image dimensions.
     *
     * @return string Return thumbnail image data.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ConversionException
     * @throws IOException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function getThumbnail($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_THUMBNAIL, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClientWithUploadResponse($client);
            if ($response->code == Status::OK) {
                return $response->body;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::CONVERSION_EXCEPTION) {
                        throw new ConversionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Document children
     *
     * @param string $uuid The uuid or path of the Folder or a record node.
     * @return array Return a list of all documents which their parent is fldId.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getDocumentChildren($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_CHILDREN, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $documents = [];
                foreach ($response->body as $documentJSON) {
                    $documents[] = $this->phpDocument($documentJSON);
                }
                return $documents;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Change the name of a document.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $newName The new name for the Document
     * @return Document Returns the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ItemExistsException
     * @throws UnknowException
     */
    public function renameDocument($uuid, $newName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_PUT_RENAME, ['uuid' => $uuid]));
            $client = Request::put($uri);

            $params = [];
            $params['newName'] = $newName;
            $response = $this->getClientWithParams($client, $params);
            if ($response->code == Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Change some document properties.
     * Variables allowed to be changed:
     *
     *  - Title
     *  - Description
     *  - Language
     *  - Associated categories
     *  - Associated keywords
     *
     * The parameter Language must be ISO 691-1 compliant.
     *
     * More information at https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes.
     *
     * Only not null and not empty variables will be take on consideration.
     *
     * @param Document $document The Document
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws VersionException
     * @throws UnknowException
     */
    public function setProperties(Document $document) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_SET_PROPERTIES);
            $client = Request::put($uri);
            $documentXML = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><document></document>');
            $documentXML->addChild('author', $document->getAuthor());
            $documentXML->addChild('created', $document->getCreated());
            $documentXML->addChild('nodeClass', $document->getNodeClass());
            $documentXML->addChild('path', $document->getPath());
            $documentXML->addChild('permissions', $document->getPermissions());
            if ($document->isSubscribed() == 1) {
                $documentXML->addChild('subscribed', 'true');
            } else {
                $documentXML->addChild('subscribed', 'false');
            }
            $documentXML->addChild('uuid', $document->getUuid());
            if ($document->getActualVersion() != null) {
                //version
                $versionXML = $documentXML->addChild('actualVersion');
                $versionXML->addChild('actual', $document->getActualVersion()->getActual());
                $versionXML->addChild('author', $document->getActualVersion()->getAuthor());
                $versionXML->addChild('checksum', $document->getActualVersion()->getChecksum());
                $versionXML->addChild('created', $document->getActualVersion()->getCreated());
                $versionXML->addChild('name', $document->getActualVersion()->getName());
                $versionXML->addChild('size', $document->getActualVersion()->getSize());
            }
            if ($document->isCheckedOut() == 1) {
                $documentXML->addChild('checkedOut', 'true');
            } else {
                $documentXML->addChild('checkedOut', 'false');
            }
            if ($document->isConvertibleToDxf() == 1) {
                $documentXML->addChild('convertibleToDxf', 'true');
            } else {
                $documentXML->addChild('convertibleToDxf', 'false');
            }
            if ($document->isConvertibleToPdf() == 1) {
                $documentXML->addChild('convertibleToPdf', 'true');
            } else {
                $documentXML->addChild('convertibleToPdf', 'false');
            }
            if ($document->isConvertibleToSwf() == 1) {
                $documentXML->addChild('convertibleToSwf', 'true');
            } else {
                $documentXML->addChild('convertibleToSwf', 'false');
            }

            $documentXML->addChild('title', $document->getTitle());
            $documentXML->addChild('description', $document->getDescription());
            $documentXML->addChild('language', $document->getLanguage());
            $documentXML->addChild('lastModified', $document->getLastModified());
            if ($document->getLockInfo() != null) {
                //LockInfo
                $lockInfoXML = $documentXML->addChild('lockInfo');
                $lockInfoXML->addChild('nodePath', $document->getLockInfo()->getNodePath());
                $lockInfoXML->addChild('owner', $document->getLockInfo()->getOwner());
                $lockInfoXML->addChild('token', $document->getLockInfo()->getToken());
            }

            if ($document->isLocked() == 1) {
                $documentXML->addChild('locked', 'true');
            } else {
                $documentXML->addChild('locked', 'false');
            }
            $documentXML->addChild('mimeType', $document->getMimeType());
            if ($document->isSigned() == 1) {
                $documentXML->addChild('signed', 'true');
            } else {
                $documentXML->addChild('signed', 'false');
            }

            foreach ($document->getCategories() as $category) {
                $categoryXML = $documentXML->addChild('categories');
                $categoryXML->addChild('author', $category->getAuthor());
                $categoryXML->addChild('created', $category->getCreated());
                $categoryXML->addChild('nodeClass', $category->getNodeClass());
                $categoryXML->addChild('path', $category->getPath());
                $categoryXML->addChild('permissions', $category->getPermissions());
                if ($category->isSubscribed() == 1) {
                    $categoryXML->addChild('subscribed', 'true');
                } else {
                    $categoryXML->addChild('subscribed', 'false');
                }
                $categoryXML->addChild('uuid', $category->getUuid());
                if ($category->isHasChildren() == 1) {
                    $categoryXML->addChild('hasChildren', 'true');
                } else {
                    $categoryXML->addChild('hasChildren', 'false');
                }
                $categoryXML->addChild('style', $category->getStyle());
            }
            foreach ($document->getKeywords() as $keyword) {
                $documentXML->addChild('keywords', $keyword);
            }

            foreach ($document->getNotes() as $note) {
                $noteXML = $documentXML->addChild('notes');
                $noteXML->addChild('author', $note->getAuthor());
                $noteXML->addChild('date', $note->getDate());
                $noteXML->addChild('path', $note->getPath());
                $noteXML->addChild('text', $note->getText());
            }
            foreach ($document->getSubscriptors() as $subscriptor) {
                $documentXML->addChild('subscriptors', $subscriptor);
            }
            $client->body($documentXML->asXML());
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else if ($error == TypeException::VERSION_EXCEPTION) {
                            throw new VersionException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Set document language.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $lang The lang must be ISO 691-1 compliant.
     *                     More information at https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes.
     *
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws VersionException
     * @throws LockException
     * @throws UnknowException
     */
    public function setLanguage($uuid, $lang) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_SET_LANGUAGE);
            $uri .= '?docId=' . urlencode($uuid) . '&lang=' . urlencode($lang);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::VERSION_EXCEPTION) {
                            throw new VersionException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Set document title.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $title The title of the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws VersionException
     * @throws LockException
     * @throws UnknowException
     */
    public function setDocumentTitle($uuid, $title) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_SET_TITLE);
            $uri .= '?docId=' . urlencode($uuid) . '&title=' . urlencode($title);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::VERSION_EXCEPTION) {
                            throw new VersionException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Mark the document for edition.
     *
     * Only one user can modify a document at same time.
     *
     * Before starting edition must do a checkout action that lock the edition process for other users and allows only to the user who has executed the action.
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function checkout($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_PUT_CHECKOUT, ['uuid' => $uuid]));
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Cancel a document edition.
     *
     * This action can only be done by the user who previously executed the checkout action.
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function cancelCheckout($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_DEL_CANCEL_CHECKOUT, ['uuid' => $uuid]));
            $client = Request::delete($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Cancel a document edition.
     *
     * This method allows to cancel edition on any document.
     * It is not mandatory execute this action by the same user who previously executed the checkout action
     *
     *  - This action can only be done by a super user ( user with ROLE_ADMIN ).
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws PrincipalAdapterException
     * @throws UnknowException
     */
    public function forceCancelCheckout($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_DEL_CANCEL_CHECKOUT, ['uuid' => $uuid]));
            $uri .= '?force=true';
            $client = Request::delete($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PRINCIPAL_ADAPTER_EXCEPTION) {
                        throw new PrincipalAdapterException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Is checked out
     *
     * @param string $uuid The uuid or path of the Document
     * @return bool Return a boolean that indicate if the document is on edition or not.
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function isCheckedOut($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_IS_CHECKOUT, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                if ($response->body == 'true') {
                    return true;
                } else {
                    return false;
                }
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Update document with new version
     *
     * The value of increment variable must be 1 or greater.
     * The valid values of increment variable depends on the VersionNumberAdapter you  have enabled.
     *
     * Only the user who started the edition - checkout - is allowed to update the document.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @param string $comment The comment for the new version the document
     * @param int $increment The increment variable must be 1 or greater
     * @return Version Return an object with new Version values
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws IOException
     * @throws FileSizeExceededException
     * @throws UserQuotaExceededException
     * @throws VirusDetectedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws AutomationException
     * @throws LockException
     * @throws UnknowException
     */
    public function checkin($uuid, $content, $comment, $increment) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_POST_CHECKIN, ['uuid' => $uuid]));

            $params = [];

            $param1 = [];
            $param1['name'] = 'comment';
            $param1['body'] = $comment;
            $params[] = $param1;

            $param2 = [];
            $param2['name'] = 'increment';
            $param2['body'] = $increment;
            $params[] = $param2;

            $files = [];
            $file = [];
            $file['name'] = 'content';
            $file['body'] = $content;
            $file['fileName'] = '';
            $files[] = $file;

            $body = [];
            $body['params'] = $params;
            $body['files'] = $files;

            $client = Request::post($uri);
            $client->setCurlPostFile(true);
            $client->sends(Mime::UPLOAD);
            $client->body($body);
            $client->addHeader('Authorization', $this->authorizationToken);
            $client->expects(Mime::JSON);

            $response = $client->send();
            if ($response->code == Status::OK) {
                return $this->phpVersion($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                        throw new FileSizeExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                        throw new UserQuotaExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::VIRUS_DETECTED_EXCEPTION) {
                        throw new VirusDetectedException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else {
                        throw new UnknowException($error . ': ' . $msg);
                    }
                } else {
                    throw new UnknowException($restException->getMessage());
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_CHECKIN);
            $params = [];
            $params['docId'] = $uuid;
            $params['content'] = $content;
            $params['comment'] = $comment;
            $params['increment'] = $increment;
            $client = Request::post($uri);
            $client->body($params, Mime::UPLOAD);
            $client->authenticateWith($this->user, $this->password);
            $client->expects(Mime::XML);
            $response = $client->send();
            if ($response->code == Status::OK) {
                return $this->phpVersion($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else if ($error == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                            throw new FileSizeExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::VIRUS_DETECTED_EXCEPTION) {
                            throw new VirusDetectedException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::EXTENSION_EXCEPTION) {
                            throw new ExtensionException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Version History
     *
     * @param string $uuid The uuid or path of the Document
     * @return array Return a list of all document versions.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getVersionHistory($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_VERSION_HISTORY);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $versions = [];
                foreach ($response->body->version as $versionXML) {
                    $versions[] = $this->phpVersion($versionXML);
                }
                return $versions;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Lock a document
     *
     * Only the user who locked the document is allowed to unlock.
     * A locked document can not be modified by other users.
     *
     * @param string $uuid The uuid or path of the Document
     * @return LockInfo Return an object with the Lock information.
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function lock($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_LOCK);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpLockInfo($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Unlock a locked document.
     *
     * Only the user who locked the document is allowed to unlock.
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function unlock($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_UNLOCK);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Unlock a locked document.
     *
     * This method allows to unlcok any locked document.
     * It is not mandatory execute this action by the same user who previously executed the checkout lock action.
     *  - This action can only be done by a super user ( user with ROLE_ADMIN ).
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function forceUnlock($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_FORCE_UNLOCK);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Is locked
     *
     * @param string $uuid The uuid or path of the Document
     * @return bool Return a boolean that indicate if the document is locked or not.
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function isLocked($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_IS_LOCKED);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                if ($response->body == 'true') {
                    return true;
                } else {
                    return false;
                }
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get lock information
     *
     * @param string $uuid The uuid or path of the Document
     * @return LockInfo Return an object with the Lock information
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function getLockInfo($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_LOCKINFO);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpLockInfo($response->body);
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Document is definitely removed from repository.
     *
     * Usually you will purge documents into /okm:trash/userId - the personal trash user locations - but is possible to directly purge any document from the whole repository.
     *  - When a document is purged only will be able to be restored from a previously repository backup. The purge action remove the document definitely from the repository.
     *
     * @param string $uuid string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws ExtensionException
     * @throws UnknowException
     */
    public function purgeDocument($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_DEL_PURGE, ['uuid' => $uuid]));
            $client = Request::delete($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException($restException->getMessage());
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Move document into some folder or record.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $dstId The uuid or path of the Folder or Record
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws ExtensionException
     * @throws ItemExistsException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function moveDocument($uuid, $dstId) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_PUT_MOVE, ['uuid' => $uuid, 'dstId' => $dstId]));
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Copy a document into some folder or record.
     * Only the binary data and the security grants are copyed to destionation, the metadata, keywords, etc. of the document are not copyed.See "extendedDocumentCopy" method for this feature.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $dstId The uuid or path of the Folder or Record
     * @param string $newName The new name for the Document. Value is null, document will preservate the same name.
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws ItemExistsException
     * @throws AutomationException
     * @throws IOException
     * @throws UnknowException
     */
    public function copyDocument($uuid, $dstId, $newName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_POST_COPY, ['uuid' => $uuid, 'dstId' => $dstId]));
            $client = Request::post($uri);

            $params = [];
            $params['newName'] = $newName;
            $response = $this->getClientWithParams($client, $params);
            if ($response->code != Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Promote previously document version to actual version.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $versionId The version of the Document
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws LockException
     * @throws UnknowException
     */
    public function restoreVersion($uuid, $versionId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_RESTORE_VERSION);
            $uri .= '?docId=' . urlencode($uuid) . '&versionId=' . urlencode($versionId);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::EXTENSION_EXCEPTION) {
                            throw new ExtensionException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Purge all documents version except the actual version.
     *
     * This action compact the version history of a document.
     * This action can not be reverted.
     *
     * @param string $uuid The uuid or path of the Document
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws LockException
     * @throws UnknowException
     */
    public function purgeVersionHistory($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_PURGE_VERSION_HISTORY);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::put($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::NO_CONTENT) {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::EXTENSION_EXCEPTION) {
                            throw new ExtensionException($error . ': ' . $msg);
                        } else if ($error == TypeException::LOCK_EXCEPTION) {
                            throw new LockException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get version history size
     *
     * @param string $uuid The uuid or path of the Document
     * @return int Return the sum in bytes of all documents into documents history.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getVersionHistorySize($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_VERSION_HISTORY_SIZE);
            $uri .= '?docId=' . urlencode($uuid);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (int)$response->body;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Is valid Document
     *
     * @param string $uuid The uuid or path of the Document
     * @return bool Return a boolean that indicate if the node is a document or not.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function isValidDocument($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_GET_IS_VALID, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                if ($response->body == 'true') {
                    return true;
                } else {
                    return false;
                }
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ACCESS_DENIED_EXCEPTION) {
                        throw new AccessDeniedException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Document path
     *
     * @param string $uuid The uuid of the Document
     * @return string Convert document UUID to document path
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getDocumentPath($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_PATH);
            $uri .= '/' . urlencode($uuid);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (string)$response->body;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Return a list of available document languages what OpenKM can identify
     *
     * @return array Returns the Languages
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getDetectedLanguages() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_DETECTED_LANGUAGES);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $languages = [];
                foreach ($response->body as $languageXML) {
                    $languages[] = (string)$languageXML;
                }
                return $languages;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Copy a document with asociated data into some folder or record.
     *
     *  By default only the binary data and the security grants, the metadata, keywords etc... of the folder are not copyed.
     *  Additional:
     *
     *  > When category paramater is true the original values of the categories will be copied.
     *  > When keywords paramater is true the original values of the keywords will be copied.
     *  > When propertyGroups paramater is true the original values of the metadata groups will be copied.
     *  > When notes paramater is true the original values of the notes will be copied.
     *  > When security paramater is true the original values of the security will be copied.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $dstId The uuid or path of the Folder or Record
     * @param string $newName The new name for the Document. Value is null, document will preservate the same name.
     * @param bool $categories
     * @param bool $keywords
     * @param bool $propertyGroups
     * @param bool $notes
     * @param bool $security
     * @return \openkm\bean\Folder
     * @throws AutomationException
     * @throws ConnectionErrorException
     * @throws DatabaseException
     * @throws IOException
     * @throws ItemExistsException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws UnknowException
     * @throws UserQuotaExceededException
     */
    public function extendedDocumentCopy($uuid, $dstId, $newName, $categories, $keywords, $propertyGroups, $notes, $security) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_POST_EXTENDED_COPY, ['uuid' => $uuid, 'dstId' => $dstId]));

            $params = [];
            $params['name'] = $newName;
            $params['categories'] = $categories;
            $params['keywords'] = $keywords;
            $params['propertyGroups'] = $propertyGroups;
            $params['notes'] = $notes;
            $params['security'] = $security;

            $client = Request::post($uri);
            $response = $this->getClientWithParams($client, $params);
            if ($response->code == Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                        throw new UserQuotaExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Create a new document from template
     *
     * When template use metadata groups to fill fields into, then these values are mandatory and must be set into properties parameter.
     *
     * For more information about Templates and metadata take a look at Creating templates.
     *
     * By default only the binary data and the security grants, the metadata, keywords etc... of the folder are not copyed.
     * Additional:
     *
     * > When category paramater is true the original values of the categories will be copied.
     * > When keywords paramater is true the original values of the keywords will be copied.
     * > When notes paramater is true the original values of the notes will be copied.
     *
     * @param string $uuid The uuid or path of the Template
     * @param string $dstPath The path of the Document
     * @param bool $categories
     * @param bool $keywords
     * @param bool $notes
     * @param array $properties An array of the SimplePropertyGroup
     * @return Document Returns an object Document.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws ItemExistsException
     * @throws IOException
     * @throws DatabaseException
     * @throws DocumentException
     * @throws TemplateException
     * @throws DocumentTemplateException
     * @throws ConversionException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws UserQuotaExceededException
     * @throws VirusDetectedException
     * @throws AutomationException
     * @throws ParseException
     * @throws NoSuchGroupException
     * @throws NoSuchPropertyException
     * @throws LockException
     * @throws UnknowException
     */
    public function createFromTemplate($uuid, $dstPath, $categories, $keywords, $notes, $properties = []) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_POST_CREATE_FROM_TEMPLATE, ['uuid' => $uuid]));

            $templateParams = new TemplateParams();
            $templateParams->setDstPath($dstPath);
            $templateParams->setCategories($categories);
            $templateParams->setKeywords($keywords);
            $templateParams->setProperties(BeanHelper::copyToGroupPropertyList($properties));

            $client = Request::post($uri);
            $response = $this->getClientWithBody($client, $templateParams);
            if ($response->code == Status::OK) {
                return $this->phpDocument($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DOCUMENT_EXCEPTION) {
                        throw new DocumentException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::TEMPLATE_EXCEPTION) {
                        throw new TemplateException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DOCUMENT_TEMPLATE_EXCEPTION) {
                        throw new DocumentTemplateException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::CONVERSION_EXCEPTION) {
                        throw new ConversionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                        throw new UnsupportMimeTypeException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                        throw new FileSizeExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                        throw new UserQuotaExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::VIRUS_DETECTED_EXCEPTION) {
                        throw new VirusDetectedException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_PROPERTY_EXCEPTION) {
                        throw new NoSuchPropertyException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Update a document previously created from template
     *
     * This method only has sense when template use metadata groups to fill fields into.
     * For more information about Templates and metadata take a look at Creating templates.
     *
     * @param string $uuid The uuid or path of the Template
     * @param string $dstId The uuid or path of the Document
     * @param array $properties An array of the SimplePropertyGroup
     * @return Document Returns an object Document.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws IOException
     * @throws DatabaseException
     * @throws DocumentException
     * @throws TemplateException
     * @throws DocumentTemplateException
     * @throws ConversionException
     * @throws UnsupportMimeTypeException
     * @throws FileSizeExceededException
     * @throws UserQuotaExceededException
     * @throws VirusDetectedException
     * @throws AutomationException
     * @throws ParseException
     * @throws NoSuchGroupException
     * @throws NoSuchPropertyException
     * @throws LockException
     * @throws UnknowException
     */
    public function updateFromTemplate($uuid, $dstId, $properties = []) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::DOCUMENT_PUT_UPDATE_FROM_TEMPLATE, ['uuid' => $uuid]));

            $updateTemplateParams = new UpdateTemplateParams();
            $updateTemplateParams->setDstId($dstId);
            $updateTemplateParams->setProperties(BeanHelper::copyToGroupPropertyList($properties));

            $client = Request::put($uri);
            $response = $this->getClientWithBody($client, $updateTemplateParams);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::ITEM_EXISTS_EXCEPTION) {
                        throw new ItemExistsException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DOCUMENT_EXCEPTION) {
                        throw new DocumentException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::TEMPLATE_EXCEPTION) {
                        throw new TemplateException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DOCUMENT_TEMPLATE_EXCEPTION) {
                        throw new DocumentTemplateException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::CONVERSION_EXCEPTION) {
                        throw new ConversionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::UNSUPPORTED_MIME_TYPE_EXCEPTION) {
                        throw new UnsupportMimeTypeException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::FILE_SIZE_EXCEEDED_EXCEPTION) {
                        throw new FileSizeExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                        throw new UserQuotaExceededException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::VIRUS_DETECTED_EXCEPTION) {
                        throw new VirusDetectedException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_PROPERTY_EXCEPTION) {
                        throw new NoSuchPropertyException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Return the document annotations of some document version.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $verName The version name of the Document
     * @return string Return the document annotations of some document version.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws IOException
     * @throws UnknowException
     */
    public function getAnnotations($uuid, $verName) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_ANNOTATIONS);
            $uri .= '?docId=' . urlencode($uuid) . '&verName=' . urlencode($verName);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (string)$response->body;
            } else if ($response->code == Status::NO_CONTENT) {
                return "";
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Return a PDF document with the differences between two document versions.
     *
     * @param string $uuid The uuid or path of the Document
     * @param string $v1 The version of the document
     * @param string $v2 The version of the document
     * @return string Return a PDF document with the differences between two document versions.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws RepositoryException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws AutomationException
     * @throws ConversionException
     * @throws TemplateException
     * @throws InterruptedException
     * @throws UnknowException
     */
    public function getDifferences($uuid, $v1, $v2) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_DIFFERENCES);
            $uri .= '?docId=' . urlencode($uuid) . '&v1=' . urlencode($v1) . '&v2=' . urlencode($v2);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return $response->body;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($error . ': ' . $msg);
                        } else if ($error == TypeException::CONVERSION_EXCEPTION) {
                            throw new ConversionException($error . ': ' . $msg);
                        } else if ($error == TypeException::TEMPLATE_EXCEPTION) {
                            throw new TemplateException($error . ': ' . $msg);
                        } else if ($error == TypeException::INTERRUPTED_EXCEPTION) {
                            throw new InterruptedException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Return a list of documents checkout by the user.
     *
     * @return array Return a list of documents checkout by the user.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getCheckedOut() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_GET_CHECKEDOUT);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $documents = [];
                foreach ($response->body->document as $documentXML) {
                    $documents[] = $this->phpDocument($documentXML);
                }
                return $documents;
            } else {
                if ($response->code == Status::UNAUTHORIZED) {
                    throw new AccessDeniedException($response->body, $response->code);
                } else if ($response->code == Status::INTERNAL_SERVER_ERROR) {
                    $position = strpos($response->body, ':');
                    if ($position) {
                        $error = substr($response->body, 0, $position);
                        $msg = substr($response->body, $position + 1, strlen($response->body));
                        if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                            throw new PathNotFoundException($error . ': ' . $msg);
                        } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                            throw new RepositoryException($error . ': ' . $msg);
                        } else if ($error == TypeException::DATABASE_EXCEPTION) {
                            throw new DatabaseException($error . ': ' . $msg);
                        } else {
                            throw new UnknowException($error . ': ' . $msg);
                        }
                    } else {
                        throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    public function mergePdf($destinationUuid, $docName, $uuids = []) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::DOCUMENT_PUT_MERGE_PDF);

            $params = [];

            $param1 = [];
            $param1['name'] = 'destinationUuid';
            $param1['body'] = $destinationUuid;
            $params[] = $param1;

            $param2 = [];
            $param2['name'] = 'name';
            $param2['body'] = $docName;
            $params[] = $param2;

            foreach ($uuids as $uuid) {
                $param3 = [];
                $param3['name'] = 'uuidList';
                $param3['body'] = $uuid;
                $params[] = $param3;
            }

            $body = [];
            $body['params'] = $params;

            $client = Request::put($uri);
            $client->setCurlForm(true);
            $client->sends(Mime::FORM);
            $client->body($body);
            $client->addHeader('Authorization', $this->authorizationToken);
            $client->expects(Mime::JSON);

            $response = $client->send();

            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::ACCESS_DENIED_EXCEPTION) {
                        throw new AccessDeniedException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PRINCIPAL_ADAPTER_EXCEPTION) {
                        throw new PrincipalAdapterException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

}

?>
