# HG changeset patch # User Thierry Florac # Date 1545988785 -3600 # Node ID 9870e7467087399ab61cbc580ce4a6805d91ad61 # Parent d4ae54d8fe174339bac6b1c73862ad6306303294 Added glossary management features diff -r d4ae54d8fe17 -r 9870e7467087 src/pyams_content/features/glossary/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/glossary/__init__.py Fri Dec 28 10:19:45 2018 +0100 @@ -0,0 +1,57 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +import logging +import pickle +from ahocorasick import Automaton + +from pyams_cache.beaker import get_cache +from pyams_content.component.theme import ITagsManager +from pyams_thesaurus.interfaces.thesaurus import IThesaurus +from pyams_utils.registry import query_utility + + +logger = logging.getLogger("PyAMS (content)") + +GLOSSARY_CACHE_REGION = 'persistent' +GLOSSARY_CACHE_NAME = 'PyAMS::glossary' +GLOSSARY_CACHE_KEY = 'automaton' + + +def get_glossary_automaton(root): + """Generate and store glossary automaton""" + # generate Automaton + tags_manager = ITagsManager(root) + if not tags_manager.enable_glossary: + return + thesaurus = query_utility(IThesaurus, name=tags_manager.glossary_thesaurus_name) + if thesaurus is None: + return + logger.debug("Building glossary automaton...") + automaton = Automaton() + for term in thesaurus.terms.values(): + if term.status == 'published': + automaton.add_word(term.label, term.label) + automaton.make_automaton() + logger.debug("Automaton built with {} terms".format(len(automaton))) + # store automaton items + glossary_cache = get_cache(GLOSSARY_CACHE_REGION, GLOSSARY_CACHE_NAME) + glossary_cache.set_value(GLOSSARY_CACHE_KEY, pickle.dumps(automaton)) + return automaton + + +def reset_glossary_automaton(): + """Re-initialize glossary automaton""" + glossary_cache = get_cache(GLOSSARY_CACHE_REGION, GLOSSARY_CACHE_NAME) + glossary_cache.clear() diff -r d4ae54d8fe17 -r 9870e7467087 src/pyams_content/features/glossary/interfaces.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/glossary/interfaces.py Fri Dec 28 10:19:45 2018 +0100 @@ -0,0 +1,25 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.interface import Interface + +from pyams_scheduler.interfaces import ITask + + +class IGlossaryUpdaterTaskInfo(Interface): + """Glossary updater task info""" + + +class IGlossaryUpdaterTask(ITask, IGlossaryUpdaterTaskInfo): + """Glossary updater task interface""" diff -r d4ae54d8fe17 -r 9870e7467087 src/pyams_content/features/glossary/task.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/glossary/task.py Fri Dec 28 10:19:45 2018 +0100 @@ -0,0 +1,54 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from pyramid.events import subscriber +from zope.interface import implementer +from zope.lifecycleevent import IObjectAddedEvent, IObjectModifiedEvent + +from pyams_content.component.theme import ITagsManager +from pyams_content.features.glossary import get_glossary_automaton +from pyams_content.features.glossary.interfaces import IGlossaryUpdaterTask +from pyams_content.root import ISiteRoot +from pyams_scheduler.interfaces import IScheduler +from pyams_scheduler.task import Task +from pyams_thesaurus.interfaces.term import IThesaurusTerm +from pyams_utils.registry import get_utility +from pyams_utils.request import check_request +from pyams_utils.traversing import get_parent + + +@implementer(IGlossaryUpdaterTask) +class GlossaryUpdaterTask(Task): + """Glossary updater task""" + + settings_view_name = None + + def run(self, report): + root = get_parent(self, ISiteRoot) + get_glossary_automaton(root) + + +@subscriber(IObjectAddedEvent, context_selector=IThesaurusTerm) +@subscriber(IObjectModifiedEvent, context_selector=IThesaurusTerm) +def handle_updated_thesaurus_term(event): + """Reset glossary automaton on term update""" + request = check_request() + tags_manager = ITagsManager(request.root) + if not tags_manager.enable_glossary: + return + scheduler = get_utility(IScheduler) + for task in scheduler.values(): + if IGlossaryUpdaterTask.providedBy(task): + task.launch() + break diff -r d4ae54d8fe17 -r 9870e7467087 src/pyams_content/features/glossary/zmi/__init__.py diff -r d4ae54d8fe17 -r 9870e7467087 src/pyams_content/features/glossary/zmi/task.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_content/features/glossary/zmi/task.py Fri Dec 28 10:19:45 2018 +0100 @@ -0,0 +1,53 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + +from zope.component.interfaces import ISite + +from pyams_content.features.glossary.task import GlossaryUpdaterTask +from pyams_form.form import ajax_config, AJAXAddForm +from pyams_pagelet.pagelet import pagelet_config +from pyams_scheduler.zmi.scheduler import SchedulerTasksTable +from pyams_scheduler.zmi.task import TaskBaseAddForm +from pyams_skin.interfaces.viewlet import IToolbarAddingMenu +from pyams_skin.layer import IPyAMSLayer +from pyams_skin.viewlet.toolbar import ToolbarMenuItem +from pyams_utils.interfaces import MANAGE_SYSTEM_PERMISSION +from pyams_viewlet.viewlet import viewlet_config + +from pyams_content import _ + + +@viewlet_config(name='add-glossary-updater-task.menu', context=ISite, layer=IPyAMSLayer, + view=SchedulerTasksTable, manager=IToolbarAddingMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=110) +class GlossaryUpdaterTaskAddMenu(ToolbarMenuItem): + """Glossary updater task add menu""" + + label = _("Add glossary updater task...") + label_css_class = 'fa fa-fw fa-book' + url = 'add-glossary-updater-task.html' + modal_target = True + + +@pagelet_config(name='add-glossary-updater-task.html', context=ISite, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +@ajax_config(name='add-glossary-updater-task.json', context=ISite, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, base=AJAXAddForm) +class GlossaryUpdaterTaskAddForm(TaskBaseAddForm): + """Glossary updater task add form""" + + legend = _("Add glossary updater") + icon_css_class = 'fa fa-fw fa-book' + + task_factory = GlossaryUpdaterTask