Exemple #1
0
    def filter_stream(self, req, method, filename, stream, data):
        """
        Adds project total count information in project summary block::

            Downloads: 288

        """
        # TODO: Make interface for the project summary box and implement it here

        # Filter only the summary table wiki macro
        if filename != 'multiproject_summary.html':
            return stream

        # Load project and followers info
        project = Project.get(self.env)
        count = ProjectDownloadEntry.total_download_count(project.id)

        if count == 0:
            return stream

        # Add following information into project summary block
        trans = Transformer('//div[@class="summary"]/table').append(
            tag.tr(
                tag.th('Downloads:'),
                tag.td(count)
            )
        )

        return stream | trans
    def handle_change(self, download_config, new_downloads_dir, can_be_moved, node_factory, warning, notice):
        """
        :param FilesDownloadConfig download_config: download_configuration configuration
        :returns: True if new
        """
        old_node, old_dir_exists = self.get_dir_data(download_config, node_factory)

        try:
            download_config.downloads_dir = new_downloads_dir
        except DownloadDirValidationException as e:
            raise TracError(_("New downloads directory is not valid: ") + str(e))

        new_node = FileSystemNode.from_path(download_config.downloads_dir, node_factory)
        if new_node.exists() and not new_node.is_dir():
            raise TracError(_("Error: Destination path exists and is a file"))
        elif new_node.exists() and can_be_moved:
            raise TracError(_("Error: Destination path already exists"))

        try:
            download_config.save()
            notice(_("Your changes have been saved."))
        except Exception as e:
            self.log.exception("Failed to save downloads directory")
            raise TracError(_("Saving new value failed"))

        was_created = False
        if old_dir_exists and can_be_moved:
            try:
                old_node.move(new_node.relative_path)
                notice(_("Moved old downloads directory to be new one"))
                was_created = True
            except Exception as e:
                self.log.exception("Exception while moving old directory to new one")
                warning(_("Error while moving the old directory."))
        elif not new_node.exists():
            try:
                new_node.get_parent_dir().create_dir(new_node.filename)
                notice(_("Created new downloads directory"))
                was_created = True
            except Exception as e:
                self.log.exception("Creating new downloads directory failed.")
                warning(_("Creating new downloads directory failed."))
        else:
            # not can_be_moved
            if old_dir_exists:
                try:
                    for entry in ProjectDownloadEntry.get_all_download_entries(node_factory.project_id):
                        entry.delete()
                except Exception as e:
                    warning(_("Marking files as deleted failed"))
            notice(_("Set the new downloads directory to be the directory chosen."))

        return was_created
 def handle_unset(self, warning, notice):
     try:
         env_name = self.env.project_identifier
     except AttributeError as e:
         # In case of trac admin commands, project_identifier is not found
         env_name = self.env.path.split("/")[-1]
         self.env.project_identifier = env_name
     try:
         files_core = FilesCoreComponent(self.env)
         node_factory, download_config = files_core.files_node_factory_and_config()
         download_config.delete()
         notice(_("Your changes have been saved."))
     except Exception as e:
         self.log.exception("Failed to unset downloads directory")
         raise TracError(_("Unsetting failed"))
     try:
         for entry in ProjectDownloadEntry.get_all_download_entries(node_factory.project_id):
             entry.delete()
     except Exception as e:
         warning(_("Marking files as deleted failed"))
 def handle_unset(self, warning, notice):
     try:
         env_name = self.env.project_identifier
     except AttributeError as e:
         # In case of trac admin commands, project_identifier is not found
         env_name = self.env.path.split('/')[-1]
         self.env.project_identifier = env_name
     try:
         files_core = FilesCoreComponent(self.env)
         node_factory, download_config = files_core.files_node_factory_and_config(
         )
         download_config.delete()
         notice(_('Your changes have been saved.'))
     except Exception as e:
         self.log.exception('Failed to unset downloads directory')
         raise TracError(_('Unsetting failed'))
     try:
         for entry in ProjectDownloadEntry.get_all_download_entries(
                 node_factory.project_id):
             entry.delete()
     except Exception as e:
         warning(_("Marking files as deleted failed"))
    def filter_stream(self, req, method, filename, stream, data):
        """
        Adds project total count information in project summary block::

            Downloads: 288

        """
        # TODO: Make interface for the project summary box and implement it here

        # Filter only the summary table wiki macro
        if filename != "multiproject_summary.html":
            return stream

        # Load project and followers info
        project = Project.get(self.env)
        count = ProjectDownloadEntry.total_download_count(project.id)

        if count == 0:
            return stream

        # Add following information into project summary block
        trans = Transformer('//div[@class="summary"]/table').append(tag.tr(tag.th("Downloads:"), tag.td(count)))

        return stream | trans
