Commit 37616dd8 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

* merge Base_showFoundText from erp5_dms.

* move Base_parseSearchString from erp5_dms.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@27500 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent c0c2b23b
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<tuple>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
"""\n
Make SQLCatalog parse given search string and generate an Abstract Syntax Tree.\n
Then, walk this tree and categorize criterion by type (and their alias, see code).\n
"""\n
from DateTime import DateTime\n
\n
def render_filetype_list(filetype_list):\n
return [\'%%.%s\' % (x, ) for x in filetype_list]\n
\n
def render_state_list(state_list):\n
# Note: also used to render type list\n
result = []\n
append = result.append\n
for state in state_list:\n
if state != \'all\':\n
append(state)\n
return result\n
\n
def render_date_range(date_range_list):\n
result = []\n
append = result.append\n
now = DateTime()\n
for date_range in date_range_list:\n
# XXX: original version used a regex, but we can\'t import\n
# "re" module here, so fallback on hand-crafted parsing.\n
# Original regex: \'(\\d)([wmy]).*\'\n
# State meaning:\n
# 0: we expect only decimals\n
# 1: we expect one of \'w\', \'m\', or \'y\'\n
state = 0\n
duration_char_list = []\n
multiplicator = None\n
for char in date_range:\n
if state == 0:\n
if \'0\' <= char <= \'9\':\n
duration_char_list.append(char)\n
else:\n
state = 1\n
if state == 1:\n
if len(duration_char_list):\n
if char == \'w\':\n
multiplicator = 7\n
elif char == \'m\':\n
multiplicator = 30\n
elif char == \'y\':\n
multiplicator = 365\n
break\n
if multiplicator is not None:\n
duration = int(\'\'.join(duration_char_list))\n
append(now - duration * multiplicator)\n
return result\n
\n
criterion_alias_dict = {\n
\'state\': (\'simulation_state\', render_state_list),\n
\'type\': (\'portal_type\', render_state_list),\n
\'filetype\': (\'source_reference\', render_filetype_list),\n
\'file\': (\'source_reference\', None),\n
\'created\': (\'creation_from\', render_date_range),\n
\'simulation_state\': (True, None),\n
\'language\': (True, None),\n
\'version\': (True, None),\n
\'reference\': (True, None),\n
\'portal_type\': (True, None),\n
\'source_reference\': (True, None),\n
\'creation_from\': (True, None),\n
\'searchabletext\': (True, None),\n
}\n
\n
DEFAULT_CRITERION_ALIAS = \'searchabletext\'\n
\n
def resolveCriterion(criterion_alias, criterion_value_list):\n
initial_criterion_alias = criterion_alias\n
# XXX: should be a set\n
seen_alias_dict = {} # Protection against endless loops\n
while True:\n
next_alias, value_list_renderer = criterion_alias_dict.get(criterion_alias, (DEFAULT_CRITERION_ALIAS, None))\n
if value_list_renderer is not None:\n
criterion_value_list = value_list_renderer(criterion_value_list)\n
if next_alias is True:\n
break\n
seen_alias_dict[criterion_alias] = None\n
if next_alias in seen_alias_dict:\n
raise Exeption, \'Endless alias loop detected: lookup of %r reached alias %r twice\' % (initial_criterion_alias, next_alias)\n
criterion_alias = next_alias\n
return criterion_alias, criterion_value_list\n
\n
def recurseSyntaxNode(node, criterion=DEFAULT_CRITERION_ALIAS):\n
if node.isColumn():\n
result = recurseSyntaxNode(node.getSubNode(), criterion=node.getColumnName())\n
else:\n
result = {}\n
if node.isLeaf():\n
result[criterion] = [node.getValue()]\n
else:\n
for subnode in node.getNodeList():\n
for criterion, value_list in recurseSyntaxNode(subnode, criterion=criterion).items():\n
result.setdefault(criterion, []).extend(value_list)\n
return result\n
\n
def acceptAllColumns(column):\n
return True\n
\n
node = context.getPortalObject().portal_catalog.getSQLCatalog().parseSearchText(searchstring, search_key=\'FullTextKey\', is_valid=acceptAllColumns)\n
result = {}\n
if node is None:\n
result[\'searchabletext\'] = searchstring\n
else:\n
for criterion, value_list in recurseSyntaxNode(node).items():\n
criterion, value_list = resolveCriterion(criterion, value_list)\n
result.setdefault(criterion, []).extend(value_list)\n
filtered_result = {}\n
for criterion, value_list in result.items():\n
if len(value_list) > 0:\n
filtered_result[criterion] = value_list\n
result = filtered_result\n
for criterion, value_list in result.items():\n
# XXX: yuck\n
if criterion == \'searchabletext\':\n
result[\'searchabletext\'] = \' \'.join(value_list)\n
if len(value_list) == 1:\n
result[criterion] = value_list[0]\n
if \'searchabletext\' not in result:\n
result[\'searchabletext\'] = \'\'\n
return result\n
]]></string> </value>
</item>
<item>
<key> <string>_code</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>searchstring</string> </value>
</item>
<item>
<key> <string>errors</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>func_code</string> </key>
<value>
<object>
<klass>
<global name="FuncCode" module="Shared.DC.Scripts.Signature"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>co_argcount</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>co_varnames</string> </key>
<value>
<tuple>
<string>searchstring</string>
<string>DateTime</string>
<string>render_filetype_list</string>
<string>render_state_list</string>
<string>render_date_range</string>
<string>None</string>
<string>True</string>
<string>criterion_alias_dict</string>
<string>DEFAULT_CRITERION_ALIAS</string>
<string>resolveCriterion</string>
<string>recurseSyntaxNode</string>
<string>acceptAllColumns</string>
<string>_getattr_</string>
<string>context</string>
<string>node</string>
<string>result</string>
<string>_write_</string>
<string>_getiter_</string>
<string>criterion</string>
<string>value_list</string>
<string>filtered_result</string>
<string>len</string>
<string>_getitem_</string>
</tuple>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>func_defaults</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_parseSearchString</string> </value>
</item>
<item>
<key> <string>warnings</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -62,23 +62,58 @@
words in the text itself.\n
"""\n
\n
is_gadget_mode = context.REQUEST.get(\'is_gadget_mode\', 0)\n
\n
if is_gadget_mode:\n
# in gadget mode less space is available thus show less text\n
max_text_length = 100\n
max_lines = 1\n
\n
def getRandomDocumentTextExcerpt(document_text):\n
# try to get somewhat arbitrary choice of searchable attrs\n
if isinstance(document_text, str) and document_text!=\'\':\n
document_text = document_text.decode(\'utf-8\', \'ignore\')\n
start = min(len(document_text) - 300, 200)\n
return \'... %s ...\' %document_text[start:start + max_text_length]\n
else:\n
return \'\'\n
\n
# get search words from listbox selection\n
argument_names = (\'advanced_search_text\', \n
\'your_search_text\',\n
\'title\',\n
\'reference\',\n
\'searchabletext\', \n
\'searchabletext_any\',\n
\'searchabletext_all\', \n
\'searchabletext_phrase\',)\n
\n
if document_text is None:\n
document_text = context.getSearchableText()\n
\n
if selection is not None:\n
params = selection.getParams()\n
else:\n
params = context.portal_selections.getSelectionParamsFor(\'search_result_selection\')\n
search_words = params.get(\'your_search_text\')\n
\n
if search_words is None:\n
return \'\'\n
else:\n
params = [params.get(name, \'\') for name in argument_names]\n
# flatten value if it is list\n
params = [(hasattr(param, \'sort\') and \' \'.join(param) or param) for param in params]\n
search_string = \' \'.join(params).strip()\n
\n
if document_text is None:\n
document_text = context.getSearchableText()\n
if search_string != \'\':\n
search_argument_list = context.Base_parseSearchString(search_string)\n
search_string = search_argument_list.get(\'searchabletext\', \'\')\n
\n
if search_string == \'\':\n
# the searched words are empty (e.g. because we used only parameters \n
# without pure searchable text)\n
return getRandomDocumentTextExcerpt(document_text)\n
else:\n
found_text_fragments = context.Base_getExcerptText(\n
context, \\\n
document_text, \\\n
search_words, \\\n
search_string, \\\n
tags = (\'<em>\', \'</em>\'), \\\n
trail = 5, \\\n
maxlines = max_lines)\n
......@@ -131,11 +166,21 @@ else:\n
<string>selection</string>
<string>max_lines</string>
<string>max_text_length</string>
<string>None</string>
<string>_getattr_</string>
<string>params</string>
<string>context</string>
<string>search_words</string>
<string>is_gadget_mode</string>
<string>getRandomDocumentTextExcerpt</string>
<string>argument_names</string>
<string>None</string>
<string>params</string>
<string>append</string>
<string>$append0</string>
<string>_getiter_</string>
<string>name</string>
<string>param</string>
<string>hasattr</string>
<string>search_string</string>
<string>search_argument_list</string>
<string>found_text_fragments</string>
<string>map</string>
<string>str</string>
......
1226
\ No newline at end of file
1227
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment