Beispiel #1
0
def reset():
    """Reset links
    """
    _links[_threading.get_id()] = {}

    for lng in _lang.langs(False):
        put(lng, _router.current_url(lang=lng))
Beispiel #2
0
    def _on_f_set(self, field_name: str, value, **kwargs):
        """Hook
        """
        if field_name == 'alias':
            from . import _api

            if value is None:
                value = ''

            if not isinstance(value, str):
                raise RuntimeError('str or None expected')

            value = value.strip()
            if not self.is_new:
                # Sanitize CHANGED alias for EXISTING term
                term = _api.find(self.model).eq('alias', value).first()
                if not term or term != self:
                    value = _api.sanitize_alias(self.model, value,
                                                self.language)
            else:
                # Sanitize alias for NEW term
                value = _api.sanitize_alias(self.model, value, self.language)

        elif field_name == 'language':
            # Check if language code is correct
            if value not in lang.langs():
                raise ValueError(
                    "Language '{}' is not supported".format(value))

        return super()._on_f_set(field_name, value, **kwargs)
Beispiel #3
0
def build_translations(pkg_name: str):
    """Compile translations
    """
    # Manage with recursive calls
    if pkg_name in _building_translations:
        return

    _building_translations.append(pkg_name)

    # Build dependencies
    for dep_pkg_name in package_info.requires_plugins(pkg_name):
        dep_pkg_name = 'plugins.' + dep_pkg_name
        if lang.is_package_registered(dep_pkg_name):
            build_translations(dep_pkg_name)

    output_file = path.join(assets_dst('assetman'), 'translations.json')

    # Prepare data structure
    if path.exists(output_file):
        data = util.load_json(output_file)
    else:
        data = {'langs': {}, 'translations': {}}

    # Update languages information
    data['langs'] = lang.langs()

    # Build translations structure
    for lang_code in lang.langs():
        if lang_code not in data['translations']:
            data['translations'][lang_code] = {}
        logger.info('Compiling translations for {} ({})'.format(
            pkg_name, lang_code))
        data['translations'][lang_code][
            pkg_name] = lang.get_package_translations(pkg_name, lang_code)

    # Create output directory
    output_dir = path.dirname(output_file)
    if not path.exists(output_dir):
        makedirs(output_dir, 0o755, True)

    # Write translations to teh file
    with open(output_file, 'wt', encoding='utf-8') as f:
        logger.debug("Writing translations into '{}'".format(output_file))
        f.write(json.dumps(data))
Beispiel #4
0
    def _on_setup_widgets(self):
        """Hook
        """
        self.add_widget(_widget.select.Checkboxes(
            uid='setting_days_of_week',
            weight=10,
            label=_lang.t('content_digest@days_of_week'),
            int_keys=True,
            items=[
                (0, _lang.t('pytsite.lang@weekday_monday')),
                (1, _lang.t('pytsite.lang@weekday_tuesday')),
                (2, _lang.t('pytsite.lang@weekday_wednesday')),
                (3, _lang.t('pytsite.lang@weekday_thursday')),
                (4, _lang.t('pytsite.lang@weekday_friday')),
                (5, _lang.t('pytsite.lang@weekday_saturday')),
                (6, _lang.t('pytsite.lang@weekday_sunday')),
            ],
            default='0',
        ))

        self.add_widget(_widget.select.DateTime(
            uid='setting_day_time',
            weight=20,
            label=_lang.t('content_digest@time'),
            default='08:00',
            datepicker=False,
            h_size='col-sm-2 col-lg-1'
        ))

        self.add_widget(_widget.input.Integer(
            uid='setting_entities_number',
            weight=30,
            label=_lang.t('content_digest@entities_number'),
            min=1,
            default=10,
            h_size='col-sm-2 col-lg-1'
        ))

        self.add_widget(_content.widget.ModelCheckboxes(
            uid='setting_models',
            weight=40,
            label=_lang.t('content_digest@content_models'),
            filter=lambda entity: entity.has_field('views_count'),
        ))

        w = 50
        for lang_code in _lang.langs():
            self.add_widget(_widget.input.Text(
                uid='setting_mail_subject_{}'.format(lang_code),
                weight=w,
                label=_lang.t('content_digest@mail_subject', {'lang': _lang.lang_title(lang_code)}),
                default=_lang.t('content_digest@default_mail_subject', language=lang_code)
            ))
            w += 1

        super()._on_setup_widgets()
