summaryrefslogtreecommitdiffstats
path: root/askbot/skins/loaders.py
blob: 04c398bcc8122210f0b2ee66f47e101251a46c4c (plain)
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
import os.path
from django.template.loaders import filesystem
from django.template import RequestContext
from django.http import HttpResponse
from django.utils import translation
from django.conf import settings as django_settings
from coffin.common import CoffinEnvironment
from jinja2 import loaders as jinja_loaders
from jinja2.exceptions import TemplateNotFound
from jinja2.utils import open_if_exists
from askbot.conf import settings as askbot_settings
from askbot.skins import utils

from coffin import template
template.add_to_builtins('askbot.templatetags.extra_filters_jinja')

#module for skinning askbot
#via ASKBOT_DEFAULT_SKIN configureation variable (not django setting)

#note - Django template loaders use method django.utils._os.safe_join
#to work on unicode file paths
#here it is ignored because it is assumed that we won't use unicode paths
ASKBOT_SKIN_COLLECTION_DIR = os.path.dirname(__file__)

def load_template_source(name, dirs=None):
    """Django template loader
    """
    if dirs is None:
        dirs = (ASKBOT_SKIN_COLLECTION_DIR, )
    else:
        dirs += (ASKBOT_SKIN_COLLECTION_DIR, )

    try:
        #todo: move this to top after splitting out get_skin_dirs()
        tname = os.path.join(askbot_settings.ASKBOT_DEFAULT_SKIN,'templates',name)
        return filesystem.load_template_source(tname,dirs)
    except:
        tname = os.path.join('default','templates',name)
        return filesystem.load_template_source(tname,dirs)
load_template_source.is_usable = True

class SkinLoader(jinja_loaders.BaseLoader):
    """loads template from the skin directory
    code largely copy-pasted from the jinja2 internals
    """
    def get_source(self, environment, template):
        pieces = jinja_loaders.split_template_path(template)
        skin = askbot_settings.ASKBOT_DEFAULT_SKIN
        skin_path = utils.get_path_to_skin(skin)
        filename = os.path.join(skin_path, 'templates', *pieces)
        print 'want file %s' % filename
        f = open_if_exists(filename)
        if f is None:
            raise TemplateNotFound(template)
        try:
            contents = f.read().decode('utf-8')
        finally:
            f.close()

        mtime = os.path.getmtime(filename)
        def uptodate():
            try:
                return os.path.getmtime(filename) == mtime
            except OSError:
                return False
        return contents, filename, uptodate

class SkinEnvironment(CoffinEnvironment):
    """Jinja template environment
    that loads templates from askbot skins
    """

    def __init__(self, *args, **kwargs):
        """save the skin path and initialize the
        Coffin Environment
        """
        self.skin = kwargs.pop('skin')
        super(SkinEnvironment, self).__init__(*args, **kwargs)

    def _get_loaders(self):
        """this method is not used
        over-ridden function _get_loaders that creates
        the loader for the skin templates
        """
        loaders = list()
        skin_dirs = utils.get_available_skins(selected = self.skin).values()
        template_dirs = [os.path.join(skin_dir, 'templates') for skin_dir in skin_dirs]
        loaders.append(jinja_loaders.FileSystemLoader(template_dirs))
        return loaders

    def set_language(self, language_code):
        """hooks up translation objects from django to jinja2
        environment.
        note: not so sure about thread safety here
        """
        trans = translation.trans_real.translation(language_code)
        self.install_gettext_translations(trans)

    def get_extra_css_link(self):
        """returns either the link tag (to be inserted in the html head element)
        or empty string - depending on the existence of file
        SKIN_PATH/media/style/extra.css
        """
        url = utils.get_media_url('style/extra.css')
        if url is not None:
            return '<link href="%s" rel="stylesheet" type="text/css" />' % url
        return ''

def load_skins():
    skins = dict()
    for skin_name in utils.get_available_skins():
        skins[skin_name] = SkinEnvironment(
                                skin = skin_name,
                                extensions=['jinja2.ext.i18n',]
                            )
        skins[skin_name].set_language(django_settings.LANGUAGE_CODE)
        #from askbot.templatetags import extra_filters_jinja as filters
        #skins[skin_name].filters['media'] = filters.media
    return skins

SKINS = load_skins()

def get_skin(request = None):
    """retreives the skin environment
    for a given request (request var is not used at this time)"""
    return SKINS[askbot_settings.ASKBOT_DEFAULT_SKIN]

def get_template(template, request = None):
    """retreives template for the skin
    request variable will be used in the future to set
    template according to the user preference or admins preference

    at this point request variable is not used though
    """
    skin = get_skin(request)
    return skin.get_template(template)

def render_into_skin(template, data, request, mimetype = 'text/html'):
    """in the future this function will be able to
    switch skin depending on the site administrator/user selection
    right now only admins can switch
    """
    context = RequestContext(request, data)
    template = get_template(template, request)
    return HttpResponse(template.render(context), mimetype = mimetype)