def editor_roles_source(): roles = [Term(value=None, token='', title=_(u"-- Choose a role --"))] for role in roleinfo.AUTHOR_ROLES: roles.append(Term(value=role, token=role, title=_(role))) return Vocabulary(roles)
def goto_column(settings, screen, cfg): if settings.folder_goto_menu: info = {'view': 'goto', 'index': {'screen': 'content', 'caption': screen.translate(_(u"Go to"))}, 'menu': [{'screen': 'preview', 'caption': screen.translate(_(u"Preview"))}, {'screen': 'properties', 'caption': screen.translate(_(u"Properties")), 'item_match': ['not', ['equal', 'access', None]]}, {'screen': 'publish', 'caption': screen.translate(_(u"Publish")), 'item_match': ['and', ['not', ['equal', 'access', None]], ['provides', 'versioned']]}, {'screen': 'settings/access', 'caption': screen.translate(_(u"Access")), 'item_match': ['and', ['equal', 'access', 'manage'], ['provides', 'container']]}]} cfg.add(info, GOTO_WIDTH)
def GET(self, intid=None, interface=None, show_index=False): self.prepare() if intid is not None: try: content = self.intid.getObject(int(intid)) except KeyError: # Invalid content id return self.json_response( { "id": "broken", "type": "Broken", "intid": "0", "url": "", "path": "", "icon": self.get_icon(None), "implements": False, "folderish": False, "title": self.translate(_(u"Missing content")), "short_title": self.translate(_(u"Missing content")), } ) return self.json_response(self.get_item_details(content)) require = interfaces.ISilvaObject if interface is not None: require = getUtility(IInterface, name=interface) return self.json_response(self.get_context_details(require=require, show_index=show_index))
def authenticated_role_vocabulary(): terms = [SimpleTerm(value=None, token='None', title=_(u'select:')), SimpleTerm(value='Authenticated', token='Authenticated', title=_('Authenticated'))] _add_silva_role(terms) return SimpleVocabulary(terms)
def __call__(self, form, authorization, line): data, errors = form.extractData(form.fields) if errors: return silvaforms.FAILURE role = data['role'] if not role: return form.revoke(authorization, line) mapping = {'role': role, 'username': authorization.identifier} try: if authorization.grant(role): form.send_message( _('Role "${role}" granted to user "${username}".', mapping=mapping), type="feedback") else: form.send_message( _('User "${username}" already has the role "${role}".', mapping=mapping), type="error") except UnauthorizedRoleAssignement as error: form.send_message( _(u'Sorry, you are not allowed to grant the role "${role}" ' u'to user "${username}": ${reason}.', mapping={'role': error.role, 'username': error.identifier, 'reason': error.reason}), type="error") return silvaforms.SUCCESS
def __call__(self, form): data, errors = form.extractData() if errors: return silvaforms.FAILURE groupname = data.getDefault('group').strip() service = component.getUtility(IGroupService) groups = set() new_groups = set() try: for group in service.find_groups(groupname, location=form.context): groupid = group.groupid() groups.add(groupid) new_groups.add(groupid) except MemberLookupError as error: form.send_message(error.args[0], type="error") return silvaforms.FAILURE store = SessionStore(form.request) if new_groups: groups = store.get(GROUP_STORE_KEY, set()).union(groups) store.set(GROUP_STORE_KEY, groups) form.send_message( _(u"Found ${count} groups: ${groups}.", mapping={'count': len(new_groups), 'groups': u', '.join(new_groups)}), type="feedback") else: form.send_message( _(u"No matching groups found."), type="error") return silvaforms.FAILURE return silvaforms.SUCCESS
def dtformat(request, formatdate, currentdate=None): """Format a datetime object into a nice human like string. """ if currentdate is None: currentdata = datetime.now() dt = currentdate - formatdate if isinstance(dt, float): # XXX args are zope's DateTime instances rather than datetimes... dt = timedelta(dt) if dt.days > 28: return str(formatdate) parts = dtformat_timedelta(request, dt) # translation helper def _(str, **kwargs): kwargs['context'] = request kwargs['domain'] = 'silvaforum' return translate(str, **kwargs) if not parts: return _('Just added') if len(parts) > 2: str_format = ', '.join(parts[:-1]) return _('Added ${time} ago', mapping={'time': str_format}) else: str_format = ', '.join(parts) return _('Added ${time} ago', mapping={'time': str_format})
def render(self, view=None): content = self.content if content is None: return _(u'Content reference is broken or missing.') block_view = queryMultiAdapter((content, self.request), IBlockView) if block_view is None: return _(u'Content is not viewable.') return block_view()
def GET(self): """Return a message after the user successfully logged in. """ return self.json_response({ 'content': { 'ifaces': ['message'], 'title': self.translate(_(u'Logged in')), 'message': self.translate(_(u'You are now authenticated.'))}})
def get_orientation(self): """Returns translated Image orientation (string). """ width, height = self.get_dimensions() if width == height: return _("square") elif width > height: return _("landscape") return _("portrait")
def __call__(self, form): manager = IOrderManager(form.context, None) if manager is not None: if manager.repair(form.context.objectValues()): form.send_message(_("Container order was repaired."), type=u"feedback") return silvaforms.SUCCESS form.send_message(_("Container order is consistent."), type=u"feedback") return silvaforms.SUCCESS
def url_validation(content): if content.relative and not content.target: raise interface.Invalid( _(u"Relative link selected without target.")) if not content.relative and not content.url: raise interface.Invalid( _(u"Absolute link selected without URL. " u"If the link goes to an internal item in Silva, " u"put a checkmark in the relative link field."))
def sort_order_source(): orders = [] for key, title in [ ('silva', _(u'Silva folder order')), ('alpha', _(u'Alphabetically')), ('reversealpha', _(u'Reverse alphabetically')), ('chronmod', _(u'Chronologically by modification date')), ('rchronmod', _(u'Reverse chronologically by modification date'))]: orders.append(SimpleTerm(value=key, token=key, title=title)) return SimpleVocabulary(orders)
def __verify_copyable(self, content): if not content.cb_isCopyable(): return ContainerError( _(u"You are unauthorized to copy this content."), content) if content.meta_type not in self.__addables: return ContainerError( _(u"You cannot add this content type in this container."), content) return None
def _status_to_string(self, status): if status == self.CONTAINS_BAD_CHARS: return _(u'The id contains strange characters. It should only ' u'contain letters, digits and ‘_’ or ‘-’ or ‘.’ ' u'Spaces are not allowed and the id should start ' u'with a letter or digit.') elif status == self.RESERVED_PREFIX: prefix = str(self._maybe_id).split('_')[0]+'_' return _(u"ids starting with ${prefix} are reserved for " u"internal use.", mapping={'prefix': prefix}) elif status == self.RESERVED: return _(u"The id ${id} is reserved for internal use.", mapping={'id': self._maybe_id}) elif status == self.IN_USE_CONTENT: return _(u"There is already an object with the id ${id} in this " u"container.", mapping={'id': self._maybe_id}) elif status == self.IN_USE_ASSET: return _(u"There is already an asset with the id ${id} in this " u"container.", mapping={'id': self._maybe_id}) elif status == self.RESERVED_POSTFIX: return _(u"The id ${id} ends with invalid characters.", mapping={'id': self._maybe_id}) elif status == self.IN_USE_ZOPE: return _(u"The id ${id} is already in use by a Zope object.", mapping={'id': self._maybe_id}) elif status == self.RESERVED_FOR_CONTENT: return _("The id ${id} cannot be used for a content of this " u"type.", mapping={'id': self._maybe_id}) return _(u"(Internal Error): An invalid status ${status_code} occured " u"while checking the id ${id}.", mapping={'status_code': status, 'id': self._maybe_id})
def delete_site(self): if not self.is_site(): raise ValueError(_(u'Not a local site.')) if interfaces.IRoot.providedBy(self.context): raise ValueError(_(u"Can't disable local site on Silva Root.")) sm = ISite(self.context).getSiteManager() if list(sm.registeredAdapters()): raise ValueError(_(u'Still have registered customizations.')) if list(sm.registeredUtilities()): raise ValueError(_(u'Still have registered services.')) disableSite(self.context)
def remove(self): values, errors = self.extractData() if not values.get("usedMarkers", None): self.send_message(_(u"You need to select a marker."), type=u"error") return silvaforms.FAILURE manager = IMarkManager(self.context) for value in values["usedMarkers"]: manager.remove_marker(value) self.send_message(_(u"Marker removed."), type=u"feedback") return silvaforms.SUCCESS
def validate_slot_identifier(value, form): if value is silvaforms.NO_VALUE: return _(u'Identifier required.') if not VALIDATE_SLOT_ID_RE.match(value): return _(u'Invalid identifier.') slots = form.context.slots if value in slots: current_slot = form.getContentData().getContent().block if current_slot != slots[value]: return _(u'A slot with that identifier already exists.') return None
def reindex(self): data, errors = self.extractData() if errors: return path = data['path'] try: self.context.reindex_subtree(path) except KeyError: self.status = _(u"Invalid path") else: self.status = _(u"Partial catalog refreshed")
def subscribability_options(context): options = [] settings = ISubscriptionManager(context) for value, title in [ (ACQUIRE_SUBSCRIBABILITY, _(u"Acquire settings from above")), (NOT_SUBSCRIBABLE, _(u"Disable subscriptions")), (SUBSCRIBABLE, _(u"Enable subscriptions")), ]: if value in settings.subscribability_possibilities: options.append(SimpleTerm(value=value, token=str(value), title=title)) return SimpleVocabulary(options)
def save(self): self.errors = self.binding.setValuesFromRequest( self.request, reindex=1) if self.errors: self.send_message(_( 'The data that was submitted did not ' 'validate properly. Please adjust ' 'the form values and submit again.'), type='error') return silvaforms.FAILURE self.send_message(_('Metadata saved.'), type='feedback') return silvaforms.SUCCESS
def add(self): data, errors = self.extractData() if errors: self.send_message(_(u'There were errors'), type='error') return silvaforms.FAILURE name = data['config'] factory = self.context.manage_addProduct['silva.core.editor'] factory.manage_addCKEditorConfiguration(name) self.send_message(_(u'Configuration for ${name} added.', mapping=dict(name=name)), type='feedback') return silvaforms.SUCCESS
def acquire(self): access = self.getContentData().getContent() if access.is_acquired(): self.send_message( _(u"The minimum role setting was already acquired."), type="error") else: access.set_acquired() self.send_message( _(u"Now acquiring the minimum role setting."), type="feedback") return silvaforms.SUCCESS
def __call__(self, form): folder = form.context if folder.get_link_status() is not None: form.send_message(_(u"Ghost Folder was not synchronized, " u"because the target is invalid."), type="error") return silvaforms.FAILURE try: folder.haunt() except ContentError as error: form.send_message(error.reason, type="error") return silvaforms.FAILURE else: form.send_message(_(u"Ghost Folder synchronized."), type="feedback") return silvaforms.SUCCESS
def POST(self): service = getUtility(IReferenceService) for reference in list(service.get_references_to(self.context)): reference.set_target_id(0) return self.json_response({ 'content': { 'ifaces': ['message'], 'title': self.translate(_(u"References broken")), 'message': self.translate( _(u"References to ${content} (${path}) have been broken.", mapping={'content': self.context.get_title_or_id(), 'path': self.get_content_path(self.context)})) }})
def description(self): if IGhostFolder.providedBy(self.context): return _(u'This Ghost Folder can be converted ' u'to a normal Publication or Folder. All ghosted content ' u'will be duplicated and can then be edited.') elif IPublication.providedBy(self.context): if self.manager.is_site(): return _(u"This Silva Publication is a local site. You need to " u"remove any local service, and the local site before " u"you can convert it to a Silva Folder.") return _(u'This Silva Publication can be converted ' u'to a Silva Folder, or can become a local site.') return _(u'This Silva Folder can be converted ' u'to a Publication.')
def deactivate(self): root = self.getPhysicalRoot() if not interfaces.IForestApplication.providedBy(root): raise ValueError( _(u"The feature is not activated.")) path = getattr(root, '__silva__', tuple()) if path != self.get_silva_path(): raise ValueError( _(u"The feature is activated by an another Silva site.")) silva_root = self.get_root() notify(events.ForestWillBeDeactivatedEvent(root, silva_root, self)) delattr(root, '__silva__') noLongerProvides(root, interfaces.IForestApplication) notify(events.ForestDeactivatedEvent(root, silva_root, self))
def __call__(self, form): data, errors = form.extractData() if errors: form.status = _(u"Sorry, there were errors.") return silvaforms.FAILURE background = data['background'] name = data['name'] logo = data['logo'] maintenance_message = data['maintenance_message'] public_url = data['public_url'] preview_url = data['preview_url'] preview_use_resolutions = data['preview_use_resolutions'] preview_resolutions = data['preview_resolutions'] notifications_life = data['notifications_life'] smi_access_root = data['smi_access_root'] smi_link_zmi = data['smi_link_zmi'] if notifications_life is not silvaforms.NO_VALUE: form.context.notifications_life = notifications_life else: form.context.notifications_life = 4000 if background != silvaforms.NO_VALUE: form.context.background = background else: form.context.background = None if logo != silvaforms.NO_VALUE: if logo != silvaforms.NO_CHANGE: form.context.logo = ZopeImage('logo', 'SMI Logo', logo) else: form.context.logo = None if maintenance_message is not silvaforms.NO_VALUE: form.context.maintenance_message = maintenance_message else: form.context.maintenance_message = None if public_url is not silvaforms.NO_VALUE: form.context.public_url = public_url else: form.context.public_url = None if preview_url is not silvaforms.NO_VALUE: form.context.preview_url = preview_url else: form.context.preview_url = None form.context.preview_use_resolutions = preview_use_resolutions if preview_resolutions is silvaforms.NO_VALUE: preview_resolutions = [] form.context.smi_link_zmi = smi_link_zmi form.context.preview_resolutions = preview_resolutions form.context.smi_access_root = smi_access_root form.context.name = name form.status = _(u"Modification saved.") return silvaforms.SUCCESS
def workflow_column(settings, screen, cfg): status = {'published': screen.translate( _(u"Published: this item is published and viewable by the public.")), 'closed': screen.translate( _(u"Closed: this item is no longer accessible to the public.")), 'pending': screen.translate( _(u"Pending: this item is waiting for approval.")), 'draft': screen.translate( _(u"Draft: this item is a working copy.")), 'approved': screen.translate( _(u"Approved: this item is approved for publication at a later time."))} info = {'name': 'status_public', 'view': 'workflow', 'status': status} cfg.add(info, PUBLIC_STATE_WIDTH) info = {'name': 'status_next', 'view': 'workflow', 'status': status} cfg.add(info, NEXT_STATE_WIDTH)
def extract(self): value = self.request.form.get(self.identifier, u'') if value == "__NO_CHANGE__": return NO_CHANGE, None if not value: return NO_VALUE, None manager = self.request.environ.get('infrae.fileupload.manager') if manager is None: raise interfaces.Error('The upload component is not available') bucket = manager.access_upload_bucket(value) if bucket is not None: if not bucket.is_complete(): return NO_VALUE, _(u"Upload is incomplete.") return UploadedFile(bucket), None return NO_VALUE, _(u"Upload failed.")
class Ghost(VersionedContent): __doc__ = _("""Ghosts are special documents that function as a placeholder for an item in another location (like an alias, symbolic link, shortcut). Unlike a hyperlink, which takes the Visitor to another location, a ghost object keeps the Visitor in the current publication, and presents the content of the ghosted item. The ghost inherits properties from its location (e.g. layout and stylesheets). """) meta_type = "Silva Ghost" security = ClassSecurityInfo() grok.implements(IGhost) silvaconf.icon('icons/ghost.png') silvaconf.version_class(GhostVersion) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_haunted') def get_haunted(self): version = self.get_previewable() if version is not None: return version.get_haunted() return None security.declareProtected(SilvaPermissions.AccessContentsInformation, 'is_published') def is_published(self): public = self.get_viewable() if public is None: return False haunted = public.get_haunted() if haunted is None: return False return haunted.is_published() security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_modification_datetime') def get_modification_datetime(self): """Return modification datetime. """ version = self.get_viewable() if version is not None: content = version.get_haunted() if content is not None: return content.get_modification_datetime() return super(Ghost, self).get_modification_datetime()
def get_crop_box(self, crop=None): """return crop box""" crop = crop or self.web_crop if crop is None or crop.strip() == '': return None rect = Rect.parse(crop) if rect is None: msg = _("'${crop} is not a valid crop identifier", mapping={'crop': crop}) raise ValueError(msg) with ImageFile(self.hires_image) as image: Crop(rect).validate(image) return (rect.lower_edge.x, rect.lower_edge.y, rect.higher_edge.x, rect.higher_edge.y)
def set_next_version_publication_datetime(self, dt): """Set publication datetime of next version. """ if self._approved_version[0]: version_id, publication_datetime, expiration_datetime = \ self._approved_version self._approved_version = version_id, dt, expiration_datetime self._update_publication_status() elif self._unapproved_version[0]: version_id, publication_datetime, expiration_datetime = \ self._unapproved_version self._unapproved_version = version_id, dt, expiration_datetime else: raise VersioningError(_('No next version.'), self)
class PartialReindexForm(silvaforms.ZMIForm): """From to partially reindex a part of the site. """ grok.name('manage_partialReindex') fields = silvaforms.Fields(IPartialReindex) fields['path'].defaultValue = lambda form: '/'.join(form.context.get_root( ).getPhysicalPath()) label = _("Reindex site") description = _("Reindex a subtree of the site in the Silva Catalog." "For big trees this may take a long time.") @silvaforms.action(_("Reindex")) def reindex(self): data, errors = self.extractData() if errors: return path = data['path'] try: self.context.reindex_subtree(path) except KeyError: self.status = _("Invalid path") else: self.status = _("Partial catalog refreshed")
class GhostAssetEditForm(silvaforms.SMISubForm): """ Edit form Ghost Folder """ grok.context(IGhostAsset) grok.view(AssetEditTab) grok.order(10) label = _('Edit ghost') ignoreContent = False dataManager = silvaforms.SilvaDataManager dataValidators = [TargetValidator('haunted', IAsset, adding=False)] fields = silvaforms.Fields(IGhostAssetSchema).omit('id') actions = silvaforms.Actions(silvaforms.CancelEditAction(), silvaforms.EditAction())
class GhostAssetAddForm(silvaforms.SMIAddForm): """ Add form for ghost folders """ grok.name(u'Silva Ghost Asset') fields = silvaforms.Fields(IGhostAssetSchema) fields['haunted'].referenceNotSetLabel = _( u"Click the Lookup button to select an asset to haunt.") dataValidators = [TargetValidator('haunted', IAsset, adding=True)] def _add(self, parent, data): factory = parent.manage_addProduct['Silva'] return factory.manage_addGhostAsset(data['id'], None, haunted=data['haunted'])
class ImageFormatAndScalingForm(silvaforms.SMISubForm): """ form to resize / change format of image. """ grok.context(IImage) grok.view(AssetEditTab) grok.order(20) ignoreContent = False dataManager = silvaforms.SilvaDataManager label = _('Format and scaling') actions = silvaforms.Actions(silvaforms.CancelEditAction()) fields = silvaforms.Fields(IFormatAndScalingFields) fields['web_format'].mode = 'radio' fields['web_scale'].defaultValue = '100%' @silvaforms.action( title=_('Change'), description=_('Scale and/or crop the image with the new settings'), implements=silvaforms.IDefaultAction) def set_properties(self): data, errors = self.extractData() if errors: return silvaforms.FAILURE try: self.context.set_web_presentation_properties( data.getWithDefault('web_format'), data.getWithDefault('web_scale'), data.getWithDefault('web_crop')) except ValueError as e: self.send_message(e.args[0], type='error') return silvaforms.FAILURE notify(ObjectModifiedEvent(self.context)) self.send_message(_('Scaling and/or format changed.'), type='feedback') return silvaforms.SUCCESS
def publish(self): # Do the same job than approve, but works on closed content as # well. if not self.context.get_unapproved_version(): if self.context.is_published(): raise VersioningError( _("There is no unapproved version to approve."), self.context) self.context.create_copy() current = self.context.get_unapproved_version_publication_datetime() if current is None or current.isFuture(): # If the publication date is in the future, set it correct to now. self.context.set_unapproved_version_publication_datetime(DateTime()) self.context.approve_version() return True
def close_version(self): """Close public version. """ if self._public_version == empty_version: raise VersioningError( _(u"There is no public version to close."), self) previous_versions = self._previous_versions or [] previous_versions.append(self._public_version) self._public_version = empty_version self._previous_versions = previous_versions version = self._getOb(self._previous_versions[-1][0]) notify(events.ContentClosedEvent(version))
def deleter(self): to_delete = [] container_ids = set(self.context.objectIds()) try: protected = self.context._reserved_names except: protected = () content = yield while content is not None: try: content.is_deletable() except ContentError as error: result = error else: content_id = content.getId() if (content_id in container_ids and content_id not in protected and aq_base(self.context) is aq_base(aq_parent(content))): to_delete.append((content_id, content)) result = content else: result = ContentError(_("Cannot delete content."), content) content = yield result # Event for identifier, content in to_delete: compatibilityCall('manage_beforeDelete', content, content, self.context) notify(ObjectWillBeRemovedEvent(content, self.context, identifier)) # Delete for identifier, content in to_delete: self.context._objects = tuple( [i for i in self.context._objects if i['id'] != identifier]) self.context._delOb(identifier) try: content._v__object_deleted__ = 1 except: pass # Event for identifier, content in to_delete: notify(ObjectRemovedEvent(content, self.context, identifier)) if to_delete: notifyContainerModified(self.context)
class ContainerView(silvaviews.View): """Default view for containers. """ grok.context(IContainer) unavailable_message = _(u'This container has no index.') def render(self): default = self.context.get_default() if default is None: return self.unavailable_message view = queryMultiAdapter((default, self.request), name="content.html") if view is None: return self.unavailable_message if IView.providedBy(view) and view.content is None: return self.unavailable_message return view()
def set_properties(self): data, errors = self.extractData() if errors: return silvaforms.FAILURE try: self.context.set_web_presentation_properties( data.getWithDefault('web_format'), data.getWithDefault('web_scale'), data.getWithDefault('web_crop')) except ValueError as e: self.send_message(e.args[0], type='error') return silvaforms.FAILURE notify(ObjectModifiedEvent(self.context)) self.send_message(_('Scaling and/or format changed.'), type='feedback') return silvaforms.SUCCESS
def renamer(self): any_renames = False data = yield while data is not None: content, to_identifier, to_title = data result = None # Rename identifier from_identifier = content.getId() if to_identifier is not None and from_identifier != to_identifier: result = self.__verify_moveable(content) if result is None: try: ISilvaNameChooser(self.context).checkName( to_identifier, content) except ContentError as e: result = ContainerError(reason=e.reason, content=content) if result is None: content = self.__move(content, self.context, from_identifier, to_identifier) any_renames = True # Update title if to_title is not None: if not isinstance(to_title, str): to_title = to_title.decode('utf-8') editable = content.get_editable() if editable is None: if result is None: result = ContentError( _("There is no editable version to set the title on." ), content) elif editable.get_title() != to_title: try: editable.set_title(to_title) except ContentError as error: result = error if result is None: result = content data = yield result if any_renames: notifyContainerModified(self.context)
def dtformat_timedelta(request, dt): """Format a timedelta object in a nice human like string. """ # calculate time units weeks = int(dt.days / 7) days = dt.days % 7 hours = int(dt.seconds / 3600) seconds = dt.seconds % 3600 minutes = int(seconds / 60) # translation helper def _(str, **kwargs): kwargs['context'] = request kwargs['domain'] = 'silvaforum' return translate(str, **kwargs) ret = [] if weeks: if weeks == 1: ret.append(_('one week')) else: ret.append(_('${number} weeks', mapping={'number': weeks})) if days: if days == 1: ret.append(_('one day')) else: ret.append(_('${number} days', mapping={'number': days})) if hours: if hours == 1: ret.append(_('one hour')) else: ret.append(_('${number} hours', mapping={'number': hours})) if minutes: if minutes == 1: ret.append(_('one minute')) else: ret.append(_('${number} minutes', mapping={'number': minutes})) return ret
def query(self, querypath): """Return a dictionary with path -> node mappings matching the querypath. querypath has the syntax name1/name2/... and each name can be * for any children tag or ** for any children tag in the complete subtree and it can look like "one|or|theother" which would match tags named eitehr 'one', 'or' or 'theother'. The implementation uses the regular expression module. """ # compile regular expression match-string l = [] for i in querypath.split('/'): if i == '*': l.append(r'[^/]+') elif i == '**': l.append(r'.+') elif '*' in i: message = _("intermingling * is not allowed ${i}", mapping={'i': i}) raise ValueError(message) elif '|' in i: l.append("(%s)" % i) else: l.append(i) searchstring = "/".join(l) + '$' rex = re.compile(searchstring) # apply regex to all paths dic = {} for path, tag in build_pathmap(self): line = "/".join(path) if rex.match(line): dic.setdefault(line, []).append(tag) return dic
def make_editable(self): """Make the version editable. """ current_version = self.content.get_unapproved_version() if current_version is not None: # move the current editable version to _previous_versions if self.content.is_approval_requested(): raise VersioningError( _('A version is already waiting approval.'), self) version_tuple = self.content._unapproved_version if self.content._previous_versions is None: self.content._previous_versions = [] self.content._previous_versions.append(version_tuple) self.content._unapproved_version = (None, None, None) self.content.create_copy(version_id=self.version.id) return True
def save(self): data, errors = self.extractData() source_data, source_errors = self.source.extractData() if errors or source_errors: return silvaforms.FAILURE try: content = self._add(self.context, data) except ValueError as error: self.send_message(error.args[0], type="error") return silvaforms.FAILURE editable = content.get_editable() factory = getWrapper(editable, IExternalSourceManager) source = factory(self.request, name=self.source.getSourceId()) source.create() editable.set_parameters_identifier(source.getId()) notify(ObjectModifiedEvent(content)) self.send_message(_("Source Asset added."), type="feedback") raise RedirectToPage(content=content)
class ImageAddForm(silvaforms.SMIAddForm): """Add form for an image. """ grok.context(IImage) grok.name('Silva Image') fields = silvaforms.Fields(IImageAddFields) fields['id'].required = False fields['id'].validateForInterface = IImage fields['image'].fileNotSetLabel = _( "Click the Upload button to select an image.") def _add(self, parent, data): default_id = data['id'] is not NO_VALUE and data['id'] or '' factory = parent.manage_addProduct['Silva'] return factory.manage_addImage(default_id, data['title'], file=data['image'])
def endElementNS(self, name, qname): if name == (NS_SILVA_URI, 'ghost_asset'): importer = self.getExtra() asset = self.result() haunted = self.getData('haunted') if not haunted: importer.reportProblem(_('Missing ghost target.'), asset) else: def set_target(target): problem = self._getManager(ghost=asset).validate(target) if problem is not None: importer.reportProblem(problem.doc(), asset) else: asset.set_haunted(target) importer.resolveImportedPath(asset, set_target, haunted) self.notifyImport()
def haunt(self): """populate the the ghost folder with ghosts """ haunted = self.get_haunted() if haunted is None: return False stack = self._haunt_diff(haunted, self) errors = [] while stack: # breadth first search h_container, h_id, g_container, g_id = stack.pop(0) if h_id is None: # object was removed from haunted, so just remove it and # continue g_container.manage_delObjects([g_id]) continue h_ob = h_container._getOb(h_id) g_ob = None if g_id is not None: g_ob = g_container._getOb(g_id) try: g_ob = get_factory(h_ob)(ghost=g_ob, container=g_container, auto_delete=True, auto_publish=True).modify( h_ob, h_id).verify() except ContentError as error: errors.append(error) if IContainer.providedBy(h_ob) and g_ob is not None: stack.extend(self._haunt_diff(h_ob, g_ob)) if errors: raise ContentErrorBundle(_( u"Error while synchronizing the Ghost Folder: " u"not all its content have been updated properly."), content=self, errors=errors) return True
class SourceAssetEditForm(silvaforms.SMIEditForm): grok.context(ISourceAsset) actions = silvaforms.Actions(silvaforms.CancelEditAction()) readOnly = False def update(self): editable = self.context.get_editable() if editable is not None: self.controller = editable.get_controller(self.request) else: self.controller = self.context.get_viewable().get_controller( self.request) self.readOnly = True def updateWidgets(self): super(SourceAssetEditForm, self).updateWidgets() if self.controller is not None: self.fieldWidgets.extend( self.controller.fieldWidgets(ignoreRequest=self.readOnly, ignoreContent=False, display=self.readOnly)) @property def formErrors(self): if self.controller is not None: return self.controller.formErrors return [] def isEditable(self): return (self.controller is not None and not self.readOnly and self.controller.mode != silvaforms.DISPLAY) @silvaforms.action(_("Save"), available=isEditable, implements=silvaforms.IDefaultAction, accesskey='ctrl+s') def save(self): status = self.controller.save() if status is silvaforms.SUCCESS: self.send_message(_("Changes saved."), type="feedback") return status
class GhostView(silvaviews.View): grok.context(IGhost) broken_message = _(u"This content is unavailable. " u"Please inform the site manager.") def render(self): haunted = self.content.get_haunted() if haunted is None: return self.broken_message permission = self.is_preview and 'Read Silva content' or 'View' if not getSecurityManager().checkPermission(permission, haunted): raise Unauthorized(u"You do not have permission to " u"see the target of this ghost") view = queryMultiAdapter((haunted, self.request), name="content.html") if view is None: return self.broken_message if IView.providedBy(view) and view.content is None: return self.broken_message return view()
def endElementNS(self, name, qname): if name == (NS_SILVA_URI, 'content'): importer = self.getExtra() version = self.result() haunted = self.getData('haunted') if not haunted: importer.reportProblem(_('Missing ghost target.'), version) else: def set_target(target): problem = self._getManager( ghost=version.get_silva_object()).validate(target) if problem is not None: importer.reportProblem(problem.doc(), version) else: version.set_haunted(target) importer.resolveImportedPath(version, set_target, haunted) self.updateVersionCount() self.storeWorkflow()
class IExportOptions(Interface): include_publications = schema.Bool( title=_(u"Include sub publications?"), description=_(u"Check to export all sub publications. "), default=False, required=False) others_contents = schema.Bool( title=_(u"Include other contents?"), description=_(u"Check to export content not providing an XML " u"export functionality. This can cause problems."), default=True, required=False) only_previewable = schema.Bool( title=_(u"Export only newest versions?"), description=_(u"If not checked all versions are exported."), default=True, required=False) external_references = schema.Bool( title=_(u'Allow content refering not exported one to be exported?'), description=_(u"If checked, export content refering " u"not exported one without error."), default=False, required=False)
class SyncAction(silvaforms.Action): description = _("Synchronize target and ghost folder content") ignoreRequest = True def available(self, form): return checkPermission('silva.ChangeSilvaContent', form.context) def __call__(self, form): folder = form.context if folder.get_link_status() is not None: form.send_message(_('Ghost Folder was not synchronized, ' 'because the target is invalid.'), type='error') return silvaforms.FAILURE try: folder.haunt() except ContentError as error: form.send_message(error.reason, type='error') return silvaforms.FAILURE else: form.send_message(_('Ghost Folder synchronized.'), type='feedback') return silvaforms.SUCCESS
class FileTextEditForm(silvaforms.SMISubForm): """Edit content as a text file. """ grok.context(IFile) grok.view(AssetEditTab) grok.order(20) label = _(u'Edit text content') ignoreContent = False dataManager = silvaforms.SilvaDataManager fields = silvaforms.Fields(IFileTextFields) actions = silvaforms.Actions(silvaforms.CancelEditAction(), silvaforms.EditAction()) def available(self): if self.context.is_text_editable(): try: unicode(self.context.get_text()) return True except (UnicodeDecodeError, TypeError): return False return False
def render(self): error = None try: # Try to fetch the controller. controller = self.content.get_controller(self.request) except SourceError as error: error = error else: try: # Try to render the source. return controller.render() except SourceError as error: error = error # Render the error if it returns something. message = silvaviews.render(error, self.request).strip() if message: return message # Return the default text used by the layout otherwise (this # happens with the source is published, you don't have any # details). text = _('Sorry, this ${meta_type} is not viewable.', mapping={'meta_type': self.context.meta_type}) return '<p>%s</p>' % translate(text, context=self.request)
def get_image(self, hires=True, webformat=False): """Return image data. """ if hires: if self.hires_image is not None: if webformat: # Create web format of original image. with ImageFile(self.hires_image) as working: data = working.save(self.web_format) if data is not None: return data.getvalue() # Original format of the original image is the orginal. return self.hires_image.get_file() return None if self.image is not None: if webformat: # Webformat of the cropped/resized image is already computed. return self.image.get_file() # Original format of the cropped/resize image is not possible. raise ValueError( _(u"Low resolution image in original format is " u"not supported")) return None
class EditTabBlockAction(silvaforms.Action): grok.implements(silvaforms.IDefaultAction, silvaforms.IRESTExtraPayloadProvider, silvaforms.IRESTCloseOnSuccessAction) title = _('Save changes') def get_extra_payload(self, form): # This is kind of an hack, but the name of the form is the block id. return { 'block_id': form.__name__, 'block_data': form.getContent().render(), 'block_editable': True } def __call__(self, form): data, errors = form.extractData() if errors: return silvaforms.FAILURE manager = form.getContentData() manager.set('content', data.getWithDefault('content')) form.send_message(_(u"Tab component modified.")) notify(ObjectModifiedEvent(form.context)) return silvaforms.SUCCESS
class IFormatAndScalingFields(Interface): web_format = schema.Choice(source=image_formats, title=_("Web format"), description=_("Image format for web.")) web_scale = schema.TextLine( title=_("Scaling"), description=_('Image scaling for web: use width x ' 'height in pixels, or one axis length, ' 'or a percentage (100x200, 100x*, *x200, 40%).' 'Use 100% to scale back to the orginal format.'), required=False) web_crop = silvaschema.CropCoordinates( title=_("Cropping"), description=_("Image cropping for web: use the" " ‘set crop coordinates’ " "button, or enter X1xY1-X2xY2" " to define the cropping box."), required=False)