src/pyams_content/generations/__init__.py
changeset 458 7e500a7ecf38
parent 392 8fc847d83992
child 470 2b552177c142
equal deleted inserted replaced
457:f78bfebec3d6 458:7e500a7ecf38
    12 
    12 
    13 __docformat__ = 'restructuredtext'
    13 __docformat__ = 'restructuredtext'
    14 
    14 
    15 
    15 
    16 # import standard library
    16 # import standard library
       
    17 import logging
       
    18 logger = logging.getLogger("PyAMS (content)")
    17 
    19 
    18 # import interfaces
    20 # import interfaces
    19 from pyams_catalog.interfaces import MINUTE_RESOLUTION, DATE_RESOLUTION
    21 from pyams_catalog.interfaces import MINUTE_RESOLUTION, DATE_RESOLUTION
    20 from pyams_content.interfaces import IBaseContent
    22 from pyams_content.interfaces import IBaseContent
    21 from pyams_content.root.interfaces import ISiteRootToolsConfiguration
    23 from pyams_content.root.interfaces import ISiteRootToolsConfiguration
    22 from pyams_content.shared.common.interfaces import IWfSharedContent
    24 from pyams_content.shared.common.interfaces import IWfSharedContent
    23 from pyams_utils.interfaces.site import ISiteGenerations
    25 from pyams_utils.interfaces.site import ISiteGenerations
    24 from pyams_utils.interfaces.traversing import IPathElements
    26 from pyams_utils.interfaces.traversing import IPathElements
    25 from pyams_workflow.interfaces import IWorkflowState, IWorkflowPublicationInfo
    27 from pyams_workflow.interfaces import IWorkflowState, IWorkflowPublicationInfo
    26 from zope.dublincore.interfaces import IZopeDublinCore
    28 from zope.dublincore.interfaces import IZopeDublinCore
    27 from zope.site.interfaces import INewLocalSite
       
    28 
    29 
    29 # import packages
    30 # import packages
    30 from hypatia.text.lexicon import Lexicon
    31 from hypatia.text.lexicon import Lexicon
    31 from pyams_catalog.index import FieldIndexWithInterface, KeywordIndexWithInterface, DatetimeIndexWithInterface
    32 from pyams_catalog.index import FieldIndexWithInterface, KeywordIndexWithInterface, DatetimeIndexWithInterface
    32 from pyams_catalog.nltk import NltkFullTextProcessor
    33 from pyams_catalog.nltk import NltkFullTextProcessor
    33 from pyams_catalog.site import check_required_indexes
    34 from pyams_catalog.site import check_required_indexes
       
    35 from pyams_content.reference import ReferencesManager
    34 from pyams_content.shared.common.manager import SharedToolContainer
    36 from pyams_content.shared.common.manager import SharedToolContainer
    35 from pyams_content.shared.form.manager import FormsManager
    37 from pyams_content.shared.form.manager import FormsManager
    36 from pyams_content.shared.imagemap.manager import ImageMapsManager
    38 from pyams_content.shared.imagemap.manager import ImageMapsManager
    37 from pyams_content.shared.logo.manager import LogosManager
    39 from pyams_content.shared.logo.manager import LogosManager
    38 from pyams_content.shared.news.manager import NewsManager
    40 from pyams_content.shared.news.manager import NewsManager
    39 from pyams_content.shared.view.manager import ViewsManager
    41 from pyams_content.shared.view.manager import ViewsManager
    40 from pyams_i18n.index import I18nTextIndexWithInterface
    42 from pyams_i18n.index import I18nTextIndexWithInterface
    41 from pyams_security.index import PrincipalsRoleIndex
    43 from pyams_security.index import PrincipalsRoleIndex
    42 from pyams_utils.registry import utility_config, get_global_registry
    44 from pyams_utils.registry import utility_config, get_global_registry
    43 from pyams_utils.site import check_required_utilities
    45 from pyams_utils.site import check_required_utilities
    44 from pyramid.events import subscriber
       
    45 from pyramid.path import DottedNameResolver
    46 from pyramid.path import DottedNameResolver
    46 from zope.lifecycleevent import ObjectCreatedEvent
    47 from zope.lifecycleevent import ObjectCreatedEvent
    47 
    48 
    48 
    49 
    49 def get_fulltext_lexicon(language):
    50 def get_fulltext_lexicon(language):
    50     return Lexicon(NltkFullTextProcessor(language=language))
    51     return Lexicon(NltkFullTextProcessor(language=language))
    51 
    52 
    52 
    53 
    53 REQUIRED_UTILITIES = ()
    54 REQUIRED_UTILITIES = ()
    54 
    55 
    55 
    56 REQUIRED_TABLES = ()
    56 REQUIRED_TOOLS = [('views', ViewsManager),
    57 
    57                   ('news', NewsManager),
    58 REQUIRED_TOOLS = [
    58                   ('logos', LogosManager),
    59     ('views', ViewsManager),
    59                   ('forms', FormsManager),
    60     ('logos', LogosManager),
    60                   ('imagemaps', ImageMapsManager)]
    61     ('imagemaps', ImageMapsManager),
    61 
    62     ('forms', FormsManager),
    62 
    63     ('news', NewsManager)
    63 REQUIRED_INDEXES = [('content_type', FieldIndexWithInterface, {'interface': IBaseContent,
    64 ]
    64                                                                'discriminator': 'content_type'}),
    65 
    65                     ('role:owner', PrincipalsRoleIndex, {'role_id': 'pyams.Owner'}),
    66 REQUIRED_INDEXES = [
    66                     ('role:pilot', PrincipalsRoleIndex, {'role_id': 'pyams.Pilot'}),
    67     ('content_type', FieldIndexWithInterface, {'interface': IBaseContent,
    67                     ('role:manager', PrincipalsRoleIndex, {'role_id': 'pyams.Manager'}),
    68                                                'discriminator': 'content_type'}),
    68                     ('role:contributor', PrincipalsRoleIndex, {'role_id': 'pyams.Contributor'}),
    69     ('role:owner', PrincipalsRoleIndex, {'role_id': 'pyams.Owner'}),
    69                     ('role:webmaster', PrincipalsRoleIndex, {'role_id': 'pyams.Webmaster'}),
    70     ('role:pilot', PrincipalsRoleIndex, {'role_id': 'pyams.Pilot'}),
    70                     ('parents', KeywordIndexWithInterface, {'interface': IPathElements,
    71     ('role:manager', PrincipalsRoleIndex, {'role_id': 'pyams.Manager'}),
    71                                                             'discriminator': 'parents'}),
    72     ('role:contributor', PrincipalsRoleIndex, {'role_id': 'pyams.Contributor'}),
    72                     ('workflow_state', FieldIndexWithInterface, {'interface': IWorkflowState,
    73     ('role:webmaster', PrincipalsRoleIndex, {'role_id': 'pyams.Webmaster'}),
    73                                                                  'discriminator': 'state'}),
    74     ('parents', KeywordIndexWithInterface, {'interface': IPathElements,
    74                     ('workflow_principal', FieldIndexWithInterface, {'interface': IWorkflowState,
    75                                             'discriminator': 'parents'}),
    75                                                                      'discriminator': 'state_principal'}),
    76     ('workflow_state', FieldIndexWithInterface, {'interface': IWorkflowState,
    76                     ('modifiers', KeywordIndexWithInterface, {'interface': IWfSharedContent,
    77                                                  'discriminator': 'state'}),
    77                                                               'discriminator': 'modifiers'}),
    78     ('workflow_principal', FieldIndexWithInterface, {'interface': IWorkflowState,
    78                     ('created_date', DatetimeIndexWithInterface, {'interface': IZopeDublinCore,
    79                                                      'discriminator': 'state_principal'}),
    79                                                                   'discriminator': 'created',
    80     ('modifiers', KeywordIndexWithInterface, {'interface': IWfSharedContent,
    80                                                                   'resolution': DATE_RESOLUTION}),
    81                                               'discriminator': 'modifiers'}),
    81                     ('modified_date', DatetimeIndexWithInterface, {'interface': IZopeDublinCore,
    82     ('created_date', DatetimeIndexWithInterface, {'interface': IZopeDublinCore,
    82                                                                    'discriminator': 'modified',
    83                                                   'discriminator': 'created',
    83                                                                    'resolution': DATE_RESOLUTION}),
    84                                                   'resolution': DATE_RESOLUTION}),
    84                     ('publication_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    85     ('modified_date', DatetimeIndexWithInterface, {'interface': IZopeDublinCore,
    85                                                                       'discriminator': 'publication_date',
    86                                                    'discriminator': 'modified',
    86                                                                       'resolution': MINUTE_RESOLUTION}),
    87                                                    'resolution': DATE_RESOLUTION}),
    87                     ('effective_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    88     ('publication_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    88                                                                     'discriminator': 'publication_effective_date',
    89                                                       'discriminator': 'publication_date',
    89                                                                     'resolution': MINUTE_RESOLUTION}),
    90                                                       'resolution': MINUTE_RESOLUTION}),
    90                     ('push_end_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    91     ('effective_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    91                                                                    'discriminator': 'push_end_date_index',
    92                                                     'discriminator': 'publication_effective_date',
    92                                                                    'resolution': MINUTE_RESOLUTION}),
    93                                                     'resolution': MINUTE_RESOLUTION}),
    93                     ('expiration_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    94     ('push_end_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    94                                                                      'discriminator': 'publication_expiration_date',
    95                                                    'discriminator': 'push_end_date_index',
    95                                                                      'resolution': MINUTE_RESOLUTION}),
    96                                                    'resolution': MINUTE_RESOLUTION}),
    96                     ('first_publication_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    97     ('expiration_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
    97                                                                             'discriminator': 'first_publication_date',
    98                                                      'discriminator': 'publication_expiration_date',
    98                                                                             'resolution': MINUTE_RESOLUTION})]
    99                                                      'resolution': MINUTE_RESOLUTION}),
    99 
   100     ('first_publication_date', DatetimeIndexWithInterface, {'interface': IWorkflowPublicationInfo,
   100 
   101                                                             'discriminator': 'first_publication_date',
   101 def get_tools_manager(site, config, registry=None):
   102                                                             'resolution': MINUTE_RESOLUTION})
   102     """Check for shared tools manager"""
   103 ]
   103     if registry is None:
   104 
   104         registry = get_global_registry()
   105 
   105     name = config.tools_name or \
   106 #
   106            registry.settings.get('pyams_content.config.tools_name', 'tools')
   107 # Checker for required shared tables
   107     if name not in site:
   108 #
   108         manager = SharedToolContainer()
   109 
   109         registry.notify(ObjectCreatedEvent(manager))
   110 def check_required_tables(site, tables=REQUIRED_TABLES, registry=None):
   110         manager.title = {'en': "Shared tools",
   111     """Check for required reference tables"""
   111                          'fr': "Outils partagés"}
   112 
   112         manager.short_name = {'en': "Shared tools",
   113     def get_tables_manager():
   113                               'fr': "Outils partagés"}
   114         # check references tables manager
   114         manager.navigation_name = {'en': "Shared tools",
   115         tables_name = tools_configuration.tables_name or \
   115                                    'fr': "Outils partagés"}
   116                       registry.settings.get('pyams_content.config.tables_name', 'references')
   116         site[name] = manager
   117         if tables_name not in site:
   117         config.tools_name = name
   118             logger.info("Creating references table manager...")
   118     else:
   119             manager = ReferencesManager()
   119         manager = site[name]
   120             registry.notify(ObjectCreatedEvent(manager))
   120     return manager
   121             manager.title = {
   121 
   122                 'en': "References tables",
   122 
   123                 'fr': "Tables de références"
   123 def get_required_tools(manager, config, tools=REQUIRED_TOOLS, registry=None):
   124             }
   124     """Create required shared tools"""
   125             manager.short_name = {
   125     if registry is None:
   126                 'en': "References tables",
   126         registry = get_global_registry()
   127                 'fr': "Tables de références"
   127     for name, default_factory in tools:
   128             }
   128         factory = registry.settings.get('pyams_content.config.{name}_tool_factory'.format(name=name))
   129             site[tables_name] = manager
   129         if (factory is None) or (factory.upper() not in ('NONE', '--')):
   130             tools_configuration.tables_name = tables_name
   130             attr_name = '{name}_tool_name'.format(name=name)
   131         else:
   131             tool_name = getattr(config, attr_name, None) or \
   132             manager = site[tables_name]
   132                         registry.settings.get('pyams_content.config.{name}'.format(name=attr_name), name)
   133         return manager
   133             if tool_name not in manager:
   134 
   134                 if factory is not None:
   135     tools_configuration = ISiteRootToolsConfiguration(site, None)
   135                     factory = DottedNameResolver().resolve(factory)
   136     if tools_configuration is not None:
   136                 else:
   137         if registry is None:
   137                     factory = default_factory
   138             registry = get_global_registry()
   138                 tool = factory()
   139         tables_manager = get_tables_manager()
   139                 registry.notify(ObjectCreatedEvent(tool))
   140         for attr, name, factory in tables:
   140                 manager[tool_name] = tool
   141             table_name = getattr(tools_configuration, attr, None) or \
   141                 setattr(config, attr_name, tool_name)
   142                          registry.settings.get('pyams_config.config.{0}'.format(attr), name)
   142 
   143             if table_name not in tables_manager:
       
   144                 table = factory()
       
   145                 logger.info("Creating table {0!r}...".format(table))
       
   146                 registry.notify(ObjectCreatedEvent(table))
       
   147                 tables_manager[table_name] = table
       
   148                 setattr(tools_configuration, attr, table_name)
       
   149 
       
   150 
       
   151 #
       
   152 # Checker for required shared tools
       
   153 #
   143 
   154 
   144 def check_required_tools(site, config_interface, tools):
   155 def check_required_tools(site, config_interface, tools):
   145     """Check for required shared tools"""
   156     """Check for required shared tools"""
       
   157 
       
   158     def get_tools_manager(site, config, registry=None):
       
   159         """Check for shared tools manager"""
       
   160         if registry is None:
       
   161             registry = get_global_registry()
       
   162         name = config.tools_name or \
       
   163                registry.settings.get('pyams_content.config.tools_name', 'tools')
       
   164         if name not in site:
       
   165             manager = SharedToolContainer()
       
   166             registry.notify(ObjectCreatedEvent(manager))
       
   167             manager.title = {
       
   168                 'en': "Shared tools",
       
   169                 'fr': "Outils partagés"
       
   170             }
       
   171             manager.short_name = {
       
   172                 'en': "Shared tools",
       
   173                 'fr': "Outils partagés"
       
   174             }
       
   175             manager.navigation_name = {
       
   176                 'en': "Shared tools",
       
   177                 'fr': "Outils partagés"
       
   178             }
       
   179             site[name] = manager
       
   180             config.tools_name = name
       
   181         else:
       
   182             manager = site[name]
       
   183         return manager
       
   184 
       
   185     def get_required_tools(manager, config, tools=REQUIRED_TOOLS, registry=None):
       
   186         """Create required shared tools"""
       
   187         if registry is None:
       
   188             registry = get_global_registry()
       
   189         for name, default_factory in tools:
       
   190             factory = registry.settings.get('pyams_content.config.{name}_tool_factory'.format(name=name))
       
   191             if (factory is None) or (factory.upper() not in ('NONE', '--')):
       
   192                 attr_name = '{name}_tool_name'.format(name=name)
       
   193                 tool_name = getattr(config, attr_name, None) or \
       
   194                             registry.settings.get('pyams_content.config.{name}'.format(name=attr_name), name)
       
   195                 if tool_name not in manager:
       
   196                     if factory is not None:
       
   197                         factory = DottedNameResolver().resolve(factory)
       
   198                     else:
       
   199                         factory = default_factory
       
   200                     tool = factory()
       
   201                     registry.notify(ObjectCreatedEvent(tool))
       
   202                     manager[tool_name] = tool
       
   203                     setattr(config, attr_name, tool_name)
       
   204 
   146     configuration = config_interface(site, None)
   205     configuration = config_interface(site, None)
   147     if configuration is not None:
   206     if configuration is not None:
   148         # check shared tools manager
   207         # check shared tools manager
   149         manager = get_tools_manager(site, configuration)
   208         manager = get_tools_manager(site, configuration)
   150         # check for shared tools
   209         # check for shared tools
   151         get_required_tools(manager, configuration, tools)
   210         get_required_tools(manager, configuration, tools)
   152 
   211 
   153 
   212 
   154 def get_required_indexes():
   213 def get_required_indexes():
       
   214     """Get list of required indexes based on lexicon settings"""
   155     indexes = REQUIRED_INDEXES
   215     indexes = REQUIRED_INDEXES
   156     registry = get_global_registry()
   216     registry = get_global_registry()
   157     for code, language in map(lambda x: x.split(':'),
   217     for code, language in map(lambda x: x.split(':'),
   158                               registry.settings.get('pyams_content.lexicon.languages', 'en:english').split()):
   218                               registry.settings.get('pyams_content.lexicon.languages', 'en:english').split()):
   159         indexes.append(('title:{0}'.format(code), I18nTextIndexWithInterface,
   219         indexes.append(('title:{0}'.format(code), I18nTextIndexWithInterface,
   162                          'discriminator': 'title',
   222                          'discriminator': 'title',
   163                          'lexicon': lambda: get_fulltext_lexicon(language)}))
   223                          'lexicon': lambda: get_fulltext_lexicon(language)}))
   164     return indexes
   224     return indexes
   165 
   225 
   166 
   226 
   167 @subscriber(INewLocalSite)
       
   168 def handle_new_local_site(event):
       
   169     """Check for required utilities when a site is created"""
       
   170     site = event.manager.__parent__
       
   171     check_required_utilities(site, REQUIRED_UTILITIES)
       
   172     check_required_indexes(site, get_required_indexes())
       
   173     check_required_tools(site, ISiteRootToolsConfiguration, REQUIRED_TOOLS)
       
   174 
       
   175 
       
   176 @utility_config(name='PyAMS content', provides=ISiteGenerations)
   227 @utility_config(name='PyAMS content', provides=ISiteGenerations)
   177 class WebsiteGenerationsChecker(object):
   228 class WebsiteGenerationsChecker(object):
   178     """PyAMS content package generations checker"""
   229     """PyAMS content package generations checker"""
   179 
   230 
       
   231     order = 100
   180     generation = 1
   232     generation = 1
   181 
   233 
   182     def evolve(self, site, current=None):
   234     def evolve(self, site, current=None):
   183         """Check for required utilities"""
   235         """Check for required utilities, tables and tools"""
   184         check_required_utilities(site, REQUIRED_UTILITIES)
   236         check_required_utilities(site, REQUIRED_UTILITIES)
   185         check_required_indexes(site, get_required_indexes())
   237         check_required_indexes(site, get_required_indexes())
       
   238         check_required_tables(site, REQUIRED_TABLES)
   186         check_required_tools(site, ISiteRootToolsConfiguration, REQUIRED_TOOLS)
   239         check_required_tools(site, ISiteRootToolsConfiguration, REQUIRED_TOOLS)