Exemple #6
0
    def expand_macro(self, formatter, name, content, args=None):

        # Parse optional arguments
        if args is None:
            args = parse_args(content)
            if len(args) > 1:
                args = args[1]

        files_core = FilesCoreComponent(self.env)
        node_factory, download_config = files_core.files_node_factory_and_config(formatter.req)
        if 'FILES_DOWNLOADS_VIEW' not in formatter.req.perm:
            return ''

        if name == 'FilesDownloadsCount':
            count = ProjectDownloadEntry.total_download_count(node_factory.project_id)
            return html.span(count, class_="files_downloads_count")
        elif name == 'FilesDownloads' or name == 'FilesDownloadsNarrow':
            is_narrow = True
            if name == 'FilesDownloads':
                is_narrow = False

            no_hide = False
            if args.has_key('no_hide') and args['no_hide'].lower() == 'true':
                no_hide = True

            only_featured = False
            if args.has_key('only_featured') and args['only_featured'].lower() == 'true':
                only_featured = True

            title = _('Featured downloads') if only_featured else _('Downloads')
            try:
                title = _(args['title'])
            except KeyError:
                title = _('Featured downloads') if only_featured else _('Downloads')
            except ValueError as e:
                title = _('Invalid title: %(reason)s', reason=str(e))

            download_entries = ProjectDownloadEntry.get_all_download_entries(node_factory.project_id,
                only_featured=only_featured)

            downloads = []
            user_store = None
            user_by_id = {}
            if not is_narrow:
                user_store = get_userstore()

            for download_entry in download_entries:
                if not is_narrow and not user_by_id.has_key(download_entry.uploader_id):
                    user = user_store.getUserWhereId(download_entry.uploader_id)
                    user_by_id[download_entry.uploader_id] = user

                # This doesn't check whether the node really exists
                node = MappedFileNode.from_download_entry(download_entry, node_factory)
                downloads.append(node)

            add_stylesheet(formatter.req, 'multiproject/css/files.css')
            add_script(formatter.req, 'multiproject/js/files.js')

            return Chrome(self.env).render_template(formatter.req,
                'multiproject_files_wiki.html',
                    {'downloads' : downloads,
                     'downloads_dir': download_config.downloads_dir,
                     'is_narrow': is_narrow,
                     'no_hide': no_hide,
                     'only_featured': only_featured,
                     'user_by_id': user_by_id,
                     'title': title,
                     'format_filename': format_filename},
                'text/html', True)
