Skip to content
Snippets Groups Projects
plugin.py 15.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • root's avatar
    root committed
    # import from third parties
    
    from dateutil.parser import parse
    
    root's avatar
    root committed
    import json
    
    from ckan.types import Schema
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
    # imports from ckan
    
    from ckan.lib.plugins import DefaultTranslation
    import ckan.plugins as p
    import ckan.plugins.toolkit as tk
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
    # imports from this extension
    
    import ckanext.odsh.helpers as helpers_odsh
    
    root's avatar
    root committed
    import ckanext.odsh.helper_pkg_dict as helper_pkg_dict
    
    Thorge Petersen's avatar
    Thorge Petersen committed
    from .helper_pkg_dict import HelperPgkDict
    
    root's avatar
    root committed
    import ckanext.odsh.logic.action as action
    import ckanext.odsh.validation as validation
    import ckanext.odsh.search as search
    import ckanext.odsh.tools as tools
    
    from ckanext.odsh.views import default
    
    # from ckanext.odsh.views import package
    
    from ckanext.odsh.views import user
    
    from ckanext.odsh.views import harvest
    
    Thorge Petersen's avatar
    Thorge Petersen committed
    from ckanext.odsh.views import feed
    
    # from ckanext.dcat import blueprints as dcat_view
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
    log = logging.getLogger(__name__)
    
    anonymous's avatar
    anonymous committed
    
    
    anonymous's avatar
    anonymous committed
    
    
    class OdshPlugin(p.SingletonPlugin, DefaultTranslation, tk.DefaultDatasetForm):
        p.implements(p.IActions)
        p.implements(p.IConfigurer)
        p.implements(p.IDatasetForm)
        p.implements(p.IFacets)
        p.implements(p.IPackageController, inherit=True)
        p.implements(p.ITemplateHelpers)
        p.implements(p.ITranslation)
        p.implements(p.IValidators)
        p.implements(p.IResourceController, inherit=True)
        p.implements(p.IBlueprint)
    
    
        # IBlueprint
        def get_blueprint(self):
    
            log.debug("OdshPlugin::get_blueprint")
    
    
            # Default
            bp_default = default.blueprint
            rules = [
                ('/info_page', 'info_page', default.info_page),
                ('/home', 'start', default.start),
    
                ('/robots.txt', 'robots_txt', default.robots_txt),
    
                ('/not_found', 'not_found', default.not_found), ]
            for rule in rules:
                bp_default.add_url_rule(*rule)
    
            # DCAT
    
            # if tk.asbool(tk.config.get('ckanext.dcat.enable_rdf_endpoints', True)):
    
            #     helpers_odsh.odsh_remove_route(map, 'dcat_catalog')
    
            #     bp_default.add_url_rule('/catalog.<any("xml", "rdf", "n3", "ttl", "jsonld"):_format>', view_func=dcat_view.read_catalog, defaults={'_format': 'xml'}, methods=['GET'])
    
            # Package
    
            # bp_package = package.blueprint
            # rules = [
            #     ('/dataset/<id>/resource/<resource_id>', 'redirect_dataset_resource', package.redirect_dataset_resource), ]
            # for rule in rules:
            #     bp_package.add_url_rule(*rule)
    
    
            # User
            bp_user = user.blueprint
            bp_user.add_url_rule(u'/user', endpoint='user_index',
                                 view_func=user.index, strict_slashes=False)
    
    Thorge Petersen's avatar
    Thorge Petersen committed
            # bp_user.add_url_rule(u'/user/register', view_func=user.register)
    
    Thorge Petersen's avatar
    Thorge Petersen committed
    
            # Harvest
    
            bp_harvest = harvest.blueprint
    
            bp_harvest.add_url_rule(u'/harvest', view_func=harvest.search, strict_slashes=False)
    
            bp_harvest.add_url_rule(u'/harvest/new', view_func=harvest.new)
    
            bp_harvest.add_url_rule(u'/harvest/<id>', view_func=harvest.read)
    
            bp_harvest.add_url_rule(u'/harvest/about/<id>', view_func=harvest.about)
    
    Thorge Petersen's avatar
    Thorge Petersen committed
            # Feed
            bp_feed = feed.blueprint
            bp_feed.add_url_rule(u'/feeds/custom.atom', methods=[u'GET'], view_func=feed.custom)
    
    
            return [bp_default, bp_user, bp_harvest, bp_feed] # bp_package
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        # IActions
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        def get_actions(self):
            return {'package_create': action.odsh_package_create,
    
                    'user_update': action.odsh_user_update,
    
                    'user_create': action.odsh_user_create,
    
                    'resource_create': action.odsh_resource_create, }
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        # IConfigurer
    
    anonymous's avatar
    anonymous committed
    
        def update_config(self, config_):
    
            tk.add_template_directory(config_, 'templates')
            tk.add_public_directory(config_, 'public')
            tk.add_resource('assets', 'ckanext-odsh')
    
        def after_map(self, map):
            return map
    
    root's avatar
    root committed
        def package_types(self):
            # This plugin doesn't handle any special package types, it just
            # registers itself as the default (above).
            return []
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        def is_fallback(self):
            # Return True to register this plugin as the default handler for
            # package types not handled by any other IDatasetForm plugin.
            return True
    
        def create_package_schema(self) -> Schema:
            log.debug("OdshPlugin::create_package_schema")
            schema: Schema = super(OdshPlugin, self).create_package_schema()
            schema = self._update_schema(schema)
            schema = self._update_create_or_update_package_schema(schema)
    
    root's avatar
    root committed
            return schema
    
        def update_package_schema(self) -> Schema:
            log.debug("OdshPlugin::update_package_schema")
            schema: Schema = super(OdshPlugin, self).update_package_schema()
            schema = self._update_schema(schema)
            schema = self._update_create_or_update_package_schema(schema)
    
    root's avatar
    root committed
            return schema
    
        def show_package_schema(self) -> Schema:
            log.debug("OdshPlugin::show_package_schema")
            schema: Schema = super(OdshPlugin, self).show_package_schema()
            schema = self._update_show_package_schema(schema)
    
    root's avatar
    root committed
            return schema
    
        def _update_schema(self, schema: Schema) -> Schema:
    
    root's avatar
    root committed
            for field in ['title', 'license_id']:
    
                schema.update({field: [tk.get_converter('not_empty')]})
    
            for field in ['reference','applicableLegislation','hvdCategory', 'is_replaced_by', 'version_notes']:
    
                      tk.get_validator('ignore_missing'),
                      tk.get_converter('convert_to_extras')
    
    root's avatar
    root committed
            schema['resources'].update({
    
                'url': [tk.get_converter('not_empty')],
                'format': [tk.get_converter('odsh_validate_format')],
    
    root's avatar
    root committed
            })
    
    root's avatar
    root committed
            schema['extras'].update({
                'key': [
    
                    tk.get_converter('known_spatial_uri'),
                    tk.get_converter('validate_licenseAttributionByText'),
    
    root's avatar
    root committed
                ]
            })
            schema.update(
    
                {'__extras':  [tk.get_converter('odsh_validate_extras')]})
            return schema
    
        def _update_create_or_update_package_schema(self, schema: Schema) -> Schema:
    
    root's avatar
    root committed
            schema.update({
                'language': [
    
                    tk.get_validator('ignore_missing'),
                    tk.get_converter('convert_to_extras')
    
    root's avatar
    root committed
                ],
                'thumbnail': [
    
                    tk.get_validator('ignore_missing'),
                    tk.get_converter('convert_to_extras')
    
    root's avatar
    root committed
                ],
    
                'relatedPackage': [
    
                    tk.get_validator('validate_relatedPackage'),
                    tk.get_converter('convert_to_extras')
    
                ],
                'accessibility': [
    
                    tk.get_validator('ignore_missing'),
                    tk.get_converter('convert_to_extras')
    
                    tk.get_validator('ignore_missing'),
                    tk.get_converter('convert_to_extras')
    
                    tk.get_validator('ignore_missing'),
                    tk.get_converter('convert_to_extras')
    
    root's avatar
    root committed
            })
            return schema
    
        def _update_show_package_schema(self, schema: Schema) -> Schema:
    
    root's avatar
    root committed
            schema.update({
                'language': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
    root's avatar
    root committed
                ],
                'thumbnail': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
    root's avatar
    root committed
                ],
    
                'relatedPackage': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
                ],
                'accessibility': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
    Thorge Petersen's avatar
    Thorge Petersen committed
                ],
                'reference': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
    Thorge Petersen's avatar
    Thorge Petersen committed
                ],
                'hvdCategory': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
    Thorge Petersen's avatar
    Thorge Petersen committed
                ],
                'applicableLegislation': [
    
                    tk.get_converter('convert_from_extras'),
                    tk.get_validator('ignore_missing')
    
    root's avatar
    root committed
            })
            return schema
    
    root's avatar
    root committed
        # IFacets
    
    root's avatar
    root committed
        def dataset_facets(self, facets_dict, package_type):
    
    Thorge Petersen's avatar
    Thorge Petersen committed
            return OrderedDict({'organization': _('Organizations'),
                                'groups': _('Category'),
                                'res_format': _('File format'),
                                'license_title': _('License'),
    
                                #                            'tags': _('Tags'),
    
    root's avatar
    root committed
                                'openness': _('Open-Data-Eigenschaften')
                                })
    
    root's avatar
    root committed
        def group_facets(self, facets_dict, group_type, package_type):
    
    Thorge Petersen's avatar
    Thorge Petersen committed
            return OrderedDict({'organization': _('Organizations'),
                                'res_format': _('File format'),
                                'license_title': _('License'),
                                'groups': _('Category')})
    
    root's avatar
    root committed
        def organization_facets(self, facets_dict, organization_type, package_type):
    
    Thorge Petersen's avatar
    Thorge Petersen committed
            return OrderedDict({'organization': _('Organizations'),
                                'res_format': _('File format'),
                                'license_title': _('License'),
                                'groups': _('Category')})
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        # IPackageController
    
    anonymous's avatar
    anonymous committed
    
    
        def after_dataset_show(self, context, pkg_dict):
    
    root's avatar
    root committed
            '''
            corrects missing relationships in pkg dict
            adds the following key-value-pairs to pkg_dict:
            # key: 'is_new', value: True if the dataset has been created within the last month
            '''
    
            pkg_dict = helpers_odsh.correct_missing_relationship(
    
    root's avatar
    root committed
                pkg_dict,
    
                helpers_odsh.get_pkg_relationships_from_model(pkg_dict)
    
    root's avatar
    root committed
            )
            self._update_is_new_in_pkg_dict(pkg_dict)
    
    root's avatar
    root committed
            return pkg_dict
    
    root's avatar
    root committed
            '''
            adds the following key-value-pairs to pkg_dict:
            # key: 'is_new', value: True if the dataset has been created within the last month
            '''
            self._update_is_new_in_pkg_dict(pkg_dict)
            return pkg_dict
    
        def after_dataset_create(self, context, resource):
    
    root's avatar
    root committed
            if resource.get('package_id'):
                tools.add_attributes_resources(context, resource)
    
        def after_dataset_update(self, context, resource):
    
    root's avatar
    root committed
            if resource.get('package_id'):
                tools.add_attributes_resources(context, resource)
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        @staticmethod
        def _update_is_new_in_pkg_dict(pkg_dict):
            is_new = HelperPgkDict(pkg_dict).is_package_new()
            pkg_dict.update({'is_new': is_new})
    
    
    root's avatar
    root committed
            # make special date fields solr conform
            fields = ["issued", "temporal_start", "temporal_end"]
            for field in fields:
                field = 'extras_' + field
                if field in dict_pkg and dict_pkg[field]:
                    d = parse(dict_pkg[field])
                    dict_pkg[field] = '{0.year:04d}-{0.month:02d}-{0.day:02d}T00:00:00Z'.format(
                        d)
    
    root's avatar
    root committed
            self.map_qa_score(dict_pkg)
    
            if 'qa' in dict_pkg:
              dict_pkg.pop('qa')
    
    
    root's avatar
    root committed
            return dict_pkg
    
    Thorge Petersen's avatar
    Thorge Petersen committed
        
        # Add the custom parameters to Solr's facet queries
        # use several daterange queries agains temporal_start and temporal_end field
        # TODO: use field of type date_range in solr index instead
        def before_dataset_search(self, search_params):
            return search.before_dataset_search(search_params)
    
    anonymous's avatar
    anonymous committed
    
    
    root's avatar
    root committed
        # ITemplateHelpers
    
    root's avatar
    root committed
        def get_helpers(self):
            # Template helper function names should begin with the name of the
            # extension they belong to, to avoid clashing with functions from
            # other extensions.
    
            return {
    
    	        'odsh_main_groups': helpers_odsh.odsh_main_groups,
    
    Thorge Petersen's avatar
    Thorge Petersen committed
              'odsh_now': helpers_odsh.odsh_now,
              'odsh_group_id_selected': helpers_odsh.odsh_group_id_selected,
              'odsh_get_facet_items_dict': helpers_odsh.odsh_get_facet_items_dict,
              'odsh_openness_score_dataset_html': helpers_odsh.odsh_openness_score_dataset_html,
              'odsh_get_resource_details': helpers_odsh.odsh_get_resource_details,
              'odsh_get_resource_views': helpers_odsh.odsh_get_resource_views,
              'odsh_get_bounding_box': helpers_odsh.odsh_get_bounding_box,
              'odsh_get_spatial_text': helpers_odsh.odsh_get_spatial_text,
              'odsh_render_datetime': helpers_odsh.odsh_render_datetime,
              'odsh_resource_formats': helpers_odsh.odsh_resource_formats,
              'odsh_encodeurl': helpers_odsh.odsh_encodeurl,
              'odsh_extract_error': helpers_odsh.odsh_extract_error,
              'odsh_extract_error_new': helpers_odsh.odsh_extract_error_new,
              'odsh_extract_value_from_extras': helpers_odsh.odsh_extract_value_from_extras,
    
    Thorge Petersen's avatar
    Thorge Petersen committed
              'odsh_create_checksum': helpers_odsh.odsh_create_checksum,
              'presorted_license_options': helpers_odsh.presorted_license_options,
              'odsh_has_more_facets': helpers_odsh.odsh_has_more_facets,
              'odsh_public_url': helpers_odsh.odsh_public_url,
              'odsh_spatial_extends_available': helpers_odsh.spatial_extends_available,
              'odsh_public_resource_url': helpers_odsh.odsh_public_resource_url,
              'odsh_show_testbanner': helpers_odsh.odsh_show_testbanner,
              'get_daterange_prettified': helper_pkg_dict.get_daterange_prettified,
              'get_language_of_package': helpers_odsh.get_language_of_package,
              'get_language_icon': helpers_odsh.get_language_icon,
              'short_name_for_category': helpers_odsh.short_name_for_category,
              'get_spatial_for_selection': helpers_odsh.get_spatial_for_selection,
              'get_language_for_selection': helpers_odsh.get_language_for_selection,
              'get_resource_size': helpers_odsh.get_resource_size,
              'get_address_org':helpers_odsh.get_address_org,
              'get_body_mail':helpers_odsh.get_body_mail,
    
              'odsh_load_applicable_legislations': helpers_odsh.odsh_load_applicable_legislations,
              'odsh_load_hvd_categories': helpers_odsh.odsh_load_hvd_categories,
    
    Thorge Petersen's avatar
    Thorge Petersen committed
              'odsh_load_mdk_sample_dataset': helpers_odsh.odsh_load_mdk_sample_dataset,
              'odsh_load_raw_mdk_sample_dataset': helpers_odsh.odsh_load_raw_mdk_sample_dataset,
    
              'format_resource_format': helpers_odsh.format_resource_format,
    
              'odsh_matomo_enabled': helpers_odsh.odsh_show_testbanner,
              'odsh_matomo_base_uri': helpers_odsh.odsh_matomo_base_uri,
              'odsh_matomo_site_id': helpers_odsh.odsh_matomo_site_id,
    
    root's avatar
    root committed
        
        # IValidators
    
        def get_validators(self):
    
    anonymous's avatar
    anonymous committed
            return validation.get_validators()
    
    anonymous's avatar
    anonymous committed
        scores = [['0OL'], ['0OL', '1RE'], ['0OL', '1RE', '2OF'], [
            '0OL', '1RE', '2OF', '3URI'], ['0OL', '1RE', '2OF', '3URI', '4LD']]
    
    
        def map_qa_score(self, dict_pkg):
            if 'validated_data_dict' in dict_pkg and 'openness_score' in dict_pkg['validated_data_dict']:
    
    anonymous's avatar
    anonymous committed
                d = json.loads(dict_pkg['validated_data_dict'])
                score = -1
                for r in d['resources']:
    
                    if ('qa' in r) and (type(r['qa']) is dict) and ('openness_score' in r['qa']):
                        s = int(r['qa']['openness_score'])
                        if s > score:
                            score = s
    
    anonymous's avatar
    anonymous committed
                if score > 0:
                    dict_pkg['openness'] = OdshPlugin.scores[score-1]