Beispiel #5
0
def _generate_feeds():
    # For each language we have separate feed
    for lng in lang.langs():
        # Generate RSS feed for each model
        for model in reg.get('content.rss_models', ()):
            filename = 'rss-{}'.format(model)
            _api.generate_rss(model,
                              filename,
                              lng,
                              length=reg.get('content.feed_length', 20))
Beispiel #6
0
    def _on_after_save(self, first_save: bool = False, **kwargs):
        """Hook
        """
        from . import _api

        # Recalculate tags weights
        if first_save and self.has_field('tags'):
            for t in self.tags:
                weight = 0
                for model in _api.get_models().keys():
                    try:
                        weight += _api.find(model, language=self.language).inc('tags', [t]).count()
                    except odm.error.FieldNotDefined:
                        pass

                try:
                    auth.switch_user_to_system()
                    t.f_set('weight', weight).save(fast=True)
                finally:
                    auth.restore_user()

        # Update localization entities references
        # For each language except current one
        for lng in lang.langs(False):
            # Get localization ref for lng
            localization = self.f_get('localization_' + lng)

            # If localization is set
            if isinstance(localization, Content):
                # If localized entity hasn't reference to this entity, set it
                if localization.f_get('localization_' + self.language) != self:
                    localization.f_set('localization_' + self.language, self).save()

            # If localization is not set
            elif localization is None:
                # Clear references from localized entities
                f = _api.find(self.model, language=lng).eq('localization_' + self.language, self)
                for referenced in f.get():
                    referenced.f_set('localization_' + self.language, None).save()

        # Notify content status change
        if self.has_field('status') and self.has_field('prev_status') and self.status != self.prev_status:
            self.content_on_status_change()

        events.fire('*****@*****.**', entity=self)
        events.fire('content@entity.{}.save'.format(self.model), entity=self)
Beispiel #7
0
    def _on_setup_widgets(self):
        """Hook
        """
        # Application names
        w = 10
        for l in lang.langs():
            self.add_widget(widget.input.Text(
                uid='setting_app_name_' + l,
                weight=w,
                label=lang.t('settings@application_name', {'lang': lang.lang_title(l)}, l),
                default=lang.t('app_name'),
            ))
            w += 1

            self.add_widget(widget.input.Text(
                uid='setting_home_title_' + l,
                label=lang.t('settings@home_page_title', {'lang': lang.lang_title(l)}, l),
                weight=w,
            ))
            w += 1

            self.add_widget(widget.input.Text(
                uid='setting_home_description_' + l,
                label=lang.t('settings@home_page_description', {'lang': lang.lang_title(l)}, l),
                weight=w,
            ))
            w += 1

            self.add_widget(widget.input.Tokens(
                uid='setting_home_keywords_' + l,
                label=lang.t('settings@home_page_keywords', {'lang': lang.lang_title(l)}, l),
                weight=w,
            ))
            w += 1

        # Links
        self.add_widget(widget.input.StringList(
            uid='setting_links',
            weight=200,
            label=lang.t('settings@links'),
            add_btn_label=lang.t('settings@add_link'),
            rules=validation.rule.Url(),
        ))

        # It is important to call super method AFTER
        super()._on_setup_widgets()
