Ejemplo n.º 1
0
class Channeling(object):
    channel = db.ReferenceField(Channel, required=True,
                                reverse_delete_rule=db.DENY)
    related_channels = db.ListField(
        db.ReferenceField('Channel', reverse_delete_rule=db.PULL)
    )
    related_mpath = db.ListField(db.StringField())
    show_on_channel = db.BooleanField(default=True)
    channel_roles = db.ListField(db.StringField())

    def populate_related_mpath(self):
        self.related_mpath = [rel.mpath for rel in self.related_channels]

    def populate_channel_roles(self):
        self.channel_roles = [role.name for role in self.channel.roles]
Ejemplo n.º 2
0
class Comment(Publishable, BaseComment, db.Document):
    path = db.StringField(max_length=255, required=True)
    replies = db.ListField(db.EmbeddedDocumentField(Reply))

    def __unicode__(self):
        return u"{0} - {1}...".format(self.author_name, self.body[:15])

    def get_canonical_url(self):
        return "/{0}.{1}".format(
            self.path, get_setting_value(
                'CONTENT_EXTENSION',
                'html')) if not self.path.startswith("/") else self.path

    meta = {"ordering": ['-created_at'], "indexes": ['-created_at', 'path']}
Ejemplo n.º 3
0
class Owned(object):
    created_by = db.ReferenceField(User)
    last_updated_by = db.ReferenceField(User)
    authors = db.ListField(db.ReferenceField(User))

    def get_authors(self):
        if self.created_by is None:
            raise db.ValidationError(
                'The created_by field is None, '
                'a object must have been created by someone.')
        return list(
            [self.created_by] +
            [author for author in self.authors if author != self.created_by])

    @property
    def has_multiple_authors(self):
        return len(self.get_authors()) > 1
Ejemplo n.º 4
0
class HasCustomValue(object):
    values = db.ListField(db.EmbeddedDocumentField(CustomValue))

    def get_values_tuple(self):
        return [(value.name, value.value, value.formatter)
                for value in self.values]

    def get_value(self, name, default=None):
        try:
            return self.values.get(name=name).value
        except:
            return default

    def add_value(self, name, value, formatter='text'):
        custom_value = CustomValue(name=name, value=value, formatter=formatter)
        self.values.append(custom_value)

    def clean(self):
        current_names = [value.name for value in self.values]
        for name in current_names:
            if current_names.count(name) > 1:
                raise Exception(_l("%(name)s already exists", name=name))
        super(HasCustomValue, self).clean()
