Esempio n. 1
0
def selector(request, keep_files=None):
    if settings.LOCAL_THEME:
        raise ESPError(THEME_ERROR_STRING, log=False)

    context = {}
    tc = ThemeController()

    if request.method == 'POST' and 'action' in request.POST:
        if request.POST['action'] == 'select':
            theme_name = request.POST['theme'].replace(' (current)', '')

            #   Check for differences between the theme's files and those in the working copy.
            #   If there are differences, require a confirmation from the user for each file.
            differences = tc.check_local_modifications(theme_name)
            if len(differences) > 0 and keep_files is None:
                return confirm_overwrite(request, current_theme=theme_name, differences=differences, orig_view='selector')

            #   Display configuration form if one is provided for the selected theme
            if tc.get_config_form_class(theme_name) is not None:
                return configure(request, current_theme=theme_name, force_display=True, keep_files=keep_files)

            tc.save_customizations('%s-last' % tc.get_current_theme())
            backup_info = tc.clear_theme(keep_files=keep_files)
            tc.load_theme(theme_name, backup_info=backup_info)
        elif request.POST['action'] == 'clear':
            tc.save_customizations('%s-last' % tc.get_current_theme())
            tc.clear_theme()

    context['theme_name'] = tc.get_current_theme()
    context['themes'] = tc.get_theme_names()
    return render_to_response('themes/selector.html', request, context)
Esempio n. 2
0
def confirm_overwrite(request, current_theme=None, differences=None, orig_view=None):
    """ Display a form asking the user which local modified files
        they would like to keep, and which they would like to overwrite
        with the ones from the theme data.  """

    if settings.LOCAL_THEME:
        raise ESPError(THEME_ERROR_STRING, log=False)

    context = {}
    tc = ThemeController()

    if current_theme is None:
        current_theme = request.POST.get('theme', '')

    if request.method == 'POST' and request.POST.get('confirm_overwrite', '0') == '1':
        files_to_keep = []
        diffs_current = tc.check_local_modifications(current_theme)

        #   Build a list of filenames that we are not supposed to overwrite.
        for entry in diffs_current:
            post_key = 'overwrite_%s' % entry['filename_hash']
            post_val = request.POST.get(post_key, None)
            if post_val is not None:
                if post_val != 'overwrite':
                    files_to_keep.append(entry['filename'])

        #   Continue with the original view (typically the theme selector).
        view_func = selector
        if request.POST.get('orig_view', '') == 'recompile':
            view_func = recompile
        return view_func(request, keep_files=files_to_keep)

    #   Display the form asking the user which files to keep/overwrite.
    if differences is None:
        differences = tc.check_local_modifications(current_theme)

    context['theme_name'] = current_theme
    context['differences'] = differences
    context['orig_view'] = orig_view
    return render_to_response('themes/confirm_overwrite.html', request, context)
Esempio n. 3
0
def recompile(request, keep_files=None):
    if settings.LOCAL_THEME:
        raise ESPError(THEME_ERROR_STRING, log=False)

    tc = ThemeController()

    #   Check for differences between the theme's files and those in the working copy.
    #   If there are differences, require a confirmation from the user for each file.
    theme_name = tc.get_current_theme()
    differences = tc.check_local_modifications(theme_name)
    if len(differences) > 0 and keep_files is None:
        return confirm_overwrite(request, current_theme=theme_name, differences=differences, orig_view='recompile')

    tc.recompile_theme(keep_files=keep_files)
    return HttpResponseRedirect('/themes/')
