public static function copyDir($source, $destination, $permission = 0777, $recursive = true) {
        if (substr($source, strlen($destination) - 1) !== DIRECTORY_SEPARATOR)
            $destination .= DIRECTORY_SEPARATOR;

        try {
            if (!is_dir($destination))
                mkdir($destination, $permission);

            $contents = self::readDir($source, self::ALL, $recursive, NULL);
            if (isset($contents['dirs'])) {
                foreach ($contents['dirs'] as $fullPath) {
                    @mkdir(str_replace(array($source, DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR), array($destination, DIRECTORY_SEPARATOR), $fullPath), $permission);
                }
            }

            if (isset($contents['files'])) {
                foreach ($contents['files'] as $fullPathsArray) {
                    foreach ($fullPathsArray as $fullPath) {
                        @copy($fullPath, str_replace(array($source, DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR), array($destination, DIRECTORY_SEPARATOR), $fullPath));
                    }
                }
            }
        } catch (\Exception $ex) {
            throw new \Exception($ex->getMessage());
        }
    }