def create_section(path, parent_path=None, name='', title='', keywords='', description='', theme='', is_private=False, is_default=False, redirect_to='', new_window=False, force=False): path = path.replace('/', '-').replace(' ', '-').strip() if path else None parent_path = parent_path.replace('/', '-').replace(' ', '-').strip() if parent_path else None if not force and not can_path_exist(path, parent_path): return None if is_default: try: old_default = Section.query(Section.is_default == True).fetch(1)[0] old_default.is_default=False old_default.put() except: pass # Probably no sections yet max_rank = 0 for item, _ in get_children(parent_path): if item['rank'] <= max_rank: max_rank = item['rank'] + 1 default_theme = configuration.default_theme() if not default_theme: default_theme = template.DEFAULT_LOCAL_THEME_TEMPLATE if theme == default_theme: theme = '' section = Section(parent=section_key(path), path=path, parent_path=parent_path, rank=max_rank, name=name, title=title, keywords=keywords, description=description, theme=(theme if theme != template.DEFAULT_LOCAL_THEME_TEMPLATE else ''), is_private=is_private, redirect_to=redirect_to, new_window=new_window, is_default=is_default) section.put() cache.delete(CACHE_KEY_HIERARCHY) return section
def action_edit(self): if self.section.handler.request.get('submit'): self.SITE_HEADER = self.section.handler.request.get('SITE_HEADER') self.SITE_SUB_HEADER = self.section.handler.request.get('SITE_SUB_HEADER') self.DEFAULT_THEME = self.section.handler.request.get('DEFAULT_THEME') self.GOOGLE_ANALYTICS_UA = self.section.handler.request.get('GOOGLE_ANALYTICS_UA') self.ROBOTS_TXT = self.section.handler.request.get('ROBOTS_TXT') if self.section.handler.request.get('FAVICON_ICO'): data = db.Blob(self.section.handler.request.get('FAVICON_ICO')) if self.FAVICON_ICO: self.FAVICON_ICO.data = data else: self.FAVICON_ICO = File(filename='favicon.ico', content_type='image/x-icon', data=data) self.FAVICON_ICO.put() self.ENABLE_THEME_PREVIEW = self.section.handler.request.get('ENABLE_THEME_PREVIEW') != '' self.DEBUG_MODE = self.section.handler.request.get('DEBUG_MODE') != '' cache.delete(CACHE_KEY) self.update() raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'text', 'SITE_HEADER', self.SITE_HEADER, 'Site header', 50)) f.add_control(control(self.section, 'text', 'SITE_SUB_HEADER', self.SITE_SUB_HEADER, 'Site sub-header', 50)) combined_themes = get_local_theme_namespaces() + get_custom_theme_namespaces() f.add_control(selectcontrol(self.section, 'DEFAULT_THEME', combined_themes, self.DEFAULT_THEME if self.DEFAULT_THEME else DEFAULT_LOCAL_THEME_TEMPLATE, 'Default theme')) f.add_control(control(self.section, 'text', 'GOOGLE_ANALYTICS_UA', self.GOOGLE_ANALYTICS_UA, 'Google analytics UA')) f.add_control(control(self.section, 'file', 'FAVICON_ICO', label='favicon.ico')) f.add_control(textareacontrol(self.section, 'ROBOTS_TXT', self.ROBOTS_TXT, 'robots.txt', 90, 5)) f.add_control(checkboxcontrol(self.section, 'ENABLE_THEME_PREVIEW', self.ENABLE_THEME_PREVIEW, 'Enable theme preview')) f.add_control(checkboxcontrol(self.section, 'DEBUG_MODE', self.DEBUG_MODE, 'Debug mode')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '<h2>Edit configuration</h2>%s' % unicode(f)
def remove(self): """ Calling this method makes sure cache is cleaned up as well as any subclass level cleanup before deleting """ cache.delete(CACHE_KEY_PREPEND + str(content_key(self.__class__.__name__, self.section_path, self.namespace))) self.on_remove() self.delete()
def delete_section(section): if section.is_default: raise Exception('Cannot delete default page without appointing another page first') elif get_children(section.path): raise Exception('Cannot delete a page with children without reparenting them first') content.delete_section_path_content(section.path) cache.delete(CACHE_KEY_HIERARCHY) section.key.delete()
def action_edit(self): if self.section.handler.request.get('submit'): self.SITE_HEADER = self.section.handler.request.get('SITE_HEADER') self.SITE_SUB_HEADER = self.section.handler.request.get( 'SITE_SUB_HEADER') self.DEFAULT_THEME = self.section.handler.request.get( 'DEFAULT_THEME') self.GOOGLE_ANALYTICS_UA = self.section.handler.request.get( 'GOOGLE_ANALYTICS_UA') self.ROBOTS_TXT = self.section.handler.request.get('ROBOTS_TXT') if self.section.handler.request.get('FAVICON_ICO'): if self.FAVICON_ICO: BlobInfo.get(self.FAVICON_ICO).delete() data = self.section.handler.request.get('FAVICON_ICO') handle = files.blobstore.create( mime_type='image/x-icon', _blobinfo_uploaded_filename='favicon.ico') with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) self.FAVICON_ICO = files.blobstore.get_blob_key(handle) self.ENABLE_THEME_PREVIEW = self.section.handler.request.get( 'ENABLE_THEME_PREVIEW') != '' self.DEBUG_MODE = self.section.handler.request.get( 'DEBUG_MODE') != '' cache.delete(CACHE_KEY) self.update() raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control( control(self.section, 'text', 'SITE_HEADER', self.SITE_HEADER, 'Site header', 50)) f.add_control( control(self.section, 'text', 'SITE_SUB_HEADER', self.SITE_SUB_HEADER, 'Site sub-header', 50)) combined_themes = get_local_theme_namespaces( ) + get_custom_theme_namespaces() f.add_control( selectcontrol( self.section, 'DEFAULT_THEME', combined_themes, self.DEFAULT_THEME if self.DEFAULT_THEME else DEFAULT_LOCAL_THEME_TEMPLATE, 'Default theme')) f.add_control( control(self.section, 'text', 'GOOGLE_ANALYTICS_UA', self.GOOGLE_ANALYTICS_UA, 'Google analytics UA')) f.add_control( control(self.section, 'file', 'FAVICON_ICO', label='favicon.ico')) f.add_control( textareacontrol(self.section, 'ROBOTS_TXT', self.ROBOTS_TXT, 'robots.txt', 90, 5)) f.add_control( checkboxcontrol(self.section, 'ENABLE_THEME_PREVIEW', self.ENABLE_THEME_PREVIEW, 'Enable theme preview')) f.add_control( checkboxcontrol(self.section, 'DEBUG_MODE', self.DEBUG_MODE, 'Debug mode')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '<h2>Edit configuration</h2>%s' % unicode(f)
def on_delete(self): for i in range(len(self.filenames)): # This can be done more efficiently via GQL data = self.get_file(self.filenames[i]) cache.delete(CACHE_KEY_PREPEND + self.file_keys[i]) data.delete() del self.file_keys[i] del self.filenames[i] self.update()
def remove(self): ''' Calling this method makes sure cache is cleaned up as well as any subclass level cleanup before deleting ''' cache.delete(CACHE_KEY_PREPEND + str( content_key(self.__class__.__name__, self.section_path, self.namespace))) self.on_remove() self.key.delete()
def get_favicon_ico(): item = get_configuration() if not item.FAVICON_ICO: data = file('framework/content/configuration/assets/images/favicon.ico', 'r').read() favicon = File(filename='favicon.ico', content_type='image/x-icon', data=data) favicon.put() item.FAVICON_ICO = favicon item.update() cache.delete(CACHE_KEY) raise Exception('SendFileBlob', item.FAVICON_ICO)
def update_section(old, path, parent_path, name, title, keywords, description, theme, is_private, is_default, redirect_to, new_window): path = path.replace('/', '-').replace(' ', '-').strip() if path else None parent_path = parent_path.replace('/', '-').replace(' ', '-').strip() if parent_path else None default_theme = configuration.default_theme() if not default_theme: default_theme = template.DEFAULT_LOCAL_THEME_TEMPLATE if theme == default_theme: theme = '' if old.is_default: # Cannot change the default page except if another page is promoted is_default = True elif not old.is_default and is_default: old_default = Section.query(Section.is_default == True).fetch(1)[0] if old_default.path != old.path: old_default.is_default = False old_default.put() can_path_exist(path, parent_path, old.path) if old.path != path: for child in Section.query(Section.parent_path == old.path).fetch(): child.parent_path = path child.put() content.rename_section_paths(old.path, path) new = Section(parent=section_key(path), path=path, parent_path=parent_path, rank=old.rank, name=name, title=title, keywords=keywords, description=description, theme=theme, is_private=is_private, is_default=is_default, redirect_to=redirect_to, new_window=new_window) old.key.delete() new.put() cache.delete(CACHE_KEY_HIERARCHY) return new elif old.parent_path != parent_path: # Rerank old's siblings to account for its removal by pushing it to the end of the old sibling list update_section_rank(old, len(get_siblings(old.path))) # Make it the last of its new siblings max_rank = 0 for item, _ in get_children(parent_path): if item['rank'] <= max_rank: max_rank = item['rank'] + 1 old.rank = max_rank old.parent_path = parent_path old.name = name old.title = title old.keywords = keywords old.description = description old.theme = theme old.is_private = is_private old.is_default = is_default old.redirect_to = redirect_to old.new_window = new_window old.put() cache.delete(CACHE_KEY_HIERARCHY) return old
def get_favicon_ico(): item = get_configuration() if not item.FAVICON_ICO: data = file('framework/content/configuration/assets/images/favicon.ico', 'r').read() handle = files.blobstore.create(mime_type='image/x-icon', _blobinfo_uploaded_filename='favicon.ico') with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) item.FAVICON_ICO = files.blobstore.get_blob_key(handle) item.update() cache.delete(CACHE_KEY) raise Exception('SendFileBlob', BlobInfo.get(item.FAVICON_ICO).open().read(), 'image/x-icon')
def update_section_rank(section, new_rank): larger, smaller = max(section.rank, new_rank), min(section.rank, new_rank) for sibling in Section.query(Section.parent_path == section.parent_path, Section.rank >= smaller, Section.rank <= larger).fetch(): if sibling.rank < section.rank: sibling.rank += 1 elif sibling.rank > section.rank: sibling.rank -= 1 sibling.put() section.rank = new_rank section.put() cache.delete(CACHE_KEY_HIERARCHY)
def on_remove(self): for i in range(len(self.theme_namespaces)): # This can be done more efficiently via GQL theme = self.get_theme(self.theme_namespaces[i]) cache.delete(CACHE_KEY_PREPEND + self.theme_namespaces[i]) for key in theme.image_keys: cache.delete(CACHE_KEY_PREPEND + str(key)) BlobInfo.get(key).delete() theme.key.delete() del self.theme_keys[i] del self.theme_namespaces[i] self.update()
def on_delete(self): for i in range(len(self.theme_namespaces)): # This can be done more efficiently via GQL theme = self.get_theme(self.theme_namespaces[i]) cache.delete(CACHE_KEY_PREPEND + self.theme_namespaces[i]) for key in theme.image_keys: data = File.get(key) cache.delete(CACHE_KEY_PREPEND + key) data.delete() theme.delete() del self.theme_keys[i] del self.theme_namespaces[i] self.update()
def action_delete(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): for key in theme.image_keys: cache.delete(CACHE_KEY_PREPEND + str(key)) BlobInfo.get(key).delete() self.theme_keys.remove(theme.key) self.theme_namespaces.remove(theme.namespace) theme.key.delete() self.update() cache.flush_all() # Flush all cached resources for this theme which is important for sections where it is active raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'submit', 'submit', 'Confirm')) return '<div class="status warning">Are you sure you wish to delete theme "%s" and all associated resources?</div>%s' % (theme.namespace, unicode(f))
def action_delete(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') filename = self.section.path_params[0] if self.section.handler.request.get('submit'): data = self.get_file(filename) if not data: raise Exception('NotFound') index = self.filenames.index(filename) cache.delete(CACHE_KEY_PREPEND + self.file_keys[index]) data.delete() del self.file_keys[index] del self.filenames[index] self.update() raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'submit', 'submit', 'Confirm')) return '<div class="status warning">Are you sure you wish to delete file "%s" from "%s"?</div>%s' % (filename, self.section.path, unicode(f))
def get_favicon_ico(): item = get_configuration() if not item.FAVICON_ICO: data = file( 'framework/content/configuration/assets/images/favicon.ico', 'r').read() handle = files.blobstore.create( mime_type='image/x-icon', _blobinfo_uploaded_filename='favicon.ico') with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) item.FAVICON_ICO = files.blobstore.get_blob_key(handle) item.update() cache.delete(CACHE_KEY) raise Exception('SendFileBlob', BlobInfo.get(item.FAVICON_ICO).open().read(), 'image/x-icon')
def action_add_image(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): filename = self.section.handler.request.POST['data'].filename content_type = self.section.handler.request.POST['data'].type data = db.Blob(self.section.handler.request.get('data')) key = File(filename=filename, data=data, content_type=content_type, section_path=self.section.path).put() theme.image_filenames.append(filename) theme.image_keys.append(str(key)) theme.put() cache.delete(CACHE_KEY_PREPEND + str(theme.key())) raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'file', 'data', label='Image')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '<h2>Add image</h2>%s' % unicode(f)
def action_delete(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') filename = self.section.path_params[0] if self.section.handler.request.get('submit'): data = self.get_file(filename) if not data: raise Exception('NotFound') index = self.filenames.index(filename) cache.delete(CACHE_KEY_PREPEND + str(self.file_keys[index])) data.delete() del self.file_keys[index] del self.filenames[index] self.update() raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'submit', 'submit', 'Confirm')) return '<div class="status warning">Are you sure you wish to delete file "%s" from "%s"?</div>%s' % ( filename, self.section.path, unicode(f))
def action_delete(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): for key in theme.image_keys: cache.delete(CACHE_KEY_PREPEND + str(key)) BlobInfo.get(key).delete() self.theme_keys.remove(theme.key) self.theme_namespaces.remove(theme.namespace) theme.key.delete() self.update() cache.flush_all( ) # Flush all cached resources for this theme which is important for sections where it is active raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'submit', 'submit', 'Confirm')) return '<div class="status warning">Are you sure you wish to delete theme "%s" and all associated resources?</div>%s' % ( theme.namespace, unicode(f))
def action_delete_image(self): if not self.section.path_params or len(self.section.path_params) != 2: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) filename = self.section.path_params[1] if filename not in theme.image_filenames: raise Exception('NotFound') if self.section.handler.request.get('submit'): index = theme.image_filenames.index(filename) data = BlobInfo.get(theme.image_keys[index]) cache.delete(CACHE_KEY_PREPEND + str(theme.image_keys[index])) data.delete() del theme.image_keys[index] del theme.image_filenames[index] theme.put() cache.delete(CACHE_KEY_PREPEND + str(theme.key)) raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'submit', 'submit', 'Confirm')) return '<div class="status warning">Are you sure you wish to delete "%s"?</div>%s' % (filename, unicode(f))
def action_delete_image(self): if not self.section.path_params or len(self.section.path_params) != 2: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) filename = self.section.path_params[1] if filename not in theme.image_filenames: raise Exception('NotFound') if self.section.handler.request.get('submit'): index = theme.image_filenames.index(filename) data = BlobInfo.get(theme.image_keys[index]) cache.delete(CACHE_KEY_PREPEND + str(theme.image_keys[index])) data.delete() del theme.image_keys[index] del theme.image_filenames[index] theme.put() cache.delete(CACHE_KEY_PREPEND + str(theme.key)) raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'submit', 'submit', 'Confirm')) return '<div class="status warning">Are you sure you wish to delete "%s"?</div>%s' % ( filename, unicode(f))
def action_add_image(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): filename = self.section.handler.request.POST['data'].filename content_type = self.section.handler.request.POST['data'].type data = self.section.handler.request.get('data') handle = files.blobstore.create(mime_type=content_type, _blobinfo_uploaded_filename=filename) with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) key = files.blobstore.get_blob_key(handle) theme.image_filenames.append(filename) theme.image_keys.append(key) theme.put() cache.delete(CACHE_KEY_PREPEND + str(theme.key)) raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'file', 'data', label='Image')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '<h2>Add image</h2>%s' % unicode(f)
def action_add_image(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): filename = self.section.handler.request.POST['data'].filename content_type = self.section.handler.request.POST['data'].type data = self.section.handler.request.get('data') handle = files.blobstore.create( mime_type=content_type, _blobinfo_uploaded_filename=filename) with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) key = files.blobstore.get_blob_key(handle) theme.image_filenames.append(filename) theme.image_keys.append(key) theme.put() cache.delete(CACHE_KEY_PREPEND + str(theme.key)) raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'file', 'data', label='Image')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '<h2>Add image</h2>%s' % unicode(f)
def on_remove(self): for key in self.file_keys: cache.delete(CACHE_KEY_PREPEND + str(key)) BlobInfo.get(key).delete() self.update()
def update(self): cache.delete(CACHE_KEY_PREPEND + str(content_key(self.__class__.__name__, self.section_path, self.namespace))) return self.put()
def rename_theme_namespace_template(old, new): for s in Section.query(Section.theme == old): s.theme = new s.put() cache.delete(CACHE_KEY_HIERARCHY)
def update(self): cache.delete(CACHE_KEY_PREPEND + str( content_key(self.__class__.__name__, self.section_path, self.namespace))) return self.put()