Esempio n. 4
0
    def testSelector(self):
        """ Check that theme selector functionality is working. """

        self.client.login(username=self.admin.username, password='******')

        #   Get a ThemeController for identifying available themes.
        tc = ThemeController()

        #   Get the home page (this is a fresh site) and make sure it has a link to the theme landing.
        response = self.client.get('/')
        self.assertTrue(len(re.findall(r'<a href="/themes.*?Configure site appearance.*?</a>', response.content, flags=re.DOTALL)) == 1)

        #   Go to the themes landing page and theme selector, make sure neither errors out.
        response = self.client.get('/themes/')
        self.assertEqual(response.status_code, 200)
        response = self.client.get('/themes/select/')
        self.assertEqual(response.status_code, 200)

        # Move the existing images dir out of the way, so we don't conflict
        # with it (either what the user has there, or between themes).
        # TODO(benkraft): Do the same for styles and scripts, although in
        # practice conflicts there are less likely.
        # TODO(benkraft): This is a super hacky way to do things!  Instead we
        # should be doing all these tests in some sort of tmpdir to avoid
        # touching anything of the user's.
        images_dir = os.path.join(settings.MEDIA_ROOT, 'images', 'theme')
        # Really we should use a tempdir, but on vagrant it may be on a
        # different file system, which causes problems, so we do a hackier
        # thing instead.
        images_backup_dir = os.path.join(settings.MEDIA_ROOT, 'images',
                                         'theme_backup_for_tests')
        if os.path.exists(images_dir):
            os.rename(images_dir, images_backup_dir)

        try:
            #   Test each theme that is available.
            for theme_name in tc.get_theme_names():
                #   Delete the theme_compiled.css file so we force a new one to be generated.
                css_filename = os.path.join(settings.MEDIA_ROOT, 'styles', themes_settings.COMPILED_CSS_FILE)
                if os.path.exists(css_filename):
                    os.remove(css_filename)
                # Clobber any stray theme images dir, to avoid conflicts.
                # Note that we've already backed up any one the user had
                # created, above.
                if os.path.exists(images_dir):
                    shutil.rmtree(images_dir)

                # Make sure there won't be any conflicts between this theme and
                # existing files -- since they would cause harder-to-understand
                # errors later on.
                self.assertFalse(tc.check_local_modifications(theme_name))

                #   POST to the theme selector with our choice of theme
                response = self.client.post('/themes/select/', {'action': 'select', 'theme': theme_name})
                self.assertEqual(response.status_code, 200)

                #   Supply more settings if the theme asks for them.
                if '<form id="theme_setup_form"' in response.content:
                    field_matches = re.findall(r'<(input id="\S+"|textarea).*?name="(\S+)".*?>', response.content, flags=re.DOTALL)
                    #   This is the union of all the theme configuration settings that
                    #   have a non-trivial form (e.g. key = value fails validation).
                    settings_dict = {
                        'theme': theme_name,
                        'just_selected': 'True',
                        'front_page_style': 'bubblesfront.html',
                        'facebook_link': 'http://somehost.net',
                        'nav_structure': '[{"header": "header", "header_link": "/header_link/", "links": [{"link": "link1", "text": "text1"}]}]',
                    }
                    for entry in field_matches:
                        if entry[1] not in settings_dict:
                            #   Supply value = key if we do not already know what to say
                            settings_dict[entry[1]] = entry[1]

                    #   If theme setup succeeded, we will be redirected to the landing page.
                    response = self.client.post('/themes/setup/', settings_dict, follow=True)
                    self.assertTrue(('http://testserver/themes/', 302) in response.redirect_chain)

                #   Check that the CSS stylesheet has been included in the page.
                self.assertTrue('/media/styles/theme_compiled.css' in response.content)

                #   Check that the CSS stylesheet has been compiled.
                self.assertTrue(os.path.exists(css_filename))
                self.assertTrue(len(open(css_filename).read()) > 1000)  #   Hacky way to check that content is substantial

                #   Check that the template override is marked with the theme name.
                self.assertTrue(('<!-- Theme: %s -->' % theme_name) in response.content)

            #   Test that the theme can be cleared and the home page reverts.
            response = self.client.post('/themes/select/', {'action': 'clear'})
            response = self.client.get('/')
            self.assertTrue(len(re.findall(r'<a href="/themes.*?Configure site appearance.*?</a>', response.content, flags=re.DOTALL)) == 1)

            self.client.logout()

        finally:
            # Restore the backed up images dir.
            if os.path.exists(images_dir):
                shutil.rmtree(images_dir)
            if os.path.exists(images_backup_dir):
                os.rename(images_backup_dir, images_dir)