Exemple #7
0
    def show_dir(self, req, node, node_factory, files_core, user_store,
                  target_filename='', current_mode=''):
        """
        Shows the content of a dir in a browser

        :param MappedFileNode node: mapped file node
        """
        only_downloads_dir = False
        try:
            node.require_read_perm(req.perm)
        except PermissionError as e:
            if node.relative_path == '.' and 'FILES_DOWNLOADS_VIEW' in req.perm:
                add_warning(req, _("You must have FILES_VIEW permission "
                                   "to view files in Home folder."))
                only_downloads_dir = True
            else:
                raise

        dirs, files = self.get_dirs_and_files(only_downloads_dir, node)
        # Ajax request case (after permission check)
        if req.get_header('X-Requested-With') == 'XMLHttpRequest':
            return 'multiproject_files_tree.html', {'tree_dirs': dirs, 'tree_files': files}, None

        # Fetch information for showing dir content
        dav_url = '/'.join([self.env.abs_href().rsplit('/',1)[0], files_core.url_dav_path,
            self.env.project_identifier, ''])

        (parent_folders, current_folder,
            root_node) = self.get_breadcrumb_data(node)
        root_dirs, root_files = [], []
        if node.relative_path == '.':
            root_dirs, root_files = dirs, files
        else:
            if 'FILES_VIEW' in req.perm:
                root_dirs, root_files = root_node.get_dirs_and_files()
            elif 'FILES_DOWNLOADS_VIEW':
                root_dirs, root_files = self.get_dirs_and_files(True, root_node)

        if node.is_download():
            can_edit = 'FILES_DOWNLOADS_ADMIN' in req.perm
        else:
            can_edit = 'FILES_ADMIN' in req.perm

        files_core.order_files_and_dirs(req, node.is_download(), dirs, files)

        # Setup downloads data
        old_downloads = []
        user_by_id = {}
        if node.is_download():
            if not can_edit:
                # Show only those downloads which are available
                available_files = []
                for file in files:
                    if file.download().is_available():
                        available_files.append(file)
                files = available_files

            for file in files:
                download = file.download()
                if download.uploader_id and not user_by_id.has_key(download.uploader_id):
                    user_by_id[download.uploader_id] = user_store.getUserWhereId(
                        download.uploader_id)

            old_downloads = ProjectDownloadEntry.get_all_download_entries(node_factory.project_id,
                only_deleted=True)
            for old_download in old_downloads:
                old_download.filename = os.path.basename(old_download.download_path)
                if old_download.uploader_id and not user_by_id.has_key(old_download.uploader_id):
                    user_by_id[old_download.uploader_id] = user_store.getUserWhereId(
                        old_download.uploader_id)

        table_mode = 'no_mode'
        files_entry_class = lambda node: ''
        if target_filename:
            if current_mode:
                ok_modes = ('edit_mode', 'move_mode', 'show_mode', 'delete_mode')
                if current_mode not in ok_modes:
                    add_warning(req, _('The mode argument was not one of follows: %(list)s',
                            list=','.join(ok_modes)))
                    current_mode = 'show_mode'
                files_entry_class = lambda node: current_mode if node.filename == target_filename else ''
        else:
            if current_mode:
                ok_modes = ('move_multiple_mode', 'delete_multiple_mode', 'add_mode', 'upload_mode', 'modify_mode')
                if current_mode not in ok_modes:
                    add_warning(req, _('The mode argument was not one of follows: %(list)s',
                        list=','.join(ok_modes)))
                    current_mode = ''
                if current_mode.endswith('multiple_mode'):
                    table_mode = 'modify_mode'
                elif current_mode == 'modify_mode':
                    table_mode = 'modify_mode'
                    current_mode = 'modify_mode'
                else:
                    table_mode = current_mode
        action_row_attrs = None
        if can_edit:
            action_row_attrs = {}
            not_selected = {'row': {}, 'td': {}, 'div': {}}
            for key in ('modify_mode', 'add_mode', 'upload_mode'):
                if key == table_mode:
                    action_row_attrs[key] = {'row': {'style': 'display: table-row;'},
                                             'td': {'style': 'display: table-cell;'},
                                             'div': {'style': 'display: block;'}}
                else:
                    action_row_attrs[key] = not_selected

        data = {'dir_node': node,
                'parent_folders': parent_folders,
                'files_entry_class': files_entry_class,
                'current_folder': current_folder,
                'can_edit': can_edit,
                'target_filename': target_filename,
                'current_mode': current_mode,
                'is_current_mode': _is_current_mode,
                'current_table_mode': table_mode,
                'action_row_attrs': action_row_attrs,
                'user_by_id': user_by_id,
                'files': files,
                'dirs': dirs,
                'root_files': root_files,
                'root_dirs': root_dirs,
                'url': req.base_path,
                'dav_url': dav_url,
                'helpurl': self.config.get('multiproject', 'dav_help_url', ''),
                'old_downloads': old_downloads,
                'format_filename': format_filename,
                'get_div_class': get_div_class}

        add_stylesheet(req, 'multiproject/css/files.css')
        add_script(req, 'multiproject/js/files.js')
        if can_edit:
            add_script(req, 'multiproject/js/expand_dir.js')
        add_script_data(req, {'files_data': {
            'is_download': 1 if node.is_download() else 0
        }})

        return 'multiproject_files.html', data, None
    def show_dir(self, req, node, node_factory, files_core, user_store, target_filename="", current_mode=""):
        """
        Shows the content of a dir in a browser

        :param MappedFileNode node: mapped file node
        """
        only_downloads_dir = False
        try:
            node.require_read_perm(req.perm)
        except PermissionError as e:
            if node.relative_path == "." and "FILES_DOWNLOADS_VIEW" in req.perm:
                add_warning(req, _("You must have FILES_VIEW permission " "to view files in Home folder."))
                only_downloads_dir = True
            else:
                raise

        dirs, files = self.get_dirs_and_files(only_downloads_dir, node)
        # Ajax request case (after permission check)
        if req.get_header("X-Requested-With") == "XMLHttpRequest":
            return "multiproject_files_tree.html", {"tree_dirs": dirs, "tree_files": files}, None

        # Fetch information for showing dir content
        dav_url = "/".join(
            [self.env.abs_href().rsplit("/", 1)[0], files_core.url_dav_path, self.env.project_identifier, ""]
        )

        (parent_folders, current_folder, root_node) = self.get_breadcrumb_data(node)
        root_dirs, root_files = [], []
        if node.relative_path == ".":
            root_dirs, root_files = dirs, files
        else:
            if "FILES_VIEW" in req.perm:
                root_dirs, root_files = root_node.get_dirs_and_files()
            elif "FILES_DOWNLOADS_VIEW":
                root_dirs, root_files = self.get_dirs_and_files(True, root_node)

        if node.is_download():
            can_edit = "FILES_DOWNLOADS_ADMIN" in req.perm
        else:
            can_edit = "FILES_ADMIN" in req.perm

        files_core.order_files_and_dirs(req, node.is_download(), dirs, files)

        # Setup downloads data
        old_downloads = []
        user_by_id = {}
        if node.is_download():
            if not can_edit:
                # Show only those downloads which are available
                available_files = []
                for file in files:
                    if file.download().is_available():
                        available_files.append(file)
                files = available_files

            for file in files:
                download = file.download()
                if download.uploader_id and not user_by_id.has_key(download.uploader_id):
                    user_by_id[download.uploader_id] = user_store.getUserWhereId(download.uploader_id)

            old_downloads = ProjectDownloadEntry.get_all_download_entries(node_factory.project_id, only_deleted=True)
            for old_download in old_downloads:
                old_download.filename = os.path.basename(old_download.download_path)
                if old_download.uploader_id and not user_by_id.has_key(old_download.uploader_id):
                    user_by_id[old_download.uploader_id] = user_store.getUserWhereId(old_download.uploader_id)

        table_mode = "no_mode"
        files_entry_class = lambda node: ""
        if target_filename:
            if current_mode:
                ok_modes = ("edit_mode", "move_mode", "show_mode", "delete_mode")
                if current_mode not in ok_modes:
                    add_warning(req, _("The mode argument was not one of follows: %(list)s", list=",".join(ok_modes)))
                    current_mode = "show_mode"
                files_entry_class = lambda node: current_mode if node.filename == target_filename else ""
        else:
            if current_mode:
                ok_modes = ("move_multiple_mode", "delete_multiple_mode", "add_mode", "upload_mode", "modify_mode")
                if current_mode not in ok_modes:
                    add_warning(req, _("The mode argument was not one of follows: %(list)s", list=",".join(ok_modes)))
                    current_mode = ""
                if current_mode.endswith("multiple_mode"):
                    table_mode = "modify_mode"
                elif current_mode == "modify_mode":
                    table_mode = "modify_mode"
                    current_mode = "modify_mode"
                else:
                    table_mode = current_mode
        action_row_attrs = None
        if can_edit:
            action_row_attrs = {}
            not_selected = {"row": {}, "td": {}, "div": {}}
            for key in ("modify_mode", "add_mode", "upload_mode"):
                if key == table_mode:
                    action_row_attrs[key] = {
                        "row": {"style": "display: table-row;"},
                        "td": {"style": "display: table-cell;"},
                        "div": {"style": "display: block;"},
                    }
                else:
                    action_row_attrs[key] = not_selected

        data = {
            "dir_node": node,
            "parent_folders": parent_folders,
            "files_entry_class": files_entry_class,
            "current_folder": current_folder,
            "can_edit": can_edit,
            "target_filename": target_filename,
            "current_mode": current_mode,
            "is_current_mode": _is_current_mode,
            "current_table_mode": table_mode,
            "action_row_attrs": action_row_attrs,
            "user_by_id": user_by_id,
            "files": files,
            "dirs": dirs,
            "root_files": root_files,
            "root_dirs": root_dirs,
            "url": req.base_path,
            "dav_url": dav_url,
            "helpurl": self.config.get("multiproject", "dav_help_url", ""),
            "old_downloads": old_downloads,
            "format_filename": format_filename,
            "get_div_class": get_div_class,
        }

        add_stylesheet(req, "multiproject/css/files.css")
        add_script(req, "multiproject/js/files.js")
        if can_edit:
            add_script(req, "multiproject/js/expand_dir.js")
        add_script_data(req, {"files_data": {"is_download": 1 if node.is_download() else 0}})

        return "multiproject_files.html", data, None
    def handle_change(self, download_config, new_downloads_dir, can_be_moved,
                      node_factory, warning, notice):
        """
        :param FilesDownloadConfig download_config: download_configuration configuration
        :returns: True if new
        """
        old_node, old_dir_exists = self.get_dir_data(download_config,
                                                     node_factory)

        try:
            download_config.downloads_dir = new_downloads_dir
        except DownloadDirValidationException as e:
            raise TracError(
                _('New downloads directory is not valid: ') + str(e))

        new_node = FileSystemNode.from_path(download_config.downloads_dir,
                                            node_factory)
        if new_node.exists() and not new_node.is_dir():
            raise TracError(_('Error: Destination path exists and is a file'))
        elif new_node.exists() and can_be_moved:
            raise TracError(_("Error: Destination path already exists"))

        try:
            download_config.save()
            notice(_('Your changes have been saved.'))
        except Exception as e:
            self.log.exception('Failed to save downloads directory')
            raise TracError(_('Saving new value failed'))

        was_created = False
        if old_dir_exists and can_be_moved:
            try:
                old_node.move(new_node.relative_path)
                notice(_('Moved old downloads directory to be new one'))
                was_created = True
            except Exception as e:
                self.log.exception(
                    'Exception while moving old directory to new one')
                warning(_('Error while moving the old directory.'))
        elif not new_node.exists():
            try:
                new_node.get_parent_dir().create_dir(new_node.filename)
                notice(_('Created new downloads directory'))
                was_created = True
            except Exception as e:
                self.log.exception('Creating new downloads directory failed.')
                warning(_('Creating new downloads directory failed.'))
        else:
            # not can_be_moved
            if old_dir_exists:
                try:
                    for entry in ProjectDownloadEntry.get_all_download_entries(
                            node_factory.project_id):
                        entry.delete()
                except Exception as e:
                    warning(_("Marking files as deleted failed"))
            notice(
                _('Set the new downloads directory to be the directory chosen.'
                  ))

        return was_created