Beispiel #8
0
    def _on_f_set(self, field_name: str, value, **kwargs):
        """Hook
        """
        if field_name == 'language':
            if value not in lang.langs():
                raise ValueError("Language '{}' is not supported".format(value))

            if value == 'en':
                self.f_set('language_db', 'english')
            elif value == 'ru':
                self.f_set('language_db', 'russian')
            else:
                self.f_set('language_db', 'none')

        elif field_name == 'status':
            if value not in self.content_statuses():
                raise ValueError("'{}' is invalid content status for model '{}'".format(value, self.model))
            self.f_set('prev_status', self.f_get('status'))

        return super()._on_f_set(field_name, value, **kwargs)
Beispiel #9
0
    def odm_ui_m_form_setup_widgets(self, frm: form.Form):
        """Hook
        """
        # Parent
        from ._widget import TermSelect
        frm.add_widget(
            TermSelect(
                uid='_parent',
                model=self.model,
                exclude=self if not self.is_new else None,
                exclude_descendants=True,
                label=self.t('parent'),
                append_none_item=not self.get_field('_parent').is_required,
                value=self.parent,
            ))

        # Title
        if self.has_field('title'):
            frm.add_widget(
                widget.input.Text(
                    uid='title',
                    label=lang.t('taxonomy@title'),
                    value=self.title,
                    required=self.get_field('title').is_required,
                ))

        # Alias
        if self.has_field('alias'):
            frm.add_widget(
                widget.input.Text(
                    uid='alias',
                    label=lang.t('taxonomy@alias'),
                    value=self.f_get('alias'),
                ))

        # Weight
        if self.has_field('weight'):
            frm.add_widget(
                widget.input.Integer(uid='weight',
                                     label=lang.t('taxonomy@weight'),
                                     value=self.weight,
                                     h_size='col-sm-3 col-md-2 col-lg-1'))

        # Image
        if self.has_field('image'):
            frm.add_widget(
                file_ui.widget.ImagesUpload(
                    uid='image',
                    label=lang.t('taxonomy@image'),
                    required=self.get_field('image').is_required,
                    value=self.image,
                ))

        # Language
        if self.has_field('language'):
            lng = lang.get_current() if self.is_new else self.language
            frm.add_widget(
                widget.static.Text(
                    uid='language',
                    label=lang.t('taxonomy@language'),
                    text=lang.lang_title(lng),
                    value=lng,
                    hidden=len(lang.langs()) == 1,
                ))
Beispiel #10
0
    def _setup_fields(self, **kwargs):
        """Hook
        """
        skip = kwargs.get('skip', [])

        # Publish time
        self.define_field(odm.field.DateTime('publish_time', default=datetime.now()))

        # Author
        self.define_field(auth_storage_odm.field.User('author', is_required=True))

        # Localizations
        self.define_field(odm.field.String('language', default=lang.get_current()))
        self.define_field(odm.field.String('language_db', is_required=True))
        for lng in lang.langs():
            self.define_field(odm.field.Ref('localization_' + lng, model=self.model))

        # Title
        if 'title' not in skip:
            self.define_field(odm.field.String('title', is_required=True))

        # Description
        if 'description' not in skip:
            self.define_field(odm.field.String('description'))

        # Body
        if 'body' not in skip:
            self.define_field(odm.field.String('body', is_required=True, strip_html=False))

        # Images
        if 'images' not in skip:
            self.define_field(file_storage_odm.field.Images('images'))

        # Tags
        if 'tags' not in skip:
            self.define_field(tag.field.Tags('tags'))

        # External links
        if 'ext_links' not in skip:
            self.define_field(odm.field.UniqueStringList('ext_links'))

        # Video links
        if 'video_links' not in skip:
            self.define_field(odm.field.UniqueStringList('video_links'))

        # Views counter
        if 'views_count' not in skip:
            self.define_field(odm.field.Integer('views_count'))

        # Comments counter
        if 'comments_count' not in skip:
            self.define_field(odm.field.Integer('comments_count'))

        # Likes counter
        if 'likes_count' not in skip:
            self.define_field(odm.field.Integer('likes_count'))

        # Bookmarks count
        if 'bookmarks_count' not in skip:
            self.define_field(odm.field.Integer('bookmarks_count'))

        # Status
        if 'status' not in skip:
            self.define_field(odm.field.String('prev_status', is_required=True, default=self.content_statuses()[0]))
            self.define_field(odm.field.String('status', is_required=True, default=self.content_statuses()[0]))

        # Options
        if 'options' not in skip:
            self.define_field(odm.field.Dict('options'))