Ejemplo n.º 5
0
class Channel(Tagged, HasCustomValue, Publishable, LongSlugged,
              ChannelConfigs, ContentFormat, db.DynamicDocument):
    title = db.StringField(max_length=255, required=True)
    description = db.StringField()
    show_in_menu = db.BooleanField(default=False)
    is_homepage = db.BooleanField(default=False)
    roles = db.ListField(
        db.ReferenceField('Role', reverse_delete_rule=db.PULL))
    include_in_rss = db.BooleanField(default=True)
    indexable = db.BooleanField(default=True)
    canonical_url = db.StringField()
    order = db.IntField(default=0)

    parent = db.ReferenceField('self', required=False, default=None,
                               reverse_delete_rule=db.DENY)

    per_page = db.IntField(default=0)
    aliases = db.ListField(db.StringField(), default=[])
    channel_type = db.ReferenceField(ChannelType, required=False,
                                     reverse_delete_rule=db.NULLIFY)

    redirect_url = db.StringField(max_length=255)
    render_content = db.ReferenceField(ContentProxy,
                                       required=False,
                                       reverse_delete_rule=db.NULLIFY)
    sort_by = db.ListField(db.StringField(), default=[])
    link_in_menu = db.BooleanField(default=True)

    meta = {
        'ordering': ['order', 'title'],
    }

    def get_text(self):
        if self.content_format == "markdown":
            return markdown(self.description)
        else:
            return self.description

    def get_content_filters(self):
        filters = {}
        if self.channel_type and self.channel_type.content_filters:
            filters.update(self.channel_type.content_filters)
        if self.content_filters:
            filters.update(self.content_filters)
        return filters

    def get_ancestors_count(self):
        return len(self.get_ancestors_slugs())

    def get_ancestors_slugs(self):
        channel_list = []
        channel_slugs = self.long_slug.split('/')
        while channel_slugs:
            channel_list.append("/".join(channel_slugs))
            channel_slugs.pop()
        return channel_list

    def get_ancestors(self, **kwargs):
        channel_list = self.get_ancestors_slugs()
        ancestors = self.__class__.objects(
            long_slug__in=channel_list,
            **kwargs
        ).order_by('-long_slug')
        return ancestors

    def get_children(self, **kwargs):
        return self.__class__.objects(
            parent=self, **kwargs
        ).order_by('long_slug')

    def get_descendants(self, **kwargs):
        return self.__class__.objects(
            __raw__={'mpath': {'$regex': '^{0}'.format(self.mpath)}}
        ).order_by('long_slug')

    def get_themes(self):
        return list({
            c.channel_type.theme_name
            for c in self.get_ancestors(channel_type__ne=None)
            if c.channel_type and c.channel_type.theme_name
        })

    @classmethod
    def get_homepage(cls, attr=None):
        try:
            homepage = cls.objects.get(is_homepage=True)
        except Exception as e:
            logger.info("There is no homepage: %s", e.message)
            return None
        else:
            if not attr:
                return homepage
            else:
                return getattr(homepage, attr, homepage)

    def __unicode__(self):
        return self.long_slug

    def get_absolute_url(self, *args, **kwargs):
        if self.is_homepage:
            return "/"
        return "/{0}/".format(self.long_slug)

    def get_canonical_url(self, *args, **kwargs):
        if self.is_homepage:
            return "/"
        return self.get_absolute_url()

    def get_http_url(self):
        site_url = get_site_url()
        absolute_url = self.get_absolute_url()
        absolute_url = absolute_url[1:]
        return u"{0}{1}".format(site_url, absolute_url)

    def clean(self):
        homepage = Channel.objects(is_homepage=True)
        if self.is_homepage and homepage and self not in homepage:
            raise db.ValidationError(_l("Home page already exists"))
        super(Channel, self).clean()

    def validate_render_content(self):
        if self.render_content and \
                not isinstance(self.render_content, ContentProxy):
            self.render_content, created = ContentProxy.objects.get_or_create(
                content=self.render_content)
        else:
            self.render_content = None

    def heritage(self):
        parent = self.parent
        if not parent or not self.inherit_parent:
            return

        self.content_filters = self.content_filters or parent.content_filters
        self.include_in_rss = self.include_in_rss or parent.include_in_rss
        self.show_in_menu = self.show_in_menu or parent.show_in_menu
        self.indexable = self.indexable or parent.indexable
        self.channel_type = self.channel_type or parent.channel_type

    def update_descendants_and_contents(self):
        """
        Need to Detect if self.long_slug and self.mpath has changed.
        if so, update every descendant using get_descendatns method
        to query.
        Also update long_slug and mpath for every Content in this channel
        This needs to be done by default in araw immediate way, but if
        current_app.config.get('ASYNC_SAVE_MODE') is True it will delegate
        all those tasks to celery."""

    def save(self, *args, **kwargs):
        self.validate_render_content()
        self.validate_slug()
        self.validate_long_slug()
        self.heritage()
        self.update_descendants_and_contents()
        if not self.channel_type:
            self.channel_type = ChannelType.objects.first()
        super(Channel, self).save(*args, **kwargs)
Ejemplo n.º 6
0
class Tagged(object):
    tags = db.ListField(db.StringField(max_length=50))
