rer.solrpush 1.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rer/solrpush/__init__.py +7 -0
- rer/solrpush/adapters/__init__.py +1 -0
- rer/solrpush/adapters/configure.zcml +13 -0
- rer/solrpush/adapters/file.py +52 -0
- rer/solrpush/adapters/rss_feed.py +28 -0
- rer/solrpush/behaviors/__init__.py +0 -0
- rer/solrpush/behaviors/configure.zcml +16 -0
- rer/solrpush/behaviors/solr_fields.py +41 -0
- rer/solrpush/browser/__init__.py +0 -0
- rer/solrpush/browser/configure.zcml +111 -0
- rer/solrpush/browser/controlpanel.py +96 -0
- rer/solrpush/browser/elevate_settings.py +35 -0
- rer/solrpush/browser/maintenance.py +476 -0
- rer/solrpush/browser/query_debug.py +12 -0
- rer/solrpush/browser/querybuilder.py +168 -0
- rer/solrpush/browser/scales.py +80 -0
- rer/solrpush/browser/static/.gitkeep +0 -0
- rer/solrpush/browser/static/dist/dev/main.js +58240 -0
- rer/solrpush/browser/static/dist/dev/main.js.map +180 -0
- rer/solrpush/browser/static/dist/prod/main.js +9604 -0
- rer/solrpush/browser/static/dist/prod/main.js.map +1 -0
- rer/solrpush/browser/static/javascripts/FacetsContainer/index.js +46 -0
- rer/solrpush/browser/static/javascripts/ProgressBar/index.js +40 -0
- rer/solrpush/browser/static/javascripts/ProgressBarContainer/index.js +66 -0
- rer/solrpush/browser/static/javascripts/index.js +14 -0
- rer/solrpush/browser/static/package.json +13 -0
- rer/solrpush/browser/static/styles.css +22 -0
- rer/solrpush/browser/static/styles.css.map +1 -0
- rer/solrpush/browser/static/styles.scss +27 -0
- rer/solrpush/browser/static/yarn.lock +1408 -0
- rer/solrpush/browser/templates/controlpanel_layout.pt +49 -0
- rer/solrpush/browser/templates/query_debug.pt +17 -0
- rer/solrpush/browser/templates/reindex_solr.pt +35 -0
- rer/solrpush/configure.zcml +81 -0
- rer/solrpush/indexer.py +120 -0
- rer/solrpush/interfaces/__init__.py +8 -0
- rer/solrpush/interfaces/adapter.py +13 -0
- rer/solrpush/interfaces/elevate.py +98 -0
- rer/solrpush/interfaces/layer.py +6 -0
- rer/solrpush/interfaces/queueprocessor.py +6 -0
- rer/solrpush/interfaces/settings.py +194 -0
- rer/solrpush/locales/README.rst +37 -0
- rer/solrpush/locales/__init__.py +0 -0
- rer/solrpush/locales/en/LC_MESSAGES/rer.solrpush.mo +0 -0
- rer/solrpush/locales/en/LC_MESSAGES/rer.solrpush.po +399 -0
- rer/solrpush/locales/it/LC_MESSAGES/rer.solrpush.mo +0 -0
- rer/solrpush/locales/it/LC_MESSAGES/rer.solrpush.po +399 -0
- rer/solrpush/locales/rer.solrpush.pot +402 -0
- rer/solrpush/locales/update.py +71 -0
- rer/solrpush/locales/update.sh +12 -0
- rer/solrpush/parser.py +211 -0
- rer/solrpush/permissions.zcml +18 -0
- rer/solrpush/profiles/default/actions.xml +21 -0
- rer/solrpush/profiles/default/browserlayer.xml +7 -0
- rer/solrpush/profiles/default/catalog.xml +4 -0
- rer/solrpush/profiles/default/controlpanel.xml +31 -0
- rer/solrpush/profiles/default/metadata.xml +8 -0
- rer/solrpush/profiles/default/registry/bundle.xml +25 -0
- rer/solrpush/profiles/default/registry/criteria.xml +55 -0
- rer/solrpush/profiles/default/registry/settings.xml +6 -0
- rer/solrpush/profiles/default/rolemap.xml +13 -0
- rer/solrpush/profiles/default/types/Document.xml +12 -0
- rer/solrpush/profiles/to_1100/componentregistry.xml +9 -0
- rer/solrpush/profiles/to_1100/metadata.xml +5 -0
- rer/solrpush/profiles/to_1300/controlpanel.xml +13 -0
- rer/solrpush/profiles/to_1300/registry.xml +5 -0
- rer/solrpush/profiles/uninstall/browserlayer.xml +7 -0
- rer/solrpush/profiles/uninstall/controlpanel.xml +21 -0
- rer/solrpush/profiles/uninstall/registry.xml +17 -0
- rer/solrpush/restapi/__init__.py +0 -0
- rer/solrpush/restapi/configure.zcml +8 -0
- rer/solrpush/restapi/services/__init__.py +0 -0
- rer/solrpush/restapi/services/configure.zcml +8 -0
- rer/solrpush/restapi/services/elevate_schema/__init__.py +0 -0
- rer/solrpush/restapi/services/elevate_schema/configure.zcml +14 -0
- rer/solrpush/restapi/services/elevate_schema/get.py +12 -0
- rer/solrpush/restapi/services/solr_search/__init__.py +0 -0
- rer/solrpush/restapi/services/solr_search/batch.py +129 -0
- rer/solrpush/restapi/services/solr_search/configure.zcml +14 -0
- rer/solrpush/restapi/services/solr_search/get.py +25 -0
- rer/solrpush/restapi/services/solr_search/solr_search_handler.py +86 -0
- rer/solrpush/setuphandlers.py +20 -0
- rer/solrpush/testing.py +161 -0
- rer/solrpush/tests/__init__.py +0 -0
- rer/solrpush/tests/docs/example.docx +0 -0
- rer/solrpush/tests/docs/example.ods +0 -0
- rer/solrpush/tests/docs/example.pdf +0 -0
- rer/solrpush/tests/docs/plone_logo.png +0 -0
- rer/solrpush/tests/test_behaviors.py +61 -0
- rer/solrpush/tests/test_elevate.py +124 -0
- rer/solrpush/tests/test_events.py +181 -0
- rer/solrpush/tests/test_image_tags.py +85 -0
- rer/solrpush/tests/test_maintenance.py +165 -0
- rer/solrpush/tests/test_querybuilder.py +272 -0
- rer/solrpush/tests/test_restapi_search.py +127 -0
- rer/solrpush/tests/test_search.py +177 -0
- rer/solrpush/tests/test_setup.py +67 -0
- rer/solrpush/tests/test_solr_interface.py +359 -0
- rer/solrpush/tests/test_tika.py +85 -0
- rer/solrpush/tests/test_vocabularies.py +113 -0
- rer/solrpush/upgrades.py +76 -0
- rer/solrpush/upgrades.zcml +86 -0
- rer/solrpush/utils/__init__.py +6 -0
- rer/solrpush/utils/solr_common.py +122 -0
- rer/solrpush/utils/solr_indexer.py +295 -0
- rer/solrpush/utils/solr_search.py +352 -0
- rer/solrpush/vocabularies.py +50 -0
- rer.solrpush-1.3.4-py3.10-nspkg.pth +1 -0
- rer.solrpush-1.3.4.dist-info/LICENSE.GPL +339 -0
- rer.solrpush-1.3.4.dist-info/LICENSE.rst +15 -0
- rer.solrpush-1.3.4.dist-info/METADATA +507 -0
- rer.solrpush-1.3.4.dist-info/RECORD +116 -0
- rer.solrpush-1.3.4.dist-info/WHEEL +5 -0
- rer.solrpush-1.3.4.dist-info/entry_points.txt +5 -0
- rer.solrpush-1.3.4.dist-info/namespace_packages.txt +1 -0
- rer.solrpush-1.3.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<configure
|
|
2
|
+
xmlns="http://namespaces.zope.org/zope"
|
|
3
|
+
xmlns:zcml="http://namespaces.zope.org/zcml"
|
|
4
|
+
i18n_domain="plone">
|
|
5
|
+
|
|
6
|
+
<configure zcml:condition="installed AccessControl.security">
|
|
7
|
+
<permission
|
|
8
|
+
id="rer.solrpush.editElevate"
|
|
9
|
+
title="rer.solrpush: Edit Elevate"
|
|
10
|
+
/>
|
|
11
|
+
<permission
|
|
12
|
+
id="rer.solrpush.editSettings"
|
|
13
|
+
title="rer.solrpush: Edit Settings"
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
</configure>
|
|
17
|
+
|
|
18
|
+
</configure>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<object name="portal_actions" meta_type="Plone Actions Tool"
|
|
3
|
+
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
|
|
4
|
+
<object name="user" meta_type="CMF Action Category" purge="False">
|
|
5
|
+
<object name="solr-elevate"
|
|
6
|
+
meta_type="CMF Action"
|
|
7
|
+
i18n:domain="rer.solrpush"
|
|
8
|
+
insert-before="logout">
|
|
9
|
+
<property name="title" i18n:translate="">Elevate configuration</property>
|
|
10
|
+
<property name="description" i18n:translate=""></property>
|
|
11
|
+
<property
|
|
12
|
+
name="url_expr">string:${portal_url}/@@elevate-settings</property>
|
|
13
|
+
<property name="icon_expr"></property>
|
|
14
|
+
<property name="available_expr">python:member is not None</property>
|
|
15
|
+
<property name="permissions">
|
|
16
|
+
<element value="rer.solrpush: Edit Elevate"/>
|
|
17
|
+
</property>
|
|
18
|
+
<property name="visible">True</property>
|
|
19
|
+
</object>
|
|
20
|
+
</object>
|
|
21
|
+
</object>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<object
|
|
3
|
+
name="portal_controlpanel"
|
|
4
|
+
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
5
|
+
i18n:domain="rer.bandisolr">
|
|
6
|
+
|
|
7
|
+
<configlet
|
|
8
|
+
title="Configurazione RER SolrPush"
|
|
9
|
+
action_id="solrpush.configuration"
|
|
10
|
+
appId="solrpush"
|
|
11
|
+
category="Products"
|
|
12
|
+
condition_expr=""
|
|
13
|
+
url_expr="string:${portal_url}/@@solrpush-settings"
|
|
14
|
+
icon_expr=""
|
|
15
|
+
visible="True"
|
|
16
|
+
i18n:attributes="title">
|
|
17
|
+
<permission>rer.solrpush: Edit Settings</permission>
|
|
18
|
+
</configlet>
|
|
19
|
+
<configlet
|
|
20
|
+
title="Configurazione Elevate"
|
|
21
|
+
action_id="solrpush.elevate"
|
|
22
|
+
appId="solrpush-elevate"
|
|
23
|
+
category="Products"
|
|
24
|
+
condition_expr=""
|
|
25
|
+
url_expr="string:${portal_url}/@@elevate-settings"
|
|
26
|
+
icon_expr=""
|
|
27
|
+
visible="True"
|
|
28
|
+
i18n:attributes="title">
|
|
29
|
+
<permission>rer.solrpush: Edit Elevate</permission>
|
|
30
|
+
</configlet>
|
|
31
|
+
</object>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
3
|
+
i18n:domain="rer.solrpush">
|
|
4
|
+
|
|
5
|
+
<!-- RESOURCE -->
|
|
6
|
+
<records prefix="plone.resources/rer-solrpush-css"
|
|
7
|
+
interface='Products.CMFPlone.interfaces.IResourceRegistry'>
|
|
8
|
+
<value key="css">
|
|
9
|
+
<element>++plone++rer.solrpush/styles.css</element>
|
|
10
|
+
</value>
|
|
11
|
+
</records>
|
|
12
|
+
|
|
13
|
+
<!-- BUNDLE -->
|
|
14
|
+
<records prefix="plone.bundles/rer-solrpush-css-bundle"
|
|
15
|
+
interface='Products.CMFPlone.interfaces.IBundleRegistry'>
|
|
16
|
+
<value key="enabled">True</value>
|
|
17
|
+
<value key="resources" purge="false">
|
|
18
|
+
<element>rer-solrpush-css</element>
|
|
19
|
+
</value>
|
|
20
|
+
<value key="csscompilation">++plone++rer.solrpush/styles.css</value>
|
|
21
|
+
<value key="last_compilation">2020-11-17 00:00:00</value>
|
|
22
|
+
<value key="compile">True</value>
|
|
23
|
+
<value key="depends">plone</value>
|
|
24
|
+
</records>
|
|
25
|
+
</registry>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
3
|
+
i18n:domain="rer.solrpush">
|
|
4
|
+
|
|
5
|
+
<records interface="plone.app.querystring.interfaces.IQueryField"
|
|
6
|
+
prefix="plone.app.querystring.field.searchWithSolr">
|
|
7
|
+
<value key="title" i18n:translate="">Search with Solr</value>
|
|
8
|
+
<value key="description"
|
|
9
|
+
i18n:translate="Select if perform search with SOLR or with Plone (local) catalog.">
|
|
10
|
+
</value>
|
|
11
|
+
<value key="enabled">True</value>
|
|
12
|
+
<value key="sortable">False</value>
|
|
13
|
+
<value key="operations">
|
|
14
|
+
<element>plone.app.querystring.operation.boolean.isTrue</element>
|
|
15
|
+
<element>plone.app.querystring.operation.boolean.isFalse</element>
|
|
16
|
+
</value>
|
|
17
|
+
<value key="group" i18n:translate="">SOLR</value>
|
|
18
|
+
</records>
|
|
19
|
+
<records interface="plone.app.querystring.interfaces.IQueryField"
|
|
20
|
+
prefix="plone.app.querystring.field.solr_sites">
|
|
21
|
+
<value key="title" i18n:translate="">Sites</value>
|
|
22
|
+
<value key="description" i18n:translate="">A list of (SOLR indexed) sites where search items.</value>
|
|
23
|
+
<value key="enabled">True</value>
|
|
24
|
+
<value key="sortable">False</value>
|
|
25
|
+
<value key="operations">
|
|
26
|
+
<element>plone.app.querystring.operation.selection.any</element>
|
|
27
|
+
</value>
|
|
28
|
+
<value key="vocabulary">rer.solrpush.vocabularies.AvailableSites</value>
|
|
29
|
+
<value key="group" i18n:translate="">SOLR</value>
|
|
30
|
+
</records>
|
|
31
|
+
<records interface="plone.app.querystring.interfaces.IQueryField"
|
|
32
|
+
prefix="plone.app.querystring.field.solr_subjects">
|
|
33
|
+
<value key="title" i18n:translate="">Keywords in SOLR</value>
|
|
34
|
+
<value key="description" i18n:translate="">A complete list of keywords stored in SOLR.</value>
|
|
35
|
+
<value key="enabled">True</value>
|
|
36
|
+
<value key="sortable">False</value>
|
|
37
|
+
<value key="operations">
|
|
38
|
+
<element>plone.app.querystring.operation.selection.any</element>
|
|
39
|
+
</value>
|
|
40
|
+
<value key="vocabulary">rer.solrpush.vocabularies.AvailableSubjects</value>
|
|
41
|
+
<value key="group" i18n:translate="">SOLR</value>
|
|
42
|
+
</records>
|
|
43
|
+
<records interface="plone.app.querystring.interfaces.IQueryField"
|
|
44
|
+
prefix="plone.app.querystring.field.solr_portal_types">
|
|
45
|
+
<value key="title" i18n:translate="">Portal types in SOLR</value>
|
|
46
|
+
<value key="description" i18n:translate="">A complete list of portal_types stored in SOLR.</value>
|
|
47
|
+
<value key="enabled">True</value>
|
|
48
|
+
<value key="sortable">False</value>
|
|
49
|
+
<value key="operations">
|
|
50
|
+
<element>plone.app.querystring.operation.selection.any</element>
|
|
51
|
+
</value>
|
|
52
|
+
<value key="vocabulary">rer.solrpush.vocabularies.AvailablePortalTypes</value>
|
|
53
|
+
<value key="group" i18n:translate="">SOLR</value>
|
|
54
|
+
</records>
|
|
55
|
+
</registry>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
3
|
+
i18n:domain="rer.solrpush">
|
|
4
|
+
<records interface="rer.solrpush.interfaces.settings.IRerSolrpushSettings" />
|
|
5
|
+
<records interface="rer.solrpush.interfaces.IElevateSettings" />
|
|
6
|
+
</registry>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<rolemap>
|
|
3
|
+
<permissions>
|
|
4
|
+
<permission name="rer.solrpush: Edit Elevate" acquire="True">
|
|
5
|
+
<role name="Manager" />
|
|
6
|
+
<role name="Site Administrator" />
|
|
7
|
+
</permission>
|
|
8
|
+
<permission name="rer.solrpush: Edit Settings" acquire="True">
|
|
9
|
+
<role name="Manager" />
|
|
10
|
+
<role name="Site Administrator" />
|
|
11
|
+
</permission>
|
|
12
|
+
</permissions>
|
|
13
|
+
</rolemap>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<object
|
|
3
|
+
name="Document"
|
|
4
|
+
meta_type="Dexterity FTI"
|
|
5
|
+
i18n:domain="plone"
|
|
6
|
+
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
|
|
7
|
+
|
|
8
|
+
<property name="behaviors" purge="false">
|
|
9
|
+
<element value="rer.solrpush.behaviors.solr_fields.ISolrFields" />
|
|
10
|
+
</property>
|
|
11
|
+
|
|
12
|
+
</object>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<object
|
|
3
|
+
name="portal_controlpanel"
|
|
4
|
+
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
5
|
+
i18n:domain="rer.bandisolr">
|
|
6
|
+
|
|
7
|
+
<configlet
|
|
8
|
+
title="Configurazione Elevate"
|
|
9
|
+
action_id="solrpush.elevate"
|
|
10
|
+
appId="solrpush-elevate"
|
|
11
|
+
remove="True">
|
|
12
|
+
</configlet>
|
|
13
|
+
</object>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<object
|
|
3
|
+
name="portal_controlpanel"
|
|
4
|
+
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
|
|
5
|
+
i18n:domain="rer.solrpush">
|
|
6
|
+
|
|
7
|
+
<configlet
|
|
8
|
+
title="Configurazione RER SolrPush"
|
|
9
|
+
action_id="solrpush.configuration"
|
|
10
|
+
appId="solrpush"
|
|
11
|
+
category="SOLR"
|
|
12
|
+
remove="True">
|
|
13
|
+
</configlet>
|
|
14
|
+
<configlet
|
|
15
|
+
title="Configurazione Elevate"
|
|
16
|
+
action_id="solrpush.elevate"
|
|
17
|
+
appId="solrpush-elevate"
|
|
18
|
+
category="SOLR"
|
|
19
|
+
remove="True">
|
|
20
|
+
</configlet>
|
|
21
|
+
</object>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<registry>
|
|
3
|
+
<!-- -*- extra stuff goes here -*- -->
|
|
4
|
+
<records interface="rer.solrpush.interfaces.settings.IRerSolrpushSettings" remove="True"/>
|
|
5
|
+
<records interface="rer.solrpush.interfaces.IElevateSettings" remove="True"/>
|
|
6
|
+
|
|
7
|
+
<!-- RESOURCE -->
|
|
8
|
+
<records prefix="plone.resources/rer-solrpush-css"
|
|
9
|
+
interface='Products.CMFPlone.interfaces.IResourceRegistry' remove="True">
|
|
10
|
+
</records>
|
|
11
|
+
|
|
12
|
+
<!-- BUNDLE -->
|
|
13
|
+
<records prefix="plone.bundles/rer-solrpush-css-bundle"
|
|
14
|
+
interface='Products.CMFPlone.interfaces.IBundleRegistry' remove="True">
|
|
15
|
+
</records>
|
|
16
|
+
|
|
17
|
+
</registry>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<configure
|
|
2
|
+
xmlns="http://namespaces.zope.org/zope"
|
|
3
|
+
xmlns:plone="http://namespaces.plone.org/plone">
|
|
4
|
+
|
|
5
|
+
<plone:service
|
|
6
|
+
method="GET"
|
|
7
|
+
for="zope.interface.Interface"
|
|
8
|
+
factory=".get.ElevateSchemaGet"
|
|
9
|
+
name="@elevate-schema"
|
|
10
|
+
permission="zope2.View"
|
|
11
|
+
layer="rer.solrpush.interfaces.IRerSolrpushLayer"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
</configure>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from plone.restapi.services import Service
|
|
3
|
+
from rer.solrpush.utils.solr_common import get_setting
|
|
4
|
+
from rer.solrpush.interfaces import IElevateSettings
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ElevateSchemaGet(Service):
|
|
10
|
+
def reply(self):
|
|
11
|
+
data = get_setting(field="elevate_schema", interface=IElevateSettings)
|
|
12
|
+
return json.loads(data)
|
|
File without changes
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from plone.restapi.deserializer import json_body
|
|
3
|
+
from six.moves.urllib.parse import parse_qsl
|
|
4
|
+
from six.moves.urllib.parse import urlencode
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
DEFAULT_BATCH_SIZE = 25
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SolrHypermediaBatch(object):
|
|
11
|
+
def __init__(self, request, results):
|
|
12
|
+
self.request = request
|
|
13
|
+
|
|
14
|
+
self.b_start = int(
|
|
15
|
+
json_body(self.request).get("b_start", False)
|
|
16
|
+
) or int(self.request.form.get("b_start", 0))
|
|
17
|
+
self.b_size = int(json_body(self.request).get("b_size", False)) or int(
|
|
18
|
+
self.request.form.get("b_size", DEFAULT_BATCH_SIZE)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
self.hits = getattr(results, "hits", 0)
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def canonical_url(self):
|
|
25
|
+
"""Return the canonical URL to the batched collection-like resource,
|
|
26
|
+
preserving query string params, but stripping all batching related
|
|
27
|
+
params from it.
|
|
28
|
+
"""
|
|
29
|
+
url = self.request["ACTUAL_URL"]
|
|
30
|
+
qs_params = parse_qsl(self.request["QUERY_STRING"])
|
|
31
|
+
|
|
32
|
+
# Remove any batching / sorting related parameters.
|
|
33
|
+
# Also take care to preserve list-like query string params.
|
|
34
|
+
for key, value in qs_params[:]:
|
|
35
|
+
if key in (
|
|
36
|
+
"b_size",
|
|
37
|
+
"b_start",
|
|
38
|
+
"sort_on",
|
|
39
|
+
"sort_order",
|
|
40
|
+
"sort_limit",
|
|
41
|
+
):
|
|
42
|
+
qs_params.remove((key, value))
|
|
43
|
+
|
|
44
|
+
qs = urlencode(qs_params)
|
|
45
|
+
|
|
46
|
+
if qs_params:
|
|
47
|
+
url = "?".join((url, qs))
|
|
48
|
+
return url
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def current_batch_url(self):
|
|
52
|
+
url = self.request["ACTUAL_URL"]
|
|
53
|
+
qs = self.request["QUERY_STRING"]
|
|
54
|
+
if qs:
|
|
55
|
+
url = "?".join((url, qs))
|
|
56
|
+
return url
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def links(self):
|
|
60
|
+
"""Get a dictionary with batching links.
|
|
61
|
+
"""
|
|
62
|
+
# Don't provide batching links if resultset isn't batched
|
|
63
|
+
if self.hits <= self.b_size:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
links = {}
|
|
67
|
+
|
|
68
|
+
last = self._last_page()
|
|
69
|
+
next = self._next_page()
|
|
70
|
+
prev = self._prev_page()
|
|
71
|
+
|
|
72
|
+
links["@id"] = self.current_batch_url
|
|
73
|
+
links["first"] = self._url_for_batch(0)
|
|
74
|
+
links["last"] = self._url_for_batch(last)
|
|
75
|
+
|
|
76
|
+
if next:
|
|
77
|
+
links["next"] = self._url_for_batch(next)
|
|
78
|
+
|
|
79
|
+
if prev:
|
|
80
|
+
links["prev"] = self._url_for_batch(prev)
|
|
81
|
+
|
|
82
|
+
return links
|
|
83
|
+
|
|
84
|
+
def _url_for_batch(self, pagenumber):
|
|
85
|
+
"""Return a new Batch object for the given pagenumber.
|
|
86
|
+
"""
|
|
87
|
+
new_start = pagenumber * self.b_size
|
|
88
|
+
return self._url_with_params(params={"b_start": new_start})
|
|
89
|
+
|
|
90
|
+
def _last_page(self):
|
|
91
|
+
page = self.hits / self.b_size
|
|
92
|
+
if self.hits % self.b_size == 0:
|
|
93
|
+
return page - 1
|
|
94
|
+
return page
|
|
95
|
+
|
|
96
|
+
def _next_page(self):
|
|
97
|
+
curr_page = self.b_start / self.b_size
|
|
98
|
+
if curr_page == self._last_page():
|
|
99
|
+
return None
|
|
100
|
+
return curr_page + 1
|
|
101
|
+
|
|
102
|
+
def _prev_page(self):
|
|
103
|
+
curr_page = self.b_start / self.b_size
|
|
104
|
+
if curr_page == 0:
|
|
105
|
+
return None
|
|
106
|
+
return curr_page - 1
|
|
107
|
+
|
|
108
|
+
def _url_with_params(self, params):
|
|
109
|
+
"""Build an URL based on the actual URL of the current request URL
|
|
110
|
+
and add or update some query string parameters in it.
|
|
111
|
+
"""
|
|
112
|
+
url = self.request["ACTUAL_URL"]
|
|
113
|
+
qs_params = parse_qsl(
|
|
114
|
+
self.request["QUERY_STRING"], keep_blank_values=1
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Take care to preserve list-like query string arguments (same QS
|
|
118
|
+
# param repeated multiple times). In other words, don't turn the
|
|
119
|
+
# result of parse_qsl into a dict!
|
|
120
|
+
|
|
121
|
+
# Drop params to be updated, then prepend new params in order
|
|
122
|
+
qs_params = [x for x in qs_params if x[0] not in list(params)]
|
|
123
|
+
qs_params = sorted(params.items()) + qs_params
|
|
124
|
+
|
|
125
|
+
qs = urlencode(qs_params)
|
|
126
|
+
|
|
127
|
+
if qs_params:
|
|
128
|
+
url = "?".join((url, qs))
|
|
129
|
+
return url
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<configure
|
|
2
|
+
xmlns="http://namespaces.zope.org/zope"
|
|
3
|
+
xmlns:plone="http://namespaces.plone.org/plone">
|
|
4
|
+
|
|
5
|
+
<plone:service
|
|
6
|
+
method="GET"
|
|
7
|
+
for="zope.interface.Interface"
|
|
8
|
+
factory=".get.SearchGet"
|
|
9
|
+
name="@solr-search"
|
|
10
|
+
permission="zope2.View"
|
|
11
|
+
layer="rer.solrpush.interfaces.IRerSolrpushLayer"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
</configure>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from plone.restapi.search.utils import unflatten_dotted_dict
|
|
3
|
+
from plone.restapi.services import Service
|
|
4
|
+
from rer.solrpush.restapi.services.solr_search.solr_search_handler import (
|
|
5
|
+
SolrSearchHandler,
|
|
6
|
+
)
|
|
7
|
+
from plone.restapi.search.handler import SearchHandler
|
|
8
|
+
from rer.solrpush.interfaces.settings import IRerSolrpushSettings
|
|
9
|
+
from plone import api
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SearchGet(Service):
|
|
13
|
+
def reply(self):
|
|
14
|
+
query = self.request.form.copy()
|
|
15
|
+
query = unflatten_dotted_dict(query)
|
|
16
|
+
handler = SearchHandler
|
|
17
|
+
try:
|
|
18
|
+
search_enabled = api.portal.get_registry_record(
|
|
19
|
+
"search_enabled", interface=IRerSolrpushSettings
|
|
20
|
+
)
|
|
21
|
+
except Exception:
|
|
22
|
+
return handler(self.context, self.request).search(query)
|
|
23
|
+
if search_enabled:
|
|
24
|
+
handler = SolrSearchHandler
|
|
25
|
+
return handler(self.context, self.request).search(query)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from copy import deepcopy
|
|
3
|
+
from Products.CMFCore.utils import getToolByName
|
|
4
|
+
from plone.restapi.search.handler import SearchHandler as BaseHandler
|
|
5
|
+
from rer.solrpush.utils import search as solr_search
|
|
6
|
+
from rer.solrpush.restapi.services.solr_search.batch import SolrHypermediaBatch
|
|
7
|
+
from plone.restapi.deserializer import boolean_value
|
|
8
|
+
|
|
9
|
+
DEFAULT_METADATA_FIELDS = set(
|
|
10
|
+
["@id", "@type", "description", "review_state", "title"]
|
|
11
|
+
)
|
|
12
|
+
FIELD_ACCESSORS = {
|
|
13
|
+
"@id": "getURL",
|
|
14
|
+
"@type": "PortalType",
|
|
15
|
+
"description": "Description",
|
|
16
|
+
"title": "Title",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
NON_METADATA_ATTRIBUTES = set(["getPath", "getURL"])
|
|
20
|
+
|
|
21
|
+
BLACKLISTED_ATTRIBUTES = set(["getDataOrigin", "getObject", "getUserData"])
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SolrSearchHandler(BaseHandler):
|
|
25
|
+
"""Executes a solr search based on a query dict, and returns
|
|
26
|
+
JSON compatible results.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, context, request):
|
|
30
|
+
self.context = context
|
|
31
|
+
self.request = request
|
|
32
|
+
self.catalog = getToolByName(self.context, "portal_catalog")
|
|
33
|
+
|
|
34
|
+
def search(self, query=None):
|
|
35
|
+
if query is None:
|
|
36
|
+
solr_query = {}
|
|
37
|
+
else:
|
|
38
|
+
solr_query = deepcopy(query)
|
|
39
|
+
fl = self.get_fields_list(solr_query)
|
|
40
|
+
facets = boolean_value(solr_query.get("facets", False))
|
|
41
|
+
facet_fields = solr_query.get("facet_fields", [])
|
|
42
|
+
query_params = {"fl": fl}
|
|
43
|
+
if facets:
|
|
44
|
+
query_params["facets"] = facets
|
|
45
|
+
if facet_fields:
|
|
46
|
+
query_params["facet_fields"] = facet_fields
|
|
47
|
+
del solr_query["facet_fields"]
|
|
48
|
+
if "facets" in solr_query:
|
|
49
|
+
del solr_query["facets"]
|
|
50
|
+
query_params["query"] = solr_query
|
|
51
|
+
return self.serialize_results(solr_search(**query_params))
|
|
52
|
+
|
|
53
|
+
def get_fields_list(self, query):
|
|
54
|
+
if "fullobjects" in query:
|
|
55
|
+
del query["fullobjects"]
|
|
56
|
+
return []
|
|
57
|
+
fields = []
|
|
58
|
+
for field in self.metadata_fields(query):
|
|
59
|
+
if field.startswith("_") or field in BLACKLISTED_ATTRIBUTES:
|
|
60
|
+
continue
|
|
61
|
+
fields.append(field)
|
|
62
|
+
return fields
|
|
63
|
+
|
|
64
|
+
def metadata_fields(self, query):
|
|
65
|
+
additional_metadata_fields = query.get("metadata_fields", [])
|
|
66
|
+
if not isinstance(additional_metadata_fields, list):
|
|
67
|
+
additional_metadata_fields = [additional_metadata_fields]
|
|
68
|
+
additional_metadata_fields = set(additional_metadata_fields)
|
|
69
|
+
if additional_metadata_fields:
|
|
70
|
+
del query["metadata_fields"]
|
|
71
|
+
return DEFAULT_METADATA_FIELDS | additional_metadata_fields
|
|
72
|
+
|
|
73
|
+
def serialize_results(self, solr_results):
|
|
74
|
+
batch = SolrHypermediaBatch(self.request, solr_results)
|
|
75
|
+
results = {}
|
|
76
|
+
results["@id"] = batch.canonical_url
|
|
77
|
+
results["items_total"] = solr_results.hits
|
|
78
|
+
if solr_results.facets:
|
|
79
|
+
results["facets"] = solr_results.facets.get("facet_fields", {})
|
|
80
|
+
links = batch.links
|
|
81
|
+
if links:
|
|
82
|
+
results["batching"] = links
|
|
83
|
+
|
|
84
|
+
results["items"] = solr_results.docs
|
|
85
|
+
|
|
86
|
+
return results
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from Products.CMFPlone.interfaces import INonInstallable
|
|
3
|
+
from zope.interface import implementer
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@implementer(INonInstallable)
|
|
7
|
+
class HiddenProfiles(object):
|
|
8
|
+
def getNonInstallableProfiles(self):
|
|
9
|
+
"""Hide uninstall profile from site-creation and quickinstaller."""
|
|
10
|
+
return ["rer.solrpush:uninstall", "rer.solrpush:1100"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def post_install(context):
|
|
14
|
+
"""Post install script"""
|
|
15
|
+
# Do something at the end of the installation of this package.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def uninstall(context):
|
|
19
|
+
"""Uninstall script"""
|
|
20
|
+
# Do something at the end of the uninstallation of this package.
|