Beispiel #11
0
    def load(self):
        """Load the theme
        """
        from plugins import assetman

        # Check for requirements
        try:
            package_info.check_requirements(self._package_name)
        except package_info.error.Error as e:
            raise RuntimeError('Error while loading theme {}: {}'.format(self._package_name, e))

        # Create translations directory
        lang_dir = path.join(self._path, 'res', 'lang')
        if not path.exists(lang_dir):
            makedirs(lang_dir, 0o755, True)

        # Create translation stub files
        for lng in lang.langs():
            lng_f_path = path.join(lang_dir, '{}.yml'.format(lng))
            if not path.exists(lng_f_path):
                with open(lng_f_path, 'wt'):
                    pass

        # Register translation resources
        lang.register_package(self._package_name)

        # Register template resources
        tpl_path = path.join(self._path, 'res', 'tpl')
        if not path.exists(tpl_path):
            makedirs(tpl_path, 0o755, True)
        tpl.register_package(self._package_name)

        # Register assetman resources
        assets_path = path.join(self._path, 'res', 'assets')
        if not path.exists(assets_path):
            makedirs(assets_path, 0o755, True)
        assetman.register_package(self._package_name)

        # Load required plugins
        for pn, pv in self._requires['plugins'].items():
            plugman.load(pn, VersionRange(pv))

        # Load theme's module
        try:
            self._module = import_module(self._package_name)
            if hasattr(self._module, 'theme_load') and callable(self._module.theme_load):
                self._module.theme_load()

            # theme_load_{env.type}() hook
            env_type = reg.get('env.type')
            hook_names = ['theme_load_{}'.format(env_type)]
            if env_type == 'wsgi':
                hook_names.append('theme_load_uwsgi')
            for hook_name in hook_names:
                if hasattr(self._module, hook_name):
                    getattr(self._module, hook_name)()

            logger.debug("Theme '{}' successfully loaded".format(self._package_name))
        except Exception as e:
            raise _error.ThemeLoadError("Error while loading theme package '{}': {}".format(self._package_name, e))

        # Compile assets
        if not reg.get('theme.compiled'):
            assetman.setup()
            assetman.build(self._package_name)
            reg.put('theme.compiled', True)

        self._is_loaded = True

        return self
