~yeliabmas/sloecode/sloecode-template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# 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
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Copyright 2012 Sloecode Developers

import logging
import os.path

from repoze.what.plugins.pylonshq import ActionProtector
from repoze.what.predicates import Any

from sloecode.lib.predicates import has_site_role, has_project_write_access
from sloecode.model.site_role import PROJECT_ADMIN


log = logging.getLogger(__name__)


def _add_single_page_fragments(fragments, view):
    """Adds fragments for single-page based views to the dict passed in."""
    try:
        fragments['last_modified_by'] = view.last_modified_by.display_name
        fragments['last_modified_date'] = view.last_modified_date
    except:
        pass
    fragments['listing_url'] = view.canonical_url(view.context.root_resource,
                                                  'listing')
    fragments['edit_url'] = view.canonical_url(view.context, 'edit')
    fragments['breadcrumbs'] = view.breadcrumbs
    # The template may be overwritten in child classes
    fragments['template'] = '/wiki/text.html'


def _get_base_fragments(app, environ):
    """Performs actions that are common to every view.

    Returns a dictionary containing values common to every view.

    """
    view = app.get_view(environ)
    #Perform any redirects if they need to happen
    view.before_render()

    parent = view.context.parent if view.context.parent else view.context
    newfile_url = view.canonical_url(parent, 'newfile')
    fragments = {
        'newfile_url': newfile_url,
    }
    return fragments, view


def _get_directory_fragments(app, environ):
    """Returns fragments for views related to directories."""
    fragments, view = _get_base_fragments(app, environ)

    fragments['breadcrumbs'] = view.breadcrumbs
    fragments['content'] = view.items
    fragments['template'] = '/wiki/directory.html'

    return fragments


def _get_missing_page_fragments(app, environ):
    """Returns fragments for views related to missing pages."""
    fragments, view = _get_base_fragments(app, environ)

    fragments['listing_url'] = view.canonical_url(view.context.root_resource,
                                                  'listing')
    fragments['edit_url'] = view.canonical_url(view.context, 'edit')
    fragments['breadcrumbs'] = view.breadcrumbs
    fragments['template'] = '/wiki/text.html'
    not_found_msg = "File not found: %s <br><a href='%s'>Create a new page</a>"
    fragments['content'] = not_found_msg % (view.title,
                                            view.canonical_url(view.context,
                                                               'edit'))

    return fragments


@ActionProtector(Any(has_site_role(PROJECT_ADMIN), has_project_write_access()))
def _get_edit_fragments(app, environ):
    """Returns fragments for views related to edit pages."""
    fragments, view = _get_base_fragments(app, environ)
    _add_single_page_fragments(fragments, view)

    fragments['content'] = view.content
    fragments['save_url'] = view.save_url
    fragments['cancel_url'] = view.cancel_url
    fragments['rev-id'] = view.rev_id
    fragments['cancel_url'] = view.cancel_url
    fragments['template'] = '/wiki/edit.html'

    # Get a list of all other files in the wiki relative to the current
    # directory.
    script_name = view.execution_context.script_name
    current_directory = view.context.dir_name
    file_list = view.context.factory.filestore.list_directory(
        directory_path='/', recursive=True)
    file_paths = []
    if file_list is not None:
        for the_file in file_list:
            if not the_file.is_directory:
                # Construct an absolute link to each file, solving a problem with relative
                # links where the relativity would be different for the pages:
                # /foo and /foo/+save (+save is the url that previews use).
                rel_path = os.path.relpath(the_file.path, current_directory)
                joined_path = os.path.join(current_directory, rel_path)
                joined_path = os.path.normpath(joined_path)
                # Remove the leading slash as it will no longer be absolute
                joined_path = joined_path[1:]
                abs_path = os.path.join(script_name, joined_path)
                file_paths.append((the_file.path, abs_path))
    # Stores a list of tuples, where the first element in the tuple
    # is the absolute path, the second element is the relative path.
    fragments['file_paths'] = file_paths

    try:
        fragments['preview'] = view.preview_content
    except:
        pass

    return fragments


def _get_root_fragments(app, environ):
    """Returns fragments for views related to the root resource."""
    fragments, view = _get_base_fragments(app, environ)
    # This will get redirected to the actual root resource.
    # Have put an explicit call to the function that redirects just in case.
    view.before_render()


def _get_source_text_fragments(app, environ):
    """Returns fragments for views related to source text pages."""
    fragments, view = _get_base_fragments(app, environ)
    _add_single_page_fragments(fragments, view)

    fragments['content'] = view.content

    return fragments


def _get_wiki_page_fragments(app, environ):
    """Returns fragments for views related to wiki pages."""
    fragments, view = _get_base_fragments(app, environ)
    _add_single_page_fragments(fragments, view)

    fragments['content'] = view.content

    return fragments


_view_map = {
    'DirectoryListingPage': _get_directory_fragments,
    'MissingPage': _get_missing_page_fragments,
    'MissingDirectory': _get_missing_page_fragments,
    'NewWikiPage': _get_edit_fragments,
    'RootPage': _get_root_fragments,
    'SourceTextPage': _get_wiki_page_fragments,
    'EditTextFile': _get_edit_fragments,
    'UpdateTextFile': _get_edit_fragments,
    'SaveNewTextFile': _get_edit_fragments,
    'WikiPage': _get_wiki_page_fragments,
}


def get_page_fragments(app, environ, view_name=None):
    """Returns a dictionary containing the page fragments required for the
    passed environ.

    Also performs any redirects that need to happen for the view.

    Returns None if view is not in dictionary.

    """
    if view_name is None:
        view_name = app.get_view(environ).__class__.__name__
    log.info("View: %s" % view_name)
    if view_name in _view_map:
        return _view_map[view_name](app, environ)
    return None