Exemple #1
0
    def setUp(self):
        # Enable debug mode always to ensure cache is disabled by default
        Globals.DevelopmentMode = True

        self.settings = getUtility(IRegistry).forInterface(IThemeSettings)
        self.settings.enabled = True

        createThemeFromTemplate(title="linked",
                                description="Generated from test")
        test_theme_name = createThemeFromTemplate(
            title="rapidotest", description="Generated from test")
        theme = getTheme(test_theme_name)
        applyTheme(theme)

        import transaction
        transaction.commit()

        self.portal = self.layer['portal']
        package_dir_path = os.path.join(test_dir_path, 'other')
        dir = FilesystemResourceDirectory(package_dir_path)
        provideUtility(dir,
                       provides=IResourceDirectory,
                       name=u'++theme++other')

        self.browser = Browser(self.layer['app'])
        self.browser.handleErrors = False
Exemple #2
0
 def test_createThemeFromTemplate_ja_unicode_title(self):
     from plone.app.theming.utils import createThemeFromTemplate
     title = u"copy of test theme by 日本語"
     description = u"test theme by 日本語"
     try:
         createThemeFromTemplate(title, description, baseOn="another-theme")
     except UnicodeEncodeError:
         self.fail(msg=u"Unicode Encode Error")
 def test_createThemeFromTemplate_ja_unicode_title(self):
     from plone.app.theming.utils import createThemeFromTemplate
     title = u"copy of test theme by 日本語"
     description = u"test theme by 日本語"
     try:
         createThemeFromTemplate(title, description,
                                         baseOn="another-theme")
     except UnicodeEncodeError:
         self.fail(msg=u"Unicode Encode Error")
def activateTheme():
    theme = getTheme('custom')

    if theme is None:
        createThemeFromTemplate('custom', '')
        theme = getTheme('custom')
        directory = queryResourceDirectory(THEME_RESOURCE_NAME, 'custom')
        try:
            directory['jbot']
        except:
            directory.makeDirectory('jbot')
            fi = open(os.path.join(TEST_FILES_DIR, 'footer2.pt'))
            directory.writeFile('jbot/' + CUSTOMIZED_RESOURCE, fi)
            fi.close()

    if getCurrentTheme() != 'custom':
        applyTheme(theme)
Exemple #5
0
    def setUp(self):
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        login(self.portal, TEST_USER_NAME)
        setRoles(self.portal, TEST_USER_ID, ('Member', 'Manager'))

        # part of setup is to always copy the theme to new one
        createThemeFromTemplate('foobar', '', 'castle.theme')
        themeData = getTheme('foobar')
        applyTheme(themeData)
        registry = getUtility(IRegistry)
        theme_settings = registry.forInterface(IThemeSettings, False)
        theme_settings.enabled = True

        directory = queryResourceDirectory('theme', 'foobar')
        directory.makeDirectory('tiles')
        self.tiles_directory = directory['tiles']

        # clear cache
        for key in list(self.request.environ.keys())[:]:
            if key.startswith(CACHE_KEY):
                del self.request.environ[key]
    def setUp(self):
        # Enable debug mode always to ensure cache is disabled by default
        Globals.DevelopmentMode = True

        self.settings = getUtility(IRegistry).forInterface(IThemeSettings)
        self.settings.enabled = True
        
        
        createThemeFromTemplate(title="linked", description="Generated from test")
        test_theme_name = createThemeFromTemplate(title="rapidotest", description="Generated from test")
        theme = getTheme(test_theme_name)
        applyTheme(theme)

        import transaction
        transaction.commit()

        self.portal = self.layer['portal']
        package_dir_path = os.path.join(test_dir_path, 'other')
        dir = FilesystemResourceDirectory(package_dir_path)
        provideUtility(
            dir, provides=IResourceDirectory, name=u'++theme++other')
            
        self.browser = Browser(self.layer['app'])
        self.browser.handleErrors = False