Beispiel #12
0
    def odm_ui_m_form_setup_widgets(self, frm: form.Form):
        """Hook
        """
        from . import widget as _content_widget

        # Title
        if self.has_field('title'):
            f = self.get_field('title')  # type: odm.field.String
            frm.add_widget(widget.input.Text(
                uid='title',
                label=self.t('title'),
                required=f.is_required,
                min_length=f.min_length,
                max_length=f.max_length,
                value=self.title,
            ))

        # Description
        if self.has_field('description'):
            f = self.get_field('description')  # type: odm.field.String
            frm.add_widget(widget.input.Text(
                uid='description',
                label=self.t('description'),
                required=self.get_field('description').is_required,
                min_length=f.min_length,
                max_length=f.max_length,
                value=self.description,
            ))

        # Images
        if self.has_field('images'):
            frm.add_widget(file_ui.widget.ImagesUpload(
                uid='images',
                label=self.t('images'),
                value=self.f_get('images'),
                max_file_size=reg.get('content.max_image_size', 5),
                max_files=reg.get('content.max_images', 200),
            ))
            if self.get_field('images').is_required:
                frm.add_rule('images', validation.rule.NonEmpty())

        # Video links
        if self.has_field('video_links'):
            frm.add_widget(widget.input.StringList(
                uid='video_links',
                label=self.t('video'),
                add_btn_label=self.t('add_link'),
                value=self.video_links,
            ))
            frm.add_rule('video_links', validation.rule.VideoHostingUrl())

        # Body
        if self.has_field('body'):
            frm.add_widget(ckeditor.widget.CKEditor(
                uid='body',
                label=self.t('body'),
                value=self.f_get('body', process_tags=False),
            ))
            if self.get_field('body').is_required:
                frm.add_rule('body', validation.rule.NonEmpty())

        # Tags
        if self.has_field('tags'):
            frm.add_widget(taxonomy.widget.TokensInput(
                uid='tags',
                weight=250,
                model='tag',
                label=self.t('tags'),
                value=self.tags,
                required=self.get_field('tags').is_required,
            ))

        # External links
        if self.has_field('ext_links'):
            frm.add_widget(widget.input.StringList(
                uid='ext_links',
                weight=550,
                label=self.t('external_links'),
                add_btn_label=self.t('add_link'),
                value=self.ext_links,
                required=self.get_field('ext_links').is_required,
            ))
            frm.add_rule('ext_links', validation.rule.Url())

        # Status
        if self.has_field('status'):
            frm.add_widget(_content_widget.StatusSelect(
                uid='status',
                entity=self,
            ))

        # Publish time
        if self.has_field('publish_time') and self.odm_auth_check_entity_permissions(CONTENT_PERM_SET_PUBLISH_TIME):
            frm.add_widget(widget.select.DateTime(
                uid='publish_time',
                label=self.t('publish_time'),
                value=self.publish_time,
                h_size='col-xs-12 col-12 col-sm-4 col-md-3',
                required=self.get_field('publish_time'),
            ))

        # Language
        lng = lang.get_current() if self.is_new else self.language
        frm.add_widget(widget.static.Text(
            uid='language',
            label=self.t('language'),
            text=lang.lang_title(lng),
            value=lng,
            hidden=False if len(lang.langs()) > 1 else True,
        ))

        # Localizations
        if self.has_field('localization_' + lng) and \
                self.odm_auth_check_entity_permissions(CONTENT_PERM_SET_LOCALIZATION):
            for i, l in enumerate(lang.langs(False)):
                frm.add_widget(_content_widget.EntitySelect(
                    uid='localization_' + l,
                    label=self.t('localization', {'lang': lang.lang_title(l)}),
                    model=self.model,
                    ajax_url_query={'language': l},
                    value=self.f_get('localization_' + l)
                ))

        # Author
        if self.has_field('author') and auth.get_current_user().is_admin:
            frm.add_widget(auth_ui.widget.UserSelect(
                uid='author',
                label=self.t('author'),
                value=auth.get_current_user() if self.is_new else self.author,
                h_size='col-xs-12 col-12 col-sm-4',
                required=True,
            ))
Beispiel #13
0
permissions.define_permission('app.settings.manage', 'app@manage_app_settings', 'app')

# Settings
settings.define('app', settings_form.Form, __name__ + '@application', 'fa fa-cube', 'app.settings.manage')

# Index by section route
router.add_rule('/section/<string:term_alias>', 'index_by_section', 'pytsite.content@index', {
    'model': 'article',
    'term_field': 'section',
})

# Index by tag route
router.add_rule('/tag/<string:term_alias>', 'article_index_by_tag', 'pytsite.content@index', {
    'model': 'article',
    'term_field': 'tags',
})

# Prepare language related tpl globals
language_nav = {}
search_input = {}
for l in lang.langs():
    language_nav[l] = str(widget.select.LanguageNav('language-nav', dropdown=True, language=l))
    search_input[l] = str(content.widget.Search('search-article', model='article',
                                                title=lang.t('app@search', language=l), language=l))

