def add_file(self, id, file=None, url=None, **kwargs): """Save action for the :class:`~mediacore.forms.admin.media.AddFileForm`. Creates a new :class:`~mediacore.model.media.MediaFile` from the uploaded file or the local or remote URL. :param id: Media ID. If ``"new"`` a new Media stub is created. :type id: :class:`int` or ``"new"`` :param file: The uploaded file :type file: :class:`cgi.FieldStorage` or ``None`` :param url: A URL to a recognizable audio or video file :type url: :class:`unicode` or ``None`` :rtype: JSON dict :returns: success bool message Error message, if unsuccessful media_id The :attr:`~mediacore.model.media.Media.id` which is important if new media has just been created. file_id The :attr:`~mediacore.model.media.MediaFile.id` for the newly created file. edit_form The rendered XHTML :class:`~mediacore.forms.admin.media.EditFileForm` for this file. status_form The rendered XHTML :class:`~mediacore.forms.admin.media.UpdateStatusForm` """ if id == 'new': media = Media() user = request.environ['repoze.who.identity']['user'] media.author = Author(user.display_name, user.email_address) # Create a temp stub until we can set it to something meaningful timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') media.title = u'Temporary stub %s' % timestamp media.slug = get_available_slug(Media, '_stub_' + timestamp) media.reviewed = True DBSession.add(media) DBSession.flush() else: media = fetch_row(Media, id) media_file = add_new_media_file(media, file, url) if media.slug.startswith('_stub_'): media.title = media_file.display_name media.slug = get_available_slug(Media, '_stub_' + media.title) # The thumbs may have been created already by add_new_media_file if id == 'new' and not has_thumbs(media): create_default_thumbs_for(media) media.update_status() # Render some widgets so the XHTML can be injected into the page edit_form_xhtml = unicode(edit_file_form.display( action=url_for(action='edit_file', id=media.id), file=media_file)) status_form_xhtml = unicode(update_status_form.display( action=url_for(action='update_status', id=media.id), media=media)) data = dict( success = True, media_id = media.id, file_id = media_file.id, file_type = media_file.type, edit_form = edit_form_xhtml, status_form = status_form_xhtml, title = media.title, slug = media.slug, description = media.description, link = url_for(action='edit', id=media.id), duration = helpers.duration_from_seconds(media.duration), ) return data
def edit_file(self, id, file_id, file_type=None, duration=None, delete=None, bitrate=None, width_height=None, **kwargs): """Save action for the :class:`~mediacore.forms.admin.media.EditFileForm`. Changes or delets a :class:`~mediacore.model.media.MediaFile`. XXX: We do NOT use the @validate decorator due to complications with partial validation. The JS sends only the value it wishes to change, so we only want to validate that one value. FancyValidator.if_missing seems to eat empty values and assign them None, but there's an important difference to us between None (no value from the user) and an empty value (the user is clearing the value of a field). :param id: Media ID :type id: :class:`int` :rtype: JSON dict :returns: success bool message Error message, if unsuccessful status_form Rendered XHTML for the status form, updated to reflect the changes made. """ media = fetch_row(Media, id) data = dict(success=False) file_id = int(file_id) # Just in case validation failed somewhere. for file in media.files: if file.id == file_id: break else: file = None fields = edit_file_form.c try: if file is None: data['message'] = _('File "%s" does not exist.') % file_id elif file_type: file.type = fields.file_type.validate(file_type) data['success'] = True elif duration is not None: media.duration = duration = fields.duration.validate(duration) data['success'] = True data['duration'] = helpers.duration_from_seconds(media.duration) elif width_height is not None: width_height = fields.width_height.validate(width_height) file.width, file.height = width_height or (0, 0) data['success'] = True elif bitrate is not None: file.bitrate = fields.bitrate.validate(bitrate) data['success'] = True elif delete: file.storage.delete(file.unique_id) DBSession.delete(file) DBSession.flush() media = fetch_row(Media, id) data['success'] = True else: data['message'] = _('No action to perform.') except Invalid, e: data['success'] = False data['message'] = unicode(e)
def _from_python(self, value, state): return helpers.duration_from_seconds(value)
def edit_file(self, id, file_id, file_type=None, duration=None, delete=None, **kwargs): """Save action for the :class:`~mediacore.forms.admin.media.EditFileForm`. Changes or delets a :class:`~mediacore.model.media.MediaFile`. TODO: Use the form validators to validate this form. We only POST one field at a time, so the validate decorator doesn't work, because it doesn't work for partial validation, because none of the kwargs are updated if an Invalid exception is raised by any validator. :param id: Media ID :type id: :class:`int` :rtype: JSON dict :returns: success bool message Error message, if unsuccessful status_form Rendered XHTML for the status form, updated to reflect the changes made. """ media = fetch_row(Media, id) data = dict(success=False) try: file = [file for file in media.files if file.id == file_id][0] except IndexError: file = None if file is None: data['message'] = 'File "%s" does not exist.' % file_id elif file_type: file.type = file_type DBSession.add(file) data['success'] = True elif duration is not None: try: duration = helpers.duration_to_seconds(duration) except ValueError: data['message'] = 'Bad duration formatting, use Hour:Min:Sec' else: media.duration = duration DBSession.add(media) data['success'] = True data['duration'] = helpers.duration_from_seconds(duration) elif delete: file_path = file.file_path DBSession.delete(file) transaction.commit() if file_path: helpers.delete_files([file_path], 'media') media = fetch_row(Media, id) data['success'] = True else: data['message'] = 'No action to perform.' if data['success']: data['file_type'] = file.type media.update_status() DBSession.add(media) DBSession.flush() # Return the rendered widget for injection status_form_xhtml = unicode(update_status_form.display( action=url_for(action='update_status'), media=media)) data['status_form'] = status_form_xhtml return data
def edit(self, id, **kwargs): """Display the media forms for editing or adding. This page serves as the error_handler for every kind of edit action, if anything goes wrong with them they'll be redirected here. :param id: Media ID :type id: ``int`` or ``"new"`` :param \*\*kwargs: Extra args populate the form for ``"new"`` media :returns: media :class:`~mediacore.model.media.Media` instance media_form The :class:`~mediacore.forms.media.MediaForm` instance media_action ``str`` form submit url media_values ``dict`` form values file_add_form The :class:`~mediacore.forms.media.AddFileForm` instance file_add_action ``str`` form submit url file_edit_form The :class:`~mediacore.forms.media.EditFileForm` instance file_edit_action ``str`` form submit url album_art_form The :class:`~mediacore.forms.admin.AlbumArtForm` instance album_art_action ``str`` form submit url update_status_form The :class:`~mediacore.forms.media.UpdateStatusForm` instance update_status_action ``str`` form submit url """ media = fetch_row(Media, id, incl_trash=True) if tmpl_context.action == 'save' or id == 'new': # Use the values from error_handler or GET for new podcast media media_values = kwargs user = request.environ['repoze.who.identity']['user'] media_values.setdefault('author_name', user.display_name) media_values.setdefault('author_email', user.email_address) else: # Pull the defaults from the media item media_values = dict( podcast = media.podcast_id, slug = media.slug, title = media.title, author_name = media.author.name, author_email = media.author.email, description = media.description, tags = ', '.join((tag.name for tag in media.tags)), topics = [topic.id for topic in media.topics], notes = media.notes, details = dict(duration = helpers.duration_from_seconds(media.duration)), ) # Re-verify the state of our Media object in case the data is nonsensical if id != 'new': media.update_type() media.update_status() DBSession.add(media) return dict( media = media, media_form = media_form, media_action = url_for(action='save'), media_values = media_values, file_add_form = add_file_form, file_add_action = url_for(action='add_file'), file_edit_form = edit_file_form, file_edit_action = url_for(action='edit_file'), album_art_form = album_art_form, album_art_action = url_for(action='save_album_art'), update_status_form = update_status_form, update_status_action = url_for(action='update_status'), )
file=media_file)) status_form_xhtml = unicode(update_status_form.display( action=url_for(action='update_status', id=media.id), media=media)) data = dict( success = True, media_id = media.id, file_id = media_file.id, file_type = media_file.type, edit_form = edit_form_xhtml, status_form = status_form_xhtml, title = media.title, slug = media.slug, link = url_for(action='edit', id=media.id), duration = helpers.duration_from_seconds(media.duration), ) return data @expose('json') @validate(validators={'file_id': validators.Int()}) def edit_file(self, id, file_id, file_type=None, duration=None, delete=None, **kwargs): """Save action for the :class:`~mediacore.forms.admin.media.EditFileForm`. Changes or delets a :class:`~mediacore.model.media.MediaFile`. TODO: Use the form validators to validate this form. We only POST one field at a time, so the validate decorator doesn't work, because it doesn't work for partial validation, because