Exemple #7
0
    def test_createThemeFromTemplate_rel_path(self):
        from plone.app.theming.utils import createThemeFromTemplate
        from plone.app.theming.utils import getAvailableThemes
        from plone.app.theming.utils import getTheme
        from plone.app.theming.interfaces import THEME_RESOURCE_NAME
        from plone.app.theming.interfaces import RULE_FILENAME
        title = "copy of test theme with custom prefix"
        description = "test theme creation"
        themeName = createThemeFromTemplate(title,
                                            description,
                                            baseOn="another-theme")
        titles = [theme.title for theme in getAvailableThemes()]
        self.assertTrue(title in titles)

        theme = getTheme(themeName)
        expected_prefix = u"/++%s++%s" % (THEME_RESOURCE_NAME,
                                          title.replace(" ", "-"))
        self.assertEqual(theme.absolutePrefix, expected_prefix)

        expected_rules = u"/++%s++%s/%s" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"), RULE_FILENAME)
        self.assertEqual(theme.rules, expected_rules)

        self.assertEqual(theme.enabled_bundles, ['plone'])
        self.assertEqual(theme.disabled_bundles, ['foobar'])

        expected_dev_css = u"++%s++%s/less/barceloneta.plone.less" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        expected_prod_css = u"++%s++%s/less/barceloneta-compiled.css" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        expected_tinymce = u"++%s++%s/less/barceloneta-compiled.css" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        self.assertEqual(theme.development_css, expected_dev_css)
        self.assertEqual(theme.production_css, expected_prod_css)
        self.assertEqual(theme.tinymce_content_css, expected_tinymce)

        expected_dev_js = u"++%s++%s/script.js" % (THEME_RESOURCE_NAME,
                                                   title.replace(" ", "-"))
        expected_prod_js = u"++%s++%s/script.min.js" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        self.assertEqual(theme.development_js, expected_dev_js)
        self.assertEqual(theme.production_js, expected_prod_js)
    def test_createThemeFromTemplate_custom_prefix(self):
        from plone.app.theming.utils import createThemeFromTemplate
        from plone.app.theming.utils import getAvailableThemes
        from plone.app.theming.utils import getTheme
        from plone.app.theming.interfaces import THEME_RESOURCE_NAME
        from plone.app.theming.interfaces import RULE_FILENAME
        title = "copy of test theme with custom prefix"
        description = "test theme creation"
        themeName = createThemeFromTemplate(title, description,
                                            baseOn="secondary-theme")
        titles = [theme.title for theme in getAvailableThemes()]
        self.assertTrue(title in titles)

        theme = getTheme(themeName)
        expected_prefix = u"/++%s++%s" % (THEME_RESOURCE_NAME,
                                          title.replace(" ", "-"))
        self.assertEqual(theme.absolutePrefix, expected_prefix)

        expected_rules = u"/++%s++%s/%s" % (THEME_RESOURCE_NAME,
                                            title.replace(" ", "-"),
                                            RULE_FILENAME)
        self.assertEqual(theme.rules, expected_rules)

        self.assertEqual(theme.enabled_bundles, ['plone'])
        self.assertEqual(theme.disabled_bundles, ['foobar'])

        expected_dev_css = u"/++%s++%s/less/barceloneta.plone.less" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        expected_prod_css = u"/++%s++%s/less/barceloneta-compiled.css" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        expected_tinymce = u"/++%s++%s/less/barceloneta-compiled.css" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        self.assertEqual(theme.development_css, expected_dev_css)
        self.assertEqual(theme.production_css, expected_prod_css)
        self.assertEqual(theme.tinymce_content_css, expected_tinymce)

        expected_dev_js = u"/++%s++%s/script.js" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        expected_prod_js = u"/++%s++%s/script.min.js" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"))
        self.assertEqual(theme.development_js, expected_dev_js)
        self.assertEqual(theme.production_js, expected_prod_js)