# Tpl globals
tpl.register_global('language_nav', language_nav)
tpl.register_global('search_input', search_input)
tpl.register_global('get_content_sections', lambda: list(content.get_sections()))
tpl.register_global('get_content_pages', lambda: list(content.find('page').get()))
Beispiel #14
0
def parse_json(json_data: _Union[str, dict, list], defaults: dict = None, override: dict = None) -> dict:
    """Parse package's JSON from string
    """
    from pytsite import lang as _lang

    # Load data
    if isinstance(json_data, str):
        json_data = _json.loads(json_data)

    # Check data type
    if not isinstance(json_data, dict):
        raise TypeError('Dict expected, got {}'.format(type(json_data)))

    # Check defaults
    if defaults is None:
        defaults = {}

    # Check name
    pkg_name = json_data.setdefault('name', defaults.get('name'))
    if not (pkg_name and isinstance(pkg_name, str)):
        json_data['name'] = 'Untitled'

    # Check version
    pkg_ver = json_data.setdefault('version', _semver.Version(defaults.get('version', '0.0.1')))
    if not isinstance(pkg_ver, _semver.Version):
        json_data['version'] = _semver.Version(pkg_ver)

    # Check URL
    pkg_url = json_data.setdefault('url', defaults.get('url'))
    if not (pkg_url and isinstance(pkg_url, str)):
        json_data['url'] = 'https://plugins.pytsite.xyz'

    # Check description
    pkg_desc = json_data.setdefault('description', defaults.get('description'))
    if not (pkg_desc and isinstance(pkg_desc, dict)):
        json_data['description'] = pkg_desc = {}

    # Check description translations
    for lng in _lang.langs():
        t_description = pkg_desc.get(lng)
        if not (t_description and isinstance(t_description, str)):
            json_data['description'][lng] = ''

    # Check author
    pkg_author = json_data.setdefault('author', defaults.get('author'))
    if not (pkg_author and isinstance(pkg_author, dict)):
        json_data['author'] = pkg_author = {}
    if not pkg_author.get('name'):
        json_data['author']['name'] = 'PytSite'
    if not pkg_author.get('email'):
        json_data['author']['email'] = '*****@*****.**'
    if not pkg_author.get('url'):
        json_data['author']['url'] = 'https://plugins.pytsite.xyz'

    # Check license info
    pkg_license = json_data.setdefault('license', defaults.get('license'))
    if not (pkg_license and isinstance(pkg_license, dict)):
        json_data['license'] = pkg_license = {}
    if not pkg_license.get('name'):
        json_data['license']['name'] = 'MIT'
    if not pkg_license.get('url'):
        json_data['license']['url'] = 'https://opensource.org/licenses/MIT'

    # Check requirements
    req = json_data.setdefault('requires', defaults.get('requires'))
    if not (req and isinstance(req, dict)):
        json_data['requires'] = req = {'pytsite': None, 'packages': {}, 'plugins': {}}

    # Check required pytsite version
    json_data['requires']['pytsite'] = _semver.VersionRange(req.get('pytsite', '>=0.0.1'))

    # Check required pip packages versions
    json_data['requires']['packages'] = _sanitize_req(req.get('packages', {}))

    # Check required plugins versions
    json_data['requires']['plugins'] = _sanitize_req(req.get('plugins', {}))

    # Override data
    if isinstance(override, dict):
        json_data = parse_json(_util.dict_merge(json_data, override))

    return json_data