Ejemplo n.º 7
0
class Content(HasCustomValue, Publishable, LongSlugged, Channeling, Tagged,
              ContentFormat, db.DynamicDocument):
    title = db.StringField(max_length=255, required=True)
    summary = db.StringField(required=False)
    template_type = db.ReferenceField(ContentTemplateType,
                                      required=False,
                                      reverse_delete_rule=db.NULLIFY)
    contents = db.ListField(db.EmbeddedDocumentField(SubContent))
    model = db.StringField()
    comments_enabled = db.BooleanField(default=True)
    license = db.EmbeddedDocumentField(License)
    shortened_url = db.EmbeddedDocumentField(ShortenedURL)

    meta = {
        'allow_inheritance': True,
        'indexes': ['-created_at', 'slug'],
        'ordering': ['-created_at'],
    }

    @classmethod
    def available_objects(cls, **filters):
        now = datetime.datetime.now()
        default_filters = {
            "published": True,
            'available_at__lte': now,
        }
        default_filters.update(filters)
        return cls.objects(**default_filters)

    def get_main_image_url(self,
                           thumb=False,
                           default=None,
                           identifier='mainimage'):
        """method returns the path (url) of the main image
        """
        if not isinstance(identifier, (list, tuple)):
            identifier = [identifier]

        for item in identifier:
            try:
                if not thumb:
                    path = self.contents.get(identifier=item).content.path
                else:
                    path = self.contents.get(identifier=item).content.thumb
                return url_for('flaskpress.core.media', filename=path)
            except Exception as e:
                logger.warning('get_main_image_url:' + str(e))

        return default

    def get_main_image_http(self,
                            thumb=False,
                            default=None,
                            identifier='mainimage'):
        """method returns the path of the main image with http
        """
        site_url = get_site_url()
        image_url = self.get_main_image_url(thumb=thumb,
                                            default=default,
                                            identifier=identifier)
        return u"{}{}".format(site_url, image_url)

    def get_uid(self):
        return str(self.id)

    def get_themes(self):
        themes = self.channel.get_themes()
        theme = self.template_type and self.template_type.theme_name
        if theme:
            themes.insert(0, theme)
        return list(set(themes))

    def get_http_url(self):
        site_url = get_site_url()
        absolute_url = self.get_absolute_url()
        absolute_url = absolute_url[1:]
        return u"{0}{1}".format(site_url, absolute_url)

    def get_absolute_url(self, endpoint='flaskpress.core.detail'):
        if self.channel.is_homepage:
            long_slug = self.slug
        else:
            long_slug = self.long_slug

        try:
            return url_for(self.URL_NAMESPACE, long_slug=long_slug)
        except:
            return url_for(endpoint, long_slug=long_slug)

    def get_canonical_url(self, *args, **kwargs):
        return self.get_absolute_url()

    def get_recommendations(self, limit=3, ordering='-created_at', *a, **k):
        now = datetime.datetime.now()
        filters = {
            'published': True,
            'available_at__lte': now,
            "id__ne": self.id
        }
        contents = Content.objects(**filters).filter(tags__in=self.tags or [])

        return contents.order_by(ordering)[:limit]

    def get_summary(self):
        if self.summary:
            return self.summary
        return self.get_text()

    def get_text(self):
        if hasattr(self, 'body'):
            text = self.body
        elif hasattr(self, 'description'):
            text = self.description
        else:
            text = self.summary or ""

        if self.content_format == "markdown":
            return markdown(text)
        else:
            return text

    def __unicode__(self):
        return self.title

    @property
    def short_url(self):
        return self.shortened_url.short if self.shortened_url else ''

    @property
    def model_name(self):
        return self.__class__.__name__.lower()

    @property
    def module_name(self):
        module = self.__module__
        module_name = module.replace('flaskpress.modules.', '').split('.')[0]
        return module_name

    def heritage(self):
        self.model = "{0}.{1}".format(self.module_name, self.model_name)

    def save(self, *args, **kwargs):
        # all those functions should be in a dynamic pipeline
        self.validate_slug()
        self.validate_long_slug()
        self.heritage()
        self.populate_related_mpath()
        self.populate_channel_roles()
        self.populate_shorter_url()
        super(Content, self).save(*args, **kwargs)

    def pre_render(self, render_function, *args, **kwargs):
        return render_function(*args, **kwargs)

    def populate_shorter_url(self):
        if not self.published or not get_setting_value('SHORTENER_ENABLED'):
            return

        url = self.get_http_url()
        if not self.shortened_url or url != self.shortened_url.original:
            shortener = ShorterURL()
            self.shortened_url = ShortenedURL(original=url,
                                              short=shortener.short(url))