Exemple #9
0
    def test_createThemeFromTemplate(self):
        from plone.app.theming.utils import createThemeFromTemplate
        from plone.app.theming.utils import getAvailableThemes
        from plone.app.theming.utils import getTheme
        from plone.app.theming.interfaces import THEME_RESOURCE_NAME
        from plone.app.theming.interfaces import RULE_FILENAME
        title = "copy of test theme"
        description = "test theme creation"
        themeName = createThemeFromTemplate(title,
                                            description,
                                            baseOn="plone.app.theming.tests")
        titles = [theme.title for theme in getAvailableThemes()]
        self.assertTrue(title in titles)

        theme = getTheme(themeName)
        expected_prefix = u"/++%s++%s" % (THEME_RESOURCE_NAME,
                                          title.replace(" ", "-"))
        self.assertEqual(theme.absolutePrefix, expected_prefix)

        expected_rules = u"/++%s++%s/%s" % (
            THEME_RESOURCE_NAME, title.replace(" ", "-"), RULE_FILENAME)
        self.assertEqual(theme.rules, expected_rules)
    def test_createThemeFromTemplate(self):
        from plone.app.theming.utils import createThemeFromTemplate
        from plone.app.theming.utils import getAvailableThemes
        from plone.app.theming.utils import getTheme
        from plone.app.theming.interfaces import THEME_RESOURCE_NAME
        from plone.app.theming.interfaces import RULE_FILENAME
        title = "copy of test theme"
        description = "test theme creation"
        themeName = createThemeFromTemplate(title, description,
                                            baseOn="plone.app.theming.tests")
        titles = [theme.title for theme in getAvailableThemes()]
        self.assertTrue(title in titles)

        theme = getTheme(themeName)
        expected_prefix = u"/++%s++%s" % (THEME_RESOURCE_NAME,
                                          title.replace(" ", "-"))
        self.assertEqual(theme.absolutePrefix, expected_prefix)

        expected_rules = u"/++%s++%s/%s" % (THEME_RESOURCE_NAME,
                                            title.replace(" ", "-"),
                                            RULE_FILENAME)
        self.assertEqual(theme.rules, expected_rules)
    def update(self):
        # XXX: complexity too high: refactoring needed
        processInputs(self.request)
        self._setup()
        self.errors = {}
        form = self.request.form

        if 'form.button.Cancel' in form:
            IStatusMessage(self.request).add(_(u"Changes cancelled"))
            self.redirect("{0}/@@overview-controlpanel".format(self.site_url))
            return False

        if 'form.button.Enable' in form:
            self.authorize()

            themeSelection = form.get('themeName', None)

            if themeSelection:
                themeData = self.getThemeData(
                    self.availableThemes,
                    themeSelection
                )
                applyTheme(themeData)
                self.theme_settings.enabled = True

            IStatusMessage(
                self.request
            ).add(
                _(
                    u"Theme enabled. Note that this control panel page is "
                    u"never themed."
                )
            )
            self._setup()
            return True

        if 'form.button.InvalidateCache' in form:
            self.authorize()
            policy = theming_policy()
            policy.invalidateCache()
            return True

        if 'form.button.Disable' in form:
            self.authorize()

            applyTheme(None)
            self.theme_settings.enabled = False

            IStatusMessage(self.request).add(_(u"Theme disabled."))
            self._setup()
            return True

        if 'form.button.AdvancedSave' in form:
            self.authorize()

            self.theme_settings.readNetwork = form.get('readNetwork', False)

            themeEnabled = form.get('themeEnabled', False)
            rules = form.get('rules', None)
            prefix = form.get('absolutePrefix', None)
            doctype = str(form.get('doctype', ""))

            hostnameBlacklist = form.get('hostnameBlacklist', [])

            parameterExpressions = {}
            parameterExpressionsList = form.get('parameterExpressions', [])

            for line in parameterExpressionsList:
                try:
                    name, expression = line.split('=', 1)
                    name = str(name.strip())
                    expression = str(expression.strip())
                    parameterExpressions[name] = expression
                except ValueError:
                    message = _(
                        'error_invalid_parameter_expressions',
                        default=u"Please ensure you enter one expression per "
                                u"line, in the format <name> = <expression>."
                    )
                    self.errors['parameterExpressions'] = message

            themeBase = form.get('themeBase', None)
            markSpecialLinks = form.get('markSpecialLinks', None)
            extLinksOpenInNewWindow = form.get('extLinksOpenInNewWindow', None)

            if not self.errors:
                # Trigger onDisabled() on plugins if theme was active
                # previously and rules were changed
                if self.theme_settings.rules != rules:
                    applyTheme(None)

                self.theme_settings.enabled = themeEnabled
                self.theme_settings.rules = rules
                self.theme_settings.absolutePrefix = prefix
                self.theme_settings.parameterExpressions = parameterExpressions
                self.theme_settings.hostnameBlacklist = hostnameBlacklist
                self.theme_settings.doctype = doctype

                # Theme base settings
                if themeBase is not None:
                    if six.PY2:
                        themeBase = themeBase.encode('utf-8')
                    self.pskin.default_skin = themeBase
                if markSpecialLinks is not None:
                    self.mark_special_links = markSpecialLinks
                if extLinksOpenInNewWindow is not None:
                    self.ext_links_open_new_window = extLinksOpenInNewWindow

                IStatusMessage(self.request).add(_(u"Changes saved"))
                self._setup()
                return True
            else:
                IStatusMessage(self.request).add(
                    _(u"There were errors"), 'error'
                )
                self.redirectToFieldset('advanced')
                return False

        if 'form.button.Import' in form:
            self.authorize()

            enableNewTheme = form.get('enableNewTheme', False)
            replaceExisting = form.get('replaceExisting', False)
            themeArchive = form.get('themeArchive', None)

            themeZip = None
            performImport = False

            try:
                themeZip = zipfile.ZipFile(themeArchive)
            except (zipfile.BadZipfile, zipfile.LargeZipFile):
                logger.exception("Could not read zip file")
                self.errors['themeArchive'] = _(
                    'error_invalid_zip',
                    default=u"The uploaded file is not a valid Zip archive"
                )

            if themeZip:

                try:
                    themeData = extractThemeInfo(themeZip, checkRules=False)
                except (ValueError, KeyError) as e:
                    logger.warn(str(e))
                    self.errors['themeArchive'] = _(
                        'error_no_rules_file',
                        u"The uploaded file does not contain a valid theme "
                        u"archive."
                    )
                else:

                    themeContainer = getOrCreatePersistentResourceDirectory()
                    themeExists = themeData.__name__ in themeContainer

                    if themeExists:
                        if not replaceExisting:
                            self.errors['themeArchive'] = _(
                                'error_already_installed',
                                u"This theme is already installed. Select "
                                u"'Replace existing theme' and re-upload to "
                                u"replace it."
                            )
                        else:
                            del themeContainer[themeData.__name__]
                            performImport = True
                    else:
                        performImport = True

            if performImport:
                themeContainer.importZip(themeZip)

                themeDirectory = queryResourceDirectory(
                    THEME_RESOURCE_NAME,
                    themeData.__name__
                )
                if themeDirectory is not None:
                    # If we don't have a rules file, use the template
                    if themeData.rules == u"/++{0:s}++{1:s}/{2:s}".format(
                        THEME_RESOURCE_NAME,
                        themeData.__name__,
                        RULE_FILENAME,
                    ) and not themeDirectory.isFile(RULE_FILENAME):
                        templateThemeDirectory = queryResourceDirectory(
                            THEME_RESOURCE_NAME,
                            TEMPLATE_THEME
                        )
                        themeDirectory.writeFile(
                            RULE_FILENAME,
                            templateThemeDirectory.readFile(RULE_FILENAME)
                        )

                        if not themeDirectory.isFile(DEFAULT_THEME_FILENAME):
                            IStatusMessage(self.request).add(
                                _(
                                    u"A boilerplate rules.xml was added to "
                                    u"your theme, but no index.html file "
                                    u"found. Update rules.xml to reference "
                                    u"the current theme file."
                                ),
                                'warning',
                            )

                    plugins = getPlugins()
                    pluginSettings = getPluginSettings(themeDirectory, plugins)
                    if pluginSettings is not None:
                        for name, plugin in plugins:
                            plugin.onCreated(
                                themeData.__name__,
                                pluginSettings[name],
                                pluginSettings
                            )

                if enableNewTheme:
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

            if not self.errors:
                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        self.site_url,
                        themeData.__name__
                    )
                )
                return False
            else:
                IStatusMessage(self.request).add(
                    _(u"There were errors"),
                    "error"
                )

                self.renderOverlay('upload')
                return True

        if 'form.button.CreateTheme' in form:
            self.authorize()

            title = form.get('title')
            description = form.get('description') or ''
            baseOn = form.get('baseOn', TEMPLATE_THEME)
            enableImmediately = form.get('enableImmediately', True)

            if not title:
                self.errors['title'] = _(u"Title is required")

                IStatusMessage(self.request).add(
                    _(u"There were errors"),
                    'error'
                )

                self.renderOverlay('new-theme')
                return True

            else:

                if any(x.__name__ == title for x in getZODBThemes()):
                    self.errors['title'] = _(u"Duplicate title")

                    IStatusMessage(self.request).add(
                        _(u"This title is already in use"),
                        'error'
                    )

                    return True

                name = createThemeFromTemplate(title, description, baseOn)
                self._setup()

                if enableImmediately:
                    themeData = self.getThemeData(self.availableThemes, name)
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        self.site_url,
                        name
                    )
                )
                return False

        if 'form.button.DeleteSelected' in form:
            self.authorize()

            toDelete = form.get('themes', [])
            themeDirectory = getOrCreatePersistentResourceDirectory()

            for theme in toDelete:
                del themeDirectory[theme]

            IStatusMessage(self.request).add(_(u"Theme deleted"), 'info')

            self._setup()
            return True

        return True
