<?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\AppVersion;
use openkm\bean\Folder;
use openkm\definition\BaseRepository;
use openkm\util\FormatUtils;
use openkm\util\UriHelper;
use Httpful\Request;
use Httpful\Mime;
use openkm\bean\ScriptExecutionResult;
use openkm\bean\SqlQueryResults;
use openkm\bean\SqlQueryResultColumns;
use openkm\bean\HqlQueryResults;
use openkm\bean\HqlQueryResultColumns;
use openkm\util\Status;
use openkm\bean\Configuration;
use openkm\util\TypeException;
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\bean\Translation;
use openkm\exception\AutomationException;
use openkm\exception\LockException;
use openkm\exception\UserQuotaExceededException;
use openkm\exception\IOException;
use openkm\bean\ChangeLogged;

/**
 * RepositoryImpl
 *
 * @author sochoa
 */
class RepositoryImpl extends ClientImpl implements BaseRepository {

    /**
     * Get Root Folder
     * @return Folder Return the object Folder of node "/okm:root"
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getRootFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_FOLDER);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Trash Folder
     * The returned folder will be the user trash folder.
     * For example if the method is executed by "okmAdmin" user then the folder returned will be "/okm:trash/okmAdmin".
     *
     * @return Folder Return the object Folder of node "/okm:trash/{userId}"
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getTrashFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_TRASH);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Trash Folder Base
     * @return Folder Return the object Folder of node "/okm:trash"
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getTrashFolderBase() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_TRASH_BASE);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Templates Folder
     * @return Folder Return the object Folder of node "/okm:templates"
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getTemplatesFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_TEMPLATES);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Personal Folder
     * The returned folder will be the user personal folder.
     * For example if the method is executed by "okmAdmin" user then the folder returned will be "/okm:personal/okmAdmin".
     *
     * @return Folder Return the object Folder of node "/okm:personal/{userId}"
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getPersonalFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_PERSONAL);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Personal Folder Base
     * @return Folder Return the object Folder of node "/okm:personal"
     * @throws ConnectionErrorException when unable to parse or communicate with the server
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getPersonalFolderBase() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_PERSONAL_BASE);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Mail Folder
     *
     * The returned folder will be the user mail folder.
     * For example if the method is executed by "okmAdmin" user then the folder returned will be "/okm:mail/okmAdmin".
     *
     * @return Folder Return the object Folder of node "/okm:mail/{userId}"
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getMailFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_MAIL);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Mail Folder Base
     * @return Folder Return the object Folder of node "/okm:mail"
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getMailFolderBase() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_MAIL_BASE);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Thesaurus Folder
     * @return Folder Return the object Folder of node "/okm:thesaurus"
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getThesaurusFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_THESAURUS);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Get Categories Folder
     * @return Folder Return the object Folder of node "/okm:categories"
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getCategoriesFolder() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_ROOT_CATEGORIES);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpFolderComplete($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());
        }
    }

    /**
     * Purge Trash
     *
     * Definitively remove from repository all nodes into "/okm:trash/{userId}"
     *
     * For example if the method is executed by "okmAdmin" user then the purged trash will be "/okm:trash/okmAdmin".
     *
     * When a node is purged only will be able to be restored from a previously repository backup. The purge action remove the node definitely from the repository.
     *
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws UnknowException
     */
    public function purgeTrash() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_PURGE_TRASH);
            $client = Request::delete($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());
        }
    }

    /**
     * Get Update Message
     *
     * There's an official OpenKM update message service available at Internet what based on your locally OpenKM version retrieve information messages.
     *
     * The most common message is that a new OpenKM version has been released.
     *
     * @return String Retrieve a message from OpenKM official message service at Internet based on your locally OpenKM server version.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getUpdateMessage() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_UPDATE_MESSAGE);
            $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());
        }
    }

    /**
     * Get Repository uuid
     * @return String Retrieve installation unique identifier.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getRepositoryUuid() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_RESPOSITORY_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());
        }
    }

    /**
     * Has node
     * @param string $nodeId The value of the parameter nodeId can be a valid UUID or path.
     * @return boolean Return a node that indicate if a node exists or not.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function hasNode($nodeId) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_HAS_NODE);
            $uri .= '?nodeId=' . urlencode($nodeId);
            $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 node path
     * Convert node UUID to path.
     *
     * @param string $uuid The uuid of the node
     * @return string Return path of the node
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getNodePath($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::REPOSITORY_GET_NODE_PATH, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (string)$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 {
                        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 node uuid
     * Convert node path to UUID.
     *
     * @param string $nodePath The path of the node
     * @return string Return uuid of the node
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getNodeUuid($nodePath) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_NODE_UUID);
            $uri .= '?nodePath=' . urlencode($nodePath);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (string)$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 {
                        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 App Version
     * @return AppVersion Return information about OpenKM version.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getAppVersion() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_APP_VERSION);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $appVersionXML = $response->body;
                $appVersion = new AppVersion();
                $appVersion->setBuild((string)$appVersionXML->build);
                $appVersion->setExtension((string)$appVersionXML->estension);
                $appVersion->setMaintenance((string)$appVersionXML->maintenance);
                $appVersion->setMajor((string)$appVersionXML->major);
                $appVersion->setMinor((string)$appVersionXML->minor);
                return $appVersion;
            } 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());
        }
    }

    /**
     * Copy attributes from a node to other.
     * @param string $nodeId The uuid or path of the node.
     * @param string $dstId The uuid or path of the node.
     * @param bool $categories
     * @param bool $keywords
     * @param bool $propertyGroups
     * @param bool $notes
     * @param bool $wiki
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws LockException
     * @throws IOException
     * @throws UserQuotaExceededException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function copyAttributes($nodeId, $dstId, $categories, $keywords, $propertyGroups, $notes, $wiki) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_COPY_ATTRIBUTES);
            $uri .= '?nodeId=' . urlencode($nodeId) . '&dstId=' . urlencode($dstId);
            if ($categories == 1) {
                $uri .= '&categories=true';
            } else {
                $uri .= '&categories=false';
            }
            if ($keywords == 1) {
                $uri .= '&keywords=true';
            } else {
                $uri .= '&keywords=false';
            }
            if ($propertyGroups == 1) {
                $uri .= '&propertyGroups=true';
            } else {
                $uri .= '&propertyGroups=false';
            }
            if ($notes == 1) {
                $uri .= '&notes=true';
            } else {
                $uri .= '&notes=false';
            }
            if ($wiki == 1) {
                $uri .= '&wiki=true';
            } else {
                $uri .= '&wiki=false';
            }
            $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 if ($error == TypeException::IO_EXCEPTION) {
                            throw new IOException($error . ':' . $msg);
                        } else if ($error == TypeException::USER_QUOTA_EXCEEDED_EXCEPTION) {
                            throw new UserQuotaExceededException($error . ': ' . $msg);
                        } else if ($error == TypeException::AUTOMATION_EXCEPTION) {
                            throw new AutomationException($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());
        }
    }

    /**
     * Execute an script
     *
     * The local script - test.bsh - used in the sample below:
     *
     *  import com.openkm.bean.*;
     *  import com.openkm.api.*;
     *
     *  for (Folder fld : OKMFolder.getInstance().getChildren(null,"/okm:root")) {
     *      print(fld+"\n");
     *  }
     *  // Some value can also be returned as string
     *  return "some result";
     *
     * This action can only be done by a super user ( user with ROLE_ADMIN ).
     *
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return ScriptExecutionResult
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function executeScript($content) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_POST_EXECUTE_SCRIPT);
            $params = [];
            $files = [];
            if ($content != null && $content !== '') {
                $file = [];
                $file['name'] = 'script';
                $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) {
                $scriptExecutionResultJSON = $response->body;
                $scriptExecutionResult = new ScriptExecutionResult();
                $scriptExecutionResult->setResult((string)$scriptExecutionResultJSON->result);
                $scriptExecutionResult->setStderr((string)$scriptExecutionResultJSON->stderr);
                $scriptExecutionResult->setStdout((string)$scriptExecutionResultJSON->stdout);
                return $scriptExecutionResult;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    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());
        }
    }

    /**
     * Execute SQL sentences.
     *
     * The test.sql script used in the sample below:
     *
     *  SELECT NBS_UUID, NBS_NAME FROM OKM_NODE_BASE LIMIT 10;
     *
     * The SQL script can only contains a single SQL sentence.
     *
     * This action can only be done by a super user ( user with ROLE_ADMIN ).
     *
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return SqlQueryResults
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function executeSqlQuery($content) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_POST_EXECUTE_SQL_QUERY);
            $params = [];
            $files = [];
            if ($content != null && $content !== '') {
                $file = [];
                $file['name'] = 'query';
                $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) {
                $sqlQueryResults = new SqlQueryResults();
                $results = [];
                foreach ($response->body->results as $sqlQueryResultColumnsJSON) {
                    $sqlQueryResultColumns = new SqlQueryResultColumns();
                    $columns = [];
                    foreach ($sqlQueryResultColumnsJSON->columns as $columnsJSON) {
                        $columns[] = (string)$columnsJSON;
                    }
                    $sqlQueryResultColumns->setColumns($columns);
                    $results[] = $sqlQueryResultColumns;
                }
                $sqlQueryResults->setResults($results);
                return $sqlQueryResults;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    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());
        }
    }

    /**
     * Execute HQL sentences.
     *
     * The testhql.sql script used in the sample below:
     *
     *  SELECT uuid, name from NodeBase where name = 'okm:root';
     *
     * The HQL script can only contains a single HQL sentence.
     *
     * This action can only be done by a super user ( user with ROLE_ADMIN ).
     *
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @return HqlQueryResults
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function executeHqlQuery($content) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_POST_EXECUTE_HQL_QUERY);
            $params = [];
            $files = [];
            if ($content != null && $content !== '') {
                $file = [];
                $file['name'] = 'query';
                $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) {
                $hqlQueryResults = new HqlQueryResults();
                $results = [];
                foreach ($response->body->results as $hqlQueryResultColumnsJSON) {
                    $hqlQueryResultColumns = new HqlQueryResultColumns();
                    $columns = [];
                    foreach ($hqlQueryResultColumnsJSON->columns as $columnsJSON) {
                        $columns[] = (string)$columnsJSON;
                    }
                    $hqlQueryResultColumns->setColumns($columns);
                    $results[] = $hqlQueryResultColumns;
                }
                $hqlQueryResults->setResults($results);
                return $hqlQueryResults;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException(json_decode($response->body));
                if ($restException->getSimpleName() != '') {
                    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 Translations
     * The OpenKM translations tables can be used to retrieve actually OpenKM translations or create your own translations ( insert values into new module ).
     * By default modules values are :
     *
     *     - frontend ( used by default OpenKM UI ).
     *     - extension ( used by OpenKM extension UI ).
     *     - mobile ( used by OpenKM mobile UI ).
     *
     * Example to add a new Translation module :
     * SQL values to be executed from Database query view:
     *
     *      DELETE FROM OKM_TRANSLATION WHERE TR_LANGUAGE='en-GB' and TR_MODULE='doc';
     *      INSERT INTO OKM_TRANSLATION (TR_MODULE, TR_KEY, TR_TEXT, TR_LANGUAGE) VALUES ('doc', 'document.generator.title','Document generator', 'en-GB');
     *      INSERT INTO OKM_TRANSLATION (TR_MODULE, TR_KEY, TR_TEXT, TR_LANGUAGE) VALUES ('doc', 'document.generator.logout','Logout', 'en-GB');
     *
     * The code then should be:
     *
     * $translations = $this->ws->getTranslations('en-GB', 'doc');
     *
     * @param string $lang
     * @param string $module
     * @return array Retrieve the translations of a module into an array
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getTranslations($lang, $module) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_TRANSLATIONS);
            $uri .= '?lang=' . urlencode($lang) . '&module=' . urlencode($module);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $translations = [];
                foreach ($response->body->translation as $translationXML) {
                    $translation = new Translation();
                    $translation->setKey((string)$translationXML->key);
                    $translation->setValue((string)$translationXML->value);
                    $translations[] = $translation;
                }
                return $translations;
            } 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("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 Configuration
     *
     * @param string $key A cofiguration parameter
     * @return Configuration Retrieve the value of a configuration parameter
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getConfiguration($key) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_CONFIGURATION);
            $uri .= '?key=' . urlencode($key);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $configuration = new Configuration();
                $configuration->setKey((string)$response->body->key);
                $configuration->setType((string)$response->body->type);
                $configuration->setValue((string)$response->body->value);
                return $configuration;
            } 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("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 the list of changes in some path and subfolders.
     *
     * The method is used by desktop synchronization application for retrieving the changes.
     *
     * @param string $nodePath The path of the node(Folder,Document, Mail, Record)
     * @param string $modificationsFrom The modificacions from date
     * @return array(ChangeLogged) Return the list of changes in some path and subfolders.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getChangeLog($nodePath, $modificationsFrom) {
        try {
            $time = strtotime($modificationsFrom);
            $modificationsFrom = date('YmdHis', $time);

            $uri = UriHelper::getUri($this->host, UriHelper::REPOSITORY_GET_CHANGELOG);
            $uri .= '?nodePath=' . urlencode($nodePath) . '&modificationsFrom=' . urlencode($modificationsFrom);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $changesLoggedes = [];
                foreach ($response->body->changesLogged as $changesLoggedXML) {
                    $changesLogged = new ChangeLogged();
                    $changesLogged->setAction((string)$changesLoggedXML->action);
                    $changesLogged->setChecksum((string)$changesLoggedXML->checksum);
                    $changesLogged->setDate((string)$changesLoggedXML->date);
                    $changesLogged->setPath((string)$changesLoggedXML->path);
                    $changesLogged->setPermission((int)$changesLoggedXML->permission);
                    $changesLogged->setUserRole((string)$changesLoggedXML->userRole);
                    $changesLogged->setUuid((string)$changesLoggedXML->uuid);
                    $changesLogged->setVersion((string)$changesLoggedXML->version);
                    $changesLoggedes[] = $changesLogged;
                }
                return $changesLoggedes;
            } 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::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());
        }
    }

}

?>