Beispiel #15
0
    def exec(self):
        from . import _api

        model = self.arg('model')
        entity = _api.find(model, status='*', check_publish_time=False) \
            .eq('_id', self.arg('eid')) \
            .first()  # type: _model.ContentWithURL

        # Check entity existence
        if not entity:
            raise self.not_found()

        # Check permissions
        if not entity.odm_auth_check_entity_permissions(CONTENT_PERM_VIEW):
            raise self.not_found()

        # Show non-published entities only to authors and users who can edit or delete them
        c_user = auth.get_current_user()
        if (entity.has_field('publish_time') and entity.publish_time > datetime.now()) or \
                (entity.has_field('status') and entity.status in (CONTENT_STATUS_UNPUBLISHED, CONTENT_STATUS_WAITING)):
            if not (entity.author == c_user
                    or entity.odm_auth_check_entity_permissions(
                        [PERM_MODIFY, PERM_DELETE])):
                raise self.not_found()

        # Show warnings about unpublished entities
        if entity.has_field(
                'publish_time') and entity.publish_time > datetime.now():
            router.session().add_warning_message(
                lang.t('content@content_warning_future_publish_time'))
        if entity.has_field('status') and entity.status in (
                CONTENT_STATUS_UNPUBLISHED, CONTENT_STATUS_WAITING):
            router.session().add_warning_message(
                lang.t('content@content_status_warning_{}'.format(
                    entity.status)))

        # Breadcrumb
        breadcrumb = widget.select.Breadcrumb('content-index-breadcrumb')
        breadcrumb.append_item(lang.t('content@home_page'), router.base_url())
        entity.content_breadcrumb(breadcrumb)

        # Meta title
        if entity.has_field('title'):
            title = entity.title
            metatag.t_set('title', title)
            metatag.t_set('og:title', title)
            metatag.t_set('twitter:title', title)

        # Meta description
        if entity.has_field('description'):
            description = entity.f_get('description')
            metatag.t_set('description', description)
            metatag.t_set('og:description', description)
            metatag.t_set('twitter:description', description)

        # Meta keywords
        if entity.has_field('tags'):
            metatag.t_set('keywords', entity.f_get('tags', as_string=True))

        # Meta image
        if entity.has_field('images') and entity.images:
            metatag.t_set('twitter:card', 'summary_large_image')
            image_w = 900
            image_h = 500
            image_url = entity.images[0].get_url(width=image_w, height=image_h)
            metatag.t_set('og:image', image_url)
            metatag.t_set('og:image:width', str(image_w))
            metatag.t_set('og:image:height', str(image_h))
            metatag.t_set('twitter:image', image_url)
        else:
            metatag.t_set('twitter:card', 'summary')

        # Various metatags
        metatag.t_set('og:type', 'article')
        metatag.t_set('og:url', entity.url)
        metatag.t_set('article:publisher', entity.url)

        # 'Author' metatag
        if entity.has_field('author') and entity.author:
            metatag.t_set('author', entity.author.first_last_name)
            metatag.t_set('article:author', entity.author.first_last_name)

        # Alternate languages URLs
        for lng in lang.langs(False):
            f_name = 'localization_' + lng
            if entity.has_field(f_name) and entity.f_get(f_name):
                hreflang.put(lng, entity.f_get(f_name).url)
            else:
                hreflang.remove(lng)

        # Update args
        self.args.update({
            'entity': entity,
            'breadcrumb': breadcrumb,
        })

        # Notify listeners
        events.fire('content@view', entity=entity)

        try:
            # Call a controller provided by application
            return router.call('content_view', self.args)

        except routing.error.RuleNotFound:
            # Render a template provided by application
            return tpl.render('content/view', self.args)