class ThemingControlpanel(BrowserView):
    def __call__(self):
        self.pskin = getToolByName(self.context, 'portal_skins')

        if self.update():
            return self.index()
        return ''

    def _setup(self):
        registry = getUtility(IRegistry)
        self.theme_settings = registry.forInterface(IThemeSettings, False)
        self.link_settings = registry.forInterface(ILinkSchema,
                                                   prefix="plone",
                                                   check=False)
        self.zodbThemes = getZODBThemes()
        self.availableThemes = getAvailableThemes()
        self.selectedTheme = self.getSelectedTheme(self.availableThemes,
                                                   self.theme_settings.rules)
        self.overlay = ''

        self.skinsVocabulary = getUtility(IVocabularyFactory,
                                          name='plone.app.vocabularies.Skins')(
                                              self.context)

        # Set response header to make sure control panel is never themed
        self.request.response.setHeader('X-Theme-Disabled', '1')

    def redirect(self, url):
        self.request.response.redirect(url)

    def get_mark_special_links(self):
        return self.link_settings.mark_special_links

    def set_mark_special_links(self, value):
        self.link_settings.mark_special_links = value

    mark_special_links = property(get_mark_special_links,
                                  set_mark_special_links)

    def get_ext_links_open_new_window(self):
        return self.link_settings.external_links_open_new_window

    def set_ext_links_open_new_window(self, value):
        self.link_settings.external_links_open_new_window = value

    ext_links_open_new_window = property(get_ext_links_open_new_window,
                                         set_ext_links_open_new_window)

    def update(self):
        # XXX: complexity too high: refactoring needed
        processInputs(self.request)
        self._setup()
        self.errors = {}
        form = self.request.form

        if 'form.button.Cancel' in form:
            IStatusMessage(self.request).add(_(u"Changes cancelled"))

            portalUrl = getToolByName(self.context, 'portal_url')()
            self.redirect("{0:s}/@@overview-controlpanel".format(portalUrl))

            return False

        if 'form.button.Enable' in form:
            self.authorize()

            themeSelection = form.get('themeName', None)

            if themeSelection:
                themeData = self.getThemeData(self.availableThemes,
                                              themeSelection)
                applyTheme(themeData)
                self.theme_settings.enabled = True

            IStatusMessage(self.request).add(
                _(u"Theme enabled. Note that this control panel page is "
                  u"never themed."))
            self._setup()
            return True

        if 'form.button.InvalidateCache' in form:
            self.authorize()
            policy = theming_policy()
            policy.invalidateCache()
            return True

        if 'form.button.Disable' in form:
            self.authorize()

            applyTheme(None)
            self.theme_settings.enabled = False

            IStatusMessage(self.request).add(_(u"Theme disabled."))
            self._setup()
            return True

        if 'form.button.AdvancedSave' in form:
            self.authorize()

            self.theme_settings.readNetwork = form.get('readNetwork', False)

            themeEnabled = form.get('themeEnabled', False)
            rules = form.get('rules', None)
            prefix = form.get('absolutePrefix', None)
            doctype = str(form.get('doctype', ""))

            hostnameBlacklist = form.get('hostnameBlacklist', [])

            parameterExpressions = {}
            parameterExpressionsList = form.get('parameterExpressions', [])

            for line in parameterExpressionsList:
                try:
                    name, expression = line.split('=', 1)
                    name = str(name.strip())
                    expression = str(expression.strip())
                    parameterExpressions[name] = expression
                except ValueError:
                    message = _(
                        'error_invalid_parameter_expressions',
                        default=u"Please ensure you enter one expression per "
                        u"line, in the format <name> = <expression>.")
                    self.errors['parameterExpressions'] = message

            themeBase = form.get('themeBase', None)
            markSpecialLinks = form.get('markSpecialLinks', None)
            extLinksOpenInNewWindow = form.get('extLinksOpenInNewWindow', None)

            if not self.errors:
                # Trigger onDisabled() on plugins if theme was active
                # previously and rules were changed
                if self.theme_settings.rules != rules:
                    applyTheme(None)

                self.theme_settings.enabled = themeEnabled
                self.theme_settings.rules = rules
                self.theme_settings.absolutePrefix = prefix
                self.theme_settings.parameterExpressions = parameterExpressions
                self.theme_settings.hostnameBlacklist = hostnameBlacklist
                self.theme_settings.doctype = doctype

                # Theme base settings
                if themeBase is not None:
                    self.pskin.default_skin = themeBase.encode('utf-8')
                if markSpecialLinks is not None:
                    self.mark_special_links = markSpecialLinks
                if extLinksOpenInNewWindow is not None:
                    self.ext_links_open_new_window = extLinksOpenInNewWindow

                IStatusMessage(self.request).add(_(u"Changes saved"))
                self._setup()
                return True
            else:
                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 'error')
                self.redirectToFieldset('advanced')
                return False

        if 'form.button.Import' in form:
            self.authorize()

            enableNewTheme = form.get('enableNewTheme', False)
            replaceExisting = form.get('replaceExisting', False)
            themeArchive = form.get('themeArchive', None)

            themeZip = None
            performImport = False

            try:
                themeZip = zipfile.ZipFile(themeArchive)
            except (
                    zipfile.BadZipfile,
                    zipfile.LargeZipFile,
            ):
                logger.exception("Could not read zip file")
                self.errors['themeArchive'] = _(
                    'error_invalid_zip',
                    default=u"The uploaded file is not a valid Zip archive")

            if themeZip:

                try:
                    themeData = extractThemeInfo(themeZip, checkRules=False)
                except (
                        ValueError,
                        KeyError,
                ), e:
                    logger.warn(str(e))
                    self.errors['themeArchive'] = _(
                        'error_no_rules_file',
                        u"The uploaded file does not contain a valid theme "
                        u"archive.")
                else:

                    themeContainer = getOrCreatePersistentResourceDirectory()
                    themeExists = themeData.__name__ in themeContainer

                    if themeExists:
                        if not replaceExisting:
                            self.errors['themeArchive'] = _(
                                'error_already_installed',
                                u"This theme is already installed. Select "
                                u"'Replace existing theme' and re-upload to "
                                u"replace it.")
                        else:
                            del themeContainer[themeData.__name__]
                            performImport = True
                    else:
                        performImport = True

            if performImport:
                themeContainer.importZip(themeZip)

                themeDirectory = queryResourceDirectory(
                    THEME_RESOURCE_NAME, themeData.__name__)
                if themeDirectory is not None:
                    # If we don't have a rules file, use the template
                    if themeData.rules == u"/++{0:s}++{1:s}/{2:s}".format(
                            THEME_RESOURCE_NAME,
                            themeData.__name__,
                            RULE_FILENAME,
                    ) and not themeDirectory.isFile(RULE_FILENAME):
                        templateThemeDirectory = queryResourceDirectory(
                            THEME_RESOURCE_NAME, TEMPLATE_THEME)
                        themeDirectory.writeFile(
                            RULE_FILENAME,
                            templateThemeDirectory.readFile(RULE_FILENAME))

                        if not themeDirectory.isFile(DEFAULT_THEME_FILENAME):
                            IStatusMessage(self.request).add(
                                _(u"A boilerplate rules.xml was added to "
                                  u"your theme, but no index.html file "
                                  u"found. Update rules.xml to reference "
                                  u"the current theme file."),
                                'warning',
                            )

                    plugins = getPlugins()
                    pluginSettings = getPluginSettings(themeDirectory, plugins)
                    if pluginSettings is not None:
                        for name, plugin in plugins:
                            plugin.onCreated(themeData.__name__,
                                             pluginSettings[name],
                                             pluginSettings)

                if enableNewTheme:
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

            if not self.errors:
                portalUrl = getToolByName(self.context, 'portal_url')()
                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        portalUrl, themeData.__name__))
                return False
            else:
                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 "error")

                self.renderOverlay('upload')
                return True

        if 'form.button.CreateTheme' in form:
            self.authorize()

            title = form.get('title')
            description = form.get('description') or ''
            baseOn = form.get('baseOn', TEMPLATE_THEME)
            enableImmediately = form.get('enableImmediately', True)

            if not title:
                self.errors['title'] = _(u"Title is required")

                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 'error')

                self.renderOverlay('new-theme')
                return True

            else:

                if any(x.__name__ == title for x in getZODBThemes()):
                    self.errors['title'] = _(u"Duplicate title")

                    IStatusMessage(self.request).add(
                        _(u"This title is already in use"), 'error')

                    return True

                name = createThemeFromTemplate(title, description, baseOn)
                self._setup()

                if enableImmediately:
                    themeData = self.getThemeData(self.availableThemes, name)
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

                portalUrl = getToolByName(self.context, 'portal_url')()
                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        portalUrl, name))
                return False

        if 'form.button.DeleteSelected' in form:
            self.authorize()

            toDelete = form.get('themes', [])
            themeDirectory = getOrCreatePersistentResourceDirectory()

            for theme in toDelete:
                del themeDirectory[theme]

            IStatusMessage(self.request).add(_(u"Theme deleted"), 'info')

            self._setup()
            return True

        return True