blob: 7d57fc95fe3672621cfb51fcb50999963078f33c [file] [log] [blame]
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
r"""Wiki specifics for Bloodhound Search plugin."""
from bhsearch import BHSEARCH_CONFIG_SECTION
from bhsearch.api import (ISearchParticipant, BloodhoundSearchApi,
IIndexParticipant, IndexFields)
from bhsearch.search_resources.base import BaseIndexer, BaseSearchParticipant
from bhsearch.utils import get_product
from trac.core import implements
from trac.config import ListOption, Option
from trac.wiki import IWikiChangeListener, WikiSystem, WikiPage
from genshi.builder import tag
WIKI_TYPE = u"wiki"
class WikiIndexer(BaseIndexer):
implements(IWikiChangeListener, IIndexParticipant)
#IWikiChangeListener methods
def wiki_page_added(self, page):
"""Index a recently created ticket."""
self._index_wiki(page)
def wiki_page_changed(self, page, version, t, comment, author, ipnr):
"""Reindex a recently modified ticket."""
# pylint: disable=too-many-arguments, unused-argument
self._index_wiki(page)
def wiki_page_deleted(self, page):
"""Called when a ticket is deleted."""
try:
search_api = BloodhoundSearchApi(self.env)
search_api.delete_doc(
get_product(self.env).prefix, WIKI_TYPE, page.name)
except Exception, e:
if self.silence_on_error.lower() == "true":
self.log.error("Error occurs during wiki indexing. \
The error will not be propagated. Exception: %s", e)
else:
raise
def wiki_page_version_deleted(self, page):
"""Called when a version of a page has been deleted."""
self._index_wiki(page)
def wiki_page_renamed(self, page, old_name):
"""Called when a page has been renamed."""
try:
doc = self.build_doc(page)
search_api = BloodhoundSearchApi(self.env)
search_api.change_doc_id(doc, old_name)
except Exception, e:
if self.silence_on_error:
self.log.error("Error occurs during renaming wiki from %s \
to %s. The error will not be propagated. Exception: %s",
old_name, page.name, e)
else:
raise
def _index_wiki(self, page):
try:
doc = self.build_doc(page)
search_api = BloodhoundSearchApi(self.env)
search_api.add_doc(doc)
except Exception, e:
page_name = None
if page is not None:
page_name = page.name
if self.silence_on_error:
self.log.error("Error occurs during wiki indexing: %s. \
The error will not be propagated. Exception: %s",
page_name, e)
else:
raise
#IIndexParticipant members
def build_doc(self, trac_doc):
page = trac_doc
#This is very naive prototype implementation
#TODO: a lot of improvements must be added here!!!
searchable_name = page.name + ' ' + \
WikiSystem(self.env).format_page_name(page.name, split=True)
doc = {
IndexFields.ID: page.name,
IndexFields.NAME: searchable_name,
'_stored_' + IndexFields.NAME: page.name,
IndexFields.TYPE: WIKI_TYPE,
IndexFields.TIME: page.time,
IndexFields.AUTHOR: page.author,
IndexFields.CONTENT: self.wiki_formatter.format(page.text),
IndexFields.PRODUCT: get_product(self.env).prefix,
}
return doc
def get_entries_for_index(self):
page_names = WikiSystem(self.env).get_pages()
for page_name in page_names:
page = WikiPage(self.env, page_name)
yield self.build_doc(page)
class WikiSearchParticipant(BaseSearchParticipant):
implements(ISearchParticipant)
participant_type = WIKI_TYPE
required_permission = 'WIKI_VIEW'
default_facets = [
IndexFields.PRODUCT,
]
default_grid_fields = [
IndexFields.ID,
IndexFields.TIME,
IndexFields.AUTHOR,
IndexFields.CONTENT,
]
prefix = WIKI_TYPE
default_facets = ListOption(
BHSEARCH_CONFIG_SECTION,
prefix + '_default_facets',
default=",".join(default_facets),
doc="""Default facets applied to search view of specific resource""")
default_view = Option(
BHSEARCH_CONFIG_SECTION,
prefix + '_default_view',
doc = """If true, show grid as default view for specific resource in
Bloodhound Search results""")
default_grid_fields = ListOption(
BHSEARCH_CONFIG_SECTION,
prefix + '_default_grid_fields',
default = ",".join(default_grid_fields),
doc="""Default fields for grid view for specific resource""")
#ISearchParticipant members
def get_title(self):
return "Wiki"
def format_search_results(self, res):
title = res['hilited_name'] or res['name']
return tag('[', res['product'], '] ', title)