Beispiel #16
0
def _generate_sitemap():
    """Generate content sitemap
    """
    global _sitemap_generation_works

    if _sitemap_generation_works:
        raise RuntimeError('Sitemap generation is still in progress')

    _sitemap_generation_works = True
    logger.info('Sitemap generation start.')

    output_dir = path.join(reg.get('paths.static'), 'sitemap')
    if path.exists(output_dir):
        rmtree(output_dir)
    makedirs(output_dir, 0o755, True)

    sitemap_index = sitemap.Index()
    links_per_file = 50000
    loop_count = 1
    loop_links = 1
    sm = sitemap.Sitemap()
    sm.add_url(router.base_url(), datetime.now(), 'always', 1)
    for lng in lang.langs():
        for model in reg.get('content.sitemap_models', ()):
            logger.info(
                "Sitemap generation started for model '{}', language '{}'".
                format(model, lang.lang_title(lng)))

            for entity in _api.find(model,
                                    language=lng):  # type: ContentWithURL
                sm.add_url(entity.url, entity.publish_time)
                loop_links += 1

                # Flush sitemap
                if loop_links >= links_per_file:
                    loop_count += 1
                    loop_links = 0
                    sitemap_path = sm.write(
                        path.join(output_dir, 'data-%02d.xml' % loop_count),
                        True)
                    logger.info(
                        "'{}' successfully written with {} links".format(
                            sitemap_path, loop_links))
                    sitemap_index.add_url(
                        router.url('/sitemap/{}'.format(
                            path.basename(sitemap_path))))
                    del sm
                    sm = sitemap.Sitemap()

    # If non-flushed sitemap exist
    if len(sm):
        sitemap_path = sm.write(
            path.join(output_dir, 'data-%02d.xml' % loop_count), True)
        logger.info("'{}' successfully written with {} links.".format(
            sitemap_path, loop_links))
        sitemap_index.add_url(
            router.url('/sitemap/{}'.format(path.basename(sitemap_path))))

    if len(sitemap_index):
        sitemap_index_path = sitemap_index.write(
            path.join(output_dir, 'index.xml'))
        logger.info("'{}' successfully written.".format(sitemap_index_path))

    logger.info('Sitemap generation stop.')
    _sitemap_generation_works = False
Beispiel #17
0
    def as_jsonable(self, **kwargs) -> dict:
        """Get JSONable representation of the entity
        """
        r = super().as_jsonable()

        # Publish time
        if self.has_field('publish_time'):
            r['publish_time'] = {
                'w3c': util.w3c_datetime_str(self.publish_time),
                'pretty_date': self.publish_date_pretty,
                'pretty_date_time': self.publish_date_time_pretty,
                'ago': self.publish_time_ago,
            }

        # Author
        if self.has_field('author') and self.author.is_public:
            r['author'] = self.author.as_jsonable()

        # Language
        if self.has_field('language'):
            r['language'] = self.language

        # Localizations
        for lng in lang.langs():
            if self.has_field('localization_' + lng):
                ref = self.f_get('localization_' + lng)
                if ref:
                    r['localization_' + lng] = ref.as_jsonable(**kwargs)

        # Title
        if self.has_field('title'):
            r['title'] = self.title

        # Description
        if self.has_field('description'):
            r['description'] = self.description

        # Body
        if self.has_field('body'):
            r['body'] = self.body

        # Images
        if self.has_field('images'):
            thumb_w = kwargs.get('images_thumb_width', 500)
            thumb_h = kwargs.get('images_thumb_height', 500)

            img_jsonable_args = {
                'thumb_width': thumb_w,
                'thumb_height': thumb_h,
            }
            r['images'] = [img.as_jsonable(**img_jsonable_args) for img in self.images]

            if self.images:
                r['thumbnail'] = self.images[0].get_url(width=thumb_w, height=thumb_h)

        # Tags
        if self.has_field('tags'):
            r['tags'] = [t.as_jsonable() for t in self.tags]

        # External links
        if self.has_field('ext_links'):
            r['ext_links'] = self.ext_links

        # Video links
        if self.has_field('video_links'):
            r['video_links'] = self.video_links

        # Views counter
        if self.has_field('views_count'):
            r['views_count'] = self.views_count

        # Comments counter
        if self.has_field('comments_count'):
            r['comments_count'] = self.comments_count

        # Likes counter
        if self.has_field('likes_count'):
            r['likes_count'] = self.likes_count

        # Bookmarks counter
        if self.has_field('bookmarks_count'):
            r['bookmarks_count'] = self.bookmarks_count

        # Status
        if self.has_field('status'):
            r['status'] = self.status

        # Options
        if self.has_field('options'):
            r['options'] = dict(self.options)

        return r