def parse_indico_id(indico_id): event_match = re.match('(\d+)$', indico_id) session_match = re.match('(\d+)s(\d+)$', indico_id) contrib_match = re.match('(\d+)c(\d+)$', indico_id) subcontrib_match = re.match('(\d+)c(\d+)sc(\d+)$', indico_id) if subcontrib_match: event = Event.get(subcontrib_match.group(1), is_deleted=False) if not event: return None return SubContribution.find( SubContribution.id == subcontrib_match.group(3), ~SubContribution.is_deleted, SubContribution.contribution.has(event=event, id=subcontrib_match.group(2), is_deleted=False)).first() elif session_match: event = Event.get(session_match.group(1), is_deleted=False) return Session.query.with_parent(event).filter_by( id=session_match.group(2)).first() elif contrib_match: event = Event.get(contrib_match.group(1), is_deleted=False) return Contribution.query.with_parent(event).filter_by( id=contrib_match.group(2)).first() elif event_match: return Event.get(event_match.group(1), is_deleted=False) else: return None
def test_deleted_relationships(db, dummy_event): event = dummy_event assert not event.contributions assert not event.sessions s = Session(event=event, title='s') sd = Session(event=event, title='sd', is_deleted=True) c = Contribution(event=event, title='c', session=sd, duration=timedelta(minutes=30)) cd = Contribution(event=event, title='cd', session=sd, duration=timedelta(minutes=30), is_deleted=True) sc = SubContribution(contribution=c, title='sc', duration=timedelta(minutes=10)) scd = SubContribution(contribution=c, title='scd', duration=timedelta(minutes=10), is_deleted=True) db.session.flush() db.session.expire_all() # reload all the objects from the db event = Event.get(event.id) s = Session.get(s.id) sd = Session.get(sd.id) c = Contribution.get(c.id) cd = Contribution.get(cd.id) sc = SubContribution.get(sc.id) scd = SubContribution.get(scd.id) # deleted items should not be in the lists assert event.sessions == [s] assert event.contributions == [c] assert sd.contributions == [c] assert c.subcontributions == [sc] # the other direction should work fine even in case of deletion assert s.event == event assert sd.event == event assert c.event == event assert cd.event == event assert sc.contribution == c assert scd.contribution == c
def _process_args(self): self.event = Event.get(int(request.view_args['confId'])) if self.event is None: raise NotFound(_('An event with this ID does not exist.')) elif self.event.is_deleted: raise NotFound(_('This event has been deleted.')) self._conf = self._target = self.event.as_legacy
def _checkParams(self, params): self.event_new = Event.get(int(params['confId'])) if self.event_new is None: raise NotFound(_(u'An event with this ID does not exist.')) elif self.event_new.is_deleted: raise NotFound(_(u'This event has been deleted.')) self._conf = self._target = self.event_new.as_legacy
def event_or_shorturl(event_id, shorturl_namespace=False, force_overview=False): event = Event.get(int(event_id)) if event_id.isdigit() and (event_id[0] != '0' or event_id == '0') else None if event and event.is_deleted: raise NotFound(_('This event has been deleted.')) elif event: # For obvious reasons an event id always comes first. # If it's used within the short url namespace we redirect to the event namespace, otherwise # we call the RH to display the event if shorturl_namespace: return redirect(event.url) elif not request.path.endswith('/'): return redirect(event.url, 301) else: request.view_args['event_id'] = int(event_id) return RHDisplayEvent().process() else: shorturl_event = (Event.query .filter(db.func.lower(Event.url_shortcut) == event_id.lower(), ~Event.is_deleted) .one_or_none()) if (shorturl_namespace or config.ROUTE_OLD_URLS) and shorturl_event: if shorturl_namespace: # Correct namespace => redirect to the event return redirect(shorturl_event.url) else: # Old event namespace => 301-redirect to the new shorturl first to get Google etc. to update it return redirect(shorturl_event.short_url, 301) elif is_legacy_id(event_id): mapping = LegacyEventMapping.query.filter_by(legacy_event_id=event_id).first() if mapping is not None: url = url_for('events.display', event_id=mapping.event_id) return redirect(url, 301) raise NotFound(_('An event with this ID/shortcut does not exist.'))
def _getParams(self): super(NoteExportHook, self)._getParams() event = self._obj = Event.get(self._pathParams['event_id'], is_deleted=False) if event is None: raise HTTPAPIError('No such event', 404) session_id = self._pathParams.get('session_id') if session_id: self._obj = Session.query.with_parent(event).filter_by(id=session_id).first() if self._obj is None: raise HTTPAPIError("No such session", 404) contribution_id = self._pathParams.get('contribution_id') if contribution_id: contribution = self._obj = (Contribution.query.with_parent(event) .filter_by(id=contribution_id, is_deleted=False) .first()) if contribution is None: raise HTTPAPIError("No such contribution", 404) subcontribution_id = self._pathParams.get('subcontribution_id') if subcontribution_id: self._obj = SubContribution.query.with_parent(contribution).filter_by(id=subcontribution_id, is_deleted=False).first() if self._obj is None: raise HTTPAPIError("No such subcontribution", 404) self._note = EventNote.get_for_linked_object(self._obj, preload_event=False) if self._note is None or self._note.is_deleted: raise HTTPAPIError("No such note", 404)
def event_or_shorturl(confId, shorturl_namespace=False, force_overview=False): func = None event_ = Event.get(int(confId)) if confId.isdigit() else None if event_ and event_.is_deleted: raise NotFound(_('This event has been deleted.')) elif event_: # For obvious reasons an event id always comes first. # If it's used within the short url namespace we redirect to the event namespace, otherwise # we call the RH to display the event if shorturl_namespace: func = lambda: redirect(event_.url) else: request.view_args['confId'] = int(request.view_args['confId']) func = lambda: RHDisplayEvent().process() else: shorturl_event = (Event.query.filter( db.func.lower(Event.url_shortcut) == confId.lower(), ~Event.is_deleted).one_or_none()) if (shorturl_namespace or config.ROUTE_OLD_URLS) and shorturl_event: if shorturl_namespace: # Correct namespace => redirect to the event func = lambda: redirect(shorturl_event.url) else: # Old event namespace => 301-redirect to the new shorturl first to get Google etc. to update it func = lambda: redirect(shorturl_event.short_url, 301) elif is_legacy_id(confId): mapping = LegacyEventMapping.find_first(legacy_event_id=confId) if mapping is not None: url = url_for('events.display', confId=mapping.event_id) func = lambda: redirect(url, 301) if func is None: raise NotFound(_('An event with this ID/shortcut does not exist.')) return func()
def _has_access(self, user): event = Event.get(self._eventId, is_deleted=False) if event: can_manage = user is not None and event.can_manage(user) if not can_manage and not contribution_settings.get(event, 'published'): return False return True
def _getParams(self): super()._getParams() event = self._obj = Event.get(self._pathParams['event_id'], is_deleted=False) if event is None: raise HTTPAPIError('No such event', 404) session_id = self._pathParams.get('session_id') if session_id: self._obj = Session.query.with_parent(event).filter_by( id=session_id).first() if self._obj is None: raise HTTPAPIError("No such session", 404) contribution_id = self._pathParams.get('contribution_id') if contribution_id: contribution = self._obj = ( Contribution.query.with_parent(event).filter_by( id=contribution_id, is_deleted=False).first()) if contribution is None: raise HTTPAPIError("No such contribution", 404) subcontribution_id = self._pathParams.get('subcontribution_id') if subcontribution_id: self._obj = SubContribution.query.with_parent( contribution).filter_by(id=subcontribution_id, is_deleted=False).first() if self._obj is None: raise HTTPAPIError("No such subcontribution", 404) self._note = EventNote.get_for_linked_object(self._obj, preload_event=False) if self._note is None or self._note.is_deleted: raise HTTPAPIError("No such note", 404)
def deserialize(self): if not self.force and self.data['indico_version'] != indico.__version__: click.secho('Version mismatch: trying to import event exported with {} to version {}' .format(self.data['indico_version'], indico.__version__), fg='red') return None self._load_users(self.data) for tablename, tabledata in self.data['objects']: self._deserialize_object(db.metadata.tables[tablename], tabledata) if self.deferred_idrefs: # Any reference to an ID that was exported need to be replaced # with an actual ID at some point - either immediately (if the # referenced row was already imported) or later (usually in case # of circular dependencies where one of the IDs is not available # when the row is inserted). click.secho('BUG: Not all deferred idrefs have been consumed', fg='red') for uuid, values in self.deferred_idrefs.iteritems(): click.secho('{}:'.format(uuid), fg='yellow', bold=True) for table, col, pk_value in values: click.secho(' - {}.{} ({})'.format(table.fullname, col, pk_value), fg='yellow') raise Exception('Not all deferred idrefs have been consumed') event = Event.get(self.event_id) event.log(EventLogRealm.event, EventLogKind.other, 'Event', 'Event imported from another Indico instance') self._associate_users_by_email(event) db.session.flush() return event
def event_or_shorturl(confId, shorturl_namespace=False, force_overview=False): func = None event_ = Event.get(int(confId)) if confId.isdigit() else None if event_ and event_.is_deleted: raise NotFound(_('This event has been deleted.')) elif event_: # For obvious reasons an event id always comes first. # If it's used within the short url namespace we redirect to the event namespace, otherwise # we call the RH to display the event if shorturl_namespace: func = lambda: redirect(event_.url) else: request.view_args['confId'] = int(request.view_args['confId']) func = lambda: RHDisplayEvent().process() else: shorturl_event = (Event.query .filter(db.func.lower(Event.url_shortcut) == confId.lower(), ~Event.is_deleted) .one_or_none()) if (shorturl_namespace or config.ROUTE_OLD_URLS) and shorturl_event: if shorturl_namespace: # Correct namespace => redirect to the event func = lambda: redirect(shorturl_event.url) else: # Old event namespace => 301-redirect to the new shorturl first to get Google etc. to update it func = lambda: redirect(shorturl_event.short_url, 301) elif is_legacy_id(confId): mapping = LegacyEventMapping.find_first(legacy_event_id=confId) if mapping is not None: url = url_for('events.display', confId=mapping.event_id) func = lambda: redirect(url, 301) if func is None: raise NotFound(_('An event with this ID/shortcut does not exist.')) return func()
def test_deleted_relationships(db, dummy_event_new): event = dummy_event_new assert not event.contributions assert not event.sessions s = Session(event_new=event, title='s') sd = Session(event_new=event, title='sd', is_deleted=True) c = Contribution(event_new=event, title='c', session=sd, duration=timedelta(minutes=30)) cd = Contribution(event_new=event, title='cd', session=sd, duration=timedelta(minutes=30), is_deleted=True) sc = SubContribution(contribution=c, title='sc', duration=timedelta(minutes=10)) scd = SubContribution(contribution=c, title='scd', duration=timedelta(minutes=10), is_deleted=True) db.session.flush() db.session.expire_all() # reload all the objects from the db event = Event.get(event.id) s = Session.get(s.id) sd = Session.get(sd.id) c = Contribution.get(c.id) cd = Contribution.get(cd.id) sc = SubContribution.get(sc.id) scd = SubContribution.get(scd.id) # deleted items should not be in the lists assert event.sessions == [s] assert event.contributions == [c] assert sd.contributions == [c] assert c.subcontributions == [sc] # the other direction should work fine even in case of deletion assert s.event_new == event assert sd.event_new == event assert c.event_new == event assert cd.event_new == event assert sc.contribution == c assert scd.contribution == c
def _getParams(self): super(AgreementExportHook, self)._getParams() type_ = self._pathParams['agreement_type'] try: self._definition = get_agreement_definitions()[type_] except KeyError: raise HTTPAPIError('No such agreement type', 404) self.event = Event.get(self._pathParams['event_id'], is_deleted=False) if self.event is None: raise HTTPAPIError('No such event', 404)
def restore(event_id): """Restores a deleted event.""" event = Event.get(event_id) if event is None: click.secho('This event does not exist', fg='red') sys.exit(1) elif not event.is_deleted: click.secho('This event is not deleted', fg='yellow') sys.exit(1) event.is_deleted = False db.session.commit() click.secho('Event undeleted: "{}"'.format(event.title), fg='green')
def validate_entries(self, field): if field.errors: return for entry in field.data: if entry['days'] < 0: raise ValidationError(_("'Days' must be a positive integer")) if entry['type'] not in {'category', 'event'}: raise ValidationError(_('Invalid type')) if entry['type'] == 'category' and not Category.get(entry['id'], is_deleted=False): raise ValidationError(_('Invalid category: {}').format(entry['id'])) if entry['type'] == 'event' and not Event.get(entry['id'], is_deleted=False): raise ValidationError(_('Invalid event: {}').format(entry['id']))
def get_event_from_url(url): data = url_parse(url) if not all([data.scheme, data.netloc, data.path]): raise ValueError(_('Invalid event URL')) event_path = re.match(r'/event/(\d+)(/|$)', data.path) if not event_path: raise ValueError(_('Invalid event URL')) event_id = event_path.group(1) event = Event.get(event_id, is_deleted=False) if not event: raise ValueError(_('This event does not exist')) return event
def validate_entries(self, field): if field.errors: return for entry in field.data: if entry['days'] < 0: raise ValidationError(_("'Days' must be a positive integer")) if entry['type'] not in {'category', 'category_tree', 'event'}: raise ValidationError(_('Invalid type')) if entry['type'] in {'category', 'category_tree'} and not Category.get(entry['id'], is_deleted=False): raise ValidationError(_('Invalid category: {}').format(entry['id'])) if entry['type'] == 'event' and not Event.get(entry['id'], is_deleted=False): raise ValidationError(_('Invalid event: {}').format(entry['id']))
def obj_deref(ref): """Returns the object identified by `ref`""" from indico_livesync.models.queue import EntryType if ref['type'] == EntryType.category: return CategoryManager().getById(ref['category_id'], True) elif ref['type'] == EntryType.event: return Event.get(ref['event_id']) elif ref['type'] == EntryType.contribution: return Contribution.get(ref['contrib_id']) elif ref['type'] == EntryType.subcontribution: return SubContribution.get(ref['subcontrib_id']) else: raise ValueError('Unexpected object type: {}'.format(ref['type']))
def get_linked_object(type_, id_): if type_ == LinkType.event: return Event.get(id_, is_deleted=False) elif type_ == LinkType.contribution: return (Contribution.query.filter( Contribution.id == id_, ~Contribution.is_deleted, Contribution.event.has(is_deleted=False)).first()) elif type_ == LinkType.session_block: return (SessionBlock.query.filter( SessionBlock.id == id_, SessionBlock.session.has( db.and_(~Session.is_deleted, Session.event.has(is_deleted=False)))).first())
def is_feature_enabled(event, name): """Checks if a feature is enabled for an event. :param event: The event (or event ID) to check. :param name: The name of the feature. """ feature = get_feature_definition(name) enabled_features = features_event_settings.get(event, 'enabled') if enabled_features is not None: return feature.name in enabled_features else: if isinstance(event, (basestring, int, long)): event = Event.get(event) return event and feature.is_default_for_event(event)
def session(self, idlist): event = Event.get(self._eventId, is_deleted=False) if not event: return [] idlist = set(map(int, idlist)) sessions = (Session.query.with_parent(event).filter( Session.id.in_(idlist), ~Session.is_deleted).all()) # Fallback for friendly_id sessions += (Session.query.with_parent(event).filter( Session.friendly_id.in_(idlist - {s.id for s in sessions}), ~Session.is_deleted).all()) self._detail_level = 'contributions' return self._build_sessions_api_data(sessions)
def restore(event_id, user_id, message): """Restore a deleted event.""" event = Event.get(event_id) user = User.get(user_id) if user_id else None if event is None: click.secho('This event does not exist', fg='red') sys.exit(1) elif not event.is_deleted: click.secho('This event is not deleted', fg='yellow') sys.exit(1) event.restore(message, user) signals.core.after_process.send() db.session.commit() click.secho(f'Event undeleted: "{event.title}"', fg='green')
def session(self, idlist): event = Event.get(self._eventId, is_deleted=False) if not event: return [] idlist = set(map(int, idlist)) sessions = Session.query.with_parent(event).filter(Session.id.in_(idlist), ~Session.is_deleted).all() # Fallback for friendly_id sessions += ( Session.query.with_parent(event) .filter(Session.friendly_id.in_(idlist - {s.id for s in sessions}), ~Session.is_deleted) .all() ) self._detail_level = "contributions" return self._build_sessions_api_data(sessions)
def get_linked_object(type_, id_): if type_ == LinkType.event: return Event.get(id_, is_deleted=False) elif type_ == LinkType.contribution: return (Contribution.query .filter(Contribution.id == id_, ~Contribution.is_deleted, Contribution.event.has(is_deleted=False)) .first()) elif type_ == LinkType.session_block: return (SessionBlock.query .filter(SessionBlock.id == id_, SessionBlock.session.has(db.and_(~Session.is_deleted, Session.event.has(is_deleted=False)))) .first())
def export(event_id, target_file): """Export all data associated with an event. This exports the whole event as an archive which can be imported on another other Indico instance. Importing an event is only guaranteed to work if it was exported on the same Indico version. """ event = Event.get(event_id) if event is None: click.secho('This event does not exist', fg='red') sys.exit(1) elif event.is_deleted: click.secho('This event has been deleted', fg='yellow') click.confirm('Export it anyway?', abort=True) export_event(event, target_file)
def export(event_id, target_file): """Exports all data associated with an event. This exports the whole event as an archive which can be imported on another other Indico instance. Importing an event is only guaranteed to work if it was exported on the same Indico version. """ event = Event.get(event_id) if event is None: click.secho('This event does not exist', fg='red') sys.exit(1) elif event.is_deleted: click.secho('This event has been deleted', fg='yellow') click.confirm('Export it anyway?', abort=True) export_event(event, target_file)
def restore(event_id, user_id, message): """Restore a deleted event.""" event = Event.get(event_id) user = User.get(user_id) if user_id else None if event is None: click.secho('This event does not exist', fg='red') sys.exit(1) elif not event.is_deleted: click.secho('This event is not deleted', fg='yellow') sys.exit(1) event.is_deleted = False text = f'Event restored: {message}' if message else 'Event restored' event.log(EventLogRealm.event, EventLogKind.positive, 'Event', text, user=user) db.session.commit() click.secho(f'Event undeleted: "{event.title}"', fg='green')
def get_object_from_args(args=None): """Retrieve an event object from request arguments. This utility is meant to be used in cases where the same controller can deal with objects attached to various parts of an event which use different URLs to indicate which object to use. :param args: The request arguments. If unspecified, ``request.view_args`` is used. :return: An ``(object_type, event, object)`` tuple. The event is always the :class:`Event` associated with the object. The object may be an `Event`, `Session`, `Contribution` or `SubContribution`. If the object does not exist, ``(object_type, None, None)`` is returned. """ if args is None: args = request.view_args object_type = args['object_type'] event = Event.get(args['event_id'], is_deleted=False) if event is None: obj = None elif object_type == 'event': obj = event elif object_type == 'session': obj = Session.query.with_parent(event).filter_by( id=args['session_id']).first() elif object_type == 'contribution': obj = Contribution.query.with_parent(event).filter_by( id=args['contrib_id']).first() elif object_type == 'subcontribution': obj = (SubContribution.query.filter( SubContribution.id == args['subcontrib_id'], ~SubContribution.is_deleted, SubContribution.contribution.has(event=event, id=args['contrib_id'], is_deleted=False)).first()) else: raise ValueError(f'Unexpected object type: {object_type}') if obj is not None: return object_type, event, obj else: return object_type, None, None
def _getParams(self): super()._getParams() event = self._obj = Event.get(self._pathParams['event_id'], is_deleted=False) if event is None: raise HTTPAPIError('No such event', 404) session_id = self._pathParams.get('session_id') if session_id: self._obj = Session.query.with_parent(event).filter_by(id=session_id).first() if self._obj is None: raise HTTPAPIError("No such session", 404) contribution_id = self._pathParams.get('contribution_id') if contribution_id: contribution = self._obj = Contribution.query.with_parent(event).filter_by(id=contribution_id).first() if contribution is None: raise HTTPAPIError("No such contribution", 404) subcontribution_id = self._pathParams.get('subcontribution_id') if subcontribution_id: self._obj = SubContribution.query.with_parent(contribution).filter_by(id=subcontribution_id).first() if self._obj is None: raise HTTPAPIError("No such subcontribution", 404)
def _getParams(self): super(AttachmentsExportHook, self)._getParams() event = self._obj = Event.get(self._pathParams['event_id'], is_deleted=False) if event is None: raise HTTPAPIError('No such event', 404) session_id = self._pathParams.get('session_id') if session_id: self._obj = Session.query.with_parent(event).filter_by(id=session_id).first() if self._obj is None: raise HTTPAPIError("No such session", 404) contribution_id = self._pathParams.get('contribution_id') if contribution_id: contribution = self._obj = Contribution.query.with_parent(event).filter_by(id=contribution_id).first() if contribution is None: raise HTTPAPIError("No such contribution", 404) subcontribution_id = self._pathParams.get('subcontribution_id') if subcontribution_id: self._obj = SubContribution.query.with_parent(contribution).filter_by(id=subcontribution_id).first() if self._obj is None: raise HTTPAPIError("No such subcontribution", 404)
def _send_email(with_event): from flask import session from indico.core.notifications import send_email, make_email from indico.modules.events import Event from indico.modules.users import User from indico.web.flask.templating import get_template_module tpl = get_template_module('users/emails/registration_request_accepted.txt', user=User.get(6)) kwargs = {} if with_event: kwargs = { 'event': Event.get(654658), 'module': 'Test', 'user': session.user } # send_email(make_email('m\[email protected]', template=tpl), **kwargs) # send_email(make_email('*****@*****.**', template=tpl), **kwargs) from indico.modules.events.registration.notifications import _notify_registration from indico.modules.events.registration.models.registrations import Registration _notify_registration(Registration.get(56757), 'registration_creation_to_registrant.html')
def event(self): return Event.get(int(self.event_id), is_deleted=False)
def _process_args(self): self.event = Event.get(int(request.view_args['confId'])) if self.event is None: raise NotFound(_('An event with this ID does not exist.')) elif self.event.is_deleted: raise NotFound(_('This event has been deleted.'))
def _migrate_menu(self, event, container, parent=None, used=None): if used is None: used = set() for pos, item in enumerate(container._listLink, 1): data = { 'parent': parent, 'event_id': int(event.id), 'is_enabled': item._active, 'position': pos } item_type = item.__class__.__name__ if item_type == 'SystemLink': if item._name in REMOVED_MENU_NAMES: continue data['name'] = MENU_ENTRY_NAME_MAP[item._name] if not parent and data['name'] in NOT_TOP_LEVEL_NAMES: self.print_warning(cformat( '%{yellow}Skipping top-level menu entry {}').format( data['name']), event_id=event.id) continue elif data['name'] in used: self.print_error( cformat('%{red!}duplicate menu entry name {}; skipping' ).format(data['name']), event_id=event.id) continue used.add(data['name']) data['title'] = _sanitize_title(item._caption) if not data['title']: data['title'] = None self.print_warning(cformat( '%{yellow!}Menu entry {} has no title; using default'). format(data['name']), event_id=event.id) elif data['title'].lower() in DEFAULT_MENU_TITLES[ data['name']]: data['title'] = None if item._name == 'chatrooms': data['plugin'] = 'chat' data['type'] = MenuEntryType.plugin_link else: data['type'] = MenuEntryType.internal_link elif item_type == 'Spacer': data['type'] = MenuEntryType.separator elif item_type == 'ExternLink': data['type'] = MenuEntryType.user_link data['title'] = _sanitize_title(item._caption) data['link_url'] = item._URL.strip() if not data['link_url']: if getattr(item, '_listLink', None): self.print_warning(cformat( '%{yellow!}Link "{}" has no URL but children'). format(data['title']), event_id=event.id) else: self.print_warning(cformat( '%{yellow}Skipping link "{}" with no URL').format( data['title']), event_id=event.id) continue if not data['title']: if getattr(item, '_listLink', None): self.print_warning(cformat( '%{yellow!}Link has no title but children'), event_id=event.id) else: self.print_warning( cformat('%{yellow}Skipping link with no title'), event_id=event.id) continue elif item_type == 'PageLink': data['type'] = MenuEntryType.page data['title'] = _sanitize_title(item._caption) data['page'] = EventPage(event_id=event.id, html=item._page._content) data['page'].legacy_mapping = LegacyPageMapping( event_id=event.id, legacy_page_id=item._page._id) if item._page._isHome: Event.get(event.id).default_page = data['page'] else: self.print_error( 'Unexpected menu item type: {}'.format(item_type), event_id=event.id) continue entry = MenuEntry(**data) yield entry if getattr(item, '_listLink', None): # child entries if not parent: for sub_entry in self._migrate_menu( event, item, entry, used): yield sub_entry else: self.print_warning('Skipping children inside nested entry', event_id=event.id)
def _migrate_menu(self, event, container, parent=None, used=None): if used is None: used = set() for pos, item in enumerate(container._listLink, 1): data = {'parent': parent, 'event_id': int(event.id), 'is_enabled': item._active, 'position': pos} item_type = item.__class__.__name__ if item_type == 'SystemLink': if item._name in REMOVED_MENU_NAMES: continue data['name'] = MENU_ENTRY_NAME_MAP[item._name] if not parent and data['name'] in NOT_TOP_LEVEL_NAMES: self.print_warning(cformat('%{yellow}Skipping top-level menu entry {}').format(data['name']), event_id=event.id) continue elif data['name'] in used: self.print_error(cformat('%{red!}duplicate menu entry name {}; skipping').format(data['name']), event_id=event.id) continue used.add(data['name']) data['title'] = _sanitize_title(item._caption) if not data['title']: data['title'] = None self.print_warning(cformat('%{yellow!}Menu entry {} has no title; using default').format( data['name']), event_id=event.id) elif data['title'].lower() in DEFAULT_MENU_TITLES[data['name']]: data['title'] = None if item._name == 'chatrooms': data['plugin'] = 'chat' data['type'] = MenuEntryType.plugin_link else: data['type'] = MenuEntryType.internal_link elif item_type == 'Spacer': data['type'] = MenuEntryType.separator elif item_type == 'ExternLink': data['type'] = MenuEntryType.user_link data['title'] = _sanitize_title(item._caption) data['link_url'] = item._URL.strip() if not data['link_url']: if getattr(item, '_listLink', None): self.print_warning(cformat('%{yellow!}Link "{}" has no URL but children').format( data['title']), event_id=event.id) else: self.print_warning(cformat('%{yellow}Skipping link "{}" with no URL').format( data['title']), event_id=event.id) continue if not data['title']: if getattr(item, '_listLink', None): self.print_warning(cformat('%{yellow!}Link has no title but children'), event_id=event.id) else: self.print_warning(cformat('%{yellow}Skipping link with no title'), event_id=event.id) continue elif item_type == 'PageLink': data['type'] = MenuEntryType.page data['title'] = _sanitize_title(item._caption) data['page'] = EventPage(event_id=event.id, html=item._page._content) data['page'].legacy_mapping = LegacyPageMapping(event_id=event.id, legacy_page_id=item._page._id) if item._page._isHome: Event.get(event.id).default_page = data['page'] else: self.print_error('Unexpected menu item type: {}'.format(item_type), event_id=event.id) continue entry = MenuEntry(**data) yield entry if getattr(item, '_listLink', None): # child entries if not parent: for sub_entry in self._migrate_menu(event, item, entry, used): yield sub_entry else: self.print_warning('Skipping children inside nested entry', event_id=event.id)
def _process_args(self): self.event = Event.get(request.view_args['event_id']) if self.event is None: raise NotFound(_('An event with this ID does not exist.')) elif self.event.is_deleted: raise NotFound(_('This event has been deleted.'))
def _migrate_menu(self, event, container, parent=None, used=None): if used is None: used = set() for pos, item in enumerate(container._listLink, 1): data = {"parent": parent, "event_id": int(event.id), "is_enabled": item._active, "position": pos} item_type = item.__class__.__name__ if item_type == "SystemLink": if item._name in REMOVED_MENU_NAMES: continue data["name"] = MENU_ENTRY_NAME_MAP[item._name] if not parent and data["name"] in NOT_TOP_LEVEL_NAMES: self.print_warning( cformat("%{yellow}Skipping top-level menu entry {}").format(data["name"]), event_id=event.id ) continue elif data["name"] in used: self.print_error( cformat("%{red!}duplicate menu entry name {}; skipping").format(data["name"]), event_id=event.id ) continue used.add(data["name"]) data["title"] = _sanitize_title(item._caption) if not data["title"]: data["title"] = None self.print_warning( cformat("%{yellow!}Menu entry {} has no title; using default").format(data["name"]), event_id=event.id, ) elif data["title"].lower() in DEFAULT_MENU_TITLES[data["name"]]: data["title"] = None if item._name == "chatrooms": data["plugin"] = "chat" data["type"] = MenuEntryType.plugin_link else: data["type"] = MenuEntryType.internal_link elif item_type == "Spacer": data["type"] = MenuEntryType.separator elif item_type == "ExternLink": data["type"] = MenuEntryType.user_link data["title"] = _sanitize_title(item._caption) data["link_url"] = item._URL.strip() if not data["link_url"]: if getattr(item, "_listLink", None): self.print_warning( cformat('%{yellow!}Link "{}" has no URL but children').format(data["title"]), event_id=event.id, ) else: self.print_warning( cformat('%{yellow}Skipping link "{}" with no URL').format(data["title"]), event_id=event.id ) continue if not data["title"]: if getattr(item, "_listLink", None): self.print_warning(cformat("%{yellow!}Link has no title but children"), event_id=event.id) else: self.print_warning(cformat("%{yellow}Skipping link with no title"), event_id=event.id) continue elif item_type == "PageLink": data["type"] = MenuEntryType.page data["title"] = _sanitize_title(item._caption) data["page"] = EventPage(event_id=event.id, html=item._page._content) data["page"].legacy_mapping = LegacyPageMapping(event_id=event.id, legacy_page_id=item._page._id) if item._page._isHome: Event.get(event.id).default_page = data["page"] else: self.print_error("Unexpected menu item type: {}".format(item_type), event_id=event.id) continue entry = MenuEntry(**data) yield entry if getattr(item, "_listLink", None): # child entries if not parent: for sub_entry in self._migrate_menu(event, item, entry, used): yield sub_entry else: self.print_warning("Skipping children inside nested entry", event_id=event.id)