\ No newline at end of file
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/mediathek/mediathek.info
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/mediathek/mediathek.info Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,7 @@
+name = mediathek
+description = Allows access to the mediathek
+core = 7.x
+
+files[] = mediathek.module
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/mediathek/mediathek.install
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/mediathek/mediathek.install Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,38 @@
+ array('type' => 'varchar', 'length' => 600, 'not null' => FALSE),
+ 'width' => array('type' => 'varchar', 'length' => 10, 'not null' => FALSE),
+ 'height' => array('type' => 'varchar', 'length' => 10, 'not null' => FALSE),
+ );
+ $indexes = array(
+ 'url' => array('url'),
+ );
+ return array(
+ 'columns' => $columns,
+ 'indexes' => $indexes,
+ );
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/mediathek/mediathek.module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/mediathek/mediathek.module Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,198 @@
+ 'field_mediathek_entry',
+ 'type' => 'mediathek_mediathek_entry',
+ );
+ field_create_field($field);
+
+ // Create the instance on the bundle.
+ $instance = array(
+ 'field_name' => 'field_mediathek_entry',
+ 'entity_type' => 'node',
+ 'label' => 'Mediathek Entry',
+ 'bundle' => 'node',
+ // If you don't set the "required" property then the field wont be required by default.
+ 'required' => False,
+ 'settings' => array(
+ ),
+ 'widget' => array(
+ 'type' => 'mediathek_default_mediathek_entry',
+ ),
+ );
+ field_create_instance($instance);
+ }
+}
+
+/* implements a new field type for the medithek id */
+
+function mediathek_field_info(){
+
+ return array('mediathek_mediathek_entry' => array (
+ 'label' => t('Mediathek Item'),
+ 'description' => t('This field stores an mediathek Item'),
+ 'settings' => array('max_length' =>20),
+ 'instance_settings' => array('text_processing' => 0),
+ 'default_widget' => 'mediathek_default_mediathek',
+ 'default_formatter' => 'mediathek_mediaviewer',
+ ),
+
+ );
+}
+
+function mediathek_field_is_empty($item, $field){
+ return empty($item['url']);
+}
+
+function mediathek_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+
+
+ $field_name = $field['field_name'];
+ $field_type = $field['type'];
+
+
+ $url = isset($items[$delta]['url']) ? $items[$delta]['url'] : '';
+ $height = isset($items[$delta]['url']) ? $items[$delta]['height'] : '';
+ $width = isset($items[$delta]['url']) ? $items[$delta]['width'] : '';
+
+ $widget = $element;
+ $widget['#delta'] = $delta;
+
+ switch ($instance['widget']['type']) {
+
+
+
+ case 'mediathek_default_mediathek':
+
+ $fieldset_info = element_info('fieldset');
+ $process = array_merge($fieldset_info['#process'], array('mediathek_media_entry_process'));
+
+
+ $widget+=
+ array(
+ '#type' => 'fieldset',
+ '#title' => t('Contact settings'),
+ '#weight' => 5,
+ '#collapsible' => TRUE,
+ '#collapsed' => FALSE,
+ '#tree' => TRUE,
+ '#process' => $process,
+ );
+
+
+ $widget['url'] = array(
+ '#title' => t('Url'),
+ '#type' => 'textfield',
+ '#default_value' => $url,
+ '#size' => 150,
+ '#maxlength' => 500,
+ );
+
+ $widget['height'] = array(
+ '#title' => t('Height'),
+ '#type' => 'textfield',
+ '#default_value' => $height,
+ '#size' => 20,
+ '#maxlength' => 20,
+ );
+
+
+
+ $widget['width'] = array(
+ '#title' => t('Width'),
+ '#type' => 'textfield',
+ '#default_value' => $width,
+ '#size' => 20,
+ '#maxlength' => 20,
+ );
+
+
+
+
+
+ $element['media'] = $widget;
+ break;
+
+
+
+ }
+
+
+
+
+ return $element;
+}
+
+function mediathek_media_entry_process(&$form, &$form_state, $complete){
+
+
+ array_pop($form['#parents']);
+ return $form;
+}
+
+function mediathek_field_widget_info() {
+ #TODO:both types should check if field is valid
+ return array(
+ 'mediathek_default_mediathek' => array(
+ 'label' => t('Media Item'),
+ 'field types' => array('mediathek_mediathek_entry'),
+ ),
+
+ );
+}
+
+
+function mediathek_field_formatter_info() {
+
+ return array(
+ // This formatter shows the obejct with fullmetadata
+ 'mediathek_mediaviewer' => array(
+ 'label' => t('Mediathek viewer'),
+ 'field types' => array('mediathek_mediathek_entry'),
+ )
+ );
+}
+
+
+function mediathek_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+ $element = array();
+
+
+ switch ($display['type']) {
+ // This formatter simply outputs the field as text and with a color.
+ case 'mediathek_mediaviewer':
+
+ foreach ($items as $delta => $item) {
+
+ $url = $item['url'];
+ $width = $item['width'];
+ $height= $item['height'];
+
+ if ($url!=""){
+ $element[$delta]['#markup'] = theme('mediathek_theme_mediathek_mediaviewer',array('item' => $item ));
+ }
+
+ }
+
+ break;
+ }
+
+ return $element;
+}
+
+function mediathek_theme(){
+return array(
+ 'mediathek_theme_mediathek_mediaviewer' => array(
+ 'variables' => array('item' => NULL),
+ 'template' => 'mediathek-theme-mediathek-mediaviewer',
+ )
+);
+
+}
\ No newline at end of file
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/CHANGELOG.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/CHANGELOG.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,820 @@
+Apache Solr integration 7.x-1.x, xxxx-xx-xx
+-----------------------------
+#1249616 by agentrickard, pwolanin, Nick_vh | R.Muilwijk: Fixed Apachesolr access makes assumptions that don't apply to modules like Domain Access.
+#1926896 by mkalkbrenner: Fixed missing highlighted snippets.
+#1927032 by mkalkbrenner: Fixed Avoid spaces between words and punctution marks in search result snippets.
+#1915614 by mkalkbrenner, Nick_vh: Added Complete admin settings for non-default environments.
+#1918012 by mkalkbrenner, Nick_vh, pwolanin: Added Solr query needs to be aware of more context such as Search Page ID.
+#1896470 by Nick_vh, mkalkbrenner: Fixed Integrate Apache Solr Common Configurations for Solr 3.x and 4.x (Highlighting broken).
+#1918030 by mkalkbrenner, pwolanin: Allow contrib modules to add custom settings to search pages.
+#1918566 by mkalkbrenner: Added Devel integration: debug index documents on all environments / indexes.
+#1915418 by mkalkbrenner, Nick_vh: Fixed Unable to index a node bundle in a dedicated index / environment.
+#1900036 by remimikalsen, swentel | albert78: Fixed node reference with multiple values.
+#1900006 by Nick_vh | msellers: Fixed Undefined variable causes warning on node type uninstall.
+#1874420 by Nick_vh, j0rd | dirtabulous: Fixed Solr4 Entites Not Being Removed with deleteByQuery.
+#1871866 by Nick_vh, grom358: Fixed Type bias for all entities.
+#1861544 by fizk: Fixed Incorrect use of $field_map() in SolrBaseQuery::getSolrsortUrlQuery.
+#1897556 by Nick_vh: Update documentation for all the functions and make sure it reflects reality.
+#1836262 by ianmthomasuk, Nick_vh: Added Allow indexing of a set number of items using drush.
+#1898166 by Nick_vh: Fixed Make better use of the entity cache.
+#1868870 by cpliakas | Nick_vh: Revert changes to interface cause fatal errors for modules that implement the interface.
+#1803512 by David_Rothstein | amanire: Fixed The OR operator returns no results for facets with colons in the value (such as entity reference facets).
+#1679392 by David_Rothstein, brianV: Move logic from apachesolr_default_node_facet_info() into a separate function so other modules can use it for non-node entities.
+#1814080 by Nick_vh, JordanMagnuson: Fixed Apachesolr sort block fills cache_block() table without stopping.
+#1550964 by Nick_vh, drzraf, rajivk, rjbrown99, j0rd | tinflute: Support Solr 4.0 schema.
+#1840430 by Nick_vh: Fixed add alter callbacks from facetapi to the mappings array.
+#1827320 by drumm: Fixed Upgrading from 6.x-3.x does not need apachesolr_update_7000-15.
+#1828040 by david.gil, Nick_vh: Fixed Cannot access empty property in query_type_numeric_range().inc on line 77.
+#1828014 by DeFr, Nick_vh: Fixed Mass re-indexation can miss (a lot of) content.
+#1823590 by Nick_vh, Josh Waihi: Added Tag Apachesolr index table select queries to allow other modules to alter them.
+#1825840 by firebird: Fixed Typo in menu description.
+
+Apache Solr integration 7.x-1.1, 2012-10-15
+-----------------------------
+#1780200 by pwolanin: document basic auth in README.
+#1226274 by pwolanin: Fixes for schema.xml version numbering and organization.
+
+Apache Solr integration 7.x-1.0, 2012-10-13
+-----------------------------
+#761990 by pwolanin, jhedstrom, Nick_vh, jpmckinney | morningtime: Fixed 400 Bad Status if URL length limit exceeded.
+#1811364 by Nick_vh: Fixed Add newly created content type to the indexed bundles for all environments.
+#1811456 by rupl: Fixed Improve documentation of addFilter in apachesolr.api.php.
+#1773506 by drzraf: Fixed drush solr-search notice when file entity are part of the result.
+#1688150 by HalfChem, cam8001, jhedstrom, Nick_vh: Fixed Search query string gets double encoded when core Search block form is submitted.
+#1794602 by pwolanin, Nick_vh | ppmr: Fixed Undefined index: path in ApacheSolrDocument->__get() (line 304 of ...\apachesolr\Apache_Solr_Document.
+#1773506 by drzraf: Fixed drush solr-search notice when file entity are part of the result.
+#1764334 by cpliakas: Fixed Negative percentage of documents sent to the server for indexing.
+#1806300 by Nick_vh: Separate out the creation of the document from the index process.
+#1807552 by Nick_vh, wimvds: Fixed Site and url wrong when indexing multilingual content (using i18n module).
+#1759190 by mkalkbrenner: Fixed obsolete form code?.
+#1802288 by Nick_vh: Fixed Improve testing of node deletion.
+
+Apache Solr integration 7.x-1.0-rc5, 2012-10-01
+-----------------------------
+#1698050 by duellj: fix for apachesolr_clean_text() should strip extra spaces.
+#1764450 by cpliakas: Improve the docblocks in apachesolr.index.inc.
+#1800324 by pwolanin: Clean up and align node access tests.
+#1799330 by pwolanin: fix for Stats table missing t() calls.
+#1787370 by pwolanin: Don't complain about schema version if it doesn't match expected naming pattern.
+#1790590 by pwolanin: Fix DrupalSolrOnlineWebTestCase so it works with any multicore setup.
+#1799032 by pwolanin: Remove uneeded object reference in indexing function.
+#1793610 by zengenuity: Fix for regession - spelling suggestions missing.
+
+Apache Solr integration 7.x-1.0-rc4, 2012-09-21
+-----------------------------
+#1790894 by pwolanin: fix for Cloning an environment doesn't clone the bundles to be indexed.
+#1778050 by Nick_vh, pwolanin: fix for stale cache when CTools is already enabled.
+#1778266 by Nick_vh, mkalkbrenner: Refactoring of DrupalSolrOnlineWebTestCase to be used by Others.
+#1778266 by mkalkbrenner: Refactoring of DrupalSolrOnlineWebTestCase to be used by Others.
+#1789526 by pwolanin: Clarify lack of upgrade path from 6.x-1.x.
+#1765938 by cpliakas: Added Move the variable_get() for 'apachesolr_environments()" after the cache_set() so that URLs can be modified dynamically.
+#1782436 by cspitzlay: Fixed Error and obsolete hint in code comment.
+#1732900 by cpliakas: Added Change the wording of the generic 'Apache Solr server unavailable" error message.
+#1781040 by mkalkbrenner: Fixed Switch 'Enable spell check" does not work - spell check is allways on.
+#1786450 by Nick_vh: Fixed apachesolr.interface.inc is not always loaded.
+#1760592 by cpliakas, pwolanin: fix for core_search page does not use the current default search environment.
+#1759004 by mkalkbrenner, pwolanin: fix for apachesolr_search_custom_page_search_form_submit() kills all $_GET parameters.
+#1778150 by cpliakas, pwolanin: fix for SQL error in apachesolr_environment_load_subrecords().
+#1743138 by mundanity: Fixed Invalid argument when running Drush.
+#1751640 by cpliakas: Added drush commands to see the ID of the last item indexes as well as the next item queued for indexing.
+#1708150 by ianmthomasuk, Nick_vh, pwolanin: Added additional typing to function definitions.
+#1759110 by Nick_vh: Fixed process response fails if variable was set but never removed.
+#1741066 by Nick_vh: Added geo query type to make contrib's modules life easier.
+#1730840 by pwolanin: Normalize boolean and other values for parameters like hl.
+#1729836 by pwolanin: fix for "Results per page" option for a search page is broken.
+#1719302 by Nick_vh, msti: Fixed Running an empty facet query so the facet blocks can be displayed.
+#1722966 by greggles: Fixed make apachesolr_index_batch_index_finished() message more translateable.
+#1717628 by Nick_vh, pwolanin: Added 'Save and Edit" functionality for configuration pages - Follow ups.
+
+Apache Solr integration 7.x-1.0-rc3, 2012-08-10
+------------------------------
+#1682004 by Nick_vh: Add template hints for search results based on search page.
+#1722012 by mkalkbrenner, Nick_vh: fix for Missing argument 4 for apachesolr_multilingual_apachesolr_index_documents_alter().
+#1717490 by pwolanin: fix for Search result template suggestions relies on non-required fields.
+#1708212 by ianmthomasuk, Nick_vh: Fixed Duplicate field error when indexing single value fields.
+#1702788 by mkalkbrenner: Fixed content and teaser are empty if node->language is not default.
+#1708166 by ianmthomasuk: Fixed Thow exception if asked for invalid solr environment.
+#1717628 by Nick_vh | cpliakas: Added 'Save and Edit" functionality for configuration pages.
+#1718172 by Nick_vh, pwolanin: Fixed Move search result alter hook earlier, and make sure needed data is set.
+#1702526 by Nick_vh: Fixed apachesolr_search_page_load() is quirky.
+#1717958 by pwolanin: Fix for text_und fields should be exposed for searching in the admin section.
+#1708538 by Nick_vh: Fixed Move the start param above the query alter.
+#1700472 by pwolanin: Make 'apachesolr_search_process_response_callback' a search environment variable.
+#1439564 by recidive, neochief, Nick_vh, dawehner, jhedstrom: Added Index bundles Export/Import.
+#1652746 by martins.bertins | chrisssi: Fixed Notice: Undefined offset: 3 in _menu_translate().
+#1670198 by alanmackenzie | ruedu: Fixed Unable to export/import settings using features module.
+#1681946 by Josh Waihi: Fixed apachesolr_index_nodeapi_mass_delete() doesn't work.
+#1650096 by Nick_vh | cappadona: Fixed addParam() creates duplicate filters when dealing with fq.
+#1677050 by cpliakas: Fix for Cancel link when creating a new environment.
+#1673086 by pwolanin: Add drush commands to get, set, del environment variables.
+#1682004 by cpliakas: Added template hints for search results based on search page.
+#1672738 by Nick_vh: Added Allow a dynamic apachesolr_process_results() function.
+#1473722 by levialliance: Added Bundle specific overrides.
+#1408844 by Nick_vh, jrbeeman: Added As a site builder I want to override the environment settings in settings.php.
+#1652746 by chrisssi: Fixed Notice: Undefined offset: 3 in _menu_translate() (Zeile 775 von /var/www/includes/menu.inc).
+#1402748 by Nick_vh, killua99: Fixed Check in apachesolr_do_query() if the static of the query with that name already exists, and if so return it.
+
+Apache Solr integration 7.x-1.0-rc2, 2012-06-21
+------------------------------
+Renamed schema.xml and solrconfig.xml to rc2
+
+Apache Solr integration 7.x-1.0-rc1, 2012-06-21
+------------------------------
+#1642140 by Nick_vh: Fixed Make the search query also escape the slash and move away from menu_tail() to just 1 argument.
+#1518108 by grendzy: Added Devel interface for inspecting solr documents.
+#1402748 by Nick_vh: Fixed Check in apachesolr_do_query() if the static of the query with that name already exists, and if so return it.
+#1631702 by Nick_vh | khaled.zaidan: Fixed Report at admin/reports/apachesolr doesn't always display data from the current default solr server.
+#1647668 by paulmckibben: Fixed Error messages when indexing - Notice: Undefined property: stdClass::$nid in DatabaseStatementBase->fetchAllAssoc().
+#1475014 by ceng, Nick_vh: Fixed Drush command solr-delete-index ignores type arguments.
+#1588256 by InternetDevels.Com, Nick_vh | RaulMuroc: Fixed Warning: Invalid argument supplied for foreach() in apachesolr_entity_update() (line 1766 of /apachesolr/apachesolr.module).
+#1612530 by Nick_vh, willmoy: Added Results say '0 comments' when comment.module is disabled.
+#1522174 by pwolanin: Fixed hook_node_type_delete() is wrong.
+#1576710 by skwashd: Added Indexing with drush cron generates a lot of invalid cron notifications.
+#1543754 by iamEAP: Fixed Schema inconsistency introduced by apachesolr_update_7013.
+#1481564 by milesw: Added Allow other modules to react when there are no results.
+#1470794 by pwolanin: Added Show size of index on disk in index report.
+#1586320 by cpliakas, pwolanin: Added support for the ExternalFileField field type.
+#1613328 by cpliakas: Fixed The service_class() is not passed to apachesolr_server_status() when checking each server's status on the settings page.
+#1621142 by pwolanin: Fixed Broken logic in indexing of extra data.
+#1627484 by gnucifer: Fixed 'allowed operator" not transfered from field definitions.
+#1627604 by Nick_vh: Fixed Add query type for taxonomy_term_reference().
+#1609184 by pwolanin: Minor code cleanup in MLT response handling .
+#1611338 by remimikalsen: Added Allowing several bundles to share the same field name within a given entity type after field_mapping_alter().
+#1568126 by fearlsgroove, pwolanin: Fixed Apachesolr causes all simpletests to fail.
+#1609030 by pwolanin: Fix for Missing search page still executes search.
+#1572722 by eporama, cpliakas, wonder95: Added integration with the Entity References module.
+#1567614 by pwolanin: fix for Uninstall is not complete.
+#1559880 by pwolanin: fix for 'retain filters' checkbox does not work.
+#1558626 by pwolanin: fix for broken OR facet when value has spaces (committed in 16ef187).
+#1538244 by by julianmancera: Fix for Solr base query adds an extra slash in getPath() when there is no 'q' param.
+#1532214 by setvik, pwolanin: Fox for mergePolicy syntax has changed and throws error in Apache Solr 3.6, update config versions.
+#1536936 by pwolanin: Fix for Use json.nl=map for Luke and other json data.
+#1536628 by Nick_vh: Added exclude hook that allows to skip content without removing it from the table.
+#1536600 by Nick_vh: Fixed Performance optimizations when doing hundreds of deletes.
+#1515822 by pwolanin, Nick_vh: Added Support notion of parent entity for derived documents.
+#1519900 by pwolanin, Nick_vh, Georgique: Fixed Error in apachesolr_index_get_entities_to_index() function.
+
+Apache Solr integration 7.x-1.0-beta19, 2012-04-05
+------------------------------
+#1515580 by Nick_vh | yannou: Fixed Deleting node is impossible, stdClass problem.
+
+Apache Solr integration 7.x-1.0-beta18, 2012-04-04
+------------------------------
+#1514314 by Nick_vh, Georgique: Fixed Error in apachesolr_entity_update() Follow-up.
+#1514314 by Nick_vh, Georgique: Fixed Error in apachesolr_entity_update().
+
+Apache Solr integration 7.x-1.0-beta17, 2012-04-03
+------------------------------
+#1509790 by Nick_vh: Fixed Status is not checked when a reindex is initiated.
+#1476228 by ygerasimov: Fixed Items to index determined not correct.
+#1477732 by ygerasimov: Fixed apachesolr_index_entities() sets index position that leads to cycle.
+#1508434 by lazysoundsystem, Nick_vh: Fixed whitespace problem.
+#1481326 by Nick_vh | milesw: Fixed Queries run twice after submitting search forms on a custom search page.
+#1502088 by Nick_vh | sanpi: Fixed Missing Search dependency for Apache Solr framework.
+#1498490 by Nick_vh, milesw: Fixed Menu paths for custom search pages are broken when exported as features.
+#1475010 by Nick_vh: Fixed Date filtering to minute returns faulty results.
+#1469484 by Nick_vh, Josh Waihi: Fixed Limit select queries when checking index node table to prevent memory overload.
+#1442358 by johnennew, Nick_vh: Fixed Nodes not queued to be removed from index when unpublished.
+#1456368 by Nick_vh, pwolanin: Fixed Entities not removed when excluded, unnecessary re-indexing.
+#1470042 by klaasvw: Fixed Existing node table error on drupal update.
+#1458696 by Nick_vh | m1r1k: Fixed Apache Solr bug with re-index.
+#1418834 by levialliance | drewmacphee: Beta15+ problems with i18n and entity_translation().
+#1404284 by pwolanin: Fix for possible undefined function apachesolr_default_environment() during update.
+#1441066 by pwolanin: Fix for incorrect hook_schema() definition for {apachesolr_index_entities}.
+#1411066 by Nick_vh | heacu: Fixed Unchecking 'Custom filter" has no effect if custom filter has been entered on Edit Search Page.
+#1424578 by Nick_vh | cpliakas: Fixed Errors thrown on admin/reports/apachesolr when the server is unavailable.
+#1439492 by recidive: Fixed Features importing of search page not working.
+#1446694 by edb: Fixed env_id() length is only 32 characters on apachesolr_search_page() table.
+#1437842 by duellj: Added Facetapi block titles on empty search page should use theme_facetapi_title().
+#1442358 by johnennew, Nick_vh: Fixed Nodes not queued to be removed from index when unpublished.
+#1440394 by grendzy: fix for Field bias setting has no effect.
+#1399584 by halcyonCorsair | Nick_vh: Added As a developer I want to change environment variables with drush.
+#1423130 by pwolanin | rickmanelius: Fixed apachesolr_user_update() Issues.
+#1403810 by Nick_vh | SangersDrupalDude: Fixed some warning in admin area.
+#1419290 by Nick_vh, paulmckibben: Fixed When $conditions is empty, search_data() results in 'The Apache Solr search engine is not available" (but results are returned).
+#1429230 by Nick_vh: Fixed Default values for for mapping per-field is not added correctly.
+#1427288 by Nick_vh: Fixed Change the MergePolicy for all the solrconfigs to use LogByteMergePolicy.
+
+Apache Solr integration 7.x-1.0-beta16, 2012-02-02
+------------------------------
+#1408190 by DeFr: Fix port check for url with credentials.
+#1411354 by Nick_vh: fix for Incorrect reporting of documents indexed.
+#1357588 by becw, Bußmeyer, pwolanin: improved ctools export/import support.
+#1418136 by zengenuity, pwolanin: fix for undefined function apachesolr_index_set_last_updated() in apachesolr_access.
+#995526 by chx, pwolanin: another fix for Key length greater than 1000 bytes causes install error on MyISAM.
+#1409878 by becw: Fixed Uncaught exception when the default environment does not exist (patch).
+#1398100 by thecarlhall: Fixed Configuration throws exception when starting Solr. Follow up for 7.x-1.x
+#1409076 by Nick_vh, sdrycroft: Fixed Entities that use the 'apachesolr_index_entities()" table are not indexed.
+#1409146 by Nick_vh: Fixed Add all possible index_types() to apachesolr_index_key().
+#1408856 by Nick_vh: Remove DrupalQueue from the install.php.
+#1402746 by Nick_vh: Clean up apachesolr_do_query() so the page variable will be inside the query object.
+#1408192 by becw: Fixed Add apachesolr.interface.inc to the .info file (patch).
+#1405040 by Nick_vh | chrisssi: Fixed SQLSTATE[42S22]: Column not found: 1054.
+
+Apache Solr integration 7.x-1.0-beta15, 2012-01-12
+------------------------------
+#1397526 by Nick_vh, cpliakas: Add an option to select which search page facets link to when displayed on non-search pages. Follow-Up small bugfix
+#1397138 by Nick_vh: Create Simpletests to verify base functionality of the module.
+#1402688 by Nick_vh: Fixed Upgrade from Beta13 to Beta14 does not take the excluded types into account properly.
+
+Apache Solr integration 7.x-1.0-beta14, 2012-01-12
+------------------------------
+#1397526 by Nick_vh, cpliakas: Add an option to select which search page facets link to when displayed on non-search pages.
+#713142 by ygerasimov, pwolanin, Nick_vh: Added configuration option to a search environment if we want to use Dismax or EDismax.
+#1379128 by Nick_vh, bdragon: Fixed Treat cardinality=1 fields as single-value + caching stats response - Follow up.
+#370855 by Damien Tournoud, Nick_vh: Add configuration option to a search page if we allow user input using the url or not.
+#1392940 by Nick_vh | pwolanin: Create a 3.x solrconfig.xml that sets luceneMatchVersion.
+#1031250 by EugenMayer, Nick_vh: Added an option to index as another user instead of only anonymous.
+#1388498 by Nick_vh | pwolanin: Remove s (sortable) fields from schema.xml.
+#1379128 by Nick_vh, bdragon: Fixed Treat cardinality=1 fields as single-value + caching stats response.
+#1361422 by Nick_vh: Fixed coder issues as mentioned by the drupal testing bot.
+#1398122 by Nick_vh | thecarlhall: Fixed Trying to get property of non-object in apachesolr_search_block_view().
+#1398100 by thecarlhall: Fixed Configuration throws exception when starting Solr.
+#1396606 by cpliakas: Fixed Fatal error 'Call to undefined function apachesolr_index_status()" when visiting admin/config/search/settings.
+#1392742 by Nick_vh, pwolanin: Fixed Add solr.LengthFilterFactory to the text fields.
+#592522 by Nick_vh, pwolanin | quaoar: Fixed Hooks node_type(), taxonomy and user knocks out our database server.
+#1394276 by pwolanin, Nick_vh, Fix for logic for last indexed timestamp.
+#1388916 by rwohleb, pwolanin: Fix for ctype_digit() port validation fails for ports < 256.
+#1391850 by cpliakas: Fix for Fatal error when Solr server is not available on non-search pages.
+#1389306 by Nick_vh: Fixed Wrong helptext link if facetapi is not installed.
+#1252648 by cpliakas, Nick_vh: Added Allow for enabling facet blocks on non-search pages.
+#1161608 by scor, Nick_vh: Added Index format_username()($account).
+#1380448 by Nick_vh | longwave: Fixed Menu item description for /admin/reports/apachesolr.
+#1387272 by cpliakas: Fixed The cancel links and button submission redirects in facet configuration forms are broken.
+#1387088 by swentel, Nick_vh: Fixed apachesolr_index_mark_for_reindex() not found during enable/disable and drush can't load apachesolr.index.inc.
+#1313698 by Nick_vh, denikin: Fixed Support for search of multiword content in facets/fields .
+#966796 by Nick_vh, scor, BarisW, wesnick, swentel, LSU_JBob | Crell: Added Separate indexer for multiple entity types.
+
+Apache Solr integration 7.x-1.x-beta13, 2011-12-21
+------------------------------
+#1376278 by Nick_vh: Fixed Inconsistent behavior of data facets producing unlimited filtering, inconsistent counts, or gap mismatches.
+#1372952 by pwolanin | albertosouza: Fixed Wrong variable in apachesolr.module.
+
+Apache Solr integration 7.x-1.0-beta12, 2011-12-12
+------------------------------
+#1369208 by pwolanin: Add configure links in .info files.
+#1369184 by pwolanin: Restore MLT block edit use of block module configure form.
+#1369144 by pwolanin: Fix for cleanup settings table and restore cron index operation.
+#1353422 by Nick_vh | Marty2081: Added Using view modes in 'more like this" block.
+#1212610 by Nick_vh | jeff.maes: Fixed Notice: Undefined index: module in apachesolr_search_form_search_form_alter(). - follow up
+#1365304 by brianV: Fixed Date field minimum/maximum range callbacks don't handle some cases; cause Solr exceptions.
+#1365940 by Nick_vh: Fixed Move all indexing functions to apachesolr.module.
+#1364564 by Nick_vh, pwolanin: Clarify % on the index page.
+#1357820 by Nick_vh | vrc3: Fixed Titles for taxonomy pages are double encoded.
+#1358730 by Nick_vh | rooby: Fixed Facet only searching isn't working.
+#1362294 by pwolanin: Fix for undefined variable: title in apachesolr_get_user_title().
+#1059372 by jpmckinney, Georgique, Nick_vh: Fixed References integration is broken.
+#1323676 by Nick_vh: Global functions should be context driven.
+#1359294 by Nick_vh: Follow-up : Fixed Test is not enabling the correct modules.
+#1359386 by Nick_vh: Replace all instances of $_GET['q'] with current_path().
+#1359294 by Nick_vh: Fixed Test is not enabling the correct modules.
+#1358158 by pwolanin | SangersDrupalDude: Fixed Schema issues on update to D7.
+#1351908 by Nick_vh: Added UI comments and improvements.
+#1349532 by Nick_vh: Added UI remake of the bias pages.
+#1357548 by Nick_vh: Make the unit tests for solr succeed if there is no solr environment available.
+#1356038 by Nick_vh: Added More like this / Blocks Admin UI rework.
+#1356018 by Nick_vh: Fixed Remove admin/system from solrconfig.xlm.
+#1344690 by Nick_vh: Added Search page should be cloneable.
+#1333904 by Nick_vh | vrc3: Added Please restore flexible 'results per page" option - follow up.
+#1292364 by Nick_vh, scor: Added UI redesign.
+#1336324 by Nick_vh | tinker: Added Get Solr version number to determine feature sets like facet ranges and location search.
+#1347092 by Nick_vh | cfuller12: Fixed Solrsort appears to be broken in beta11.
+#1344576 by Nick_vh: Fixed More like this should be environment dependent.
+#1344570 by Nick_vh: Fixed When installing solr the 'visit the admin page" link is not working.
+
+Apache Solr integration 7.x-1.0-beta11, 2011-11-16
+------------------------------
+#1328886 by drasgardian, Nick_vh, pwolanin: fix for access module fails for realm names with spaces.
+#1340232 by milesw, Nick_vh: Added Did You Mean suggestions should be broken out from core search form.
+#1343646 by Nick_vh: Fixed Empty Search behavior is not working.
+#1301646 by Nick_vh: Fixed Coder Review + Drupal coding standard.
+#1097976 by Nick_vh, jpmckinney: Fixed Use ShowFileRequestHandler, gettableFiles is deprecated.
+#1342134 by Nick_vh: Fixed 'Creating default object from empty value" Notice in node access and indexing test.
+#1341860 by pwolanin: Fixed Notice: Undefined index: fq in apachesolr_search_conditions_default() (line 401 of apachesolr_search().module).
+#1053126 by jpmckinney, Nick_vh | pwolanin: Remove duplicate sort hooks in 7.x? follow-up.
+#1053126 by jpmckinney, Nick_vh | pwolanin: Remove duplicate sort hooks in 7.x?.
+#1341854 by pwolanin: Pass the query object into hooks altering search results.
+#1340552 by pwolanin: Make facet generation more flexible/overrideable.
+#1341840 by pwolanin: Fix for undefined index 'core_search' while running tests.
+#1271964 by Nick_vh | wmostrey: Fix for no way to delete content recommendation blocks.
+#1314406 by Nick_vh, scor: Fixed De-duplication of the apachesolr_search_execute() and apachesolr_search_user_defined_search_page().
+#1161538 by Nick_vh, pwolanin | domidc: Fixed The numeric field id should not be used for Solr index field names.
+#1333904 by Nick_vh | vrc3: Restore flexible 'results per page' option.
+#1161444 by Nick_vh | cpliakas: Modify Facet API field definitions to reflect API change for the 'query type" key.
+#1334216 by Nick_vh: Fixed Convert all static parameters to drupal_static().
+#1328854 by Josh Waihi: Added Tag cron database queries to allow modules to alter conditions of updating index table.
+#1323758 by Nick_vh | Frippuz: Fixed hook_apachesolr_process_results() make no impact on results.
+#1265124 by InternetDevels.Com: Fixed Not output pager in search results.
+#1324842 by Nick_vh: Added setAvailableSorts to the api.
+#1000532 by craigmc, jpmckinney: Fixed Non-current/valid Node Types not excluded from index.
+#1320906 by Nick_vh | brianV: Fixed Taxonomy Search page title should be dynamic based on term.
+#1320076 by Nick_vh | egarias: Fixed Results per page should be non-negative integer less than 200.
+#1320634 by Nick_vh | jummonk: Fixed Search pages saved in static array before they are created in DB => PDO exception on creation of menu_router() records.
+#1319542 by jgalletta: Fixed Undefined index: get in apachesolr_search_user_defined_search_form_submit().
+#1313698 by Nick_vh, denikin: Fixed Support for search of date content in facets/fields
+#1316578 by Nick_vh | rooby: Added some documentation somewhere that says you need the facetapi module for facets.
+
+
+Apache Solr integration 7.x-1.0-beta10, 2011-10-19
+------------------------------
+#1312718 by pwolanin: fix for menu rebuild problems when installing apachesolr_search.
+#1134610 by pcambra, JoeMcGuire, Ravi.J: schema support for ctools export of settings.
+#1314664 by Nick_vh, brianV: fix for Search pages completely ignore the title set in the configuration.
+#1314260 by Nick_vh: Fixed hook_apachesolr_query_prepare() not also correctly documented.
+#1313698 by Nick_vh, denikin: Fixed Support for search of multiword content in facets/fields .
+#1309572 by Nick_vh: Fixed Creating new search page gives error when trying to find the search page variable.
+#1204480 by Nick_vh | chriscalip: Fixed Please update apachesolr.api.php naming convention from HOOK_ to hook_.
+#1212610 by Nick_vh: Fixed Notice: Undefined index: module in apachesolr_search_form_search_form_alter().
+#1309564 by Nick_vh: Fixed Simplifying syntax between isset and empty for search_box() in custom page.
+
+Apache Solr integration 7.x-1.0-beta9, 2011-10-13
+------------------------------
+#1307526 by pwolanin, Nick_vh: Fixes for update path, core search functionality.
+#1264786 by grndlvl: fix for double ellipses on search snippets.
+#1305282 by pwolanin, Nick_vh: Fixed Search pages problems.
+#1283924 by rjmackay, lazysoundsystem, jweowu: fix for notice undefined index errors.
+#1305052 by cpliakas: fix for Negative facets not displayed when the mincount is 0.
+#1279164 by pwolanin, fix for 'bundle' is not a required field, but apachesolr treats it as such.
+#1300380 by Nick_vh, pwolanin: Search environments not clear about being active or online.
+#1294846 by Nick_vh: Added Refactoring of the search pages.
+#1188824 by pwolanin: fix for very large watchdog entries when index is in read-only mode.
+#1270826 by pwolanin, brianV: fix for search page regex fails for complex queries.
+#989398 by pwolanin, Nick_vh: Fix tests after moving conf files.
+#1167136 by cpliakas: fix for fields attached to nodes added as facets regardless off the collection type.
+#1225554 by pwolanin: fix for pagination missing in the search page administration.
+#817286 by pfrenssen: API docs cleanup.
+#901376 by LiuShaz, pwolanin: insure UTF-8 encoding is used for POST searches.
+#1288080 by Nick_vh, brianV: make facets based on date fields work.
+#1201534 by BrianV, pwolanin: restore date field indexing.
+#1230380 by Shawn_Smiley: fix for Undefined index: 'facet mincount allowed'.
+#1292328 by Nick_vh: add clone environment feature, tweak the UI.
+#1187888 by pwolanin: move conf to a subdirectory and start supporting solr 3.3+.
+#1237472 by DeFr, sfyn: Fix for _constructURL method misforms urls with username/password.
+#1258658 by pwolanin: Fix failing node access test due to core 7.3 change.
+#1248366 by Dave Reid: Fix declaration of getInfo() test functions.
+#1219178 by cpliakas: Added support for customizable minimum facet counts.
+#1216184 by cpliakas: remove unneeded static variable.
+#1204450 by blazey: fix for parameter error in apachesolr_taxonomy module.
+#1150174 by mr.andrey, pwolanin: Strip content of script and similar tags when indexing.
+#1183742 by MrHaroldA, pwolanin: Index all numeric field API fields by default.
+#1188614 by ASupinski: Expand Hook_Hook_Info to include other hooks.
+
+Apache Solr integration 7.x-1.0-beta8, 2011-06-13
+------------------------------
+#1174960 by pwolanin: fix critical indexing bug from DBTNG error in apachesolr_cron_check_node_table().
+#1148612 by pwolanin: fix regression; Clicking "Relevancy" has no effect after choosing another sort.
+
+Apache Solr integration 7.x-1.0-beta7, 2011-05-24
+------------------------------
+#1162600 by pwolanin: Display an error if the schema version in use is incompatible.
+#1162078 by jpmckinney: fix for Undefined variable: stats_summary.
+#1159172 by jpmckinney: Remove unused facet functions.
+#1167172 by cpliakas: Improve the breadcrumb handling for facet settings forms.
+#1157864 by cpliakas: Integrate with Facet API's depencency plugin system.
+#912758 by pwolanin: use Facet API's support for faceting missing values.
+#1098860 by jpmckinney: Add apachesolr_cron_check_node_table back to cron.
+#1159172 by cpliakas: Remove unused facet functions.
+#926564 by jpmckinney: Add get_subqueries().
+#1064972 by jpmckinney: Use is_callable not function_exists, where applicable.
+#1097988 by pwolanin: Add omitHeader to save on bandwidth.
+#1154770 by jpmckinney, pwolanin: Must double quote filter query values if containing space or colon.
+#1152382 by cpliakas, pwolanin: Modify Facet API adapter for api changes.
+#1131288 by jpmckinney: Fix install and other follow-ups for renaming "server" to "search environment".
+#1150988 by pwolanin: Fix for facet blocks based on custom fields displaying field keys instead of labels.
+#1150220 by pwolanin: Fix for MLT requests are not going through query alter.
+#1150306 by pwolanin: fix for double URL encoding of plus sign (+) on search, after changing sort filters.
+
+Apache Solr integration 7.x-1.0-beta6, 2011-05-06
+------------------------------
+#1148768 by pwolanin: move the read-only index setting to the environment edit page.
+#1146976 by pwolanin: Rename hook_apachesolr_modify_query to hook_apachesolr_query_alter and other API clean up.
+#1146296 by pwolanin: integrate with Facet API current search block code.
+#1145036 by slip, pwolanin: Add support for facet browsing to custom search pages.
+#1131288 by pwolanin: Rename "server" to "search environment" for better conceptual clarity.
+#1122186 by slip, pwolanin: Allow custom user-specified search pages, supporting API changes.
+#1127520 by cpliakas, pwolanin: make the breadcrumb look reasonable on facet form.
+#1127302 by Janusman: some variables were not removed on uninstall.
+#1126806 by pwolanin, Janusman: restore facet browsing functionality.
+#1126488 by cpliakas: Implemented hierarchical taxonomy facets.
+#1126284 by pwolanin: add enabled filters tab on every server edit page.
+#1126282 by pwolanin: fix facet mincount param.
+#1124844 by pwolanin: Port over facet API adapter and hooks.
+#1121170 by pwolanin: remove facet-related code to prep for Facet API integration.
+#1122348 by pwolanin: Rework query class to provide uniform methods of getting and setting params.
+
+Apache Solr integration 7.x-1.0-beta-5, 2011-04-07
+------------------------------
+#799970 by pwolanin: update README for config changes.
+#1118646 by cpliakas, pwolanin: Fields now displayed on search index report page.
+#1117152 by cpliakas: Added a cancel link to the server edit page.
+#1117606 by cpliakas: Resolved inconsistencies with the caller parameter.
+#1118508 by pwolanin: Make the Apache Solr config link show up next to Search module.
+#1117128 by jpmckinney: Follow-up to #1088208
+
+Apache Solr integration 7.x-1.0-beta4, 2011-04-04
+------------------------------
+#1116030 by cpliakas, pwolanin: Added titles to settings pages to add transparency as to which server's settings are being edited.
+#1112022 by pwolanin, elliotttf: index node last_comment_timestamp too.
+#1114798 by pwolanin: enhancements to config based on Solr 3.1 examples.
+#1108618 by pwolanin: make numeric fields in 7.x use a sortable data type by default.
+#1103602 by pwolanin: prevent PHP Notice when there is an invalid term reference field.
+#1097988 by jpmckinney: avoid 'using default converter' warning on Solr startup.
+#920482 by jpmckinney: $info_split['date'] template variable should contain changed, not created, date.
+#379512 by pwolanin: separate schema field for indexing comments and "extra" information.
+#871440 by jpmckinney: Solr taxonomy page displays search form and blocks when the user has no access.
+#761990 by jhedstrom, pwolanin: switch to POST for long search ULRs.
+#1112362 by pwolanin: cleanup following #1107502 to better use drupal_http_request.
+#1107502 by pwolanin: Merge relevant parts of php client into DrupalApacheSolrService.
+#899590 by jpmckinney, elliotttf: Support indexing of attached fields that are not facets.
+#993476 by jpmckinney, pwolanin: allow arbitrary results per page in the 0-200 range.
+#1080652 by elliotttf, pwolanin: Allow other modules to return search results on solr failure.
+#562214 by ecofinn, wmostry, jpmckinney: Problems with double-encoded ampersands.
+#997480 by jpmckinney | davidwhthomas: Facet checkboxes are duplicated following other javascript activity on page.
+#1098038 by pwolanin, mgifford: fix spelling suggestion incorrect use of LABEL tag.
+#1099390 by jpmckinney: Fatal error: Call to undefined function apachesolr_nodeaccess_build_subquery().
+#1098222 by pwolanin: Rename and make the nodeaccess module more generic.
+#1092910 by pwolanin: missing date field conversions from #1088208.
+#1090530 by pwolanin: Further schema-related code fixes following from #1088208.
+#783366 by elliotttf: Invoke hook_apachesolr_prepare_query() in apachesolr_search_browse
+#1078766 by elliotttf: code-style cleanup according Coder module.
+#1049114 by Steven Jones, james.williams, Janusman: restore hierarchical taxonomy facets.
+#1088208 by pwolanin | Janusman: simplify the schmea to eliminate node-specific fields.
+#1089342 by elliotttf: Content Biasing not working.
+#996800 by elliotttf: trim host, port, and path strings to prevent connection errors.
+#1020780 by jpmckinney, pwolanin: cleanup of variable_get to apachesolr_server_variable_get conversion.
+#1085630 by pwolanin: Index taxonomy term ancestors into term reference-based field.
+#1050000 by pwolanin: More generically prevent calling nodeapi update_index when indexing.
+#1060536 by jpmckinney: Long title and Default shortcut link obscured in overlay.
+#1060550 by jpmckinney: admin/build/block should be admin/structure/block.
+#704190 by pwolanin | robertDouglass | jpmckinney: Add page callbacks to display conf files in the index in reports.
+#925608 by jpmckinney | janusman: Quick perf improvement: cache term ancestors on indexing.
+#1059380 by jpmckinney: apachesolr_fields_list_display_callback doesn't return if $facet in list_allowed_values.
+#1059368 by jpmckinney: apachesolr_clear_cache as a #submit callback doesn't work.
+#1072884 by justinrandell: incorrect use of query->condition() in apachesolr_cron().
+#901720 by jpmckinney | robertDouglass: Highlighting snippets in search results not flexible enough, and logic improvement.
+#1064782 by jpmckinney: Use module_load_include, module_load_install instead of include_once.
+#791916 by Network | jpmckinney: Allow facet search block to have children always show.
+#937328 by Davy Van Den Bremt | pwolanin: Drush support for indexing remaining nodes.
+#1060698 by dww | jpmckinney: Always display the current value of apachesolr_cron_limit in the admin UI.
+#904312 by pounard: Use drupal_get_breadcrumb() not menu_get_active_breadcrumb().
+#616888 by bangpound: Pass delta to MLT blocks' theme function.
+#864146 by pwolanin | jpmckinney: Fixed When moving fq to q.alt, we should parenthesize each fq.
+#896324 by ahankinson | jpmckinney: Fixed module_invoke() called too late.
+#840358 by pwolanin | torstenzenk: Fixed Error searching Taxonomies.
+#991444 by Nick_vh: None of start, end, gap should show up as date facets.
+#835674 by pwolanin: Remove search module dependency from apachesolr.
+#961570 by jpmckinney: if apachesolr_search was the default search module in D6, make it so in D7.
+#878996 by pwolanin | weri: Added Don't break the loop.
+#1050044 by pwolanin: hook_theme API fix, and revert to using core theme('search_results').
+#1026916 by dmitry_bezer: apachesolr_get_enabled_facets() mandatory parameter was omitted.
+#528086 by pwolanin: Fix for special html entity search and display bugs.
+#1020780 by pwolanin: Store variable settings per server for better flexibility.
+#891962 by jurcello, pwolanin: avoid incorrect filter substring matches, emit correct query string.
+#1018768 by pwolanin: fix notices during failed search request.
+
+Apache Solr integration 7.x-1.0-BETA3, 2011-01-06
+------------------------------
+#1017836 by Janusman, pwolanin: fix empty search behavior.
+#1017624 by pwolanin: Fix for "Did you mean" suggestion does not show.
+#1007848 by pwolanin: Fixes for apachesolr_nodeaccess for Drupal 7.
+#1017258 by pwolanin: Fix help text when there are no search results.
+#1013122 by pwolanin: some JS cleanup to use jQuery proxy.
+#1013136 by pwolanin: fix retain filters checkbox.
+#1009398 by pwolanin: fix content bias forms.
+#1007860 by pwolanin: API fix for hook_apachesolr_modify_query, add type hinting.
+#1007824 by pwolanin: use contextual links to avoid block caching mode issues.
+#1003500 fix icon and icon path.
+#957652 by aegnor, pwolanin: fix str_replace may remove a substring in filter_extract.
+
+Apache Solr integration 7.x-1.0-BETA2, 2010-12-18
+------------------------------
+#983458 by craig_ : mass update and mass delete ignore setting apachesolr_read_only.
+#996976 by scor: list item class should be an array, not a string.
+#995526 by pwolanin: Alter server schema so we don't exceed the MyISAM key size limit.
+#1000396 by dmitry_bezer: Edit server form ignored "Make this server the default" checkbox.
+#997240 by VladGh: fix parameters for apachesolr_server_edit_form for PHP 5.3.
+#993448 by pwolanin, scor: get Solr result docs as stdClass instead of Apache_Solr_Document.
+
+Apache Solr integration 7.x-1.0-BETA1, 2010-12-09
+------------------------------
+#979198 by pwolanin, janusman: Missing 'module' property on facet $block objects.
+#992860 by pwolanin, davereid: Taxonomy indexing and faceting has to be per field, not per vocab.
+#991590 by larskleiner: fix for API change to timezone param in format_date().
+#989730 by pwolanin: Using tdate instead of data cases java exception in using rord().
+#989658 by pwolanin: Drupal 7 allows multiple term refernece fields for the same vocabulary.
+#989398 by pwolanin: get some actual tests working.
+#983892 by pwolanin: update schema to use long instead of int, plus tdate fields.
+#983894 by pwolanin: add a set of conf files that can be used to create a test core.
+#983572 by amateescu, pwolanin: fix for empty filter values causing Solr error.
+#795912 by pwolanin patch 64: fixes various settings forms and variables, avoids a notice, removes use of md5() in favor of drupal_hash_base64().
+#982846 by pwolanin: split out (and deprecate) the taxonomy path hijack feature.
+#982840 by pwolanin: OO cleanup for Drupal 7 coding standards.
+#982490 by pwolanin: rip out Drupal 6.x update functions, update README.
+#904100 by das-peter, pwolanin: prevent missing table error when comment module not enabled.
+#795912 by pwolanin patch 62: requirements fixes, add a button to test server settings.
+#795912 by pwolanin patch 61: fix up server add/edit/delete funcitonality.
+#795912 by pwolanin, crell patch 60: - makes Field API handling more generic, adds a framework
+ for handling multiple Solr servers, and moves the nodeaccess module out of the contrib dir.
+#885950 by pwolanin, csevb10: preserve added/removed filters when filterstring is re-parsed.
+#864160 by pwolanin: Allow the caller a last chance to modify the query and params.
+#536990 by pwolanin | jpmckinney, janusman: always index content as an anonymous user.
+#835850 by pwolanin: add more replicated files to solrconfig.xml master section.
+#830976 by eosrei, pwolanin: make sure we return a non-zero ping time on success.
+#795912 by tjwallace, dmitry_bezer, jpmckinney, pwolanin: inital Drupal 7 port.
+
+Apache Solr integration 6.x-2.0-BETA1, 2010-04-08
+------------------------------
+#660754 by jhedstrom: Added Allow key sorting of facets.
+#614644 by netsensei | robertDouglass: Fixed Forms attached to Apachesolr search results won't work.
+#747346 by robertDouglass, pwolanin | lazysoundsystem: Fixed Typo in apachesolr_search().module.
+#763072 by robertDouglass, justinrandell | pwolanin: Fixed warnings when indexing old, crappy html.
+#658278 by cpliakas | JThan: Fixed Errors when building the search index in PHP 5.3.
+#765486 by robertDouglass: Fixed Several cases where Luke cache not getting cleared and resulting in errors.
+#765448 by robertDouglass: Fixed Facet blocks for hierarchical taxonomy broken.
+#751420 by pwolanin, skwashd | Damien Tournoud, Scott Reynolds: Fixed apachesolr_site_hash() calls md5() twice.
+#750426 by mkalkbrenner, pwolanin | robertDouglass: Fixed fieldType textTight conficts with fieldType text and textSpell.
+
+Apache Solr integration 6.x-2.0-BETA1, 2010-03-24
+------------------------------
+#649038 by brunodbo, slip | robertDouglass: Fixed Search not working on 404 page.
+
+Apache Solr integration 6.x-2.0-ALPHA3, 2010-03-22
+------------------------------
+#610656 by pwolanin, claudiu.cristea | Scott Reynolds: Fixed Facets requests for non-enabled modules.
+#686390 by pwolanin | rjbrown99: Fixed Wrong number of initial items in taxonomy facet under certain conditions.
+#573734 by drewish | robertDouglass: Added Index controls should be radio buttons with one form submission button.
+#736540 by drewish | Scott Reynolds: Changed Minimize UPDATE queries in apachesolr_nodeapi_mass_update().
+#687738 by David Lesieur | anantagati: Fixed Avoid introducing empty 'filters' query string.
+#733116 by pwolanin | drewish: Changed Implement hook_flush_caches().
+#719356 by robertDouglass, mathieu | flk: Fixed Indexing cron triggers sigsegv in apachesolr.module line 387.
+#744038 by siliconmeadow: Changed Change of Drush extension command naming conventions.
+#558160 by robertDouglass, mihha | DenRaf, mcarbone, haxney: Added date facet for cck fields.
+#666936 by pwolanin, robertDouglass, claudiu.cristea | justindodge: Fixed apachesolr.js - Drupal.behaviors.apachesolr does not respect context.
+#708424 by janusman: Changed Change gmdate() to Drupal format_date() in date facets to support localization.
+
+Apache Solr integration 6.x-2.0-ALPHA2, 2010-01-08
+------------------------------
+#679522 by pwolanin, Add gettableFiles to solr admin interface config.
+http://drupal.org/cvs?commit=309746 by robertDouglass, add entity='comment' to comments on indexing.
+#672882 by David Lesieur: Fixed Broken 'Show more' link on taxonomy facets.
+#604566 by robertDouglass | jhedstrom: Fixed index_value() never set for CCK fields that aren't of type text, node or user referrence.
+#672530 by robertDouglass: Fixed Change array key names from display callback to display_callback() and indexing callback to indexing_callback().
+#672518 by robertDouglass: Fixed Add new trie prefixes to helper function .
+#551582 by drewish: Fixed Show value instead of key in CCK facets.
+#668396 by pwolanin, closer to fix from #655006 for PHP notices.
+#664818 by robertDouglass, pounard, pwolanin | Scott Reynolds: Fixed Wrong watchdog() usage.
+#657648 by kcoop: Added Add Smaller Limit Options to Apache Solr Cron Indexing.
+
+Apache Solr integration 6.x-2.0-ALPHA1, 2009-12-26
+------------------------------
+#664818 by robertDouglass, pounard, pwolanin | Scott Reynolds: Fixed Wrong watchdog() usage.
+#662232 by pwolanin | anarchivist: Changed Use language-neutral code like D7.
+#666648 by pwolanin: Changed Make hook_apachesolr_update_index() more generic by taking a namespace param also.
+#667110 by pwolanin: Fixed Replace bogus use of pager_query().
+#667124 by pwolanin: Fixed Use current query not altered query for the breadcrumb.
+#667650 by Dave Reid: Fixed Results of apachesolr_process_response() should return absolute URLs.
+#664572 by pwolanin: Added Add schema and core name to admin screen.
+#664860 by pounard: Fixed Wrong t() usage in apachesolr_field_name_map().
+#528086 by pwolanin, better (but still problematic) handling of entities.
+#662232 by pwolanin, index zxx as the Language neutral code.
+#401234 by mkalkbrenner, janusman, and pwolanin, reflect hierarchical taxonomy vocabulary in facets.
+#661952 by pwolanin, fix no results help text for dismax syntax.
+#348668 by pwolanin, add indexing of the 'node' entity string.
+#641954 by anarchivist, swentel, pwolanin, update schema.xml.
+#651044 by kcoop use node title for comment title when comment has no title.
+#655006 by Scott Reynolds, pwolanin fix warnings on constants.
+#652512 by robertDouglass enable use of more than just the default solr server.
+#642602 by robertDouglass, change 'content type' to 'content_type' in facet definitions.
+#641452 by robertDouglass, prevent admin from trying to re-index when in read-only mode.
+#372767 by socki, robertDouglass, pwolanin allow MLT blocks to be filtered by type and custom filters.
+#372336 by der, janusman, robertDouglass, allow name sorting of facet links.
+#611670 by pwolanin, allow modules to abort the building of documents for indexing.
+#628080 by pwolanin, update to use Solr PHP library r22 and check for it in hook_requirements.
+#638236 by mkalkbrenner and robertDouglass, undocumented dependency on taxonomy module.
+#562458 by janusman, fix typo preventing menu_rebuild regarding taxonomy hijack.
+#630798 by joshk, robertDouglass make cache_apachesolr table to facilitate better memcache utilization.
+#623046 by robertDouglass make the results that come back from a search more useful.
+#622120 by robertDouglass make the "Show more" block selection dynamic to accommodate other modules.
+#621922 by robertDouglass make the "Show more" js more robust.
+#612024 by pwolanin, Add method to allow requests to additional Solr servelets.
+#561082 by pwolanin, consolidate Solr delete queries on cron.
+#580404 by pwolanin per content type comment exclusion.
+#597174 by Frando, add hook_apachesolr_prepare_query() to enable custom sorts.
+#591278 by robertDouglass fix bug that was preventing hook_apachesolr_modify_query from working correctly.
+#590982 by swentel fix warnings on indexing.
+#554136 by emackn, Jaza make results-per-page alterable.
+#580764 by robertDougalss Add a new contrib module that allows searching on just comments.
+#548160 by robertDouglass get rid of functions that begin with underscore. Yuck.
+#580404 by robertDouglass make indexing of comments optional. New variable, apachesolr_index_comments_with_node.
+#538636 by robertDouglass allow modules to register document handlers so that multiple documents can be indexed per entity.
+#557382 by Josh Waihi, Scott Reynolds mlt blocks were double encoding titles.
+#578008 by robertDouglass improve performance by not including unused facet queries.
+#552152 by robertDouglass OR operator for facet blocks.
+#576092 by robertDouglass use Drush to search the site using Solr.
+#576040 by robertDouglass use Drush to download the SolrPhpClient: drush solr phpclient
+#457826 by janusman Make the behavior of empty searches configurable.
+#573038 by robertDouglass Automatically create facets for user and node reference CCK fields.
+#570476 by robertDouglass add initial Drush support with commands drush solr delete index and drush solr reindex.
+#570476 by robertDouglass allow for deleting or reindexing single content types.
+#456420 by anarchivist, janusman, robertDouglass Reindex using Batch API.
+#551510 by Scott Reynolds Add in ability to theme different facet blocks differently.
+#551620 by robertDouglass Type dependent facet blocks.
+#549664 by Scott Reynolds Ignore node_access for Solr Views queries.
+#551582 by robertDouglass make CCK breadcrumbs, facets, and current search show the value, not the key.
+#551278 by robertDouglass CCK mappings don't respect shared fields
+#535654 by drunken monkey Add apachesolr_server_status() function
+#543226 by drunken monkey validate port on settings form.
+#502976 by Scott Reynolds followup to Other GET parameters ignored by Apache Solr Facet Blocks
+#473554 by janusman Add an "unclick" link to search keys
+#545094 by loganfsmyth add getter and setter methods for a query's keys.
+#530910 by Damien Tournoud fix offset problem in field settings administration.
+#526344 by drunken monkey Remove apachesolr_read_only check from Drupal_ Apache_Solr_Service::_sendRawPost().
+#525980 by robertDouglass Clarify the API of apachesolr_index_updated.
+#530196 by pwolanin, fix facecount form function calls in apachesolr_og.
+#548102 by robertDouglass change wording on enabled filters page to improve usability.
+#529606 by Damien Tournoud update schema.xml with WhitespaceTokenizerFactory and SnowballPorterFilterFactory. Note that you need to stop solr, replace schema.xml, delete your index, and re-index your site.
+#528002 by janusman, Add RSS discovery to taxonomy hijack page
+#528888 by robertDouglass turn spellchecker on by default
+#528596 part 1 by robertDouglass add JS enabled checkboxes to facet and unclick links
+#525918 by robertDouglass be more forceful when reindexing; rebuild the apachesolr_search_node table completely.
+#528516 by robertDouglass add apachesolr-facet and apachesolr-unclick CSS classes to unclick and facet links.
+#528484 by robertDouglass switch to Drupal.behaviors in apachesolr.js
+#515682 by robertDouglass, add confirmation form to re-index button.
+#509526 by pwolanin, {apachesolr_search_node} table should be rebuilt when index is deleted.
+#457826 by janusman, robertDouglass - show browsable facet blocks in the search well when no search term is present to allow browsing. Hello 6.2 branch of ApacheSolr :D
+
+Apache Solr integration 6.x-1.x, xxxx-xx-xx
+------------------------------
+#508364 by pwolanin, Don't offer non-indexed fields as search options.
+#508548 by pwolanin, Don't implode params['fq'] if it's not set.
+#708424 by janusman: Changed Change gmdate() to Drupal format_date() in date facets to support localization.
+
+Apache Solr integration 6.x-1.0-RC1, 2009-07-02
+------------------------------
+#502976 by pwolanin, Scott Reynolds, robertDouglass facet links and form submissions respect non ApacheSolr $_GET parameters. Note that this changes the interface API: get_url_querystring is now get_url_queryvalues and returns and array instead of a string.
+#507708 by pwolanin, fix sort parameters to use field aliases, validate in query object.
+#299539 by kleung11 and pwolanin, use 'administer search' for permission checking.
+#503644 by pwolanin and Jeremy, make sure we strip ctrl chars last, add logging.
+#505652 by bdurbin, add apachesolr-showhide class to Show more link.
+#472600 by janusman, JacobSingh, and pwolanin, optionally hijack taxonomy pages.
+#496650 by mkalkbrenner, make unclick links work after #463900.
+#495258 comment out timeAllowed params (partial roll-back of #490076)
+#495012 by pwolanin, fix Anonymous user and other 0-value facets.
+#463900 by pwolanin and JacobSingh, facet theme function clean-up.
+#405206 by pwolanin, allow Apache Solr to be the default, let core search index 0 nodes.
+#453310 by pwolanin, allow easier theming of username display.
+#490076 by pwolanin, spellcheck more popular, maxqt to 20, limit search time.
+#358166 by David Lesieur, janusman, cptnCauliflower, and pwolanin, search for just facet(s).
+#489654 by JacobSingh, and pwolanin, allow users to set their index as "read only".
+
+Apache Solr integration 6.x-1.0-beta11, 2009-06-11
+------------------------------
+#348218 by David Lesieur, janusman, and pwolanin, retain filters for next search.
+#401046 by pwolanin, revist urlencoding of query strings.
+#467810 by aufumy, Pass in page number and caller to apachesolr_search_execute.
+#481838 by JacobSingh and pwolanin, enable plus sign in search when using clean URLs.
+#480814 by mkalkbrenner and pwolanin, add more detail to logging on errors.
+#464758 by pwolanin, 4th param to htmlspecialchars breaks PHP < 5.2.3.
+#466328 by pwolanin, fix classes for sort links.
+
+Apache Solr integration 6.x-1.0-beta10, 2009-05-14
+------------------------------
+#449414 by pwolanin, aufumy, & Scott Reynolds, refactor apachesolr_search_search().
+#462836 by pwolanin, catch fatal error in _nodeaccess if no solr.
+#461506 by pwolanin, do nothing if there are no nodes to index.
+#459930 by Scott Reynolds and pwolanin, clean up hook_enable(), uninstall, update_6004
+#453338 by pwolanin and JacobSingh, move mlt functionality into the framework module.
+#365495 by pwolanin, improve admin screens and usability of field weights.
+#454608 by pwolanin, fix current search block.
+#453182 by pwolanin, use stored path rather than forcing node/$nid.
+#448298 by JacobSingh and pwolanin, use a confirm form for index deletion.
+#454352 by Damien Tournoud, make optimize interval configurable, document variables.
+
+Apache Solr integration 6.x-1.0-beta9, 2009-04-30
+------------------------------
+#435924 by pwolanin, only clear cache on cron after updates and if the server is available.
+#405780 by blackdog and pwolanin, skip excluded node types during counting and indexing.
+#441628 by aufumy and pwolanin, update _og for negative facets, minor fixes, install/enable/update hooks.
+#447622 by pwolanin and mkalkbrenner, better encoding of html entities and CCK facets.
+#447890 by pwolanin, properly respect 'access content' permission in _nodeaccess.
+#271753 by pwolanin, more granular CCK field mappings via _alter hook.
+#436074 by pwolanin, better query class handling of negative queries.
+#442198 by Scott Reynolds and pwolanin, update the Drupal_Solr_Query_Interface interface.
+#443252 by Scott Reynolds, (bugfix for regression) make protected id public again.
+#337737 by David Lesieur, mikejoconnor and Scott Reynolds, localize arg(1) dependence.
+ Changes query get_path() to facilitate generating facets outside the search page.
+
+Apache Solr integration 6.x-1.0-beta8, 2009-04-16
+------------------------------
+#343252 by pwolanin, fix nodeaccess for method name changes, make multi-site aware.
+#432946 by pwolanin, query class and sort cleanups.
+#393480 by pwolanin and Jody Lynn, provide a book facet and facets for missing fields.
+#432140 by Damien Tournoud, use format_interval() for more attractive, localizable time intervals.
+#348029 by pwolanin, Handle negative filters and improve date facet block code.
+#254565 by drunken monkey and Scott Reynolds, change the query class to enable Views integration.
+
+Apache Solr integration 6.x-1.0-beta7, 2009-04-03
+------------------------------
+#410330 by pwolanin and bhuga, return more information for error 0.
+#293989 by bjaspan and vladimir.dolgopolov, add date facets for created and changed dates.
+#420290 by mkalkbrenner and pwolanin, add spaces around tags to avoid running words together.
+#368688 by hurleyit and pwolanin, send MLT docs instead of processed links to theme function.
+#383478 by pwolanin and JacobSingh, provide more information about autocommit lag, pending deletes.
+#339490 by aufumy, pwolanin, and JacobSingh, Organic groups Apachesolr integration, new _alter hook.
+
+Apache Solr integration 6.x-1.0-beta6, 2009-03-20
+------------------------------
+#305370 by pwolanin, Handle failed delete requests so unpublished/deleted content doesn't stay in the index.
+#407570 by pwolanin and moshe weitzman, _alter for sort links, hide for < 2 results.
+#392978 by pwolanin and ncameron, workaround for those using php 5.1, update README.
+#402984 by JacobSingh and pwolanin, put MLT menu under the general ApacheSolr settings.
+#401442 by Janusman and pwolanin, no sort block when 0 results.
+#405732 by JacobSingh, pwolanin: Update to new SolrPhpClient (r6) and make ping() use drupal_http_request.
+#405722 by JacobSingh, increase ping timeout and make it variable.
+#400882 by mkalkbrenner, fix faceting bug due to static counter in method add_field.
+#382358 by pwolanin, use tokenizer solr.CharStreamAwareWhitespaceTokenizerFactory to fix highlighting.
+
+Apache Solr integration 6.x-1.0-beta5, 2009-02-27
+------------------------------
+#305370 by pwolanin, don't delete from apachesolr table if Solr query fails.
+#385348 by moshe weitzman, use key in sort links array.
+#385362 by pwolanin, Shorten hash from 32 chars to 12.
+#383804 by JacobSingh, fix query building that broke nodeaccess.
+
+Apache Solr integration 6.x-1.0-beta4, 2009-02-23
+------------------------------
+#380670 by pwolanin, only add a bq param for a node-type boost > 'Normal'.
+#379518 by pwolanin, correct mismatch in default boost between
+ solrconfig.xml and apachesolr_search.
+#380594 by pwolanin, empty the spellcheck dictionary if the index is deleted.
+#380644 by JacobSingh, Backwards compatability for old sort fields.
+#380538 by pwolanin, fix code to find vid for taxonomy facet blocks.
+
+Apache Solr integration 6.x-1.0-beta3, 2009-02-20
+------------------------------
+#378222 by janusman and pwolanin, add boost settings for "sticky" and "promote".
+#378566 by pwolanin, nodeaccess not correctly marking single nodes for re-indexing.
+#378270 by pwolanin, suppress MLT admin link when there is no block content.
+#378196 by pwolanin, remove PHP client from CVS per Drupal.org policy.
+#231200 by janusman and pwolanin, turn on mapping of accented to non-accented
+ ISO characters for indexing and search.
+#377494 by pwolanin, Update text type in schema to new example.
+#376270 by pwolanin, also add option to bias on recent comments/changes.
+#337879 by pwolanin and blackdog, Store relative not absolute paths.
+#376255 by pwolanin, Index more node fields, use boolean fields.
+#376966 by JacobSingh and pwolanin, requesting the top terms from luke is very
+ expensive, so normally request 0, and only get them for smaller indexes.
+#375991 by pwolanin, build spellcheck index on optimize.
+#370707 by pwolanin, make sort field names consistent, make ignored multiValued.
+#375723 by pwolanin, prevent fatal error if available facet list changes.
+#373921 by JacobSingh, show pending docs on index page from autocommit.
+#371858 by pwolanin, re-fill the Luke cache after we empty it on cron.
+#372120 by pwolanin, create one MLT block by default on install of apachesolr_mlt.
+#370707 compact field names, create "order by" fields in schema.xml
+ by pwolanin and Damien Tournoud.
+#370796 avoid repeated looping/indexing in apachesolr_index_nodes() by Damien Tournoud.
+#369944 Add field aliases and further clean-up the query class, by pwolanin.
+#366959 make usage of solrsort consistent in Solr_Base_Query::solrsort by Damien Tournoud.
+# Update errant watchdog calls that were using D5 signature by robertDouglass.
+#369780 Rearrange code for better organization and performance by robertDouglass.
+#365901 Fix bug where indexing might hang & improved API by adding a separate
+ hook for modules to indicate that a node is excluded, by pwolanin.
+#367361 Use the machine-readable name for disabled node types by pwolanin.
+#366957 Add a "configure" link to the more like this block by JacobSingh.
+#365901 Add a bias on node type (and node-type exclusion) by Damien Tournoud and pwolanin.
+
+Apache Solr integration 6.x-1.0-beta2, 2009-01-28 (changes since 6.x-1.0-alpha6 2009-Jan-08)
+------------------------------
+#365684 Get PHP library from new svn home by pwolanin
+#365620 clear stale data on hook_enable by pwolanin
+#365312 don't redirect after enabling filters by pwolanin
+#365245 invalid foreach when no facets available reported by Damien Tournoud
+# don't let attachements be enabled since it seems be broken by pwolanin
+#363972 fix ApacheSolr to Apache Solr
+#363972 Text improvements for UI by horncologne and pwolanin
+#365063 fix module name in admin screen by pwolanin
+#365022 fatal error in MLT when no Solr server by pwolanin
+#364446 fix space problem and clean up query class by pwolanin
+#355525 fix mis-named variables, patch by pwolanin, bug reported by flexer
+#339467 centralize/register facets blocks by paul.lovvik, JacobSingh and
+ pwolanin
+#362389 make the _image module work by pwolanin
+#364140 fix mlt schema bug, thanks to webrascal
+#364384 reorder selects to have bigger numbers at the top by pwolanin, suggested
+ by horncologne
+#350330 make sure to index dates as GMT, thanks to webrascal
+#363416 reindex without blowing away either the solr index or the core search index by pwolanin
+#360227 strip ctl chars() also on path, reported by flexer
+#348215 cleanup - simplify branching, numerically index array by pwolanin
+#348215 add missing js file with minor text chenges (js file by vladimir.dolgopolov)
+#359923 separate cron limit for apachesolr by pwolanin
+# remove lang module - code was already added to apachesolr_search
+#292662 commit after we delete the index by pwolanin
+#356696 by pwolanin: copies the author's name to a string field for use in
+ multisite search or sorting by author. Also snuck in non-compression on
+ the body for performance.
+#348215 by vladimir.dolgopolov: More link for additional facets.
+#292662 update README by pwolanin
+#344249 obey 32 char limit for block deltas by pwolanin
+#355479 fix PHP warning when request fails by pwolanin
+#355544 Add a ->clearCache(); in apachesolr_index_page(), by flexer and pwolanin
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/Drupal_Apache_Solr_Service.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/Drupal_Apache_Solr_Service.php Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,903 @@
+
+ */
+
+/**
+ * Additional code Copyright (c) 2008-2011 by Robert Douglass, James McKinney,
+ * Jacob Singh, Alejandro Garza, Peter Wolanin, and additional contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program as the file LICENSE.txt; if not, please see
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ */
+
+/**
+ * Starting point for the Solr API. Represents a Solr server resource and has
+ * methods for pinging, adding, deleting, committing, optimizing and searching.
+ */
+
+class DrupalApacheSolrService implements DrupalApacheSolrServiceInterface {
+ /**
+ * How NamedLists should be formatted in the output. This specifically effects facet counts. Valid values
+ * are 'map' (default) or 'flat'.
+ *
+ */
+ const NAMED_LIST_FORMAT = 'map';
+
+ /**
+ * Servlet mappings
+ */
+ const PING_SERVLET = 'admin/ping';
+ const UPDATE_SERVLET = 'update';
+ const SEARCH_SERVLET = 'select';
+ const LUKE_SERVLET = 'admin/luke';
+ const SYSTEM_SERVLET = 'admin/system';
+ const STATS_SERVLET = 'admin/stats.jsp';
+ const STATS_SERVLET_4 = 'admin/mbeans?wt=xml&stats=true';
+
+ /**
+ * Server url
+ *
+ * @var array
+ */
+ protected $parsed_url;
+
+ /**
+ * Constructed servlet full path URLs
+ *
+ * @var string
+ */
+ protected $update_url;
+
+ /**
+ * Default HTTP timeout when one is not specified (initialized to default_socket_timeout ini setting)
+ *
+ * var float
+ */
+ protected $_defaultTimeout;
+ protected $env_id;
+ protected $luke;
+ protected $stats;
+ protected $system_info;
+
+ /**
+ * Flag that denotes whether to use soft commits for Solr 4.x, defaults to FALSE.
+ *
+ * @var bool
+ */
+ protected $soft_commit = FALSE;
+
+ /**
+ * Call the /admin/ping servlet, to test the connection to the server.
+ *
+ * @param $timeout
+ * maximum time to wait for ping in seconds, -1 for unlimited (default 2).
+ * @return
+ * (float) seconds taken to ping the server, FALSE if timeout occurs.
+ */
+ public function ping($timeout = 2) {
+ $start = microtime(TRUE);
+
+ if ($timeout <= 0.0) {
+ $timeout = -1;
+ }
+ $pingUrl = $this->_constructUrl(self::PING_SERVLET);
+ // Attempt a HEAD request to the solr ping url.
+ $options = array(
+ 'method' => 'HEAD',
+ 'timeout' => $timeout,
+ );
+ $response = $this->_makeHttpRequest($pingUrl, $options);
+
+ if ($response->code == 200) {
+ // Add 0.1 ms to the ping time so we never return 0.0.
+ return microtime(TRUE) - $start + 0.0001;
+ }
+ else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Flags whether to use soft commits for Solr 4.x.
+ *
+ * @param bool $soft_commit
+ * Whether or not to use soft commits for Solr 4.x.
+ */
+ public function setSoftCommit($soft_commit) {
+ $this->soft_commit = (bool) $soft_commit;
+ }
+
+ /**
+ * Returns the flag that denotes whether to use soft commits for Solr 4.x.
+ *
+ * @return bool
+ * Whether to use soft commits for Solr 4.x.
+ */
+ public function getSoftCommit() {
+ return $this->soft_commit;
+ }
+
+ /**
+ * Call the /admin/system servlet
+ *
+ * @return
+ * (array) With all the system info
+ */
+ protected function setSystemInfo() {
+ $url = $this->_constructUrl(self::SYSTEM_SERVLET, array('wt' => 'json'));
+ if ($this->env_id) {
+ $this->system_info_cid = $this->env_id . ":system:" . drupal_hash_base64($url);
+ $cache = cache_get($this->system_info_cid, 'cache_apachesolr');
+ if (isset($cache->data)) {
+ $this->system_info = json_decode($cache->data);
+ }
+ }
+ // Second pass to populate the cache if necessary.
+ if (empty($this->system_info)) {
+ $response = $this->_sendRawGet($url);
+ $this->system_info = json_decode($response->data);
+ if ($this->env_id) {
+ cache_set($this->system_info_cid, $response->data, 'cache_apachesolr');
+ }
+ }
+ }
+
+ /**
+ * Get information about the Solr Core.
+ *
+ * @return
+ * (string) system info encoded in json
+ */
+ public function getSystemInfo() {
+ if (!isset($this->system_info)) {
+ $this->setSystemInfo();
+ }
+ return $this->system_info;
+ }
+
+ /**
+ * Sets $this->luke with the meta-data about the index from admin/luke.
+ */
+ protected function setLuke($num_terms = 0) {
+ if (empty($this->luke[$num_terms])) {
+ $params = array(
+ 'numTerms' => "$num_terms",
+ 'wt' => 'json',
+ 'json.nl' => self::NAMED_LIST_FORMAT,
+ );
+ $url = $this->_constructUrl(self::LUKE_SERVLET, $params);
+ if ($this->env_id) {
+ $cid = $this->env_id . ":luke:" . drupal_hash_base64($url);
+ $cache = cache_get($cid, 'cache_apachesolr');
+ if (isset($cache->data)) {
+ $this->luke = $cache->data;
+ }
+ }
+ }
+ // Second pass to populate the cache if necessary.
+ if (empty($this->luke[$num_terms])) {
+ $this->luke[$num_terms] = $this->_sendRawGet($url);
+ if ($this->env_id) {
+ cache_set($cid, $this->luke, 'cache_apachesolr');
+ }
+ }
+ }
+
+ /**
+ * Get just the field meta-data about the index.
+ */
+ public function getFields($num_terms = 0) {
+ return $this->getLuke($num_terms)->fields;
+ }
+
+ /**
+ * Get meta-data about the index.
+ */
+ public function getLuke($num_terms = 0) {
+ if (!isset($this->luke[$num_terms])) {
+ $this->setLuke($num_terms);
+ }
+ return $this->luke[$num_terms];
+ }
+
+ /**
+ * Get the current solr version. This could be 1, 3 or 4
+ *
+ * @return int
+ * 1, 3 or 4. Does not give a more details version, for that you need
+ * to get the system info.
+ */
+ public function getSolrVersion() {
+ $system_info = $this->getSystemInfo();
+ // Get our solr version number
+ if (isset($system_info->lucene->{'solr-spec-version'})) {
+ return $system_info->lucene->{'solr-spec-version'}[0];
+ }
+ return 0;
+ }
+
+ /**
+ * Sets $this->stats with the information about the Solr Core form
+ */
+ protected function setStats() {
+ $data = $this->getLuke();
+ $solr_version = $this->getSolrVersion();
+ // Only try to get stats if we have connected to the index.
+ if (empty($this->stats) && isset($data->index->numDocs)) {
+ if ($solr_version >= 4) {
+ $url = $this->_constructUrl(self::STATS_SERVLET_4);
+ }
+ else {
+ $url = $this->_constructUrl(self::STATS_SERVLET);
+ }
+ if ($this->env_id) {
+ $this->stats_cid = $this->env_id . ":stats:" . drupal_hash_base64($url);
+ $cache = cache_get($this->stats_cid, 'cache_apachesolr');
+ if (isset($cache->data)) {
+ $this->stats = simplexml_load_string($cache->data);
+ }
+ }
+ // Second pass to populate the cache if necessary.
+ if (empty($this->stats)) {
+ $response = $this->_sendRawGet($url);
+ $this->stats = simplexml_load_string($response->data);
+ if ($this->env_id) {
+ cache_set($this->stats_cid, $response->data, 'cache_apachesolr');
+ }
+ }
+ }
+ }
+
+ /**
+ * Get information about the Solr Core.
+ *
+ * Returns a Simple XMl document
+ */
+ public function getStats() {
+ if (!isset($this->stats)) {
+ $this->setStats();
+ }
+ return $this->stats;
+ }
+
+ /**
+ * Get summary information about the Solr Core.
+ */
+ public function getStatsSummary() {
+ $stats = $this->getStats();
+ $solr_version = $this->getSolrVersion();
+
+ $summary = array(
+ '@pending_docs' => '',
+ '@autocommit_time_seconds' => '',
+ '@autocommit_time' => '',
+ '@deletes_by_id' => '',
+ '@deletes_by_query' => '',
+ '@deletes_total' => '',
+ '@schema_version' => '',
+ '@core_name' => '',
+ '@index_size' => '',
+ );
+
+ if (!empty($stats)) {
+ if ($solr_version <= 3) {
+ $docs_pending_xpath = $stats->xpath('//stat[@name="docsPending"]');
+ $summary['@pending_docs'] = (int) trim(current($docs_pending_xpath));
+ $max_time_xpath = $stats->xpath('//stat[@name="autocommit maxTime"]');
+ $max_time = (int) trim(current($max_time_xpath));
+ // Convert to seconds.
+ $summary['@autocommit_time_seconds'] = $max_time / 1000;
+ $summary['@autocommit_time'] = format_interval($max_time / 1000);
+ $deletes_id_xpath = $stats->xpath('//stat[@name="deletesById"]');
+ $summary['@deletes_by_id'] = (int) trim(current($deletes_id_xpath));
+ $deletes_query_xpath = $stats->xpath('//stat[@name="deletesByQuery"]');
+ $summary['@deletes_by_query'] = (int) trim(current($deletes_query_xpath));
+ $summary['@deletes_total'] = $summary['@deletes_by_id'] + $summary['@deletes_by_query'];
+ $schema = $stats->xpath('/solr/schema[1]');
+ $summary['@schema_version'] = trim($schema[0]);
+ $core = $stats->xpath('/solr/core[1]');
+ $summary['@core_name'] = trim($core[0]);
+ $size_xpath = $stats->xpath('//stat[@name="indexSize"]');
+ $summary['@index_size'] = trim(current($size_xpath));
+ }
+ else {
+ $system_info = $this->getSystemInfo();
+ $docs_pending_xpath = $stats->xpath('//lst["stats"]/long[@name="docsPending"]');
+ $summary['@pending_docs'] = (int) trim(current($docs_pending_xpath));
+ $max_time_xpath = $stats->xpath('//lst["stats"]/str[@name="autocommit maxTime"]');
+ $max_time = (int) trim(current($max_time_xpath));
+ // Convert to seconds.
+ $summary['@autocommit_time_seconds'] = $max_time / 1000;
+ $summary['@autocommit_time'] = format_interval($max_time / 1000);
+ $deletes_id_xpath = $stats->xpath('//lst["stats"]/long[@name="deletesById"]');
+ $summary['@deletes_by_id'] = (int) trim(current($deletes_id_xpath));
+ $deletes_query_xpath = $stats->xpath('//lst["stats"]/long[@name="deletesByQuery"]');
+ $summary['@deletes_by_query'] = (int) trim(current($deletes_query_xpath));
+ $summary['@deletes_total'] = $summary['@deletes_by_id'] + $summary['@deletes_by_query'];
+ $schema = $system_info->core->schema;
+ $summary['@schema_version'] = $schema;
+ $core = $stats->xpath('//lst["core"]/str[@name="coreName"]');
+ $summary['@core_name'] = trim(current($core));
+ $size_xpath = $stats->xpath('//lst["core"]/str[@name="indexSize"]');
+ $summary['@index_size'] = trim(current($size_xpath));
+ }
+ }
+
+ return $summary;
+ }
+
+ /**
+ * Clear cached Solr data.
+ */
+ public function clearCache() {
+ // Don't clear cached data if the server is unavailable.
+ if (@$this->ping()) {
+ $this->_clearCache();
+ }
+ else {
+ throw new Exception('No Solr instance available when trying to clear the cache.');
+ }
+ }
+
+ protected function _clearCache() {
+ if ($this->env_id) {
+ cache_clear_all($this->env_id . ":stats:", 'cache_apachesolr', TRUE);
+ cache_clear_all($this->env_id . ":luke:", 'cache_apachesolr', TRUE);
+ }
+ $this->luke = array();
+ $this->stats = NULL;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param $url
+ * The URL to the Solr server, possibly including a core name. E.g. http://localhost:8983/solr/
+ * or https://search.example.com/solr/core99/
+ * @param $env_id
+ * The machine name of a corresponding saved configuration used for loading
+ * data like which facets are enabled.
+ */
+ public function __construct($url, $env_id = NULL) {
+ $this->env_id = $env_id;
+ $this->setUrl($url);
+
+ // determine our default http timeout from ini settings
+ $this->_defaultTimeout = (int) ini_get('default_socket_timeout');
+
+ // double check we didn't get 0 for a timeout
+ if ($this->_defaultTimeout <= 0) {
+ $this->_defaultTimeout = 60;
+ }
+ }
+
+ function getId() {
+ return $this->env_id;
+ }
+
+ /**
+ * Check the reponse code and thow an exception if it's not 200.
+ *
+ * @param stdClass $response
+ * response object.
+ *
+ * @return
+ * response object
+ * @thows Exception
+ */
+ protected function checkResponse($response) {
+ $code = (int) $response->code;
+ if ($code != 200) {
+ if ($code >= 400 && $code != 403 && $code != 404) {
+ // Add details, like Solr's exception message.
+ $response->status_message .= $response->data;
+ }
+ throw new Exception('"' . $code . '" Status: ' . $response->status_message);
+ }
+ return $response;
+ }
+
+ /**
+ * Make a request to a servlet (a path) that's not a standard path.
+ *
+ * @param string $servlet
+ * A path to be added to the base Solr path. e.g. 'extract/tika'
+ *
+ * @param array $params
+ * Any request parameters when constructing the URL.
+ *
+ * @param array $options
+ * @see drupal_http_request() $options.
+ *
+ * @return
+ * response object
+ *
+ * @thows Exception
+ */
+ public function makeServletRequest($servlet, $params = array(), $options = array()) {
+ // Add default params.
+ $params += array(
+ 'wt' => 'json',
+ 'json.nl' => self::NAMED_LIST_FORMAT,
+ );
+
+ $url = $this->_constructUrl($servlet, $params);
+ $response = $this->_makeHttpRequest($url, $options);
+ return $this->checkResponse($response);
+ }
+
+ /**
+ * Central method for making a GET operation against this Solr Server
+ */
+ protected function _sendRawGet($url, $options = array()) {
+ $response = $this->_makeHttpRequest($url, $options);
+ return $this->checkResponse($response);
+ }
+
+ /**
+ * Central method for making a POST operation against this Solr Server
+ */
+ protected function _sendRawPost($url, $options = array()) {
+ $options['method'] = 'POST';
+ // Normally we use POST to send XML documents.
+ if (!isset($options['headers']['Content-Type'])) {
+ $options['headers']['Content-Type'] = 'text/xml; charset=UTF-8';
+ }
+ $response = $this->_makeHttpRequest($url, $options);
+ return $this->checkResponse($response);
+ }
+
+ /**
+ * Central method for making the actual http request to the Solr Server
+ *
+ * This is just a wrapper around drupal_http_request().
+ */
+ protected function _makeHttpRequest($url, array $options = array()) {
+ if (!isset($options['method']) || $options['method'] == 'GET' || $options['method'] == 'HEAD') {
+ // Make sure we are not sending a request body.
+ $options['data'] = NULL;
+ }
+
+ $result = drupal_http_request($url, $options);
+
+ if (!isset($result->code) || $result->code < 0) {
+ $result->code = 0;
+ $result->status_message = 'Request failed';
+ $result->protocol = 'HTTP/1.0';
+ }
+ // Additional information may be in the error property.
+ if (isset($result->error)) {
+ $result->status_message .= ': ' . check_plain($result->error);
+ }
+
+ if (!isset($result->data)) {
+ $result->data = '';
+ $result->response = NULL;
+ }
+ else {
+ $response = json_decode($result->data);
+ if (is_object($response)) {
+ foreach ($response as $key => $value) {
+ $result->$key = $value;
+ }
+ }
+ }
+ return $result;
+ }
+
+
+ /**
+ * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
+ *
+ * NOTE: inside a phrase fewer characters need escaped, use {@link DrupalApacheSolrService::escapePhrase()} instead
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function escape($value)
+ {
+ //list taken from http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
+ $pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
+ $replace = '\\\$1';
+
+ return preg_replace($pattern, $replace, $value);
+ }
+
+ /**
+ * Escape a value meant to be contained in a phrase for special query characters
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function escapePhrase($value)
+ {
+ $pattern = '/("|\\\)/';
+ $replace = '\\\$1';
+
+ return preg_replace($pattern, $replace, $value);
+ }
+
+ /**
+ * Convenience function for creating phrase syntax from a value
+ *
+ * @param string $value
+ * @return string
+ */
+ static public function phrase($value)
+ {
+ return '"' . self::escapePhrase($value) . '"';
+ }
+
+ /**
+ * Return a valid http URL given this server's host, port and path and a provided servlet name
+ *
+ * @param $servlet
+ * A string path to a Solr request handler.
+ * @param $params
+ * @param $parsed_url
+ * A url to use instead of the stored one.
+ *
+ * @return string
+ */
+ protected function _constructUrl($servlet, $params = array(), $added_query_string = NULL) {
+ // PHP's built in http_build_query() doesn't give us the format Solr wants.
+ $query_string = $this->httpBuildQuery($params);
+
+ if ($query_string) {
+ $query_string = '?' . $query_string;
+ if ($added_query_string) {
+ $query_string = $query_string . '&' . $added_query_string;
+ }
+ }
+ elseif ($added_query_string) {
+ $query_string = '?' . $added_query_string;
+ }
+
+ $url = $this->parsed_url;
+ return $url['scheme'] . $url['user'] . $url['pass'] . $url['host'] . $url['port'] . $url['path'] . $servlet . $query_string;
+ }
+
+ /**
+ * Get the Solr url
+ *
+ * @return string
+ */
+ public function getUrl() {
+ return $this->_constructUrl('');
+ }
+
+ /**
+ * Set the Solr url.
+ *
+ * @param $url
+ *
+ * @return $this
+ */
+ public function setUrl($url) {
+ $parsed_url = parse_url($url);
+
+ if (!isset($parsed_url['scheme'])) {
+ $parsed_url['scheme'] = 'http';
+ }
+ $parsed_url['scheme'] .= '://';
+
+ if (!isset($parsed_url['user'])) {
+ $parsed_url['user'] = '';
+ }
+ else {
+ $parsed_url['host'] = '@' . $parsed_url['host'];
+ }
+ $parsed_url['pass'] = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
+ $parsed_url['port'] = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
+
+ if (isset($parsed_url['path'])) {
+ // Make sure the path has a single leading/trailing slash.
+ $parsed_url['path'] = '/' . ltrim($parsed_url['path'], '/');
+ $parsed_url['path'] = rtrim($parsed_url['path'], '/') . '/';
+ }
+ else {
+ $parsed_url['path'] = '/';
+ }
+ // For now we ignore query and fragment.
+ $this->parsed_url = $parsed_url;
+ // Force the update url to be rebuilt.
+ unset($this->update_url);
+ return $this;
+ }
+
+ /**
+ * Raw update Method. Takes a raw post body and sends it to the update service. Post body
+ * should be a complete and well formed xml document.
+ *
+ * @param string $rawPost
+ * @param float $timeout Maximum expected duration (in seconds)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function update($rawPost, $timeout = FALSE) {
+ // @todo: throw exception if updates are disabled.
+ if (empty($this->update_url)) {
+ // Store the URL in an instance variable since many updates may be sent
+ // via a single instance of this class.
+ $this->update_url = $this->_constructUrl(self::UPDATE_SERVLET, array('wt' => 'json'));
+ }
+ $options['data'] = $rawPost;
+ if ($timeout) {
+ $options['timeout'] = $timeout;
+ }
+ return $this->_sendRawPost($this->update_url, $options);
+ }
+
+ /**
+ * Add an array of Solr Documents to the index all at once
+ *
+ * @param array $documents Should be an array of ApacheSolrDocument instances
+ * @param boolean $allowDups
+ * @param boolean $overwritePending
+ * @param boolean $overwriteCommitted
+ *
+ * @return response objecte
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function addDocuments($documents, $overwrite = NULL, $commitWithin = NULL) {
+ $attr = '';
+
+ if (isset($overwrite)) {
+ $attr .= ' overwrite="' . empty($overwrite) ? 'false"' : 'true"';
+ }
+ if (isset($commitWithin)) {
+ $attr .= ' commitWithin="' . intval($commitWithin) . '"';
+ }
+
+ $rawPost = "";
+ foreach ($documents as $document) {
+ if (is_object($document) && ($document instanceof ApacheSolrDocument)) {
+ $rawPost .= ApacheSolrDocument::documentToXml($document);
+ }
+ }
+ $rawPost .= '';
+
+ return $this->update($rawPost);
+ }
+
+ /**
+ * Send a commit command. Will be synchronous unless both wait parameters are set to false.
+ *
+ * @param boolean $optimize Defaults to true
+ * optimizes the index files. Only valid for solr versions <= 3
+ * @param boolean $waitFlush
+ * block until index changes are flushed to disk. Only valid for solr versions <= 3
+ * @param boolean $waitSearcher
+ * block until a new searcher is opened and registered as the main query searcher, making the changes visible.
+ * @param float $timeout
+ * Maximum expected duration of the commit operation on the server (otherwise, will throw a communication exception)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function commit($optimize = TRUE, $waitFlush = TRUE, $waitSearcher = TRUE, $timeout = 3600) {
+ $optimizeValue = $optimize ? 'true' : 'false';
+ $flushValue = $waitFlush ? 'true' : 'false';
+ $searcherValue = $waitSearcher ? 'true' : 'false';
+ $softCommit = $this->soft_commit ? 'true' : 'false';
+
+ $solr_version = $this->getSolrVersion();
+ if ($solr_version <= 3) {
+ $rawPost = '';
+ }
+ else {
+ $rawPost = '';
+ }
+
+ $response = $this->update($rawPost, $timeout);
+ $this->_clearCache();
+ return $response;
+ }
+
+ /**
+ * Create a delete document based on document ID
+ *
+ * @param string $id Expected to be utf-8 encoded
+ * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function deleteById($id, $timeout = 3600) {
+ return $this->deleteByMultipleIds(array($id), $timeout);
+ }
+
+ /**
+ * Create and post a delete document based on multiple document IDs.
+ *
+ * @param array $ids Expected to be utf-8 encoded strings
+ * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function deleteByMultipleIds($ids, $timeout = 3600) {
+ $rawPost = '';
+
+ foreach ($ids as $id) {
+ $rawPost .= '' . htmlspecialchars($id, ENT_NOQUOTES, 'UTF-8') . '';
+ }
+ $rawPost .= '';
+
+ return $this->update($rawPost, $timeout);
+ }
+
+ /**
+ * Create a delete document based on a query and submit it
+ *
+ * @param string $rawQuery Expected to be utf-8 encoded
+ * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+ * @return stdClass response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function deleteByQuery($rawQuery, $timeout = 3600) {
+ $rawPost = '' . htmlspecialchars($rawQuery, ENT_NOQUOTES, 'UTF-8') . '';
+
+ return $this->update($rawPost, $timeout);
+ }
+
+ /**
+ * Send an optimize command. Will be synchronous unless both wait parameters are set
+ * to false.
+ *
+ * @param boolean $waitFlush
+ * block until index changes are flushed to disk Removed in Solr 4.0
+ * @param boolean $waitSearcher
+ * block until a new searcher is opened and registered as the main query searcher, making the changes visible.
+ * @param float $timeout
+ * Maximum expected duration of the commit operation on the server (otherwise, will throw a communication exception)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function optimize($waitFlush = TRUE, $waitSearcher = TRUE, $timeout = 3600) {
+ $flushValue = $waitFlush ? 'true' : 'false';
+ $searcherValue = $waitSearcher ? 'true' : 'false';
+ $softCommit = $this->soft_commit ? 'true' : 'false';
+
+ $solr_version = $this->getSolrVersion();
+ if ($solr_version <= 3) {
+ $rawPost = '';
+ }
+ else {
+ $rawPost = '';
+ }
+
+ return $this->update($rawPost, $timeout);
+ }
+
+ /**
+ * Like PHP's built in http_build_query(), but uses rawurlencode() and no [] for repeated params.
+ */
+ protected function httpBuildQuery(array $query, $parent = '') {
+ $params = array();
+
+ foreach ($query as $key => $value) {
+ $key = ($parent ? $parent : rawurlencode($key));
+
+ // Recurse into children.
+ if (is_array($value)) {
+ $params[] = $this->httpBuildQuery($value, $key);
+ }
+ // If a query parameter value is NULL, only append its key.
+ elseif (!isset($value)) {
+ $params[] = $key;
+ }
+ else {
+ $params[] = $key . '=' . rawurlencode($value);
+ }
+ }
+
+ return implode('&', $params);
+ }
+
+ /**
+ * Simple Search interface
+ *
+ * @param string $query The raw query string
+ * @param array $params key / value pairs for other query parameters (see Solr documentation), use arrays for parameter keys used more than once (e.g. facet.field)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ public function search($query = '', array $params = array(), $method = 'GET') {
+ // Always use JSON. See http://code.google.com/p/solr-php-client/issues/detail?id=6#c1 for reasoning
+ $params['wt'] = 'json';
+ // Additional default params.
+ $params += array(
+ 'json.nl' => self::NAMED_LIST_FORMAT,
+ );
+ if ($query) {
+ $params['q'] = $query;
+ }
+ // PHP's built in http_build_query() doesn't give us the format Solr wants.
+ $queryString = $this->httpBuildQuery($params);
+ // Check string length of the query string, change method to POST
+ $len = strlen($queryString);
+ // Fetch our threshold to find out when to flip to POST
+ $max_len = apachesolr_environment_variable_get($this->env_id, 'apachesolr_search_post_threshold', 3600);
+
+ // if longer than $max_len (default 3600) characters
+ // we should switch to POST (a typical server handles 4096 max).
+ // If this class is used independently (without environments), we switch automatically to POST at an
+ // limit of 1800 chars.
+ if (($len > 1800) && (empty($this->env_id) || ($len > $max_len))) {
+ $method = 'POST';
+ }
+
+ if ($method == 'GET') {
+ $searchUrl = $this->_constructUrl(self::SEARCH_SERVLET, array(), $queryString);
+ return $this->_sendRawGet($searchUrl);
+ }
+ else if ($method == 'POST') {
+ $searchUrl = $this->_constructUrl(self::SEARCH_SERVLET);
+ $options['data'] = $queryString;
+ $options['headers']['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
+ return $this->_sendRawPost($searchUrl, $options);
+ }
+ else {
+ throw new Exception("Unsupported method '$method' for search(), use GET or POST");
+ }
+ }
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/LICENSE.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/LICENSE.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/README.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/README.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,194 @@
+
+This module integrates Drupal with the Apache Solr search platform. Solr search
+can be used as a replacement for core content search and boasts both extra
+features and better performance. Among the extra features is the ability to have
+faceted search on facets ranging from content author to taxonomy to arbitrary
+Field API fields.
+
+The module comes with a schema.xml, solrconfig.xml, and protwords.txt file which
+must be used in your Solr installation.
+
+This module depends on the search framework in core. When used in combination
+with core search module, Apache Solr is not the default search. Access it via a
+new tab on the default search page, called "Site". You may configure it
+to be default at ?q=admin/config/search/settings
+
+Updating from 6.x
+-----------------
+
+IMPORTANT: there is no upgrade path from 6.x-1.x or 6.x-2.x. If you previously
+installed those modules you must disable and uninstall them prior to
+installing 7.x-1.x.
+
+You will have to install the new schema.xml and solrconfig.xml files, and restart
+the Solr server (or core) and delete your index and reindex all content.
+
+Installation
+------------
+
+Prerequisite: Java 5 or higher (a.k.a. 1.5.x). PHP 5.2.4 or higher.
+
+Install the Apache Solr Drupal module as you would any Drupal module. Note
+that the Drupal 7.x-1.x branch does not require the SolrPhpClient to
+be installed. All necessary code is now included with this module.
+
+Before enabling the module, you must have a working Solr server, or be
+subscribed to a service like Acquia Search.
+
+The Debian/Ubuntu packages for Solr should NOT be used to install Solr.
+For example, do NOT install the solr or solr-jetty packages.
+
+Download the latest Solr 1.4.x or 3.x release (e.g. 1.4.1 or 3.6.1) from:
+http://www.apache.org/dyn/closer.cgi/lucene/solr/
+
+Apache Lucene 3.1, 3.2 or 3.3, have a possible index corruption bug on
+server crash or power loss (LUCENE-3418) and have bugs that interfere
+with the Drupal admin reports. Solr 3.4 has a problem with
+SortMissingLast so Solr 3.5.0 or later is strongly preferred.
+
+Unpack the Solr tarball somewhere not visible to the web (not in your
+webserver docroot and not inside of your Drupal directory).
+
+The Solr download comes with an example application that you can use for
+testing, development, and even for smaller production sites. This
+application is found at apache-solr-1.4.1/example.
+
+You must use 3 Solr configuration files that come with the Drupal
+module or the integration will not work correctly.
+
+For Solr 1.4 use the ones found in:
+solr-conf/solr-1.4/
+
+for Solr 3.5.0 or 3.6.1 use:
+solr-conf/solr-3.x/
+
+While the Solr 1.4 files will work for Solr 3.5+, they are not optimal
+and you will be missing important new features.
+
+For example, when deploying solr 1.4:
+
+Move apache-solr-1.4.1/example/solr/conf/schema.xml and rename it to
+something like schema.bak. Then move the solr-conf/solr-1.4/schema.xml
+that comes with this Drupal module to take its place.
+
+Similarly, move apache-solr-1.4.1/example/solr/conf/solrconfig.xml and rename
+it like solrconfig.bak. Then move the solr-conf/solr-1.4/solrconfig.xml
+that comes with this module to take its place.
+
+Finally, move apache-solr-1.4.1/example/solr/conf/protwords.txt and rename it
+protwords.bak. Then move the solr-conf/solr-1.4/protwords.txt that comes
+with this module to take its place.
+
+Make sure that the conf directory includes the following files - the Solr core
+may not load if you don't have at least an empty file present:
+solrconfig.xml
+schema.xml
+elevate.xml
+mapping-ISOLatin1Accent.txt
+protwords.txt
+stopwords.txt
+synonyms.txt
+
+Now start the solr application by opening a shell, changing directory to
+apache-solr-1.4.1/example, and executing the command java -jar start.jar
+
+Test that your solr server is now available by visiting
+http://localhost:8983/solr/admin/
+
+Now, you should enable the "Apache Solr framework" and "Apache Solr search"
+modules. Check that you can connect to Solr at ?q=admin/setting/apachesolr
+Now run cron on your Drupal site until your content is indexed. You
+can monitor the index at ?q=admin/settings/apachesolr/index
+
+The solrconfig.xml that comes with this modules defines auto-commit, so
+it may take a few minutes between running cron and when the new content
+is visible in search.
+
+To use facets you should download facetapi http://drupal.org/project/facetapi
+This module will allow you to define and set facets next to your search pages.
+Once this module is enabled, enable blocks for facets first at
+Administer > Site configuration > Apache Solr > Enabled filters
+then position them as you like at Administer > Site building > Blocks.
+
+Settings.php
+------------
+You can override environment settings using the following syntax in your
+settings.php
+
+$conf['apachesolr_environments']['my_env_id']['url'] = 'http://localhost:8983';
+
+Configuration variables
+-----------------------
+
+The module provides some (hidden) variables that can be used to tweak its
+behavior:
+
+ - apachesolr_luke_limit: the limit (in terms of number of documents in the
+ index) above which the module will not retrieve the number of terms per field
+ when performing LUKE queries (for performance reasons).
+
+ - apachesolr_tags_to_index: the list of HTML tags that the module will index
+ (see apachesolr_add_tags_to_document()).
+
+ - apachesolr_exclude_nodeapi_types: an array of node types each of which is
+ an array of one or more module names, such as 'comment'. Any type listed
+ will have any listed modules' hook_node_update_index() implementation skipped
+ when indexing. This can be useful for excluding comments or taxonomy links.
+
+ - apachesolr_ping_timeout: the timeout (in seconds) after which the module will
+ consider the Apache Solr server unavailable.
+
+ - apachesolr_optimize_interval: the interval (in seconds) between automatic
+ optimizations of the Apache Solr index. Set to 0 to disable.
+
+ - apachesolr_cache_delay: the interval (in seconds) after an update after which
+ the module will requery the Apache Solr for the index structure. Set it to
+ your autocommit delay plus a few seconds.
+
+ - apachesolr_query_class: the default query class to use.
+
+ - apachesolr_index_comments_with_node: TRUE | FALSE. Whether to index comments
+ along with each node.
+
+ - apachesolr_cron_mass_limit: update or delete at most this many documents in
+ each Solr request, such as when making {apachesolr_search_node} consistent
+ with {node}.
+
+ - apachesolr_index_user: Define with which user you want the index process to
+ happen.
+
+Troubleshooting
+---------------
+Problem:
+You use http basic auth to limit access to your Solr server.
+
+Solution:
+Set the Server URL to include the username and password like
+http://username:password@example.com:8080/solr
+
+Problem:
+Links to nodes appear in the search results with a different host name or
+subdomain than is preferred. e.g. sometimes at http://example.com
+and sometimes at http://www.example.com
+
+Solution:
+Set $base_url in settings.php to insure that an identical absolute url is
+generated at all times when nodes are indexed. Alternately, set up a re-direct
+in .htaccess to prevent site visitors from accessing the site via more than one
+site address.
+
+Problem:
+The 'Solr Index Queries' test fails with file permission errors.
+
+Solution:
+When running this test you should have your tomcat/jetty running as the same user
+as the user under which PHP runs (often the same as the webserver). This is
+important because of the on-the-fly folder creation within PHP.
+
+
+Themers
+----------------
+
+See inline docs in apachesolr_theme and apachesolr_search_theme functions
+within apachesolr.module and apachesolr_search.module.
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/Solr_Base_Query.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/Solr_Base_Query.php Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,657 @@
+ 'is_uid', '#value' => 0)
+ * for anonymous content.
+ */
+ protected $fields = array();
+
+ /**
+ * An array of subqueries.
+ */
+ protected $subqueries = array();
+
+ function __construct($operator = 'OR') {
+ $this->operator = $operator;
+ $this->id = ++SolrFilterSubQuery::$idCount;
+ }
+
+ function __clone() {
+ $this->id = ++SolrFilterSubQuery::$idCount;
+ }
+
+ public function getFilters($name = NULL) {
+ if (empty($name)) {
+ return $this->fields;
+ }
+ reset($this->fields);
+ $matches = array();
+ foreach ($this->fields as $filter) {
+ if ($filter['#name'] == $name) {
+ $matches[] = $filter;
+ }
+ }
+ return $matches;
+ }
+
+ public function hasFilter($name, $value, $exclude = FALSE) {
+ foreach ($this->fields as $pos => $values) {
+ if ($values['#name'] == $name && $values['#value'] == $value && $values['#exclude'] == $exclude) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
+ public function addFilter($name, $value, $exclude = FALSE, $local = '') {
+ // @todo - escape the value if it has spaces in it and is not a range query or parenthesized.
+ $filter = array(
+ '#exclude' => (bool) $exclude,
+ '#name' => trim($name),
+ '#value' => trim($value),
+ '#local' => trim($local),
+ );
+ $this->fields[] = $filter;
+ return $this;
+ }
+
+ public function removeFilter($name, $value = NULL, $exclude = FALSE) {
+ // Remove from the public list of filters.
+ $this->unsetFilter($this->fields, $name, $value, $exclude);
+ return $this;
+ }
+
+ protected function unsetFilter(&$fields, $name, $value, $exclude) {
+ if (!isset($value)) {
+ foreach ($fields as $pos => $values) {
+ if ($values['#name'] == $name) {
+ unset($fields[$pos]);
+ }
+ }
+ }
+ else {
+ foreach ($fields as $pos => $values) {
+ if ($values['#name'] == $name && $values['#value'] == $value && $values['#exclude'] == $exclude) {
+ unset($fields[$pos]);
+ }
+ }
+ }
+ }
+
+ public function getFilterSubQueries() {
+ return $this->subqueries;
+ }
+
+ public function addFilterSubQuery(SolrFilterSubQuery $query) {
+ $this->subqueries[$query->id] = $query;
+ return $this;
+ }
+
+ public function removeFilterSubQuery(SolrFilterSubQuery $query) {
+ unset($this->subqueries[$query->id]);
+ return $this;
+ }
+
+ public function removeFilterSubQueries() {
+ $this->subqueries = array();
+ return $this;
+ }
+
+ public function makeFilterQuery(array $filter) {
+ $prefix = empty($filter['#exclude']) ? '' : '-';
+ if ($filter['#local']) {
+ $prefix = '{!' . $filter['#local'] . '}' . $prefix;
+ }
+ // If the field value contains a colon or a space, wrap it in double quotes,
+ // unless it is a range query or is already wrapped in double quotes or
+ // parentheses.
+ if (preg_match('/[ :]/', $filter['#value']) && !preg_match('/^[\[\{]\S+ TO \S+[\]\}]$/', $filter['#value']) && !preg_match('/^["\(].*["\)]$/', $filter['#value'])) {
+ $filter['#value'] = '"' . $filter['#value'] . '"';
+ }
+ return $prefix . $filter['#name'] . ':' . $filter['#value'];
+ }
+
+ /**
+ * Make sure our query matches the pattern name:value or name:"value"
+ * Make sure that if we are ranges we use name:[ AND ]
+ * allowed inputs :
+ * a. bundle:article
+ * b. date:[1970-12-31T23:59:59Z TO NOW]
+ * Split the text in 4 different parts
+ * 1. name, eg.: bundle or date
+ * 2. The first opening bracket (or nothing), eg.: [
+ * 3. The value of the field, eg. article or 1970-12-31T23:59:59Z TO NOW
+ * 4. The last closing bracket, eg.: ]
+ * @param string $filter
+ * The filter to validate
+ * @return boolean
+ */
+ public static function validFilterValue($filter) {
+ $opening = 0;
+ $closing = 0;
+ $name = NULL;
+ $value = NULL;
+
+ if (preg_match('/(?P[^:]+):(?P.+)?$/', $filter, $matches)) {
+ foreach ($matches as $match_id => $match) {
+ switch($match_id) {
+ case 'name' :
+ $name = $match;
+ break;
+ case 'value' :
+ $value = $match;
+ break;
+ }
+ }
+
+ // For the name we allow any character that fits between the A-Z0-9 range and
+ // any alternative for this in other languages. No special characters allowed
+ if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) {
+ return FALSE;
+ }
+
+ // For the value we allow anything that is UTF8
+ if (!drupal_validate_utf8($value)) {
+ return FALSE;
+ }
+
+ // Check our bracket count. If it does not match it is also not valid
+ $valid_brackets = TRUE;
+ $brackets['opening']['{'] = substr_count($value, '{');
+ $brackets['closing']['}'] = substr_count($value, '}');
+ $valid_brackets = ($brackets['opening']['{'] != $brackets['closing']['}']) ? FALSE : TRUE;
+ $brackets['opening']['['] = substr_count($value, '[');
+ $brackets['closing'][']'] = substr_count($value, ']');
+ $valid_brackets = ($brackets['opening']['['] != $brackets['closing'][']']) ? FALSE : TRUE;
+ $brackets['opening']['('] = substr_count($value, '(');
+ $brackets['closing'][')'] = substr_count($value, ')');
+ $valid_brackets = ($brackets['opening']['('] != $brackets['closing'][')']) ? FALSE : TRUE;
+ if (!$valid_brackets) {
+ return FALSE;
+ }
+
+ // Check the date field inputs
+ if (preg_match('/\[(.+) TO (.+)\]$/', $value, $datefields)) {
+ // Only Allow a value in the form of
+ // http://lucene.apache.org/solr/api/org/apache/solr/schema/DateField.html
+ // http://lucene.apache.org/solr/api/org/apache/solr/util/DateMathParser.html
+ // http://wiki.apache.org/solr/SolrQuerySyntax
+ // 1976-03-06T23:59:59.999Z (valid)
+ // * (valid)
+ // 1995-12-31T23:59:59.999Z (valid)
+ // 2007-03-06T00:00:00Z (valid)
+ // NOW-1YEAR/DAY (valid)
+ // NOW/DAY+1DAY (valid)
+ // 1976-03-06T23:59:59.999Z (valid)
+ // 1976-03-06T23:59:59.999Z+1YEAR (valid)
+ // 1976-03-06T23:59:59.999Z/YEAR (valid)
+ // 1976-03-06T23:59:59.999Z (valid)
+ // 1976-03-06T23::59::59.999Z (invalid)
+ if (!empty($datefields[1]) && !empty($datefields[2])) {
+ // Do not check to full value, only the splitted ones
+ unset($datefields[0]);
+ // Check if both matches are valid datefields
+ foreach ($datefields as $datefield) {
+ if (!preg_match('/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:[\d\.]{2,6}Z(\S)*)|(^([A-Z\*]+)(\A-Z0-9\+\-\/)*)/', $datefield, $datefield_match)) {
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+ return TRUE;
+ }
+
+ /**
+ * Builds a set of filter queries from $this->fields and all subqueries.
+ *
+ * Returns an array of strings that can be combined into
+ * a URL query parameter or passed to Solr as fq paramters.
+ */
+ protected function rebuildFq() {
+ $fq = array();
+ foreach ($this->fields as $pos => $field) {
+ $fq[] = $this->makeFilterQuery($field);
+ }
+ foreach ($this->subqueries as $subquery) {
+ $subfq = $subquery->rebuildFq();
+ if ($subfq) {
+ $operator = $subquery->operator;
+ $fq[] = "(" . implode(" $operator ", $subfq) . ")";
+ }
+ }
+ return $fq;
+ }
+
+}
+
+class SolrBaseQuery extends SolrFilterSubQuery implements DrupalSolrQueryInterface {
+
+ /**
+ * The parameters that get sent to Solr.
+ */
+ protected $params = array('start' => 0, 'rows' => 10, 'fq' => array());
+
+ /**
+ * The search base path.
+ */
+ protected $base_path;
+ protected $field_map = array();
+
+ /**
+ * DrupalApacheSolrService object
+ */
+ protected $solr;
+ // The array keys must always be real Solr index fields.
+ protected $available_sorts;
+
+ /**
+ * The query name is used to construct a searcher string. Mostly the
+ * environment id
+ */
+ protected $name;
+ protected $context = array();
+ // Makes sure we always have a valid sort.
+ protected $solrsort = array('#name' => 'score', '#direction' => 'desc');
+ // A flag to allow the search to be aborted.
+ public $abort_search = FALSE;
+
+ // A flag to check if need to retrieve another page of the result set
+ public $page = 0;
+
+ /**
+ * @param $name
+ * The search name, used for finding the correct blocks and other config.
+ * Typically "apachesolr".
+ *
+ * @param $solr
+ * An instantiated DrupalApacheSolrService Object.
+ * Can be instantiated from apachesolr_get_solr().
+ *
+ * @param $params
+ * Array of params to initialize the object (typically 'q' and 'fq').
+ *
+ * @param $sortstring
+ * Visible string telling solr how to sort - added to GET query params.
+ *
+ * @param $base_path
+ * The search base path (without the keywords) for this query, without trailing slash.
+ */
+ function __construct($name, $solr, array $params = array(), $sortstring = '', $base_path = '', $context = array()) {
+ parent::__construct();
+ $this->name = $name;
+ $this->solr = $solr;
+ $this->addContext((array) $context);
+ $this->addParams((array) $params);
+ $this->available_sorts = $this->defaultSorts();
+ $this->sortstring = trim($sortstring);
+ $this->parseSortString();
+ $this->base_path = $base_path;
+ }
+
+ protected function defaultSorts() {
+ return array(
+ 'score' => array('title' => t('Relevancy'), 'default' => 'desc'),
+ 'sort_label' => array('title' => t('Title'), 'default' => 'asc'),
+ 'bundle' => array('title' => t('Type'), 'default' => 'asc'),
+ 'sort_name' => array('title' => t('Author'), 'default' => 'asc'),
+ 'ds_created' => array('title' => t('Date'), 'default' => 'desc'),
+ );
+ }
+
+ /**
+ * Get query name.
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * Get query searcher name (for facetapi, views, pages, etc).
+ */
+ public function getSearcher() {
+ return $this->name . '@' . $this->solr->getId();
+ }
+
+ /**
+ * Get context values.
+ */
+ public function getContext() {
+ return $this->context;
+ }
+
+ /**
+ * Set context value.
+ */
+ public function addContext(array $context) {
+ foreach ($context as $k => $v) {
+ $this->context[$k] = $v;
+ }
+ // The env_id must match that of the actual $solr object
+ $this->context['env_id'] = $this->solr->getId();
+ return $this->context;
+ }
+
+ protected $single_value_params = array(
+ 'q' => TRUE, // http://wiki.apache.org/solr/SearchHandler#q
+ 'q.op' => TRUE, // http://wiki.apache.org/solr/SearchHandler#q.op
+ 'q.alt' => TRUE, // http://wiki.apache.org/solr/SearchHandler#q
+ 'df' => TRUE,
+ 'qt' => TRUE,
+ 'defType' => TRUE,
+ 'timeAllowed' => TRUE,
+ 'omitHeader' => TRUE,
+ 'debugQuery' => TRUE,
+ 'start' => TRUE,
+ 'rows' => TRUE,
+ 'stats' => TRUE,
+ 'facet' => TRUE,
+ 'facet.prefix' => TRUE,
+ 'facet.limit' => TRUE,
+ 'facet.offset' => TRUE,
+ 'facet.mincount' => TRUE,
+ 'facet.missing' => TRUE,
+ 'facet.method' => TRUE,
+ 'facet.enum.cache.minDf' => TRUE,
+ 'facet.date.start' => TRUE,
+ 'facet.date.end' => TRUE,
+ 'facet.date.gap' => TRUE,
+ 'facet.date.hardend' => TRUE,
+ 'facet.date.other' => TRUE,
+ 'facet.date.include' => TRUE,
+ 'hl' => TRUE,
+ 'hl.snippets' => TRUE,
+ 'hl.fragsize' => TRUE,
+ 'hl.mergeContiguous' => TRUE,
+ 'hl.requireFieldMatch' => TRUE,
+ 'hl.maxAnalyzedChars' => TRUE,
+ 'hl.alternateField' => TRUE,
+ 'hl.maxAlternateFieldLength' => TRUE,
+ 'hl.formatter' => TRUE,
+ 'hl.simple.pre/hl.simple.post' => TRUE,
+ 'hl.fragmenter' => TRUE,
+ 'hl.fragListBuilder' => TRUE,
+ 'hl.fragmentsBuilder' => TRUE,
+ 'hl.useFastVectorHighlighter' => TRUE,
+ 'hl.usePhraseHighlighter' => TRUE,
+ 'hl.highlightMultiTerm' => TRUE,
+ 'hl.regex.slop' => TRUE,
+ 'hl.regex.pattern' => TRUE,
+ 'hl.regex.maxAnalyzedChars' => TRUE,
+ 'spellcheck' => TRUE,
+ );
+
+ public function getParam($name) {
+ if ($name == 'fq') {
+ return $this->rebuildFq();
+ }
+ $empty = isset($this->single_value_params[$name]) ? NULL : array();
+ return isset($this->params[$name]) ? $this->params[$name] : $empty;
+ }
+
+ public function getParams() {
+ $params = $this->params;
+ $params['fq'] = $this->rebuildFq();
+ return $params;
+ }
+
+ public function getSolrParams() {
+ $params = $this->getParams();
+ // For certain fields Solr prefers a comma separated list.
+ foreach (array('fl', 'hl.fl', 'sort', 'mlt.fl') as $name) {
+ if (isset($params[$name])) {
+ $params[$name] = implode(',', $params[$name]);
+ }
+ }
+ return $params;
+ }
+
+ protected function addFq($string, $index = NULL) {
+ $string = trim($string);
+ $local = '';
+ $exclude = FALSE;
+ $name = NULL;
+ $value = NULL;
+
+ // Check if we are dealing with an exclude
+ if (preg_match('/^-(.*)/', $string, $matches)) {
+ $exclude = TRUE;
+ $string = $matches[1];
+ }
+
+ // If {!something} is found as first character then this is a local value
+ if (preg_match('/\{!([^}]+)\}(.*)/', $string, $matches)) {
+ $local = $matches[1];
+ $string = $matches[2];
+ }
+
+ // Anything that has a name and value
+ // check if we have a : in the string
+ if (strstr($string, ':')) {
+ list($name, $value) = explode(":", $string, 2);
+ }
+ else {
+ $value = $string;
+ }
+ $this->addFilter($name, $value, $exclude, $local);
+ return $this;
+ }
+
+ public function addParam($name, $value) {
+ if (isset($this->single_value_params[$name])) {
+ if (is_array($value)) {
+ $value = end($value);
+ }
+ $this->params[$name] = $this->normalizeParamValue($value);
+ return $this;
+ }
+ // We never actually populate $this->params['fq']. Instead
+ // we manage everything via the filter methods.
+ if ($name == 'fq') {
+ if (is_array($value)) {
+ array_walk_recursive($value, array($this, 'addFq'));
+ return $this;
+ }
+ else {
+ return $this->addFq($value);
+ }
+ }
+
+ if (!isset($this->params[$name])) {
+ $this->params[$name] = array();
+ }
+
+ if (!is_array($value)) {
+ // Convert to array for array_map.
+ $param_values = array($value);
+ }
+ else {
+ // Convert to a numerically keyed array.
+ $param_values = array_values($value);
+ }
+ $this->params[$name] = array_merge($this->params[$name], array_map(array($this, 'normalizeParamValue'), $param_values));
+
+ return $this;
+ }
+
+ protected function normalizeParamValue($value) {
+ // Convert boolean to string.
+ if (is_bool($value)) {
+ return $value ? 'true' : 'false';
+ }
+ // Convert to trimmed string.
+ return trim($value);
+ }
+
+ public function addParams(Array $params) {
+ foreach ($params as $name => $value) {
+ $this->addParam($name, $value);
+ }
+ return $this;
+ }
+
+ public function removeParam($name) {
+ unset($this->params[$name]);
+ if ($name == 'fq') {
+ $this->fields = array();
+ $this->subqueries = array();
+ }
+ return $this;
+ }
+
+ public function replaceParam($name, $value) {
+ $this->removeParam($name);
+ return $this->addParam($name, $value);
+ }
+
+ /**
+ * Handles aliases for field to make nicer URLs.
+ *
+ * @param $field_map
+ * An array keyed with real Solr index field names with the alias as value.
+ *
+ * @return DrupalSolrQueryInterface
+ * The called object.
+ */
+ public function addFieldAliases($field_map) {
+ $this->field_map = array_merge($this->field_map, $field_map);
+ // We have to re-parse the filters.
+ $this->parseSortString();
+ return $this;
+ }
+
+ public function getFieldAliases() {
+ return $this->field_map;
+ }
+
+ public function clearFieldAliases() {
+ $this->field_map = array();
+ // We have to re-parse the filters.
+ $this->parseSortString();
+ return $this;
+ }
+
+ protected function parseSortString() {
+ // Substitute any field aliases with real field names.
+ $sortstring = strtr($this->sortstring, $this->field_map);
+ // Score is a special case - it's the default sort for Solr.
+ if ('' == $sortstring || 'score desc' == $sortstring) {
+ $this->solrsort['#name'] = 'score';
+ $this->solrsort['#direction'] = 'desc';
+ unset($this->params['sort']);
+ }
+ else {
+ // Validate and set sort parameter
+ $fields = implode('|', array_keys($this->available_sorts));
+ if (preg_match('/^(?:(' . $fields . ') (asc|desc),?)+$/', $sortstring, $matches)) {
+ // We only use the last match.
+ $this->solrsort['#name'] = $matches[1];
+ $this->solrsort['#direction'] = $matches[2];
+ $this->params['sort'] = array($sortstring);
+ }
+ }
+ }
+
+ public function getAvailableSorts() {
+ return $this->available_sorts;
+ }
+
+ public function setAvailableSort($name, $sort) {
+ // We expect non-aliased sorts to be added.
+ $this->available_sorts[$name] = $sort;
+ // Re-parse the sortstring.
+ $this->parseSortString();
+ return $this;
+ }
+
+ public function setAvailableSorts($sorts) {
+ // We expect a complete array of valid sorts.
+ $this->available_sorts = $sorts;
+ $this->parseSortString();
+ return $this;
+ }
+
+ public function removeAvailableSort($name) {
+ unset($this->available_sorts[$name]);
+ // Re-parse the sortstring.
+ $this->parseSortString();
+ return $this;
+ }
+
+ public function getSolrsort() {
+ return $this->solrsort;
+ }
+
+ public function setSolrsort($name, $direction) {
+ $this->sortstring = trim($name) . ' ' . trim($direction);
+ $this->parseSortString();
+ return $this;
+ }
+
+ public function getPath($new_keywords = NULL) {
+ if (isset($new_keywords)) {
+ return $this->base_path . '/' . $new_keywords;
+ }
+ elseif ($this->getParam('q')) {
+ return $this->base_path . '/' . $this->getParam('q');
+ }
+ else {
+ // Return with empty query (the slash). The path for a facet
+ // becomes $this->base_path . '//facetinfo';
+ // We do this so we can have a consistent way of retrieving the query +
+ // additional parameters
+ return $this->base_path . '/';
+ }
+ }
+
+ public function getSolrsortUrlQuery() {
+ $queryvalues = array();
+ $solrsort = $this->solrsort;
+ if ($solrsort && ($solrsort['#name'] != 'score')) {
+ if (isset($this->field_map[$solrsort['#name']])) {
+ $solrsort['#name'] = $this->field_map[$solrsort['#name']];
+ }
+ $queryvalues['solrsort'] = $solrsort['#name'] . ' ' . $solrsort['#direction'];
+ }
+ else {
+ // Return to default relevancy sort.
+ unset($queryvalues['solrsort']);
+ }
+ return $queryvalues;
+ }
+
+ public function search($keys = NULL) {
+ if ($this->abort_search) {
+ return NULL;
+ }
+ return $this->solr->search($keys, $this->getSolrParams());
+ }
+
+ public function solr($method) {
+ return $this->solr->$method();
+ }
+
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/apachesolr.admin.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/apachesolr.admin.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,1342 @@
+ 'value',
+ '#value' => $environment['env_id'],
+ );
+ if (isset($environment['export_type']) && $environment['export_type'] == 3) {
+ $verb = t('Revert');
+ }
+ else {
+ $verb = t('Delete');
+ }
+ return confirm_form(
+ $form,
+ t('Are you sure you want to !verb search environment %name?', array('%name' => $environment['name'], '!verb' => strtolower($verb))),
+ 'admin/config/search/apachesolr',
+ t('This action cannot be undone.'),
+ $verb,
+ t('Cancel')
+ );
+}
+
+/**
+ * Submit handler for the delete form
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+function apachesolr_environment_delete_form_submit(array $form, array &$form_state) {
+ if (apachesolr_environment_delete($form_state['values']['env_id'])) {
+ drupal_set_message(t('The search environment was deleted'));
+ }
+ $form_state['redirect'] = 'admin/config/search/apachesolr/settings';
+}
+
+function apachesolr_environment_edit_delete_submit($form, &$form_state) {
+ $form_state['redirect'] = 'admin/config/search/apachesolr/settings/' . $form_state['values']['env_id'] . '/delete';
+
+ // Regardlessly of the destination parameter we want to go to another page
+ unset($_GET['destination']);
+ drupal_static_reset('drupal_get_destination');
+ drupal_get_destination();
+}
+
+/**
+ * Settings page for a specific environment (or default one if not provided)
+ *
+ * @param array|bool $environment
+ *
+ * @return array Render array for a settings page
+ */
+function apachesolr_environment_settings_page(array $environment = array()) {
+ if (empty($environment)) {
+ $env_id = apachesolr_default_environment();
+ $environment = apachesolr_environment_load($env_id);
+ }
+ $env_id = $environment['env_id'];
+
+ // Initializes output with information about which environment's setting we are
+ // editing, as it is otherwise not transparent to the end user.
+ $output = array(
+ 'apachesolr_environment' => array(
+ '#theme' => 'apachesolr_settings_title',
+ '#env_id' => $env_id,
+ ),
+ );
+ $output['form'] = drupal_get_form('apachesolr_environment_edit_form', $environment);
+ return $output;
+}
+
+/**
+ * Form to clone a certain environment
+ *
+ * @param array $form
+ * @param array $form_state
+ * @param array $environment
+ *
+ * @return array output of confirm_form()
+ */
+function apachesolr_environment_clone_form(array $form, array &$form_state, array $environment) {
+ $form['env_id'] = array(
+ '#type' => 'value',
+ '#value' => $environment['env_id'],
+ );
+ return confirm_form(
+ $form,
+ t('Are you sure you want to clone search environment %name?', array('%name' => $environment['name'])),
+ 'admin/config/search/apachesolr',
+ '',
+ t('Clone'),
+ t('Cancel')
+ );
+}
+
+/**
+ * Submit handler for the clone form
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+function apachesolr_environment_clone_form_submit(array $form, array &$form_state) {
+ if (apachesolr_environment_clone($form_state['values']['env_id'])) {
+ drupal_set_message(t('The search environment was cloned'));
+ }
+ $form_state['redirect'] = 'admin/config/search/apachesolr/settings';
+}
+
+/**
+ * Submit handler for the confirmation page of cloning an environment
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+function apachesolr_environment_clone_submit(array $form, array &$form_state) {
+ $form_state['redirect'] = 'admin/config/search/apachesolr/settings/' . $form_state['values']['env_id'] . '/clone';
+}
+
+/**
+ * Form builder for adding/editing a Solr environment used as a menu callback.
+ */
+function apachesolr_environment_edit_form(array $form, array &$form_state, array $environment = array()) {
+ if (empty($environment)) {
+ $environment = array();
+ }
+ $environment += array('env_id' => '', 'name' => '', 'url' => '', 'service_class' => '', 'conf' => array());
+
+ $form['#environment'] = $environment;
+ $form['url'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Solr server URL'),
+ '#default_value' => $environment['url'],
+ '#description' => t('Example: http://localhost:8983/solr'),
+ '#required' => TRUE,
+ );
+ $is_default = $environment['env_id'] == apachesolr_default_environment();
+ $form['make_default'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Make this Solr search environment the default'),
+ '#default_value' => $is_default,
+ '#disabled' => $is_default,
+ );
+ $form['name'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Description'),
+ '#default_value' => $environment['name'],
+ '#required' => TRUE,
+ );
+ $form['env_id'] = array(
+ '#type' => 'machine_name',
+ '#title' => t('Environment id'),
+ '#machine_name' => array(
+ 'exists' => 'apachesolr_environment_load',
+ ),
+ '#default_value' => $environment['env_id'],
+ '#disabled' => !empty($environment['env_id']), // Cannot change it once set.
+ '#description' => t('Unique, machine-readable identifier for this Solr environment.'),
+ '#required' => TRUE,
+ );
+ $form['service_class'] = array(
+ '#type' => 'value',
+ '#value' => $environment['service_class'],
+ );
+ $form['conf'] = array(
+ '#tree' => TRUE,
+ );
+ $form['conf']['apachesolr_read_only'] = array(
+ '#type' => 'radios',
+ '#title' => t('Index write access'),
+ '#default_value' => isset($environment['conf']['apachesolr_read_only']) ? $environment['conf']['apachesolr_read_only'] : APACHESOLR_READ_WRITE,
+ '#options' => array(APACHESOLR_READ_WRITE => t('Read and write (normal)'), APACHESOLR_READ_ONLY => t('Read only')),
+ '#description' => t('Read only stops this site from sending updates to this search environment. Useful for development sites.'),
+ );
+ $form['actions'] = array(
+ '#type' => 'actions',
+ );
+ $form['actions']['save'] = array(
+ '#type' => 'submit',
+ '#validate' => array('apachesolr_environment_edit_validate'),
+ '#submit' => array('apachesolr_environment_edit_submit'),
+ '#value' => t('Save'),
+ );
+ $form['actions']['save_edit'] = array(
+ '#type' => 'submit',
+ '#validate' => array('apachesolr_environment_edit_validate'),
+ '#submit' => array('apachesolr_environment_edit_submit'),
+ '#value' => t('Save and edit'),
+ );
+ $form['actions']['test'] = array(
+ '#type' => 'submit',
+ '#validate' => array('apachesolr_environment_edit_validate'),
+ '#submit' => array('apachesolr_environment_edit_test_submit'),
+ '#value' => t('Test connection'),
+ );
+ if (!empty($environment['env_id']) && !$is_default) {
+ $form['actions']['delete'] = array(
+ '#type' => 'submit',
+ '#submit' => array('apachesolr_environment_edit_delete_submit'),
+ '#value' => t('Delete'),
+ );
+ }
+
+ // Ensures destination is an internal URL, builds "cancel" link.
+ if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) {
+ $destination = $_GET['destination'];
+ }
+ else {
+ $destination = 'admin/config/search/apachesolr/settings';
+ }
+ $form['actions']['cancel'] = array(
+ '#type' => 'link',
+ '#title' => t('Cancel'),
+ '#href' => $destination,
+ );
+
+ return $form;
+}
+
+/**
+ * Submit handler for the test button in the environment edit page
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+function apachesolr_environment_edit_test_submit(array $form, array &$form_state) {
+ $ping = apachesolr_server_status($form_state['values']['url'], $form_state['values']['service_class']);
+ if ($ping) {
+ drupal_set_message(t('Your site has contacted the Apache Solr server.'));
+ }
+ else {
+ drupal_set_message(t('Your site was unable to contact the Apache Solr server.'), 'error');
+ }
+ $form_state['rebuild'] = TRUE;
+}
+
+/**
+ * Validate handler for the environment edit page
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+function apachesolr_environment_edit_validate(array $form, array &$form_state) {
+ $parts = parse_url($form_state['values']['url']);
+ foreach (array('scheme', 'host', 'path') as $key) {
+ if (empty($parts[$key])) {
+ form_set_error('url', t('The Solr server URL needs to include a !part', array('!part' => $key)));
+ }
+ }
+ if (isset($parts['port'])) {
+ // parse_url() should always give an integer for port. Since drupal_http_request()
+ // also uses parse_url(), we don't need to validate anything except the range.
+ $pattern = empty($parts['user']) ? '@://[^:]+:([^/]+)@' : '#://[^@]+@[^:]+:([^/]+)#';
+ preg_match($pattern, $form_state['values']['url'], $m);
+ if (empty($m[1]) || !ctype_digit($m[1]) || $m[1] < 1 || $m[1] > 65535) {
+ form_set_error('port', t('The port has to be an integer between 1 and 65535.'));
+ }
+ else {
+ // Normalize the url by removing extra slashes and whitespace.
+ $form_state['values']['url'] = trim($form_state['values']['url'], "/ \t\r\n\0\x0B");
+ }
+ }
+}
+
+/**
+ * Submit handler for the environment edit page
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+function apachesolr_environment_edit_submit(array $form, array &$form_state) {
+ apachesolr_environment_save($form_state['values']);
+ if (!empty($form_state['values']['make_default'])) {
+ apachesolr_set_default_environment($form_state['values']['env_id']);
+ }
+ cache_clear_all('apachesolr:environments', 'cache_apachesolr');
+ drupal_set_message(t('The %name search environment has been saved.', array('%name' => $form_state['values']['name'])));
+ if ($form_state['values']['op'] == t('Save')) {
+ $form_state['redirect'] = 'admin/config/search/apachesolr/settings';
+ }
+ else {
+ $form_state['redirect'] = current_path();
+ }
+ // Regardlessly of the destination parameter we want to go to another page
+ unset($_GET['destination']);
+ drupal_static_reset('drupal_get_destination');
+ drupal_get_destination();
+}
+
+/**
+ * Check to see if the facetapi module is installed, and if not put up
+ * a message.
+ *
+ * Only call this function if the user is already in a position for this to
+ * be useful.
+ */
+function apachesolr_check_facetapi() {
+ if (!module_exists('facetapi')) {
+ $filename = db_query_range("SELECT filename FROM {system} WHERE type = 'module' AND name = 'facetapi'", 0, 1)
+ ->fetchField();
+ if ($filename && file_exists($filename)) {
+ drupal_set_message(t('If you enable the facetapi module, Apache Solr Search will provide you with configurable facets.', array('@modules' => url('admin/modules'))));
+ }
+ else {
+ drupal_set_message(t('If you install the facetapi module from !href, Apache Solr Search will provide you with configurable facets.', array('!href' => url('http://drupal.org/project/facetapi'))));
+ }
+ }
+}
+
+/**
+ * Form builder for general settings used as a menu callback.
+ *
+ * @param array $form
+ * @param array $form_state
+ *
+ * @return array Output of the system_settings_form()
+ */
+function apachesolr_settings(array $form, array &$form_state) {
+ $form = array();
+ $rows = array();
+
+ // Environment settings
+ $id = apachesolr_default_environment();
+ $environments = apachesolr_load_all_environments();
+ $default_environment = apachesolr_default_environment();
+ apachesolr_check_facetapi();
+
+ // Reserve a row for the default one
+ $rows[$default_environment] = array();
+
+ foreach ($environments as $environment_id => $data) {
+ // Define all the Operations
+ $confs = array();
+ $ops = array();
+ // Whenever facetapi is enabled we also enable our operation link
+ if (module_exists('facetapi')) {
+ $confs['facets'] = array(
+ 'class' => 'operation',
+ 'data' => l(t('Facets'),
+ 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/facets',
+ array('query' => array('destination' => current_path()))
+ ),
+ );
+ }
+ // These are our result and bias settings
+ if (module_exists('apachesolr_search')) {
+ $confs['result_bias'] = array(
+ 'class' => 'operation',
+ 'data' => l(t('Bias'),
+ 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/bias',
+ array('query' => array('destination' => current_path()))
+ ),
+ );
+ }
+ $confs['index'] = array(
+ 'class' => 'operation',
+ 'data' => l(t('Index'),
+ 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/index'
+ ),
+ );
+ $ops['edit'] = array(
+ 'class' => 'operation',
+ 'data' => l(t('Edit'),
+ 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/edit',
+ array('query' => array('destination' => current_path()))
+ ),
+ );
+
+ $ops['clone'] = array(
+ 'class' => 'operation',
+ 'data' => l(t('Clone'),
+ 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/clone',
+ array('query' => array('destination' => $_GET['q']))
+ ),
+ );
+ $env_name = l($data['name'], 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/edit', array('query' => array('destination' => $_GET['q'])));
+
+ // Is this row our default environment?
+ if ($environment_id == $default_environment) {
+ $env_name = t('!environment (Default)', array('!environment' => $env_name));
+ $env_class_row = 'default-environment';
+ }
+ else {
+ $env_class_row = '';
+ }
+ // For every non-default we add a delete link
+ // Allow to revert a search environment or to delete it
+ $delete_value = '';
+ if (!isset($data['in_code_only'])) {
+ if ((isset($data['type']) && $data['type'] == 'Overridden')) {
+ $delete_value = array(
+ 'class' => 'operation',
+ 'data' => l(t('Revert'), 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/delete'),
+ );
+ }
+ // don't allow the deletion of the default environment
+ elseif ($environment_id != $default_environment) {
+ $delete_value = array(
+ 'class' => 'operation',
+ 'data' => l(t('Delete'), 'admin/config/search/apachesolr/settings/' . $data['env_id'] . '/delete'),
+ );
+ }
+ }
+ $ops['delete'] = $delete_value;
+
+ // When we are receiving a http POST (so the page does not show) we do not
+ // want to check the statusses of any environment
+ $class = '';
+ if (empty($form_state['input'])) {
+ $class = apachesolr_server_status($data['url'], $data['service_class']) ? 'ok' : 'error';
+ }
+
+ $headers = array(
+ array('data' => t('Name'), 'colspan' => 2),
+ t('URL'),
+ array('data' => t('Configuration'), 'colspan' => count($confs)),
+ array('data' => t('Operations'), 'colspan' => count($ops)),
+ );
+
+ $rows[$environment_id] = array('data' =>
+ array(
+ // Cells
+ array(
+ 'class' => 'status-icon',
+ 'data' => '
';
+ return $output;
+}
+
+/**
+ * Added form submit function to retain filters.
+ *
+ * @see apachesolr_search_form_search_form_alter()
+ */
+function apachesolr_search_form_search_submit($form, &$form_state) {
+ $fv = $form_state['values'];
+ // Replace keys with their rawurlencoded value
+ if (isset($fv['search_block_form'])) {
+ $raw_keys = str_replace("/","%2f",$fv['search_block_form']);
+ $form_state['redirect'] = str_replace($fv['search_block_form'], $raw_keys, $form_state['redirect']);
+ }
+}
+
+/**
+ * Implements hook_form_[form_id]_alter().
+ *
+ * Rebuild (empty) the spellcheck dictionary when the index is deleted..
+ */
+function apachesolr_search_form_apachesolr_delete_index_confirm_alter(&$form, $form_state) {
+ $form['submit']['#submit'][] = 'apachesolr_search_build_spellcheck';
+}
+
+/**
+ * submit function for the delete_index form.
+ *
+ */
+function apachesolr_search_build_spellcheck($form, &$form_state) {
+ try {
+ $solr = apachesolr_get_solr();
+ $params['spellcheck'] = 'true';
+ $params['spellcheck.build'] = 'true';
+ $response = $solr->search('solr', 0, 0, $params);
+ }
+ catch (Exception $e) {
+ watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
+ }
+}
+
+/**
+ * Implements hook_form_[form_id]_alter().
+ *
+ * Adds settings to show facet blocks on non-search pages.
+ */
+function apachesolr_search_form_facetapi_realm_settings_form_alter(&$form, &$form_state) {
+ if ('apachesolr' == $form['#facetapi']['adapter']->getId() && 'block' == $form['#facetapi']['realm']['name']) {
+ // Gets the environment ID from the searcher, stores in #facetapi property.
+ $env_id = ltrim(strstr($form['#facetapi']['adapter']->getSearcher(), '@'), '@');
+
+ $show_facets = apachesolr_environment_variable_get($env_id, 'apachesolr_search_show_facets', 0);
+ $facet_pages = apachesolr_environment_variable_get($env_id, 'apachesolr_search_facet_pages', '');
+
+ $form['#facetapi']['env_id'] = $env_id;
+
+ $form['apachesolr_search_show_facets'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Show facets on non-search pages.'),
+ '#default_value' => $show_facets,
+ '#weight' => '-10',
+ );
+
+ $form['apachesolr_search_facet_pages'] = array(
+ '#title' => t('Non-search paths'),
+ '#type' => 'textarea',
+ '#default_value' => $facet_pages,
+ '#weight' => '-10',
+ '#dependency' => array(
+ 'edit-apachesolr-search-show-facets' => array(1),
+ ),
+ );
+
+ $form['#submit'][] = 'apachesolr_search_facetapi_realm_settings_form_submit';
+ }
+}
+
+/**
+ * Form submission handler for facetapi_realm_settings_form().
+ */
+function apachesolr_search_facetapi_realm_settings_form_submit(&$form, &$form_state) {
+ $env_id = $form['#facetapi']['env_id'];
+
+ // Adds the settings to the array keyed by environment ID, saves variables.
+ $show_facets = $form_state['values']['apachesolr_search_show_facets'];
+ $facet_pages = $form_state['values']['apachesolr_search_facet_pages'];
+ if ($show_facets) {
+ apachesolr_environment_variable_set($env_id, 'apachesolr_search_show_facets', $show_facets);
+ }
+ else {
+ // Due to performance reasons, we delete it from the vars so that our init
+ // process can react on environments that hae it set and not unset.
+ // See apachesolr_search_init().
+ apachesolr_environment_variable_del($env_id, 'apachesolr_search_show_facets');
+ }
+ apachesolr_environment_variable_set($env_id, 'apachesolr_search_facet_pages', $facet_pages);
+}
+
+/**
+ * Implements hook_theme().
+ */
+function apachesolr_search_theme() {
+ return array(
+ /**
+ * Shows the facets in blocks in the search result area
+ */
+ 'apachesolr_search_browse_blocks' => array(
+ 'render element' => 'content',
+ ),
+ /**
+ * Shows the search snippet
+ */
+ 'apachesolr_search_snippets' => array(
+ 'variables' => array('doc' => NULL, 'snippets' => array()),
+ ),
+ /**
+ * Shows a message when the search does not return any result
+ */
+ 'apachesolr_search_noresults' => array(
+ 'variables' => array(),
+ ),
+ /**
+ * Shows a list of suggestions
+ */
+ 'apachesolr_search_suggestions' => array(
+ 'variables' => array('links' => NULL),
+ ),
+ /**
+ * Shows a list of results (docs) in content recommendation block
+ */
+ 'apachesolr_search_mlt_recommendation_block' => array(
+ 'variables' => array('docs' => NULL, 'delta' => NULL),
+ ),
+ );
+}
+
+/**
+ * Implements hook_theme_registry_alter().
+ */
+function apachesolr_search_theme_registry_alter(&$theme_registry) {
+ if (isset($theme_registry['search_results'])) {
+ $theme_registry['search_results']['variables']['search_page'] = NULL;
+ }
+}
+
+/**
+ * Theme the highlighted snippet text for a search entry.
+ *
+ * @param array $vars
+ *
+ */
+function theme_apachesolr_search_snippets($vars) {
+ $result = '';
+ if (is_array($vars['snippets'])) {
+ $snippets = $vars['snippets'];
+ if (isset($snippets['content'])) {
+ $result .= implode(' ... ', $snippets['content']);
+ unset($snippets['content']);
+ }
+ if (isset($snippets['teaser'])) {
+ $result .= (strlen($result) > 0) ? ' ... ' : '';
+ $result .= implode(' ... ', $snippets['teaser']);
+ unset($snippets['teaser']);
+ }
+ if (count($snippets)) {
+ $result .= (strlen($result) > 0) ? ' ... ' : '';
+ foreach ($snippets as $snippet) {
+ $result .= implode(' ... ', $snippet);
+ }
+ }
+ }
+ return $result . ' ...';
+}
+
+/**
+ * Brief message to display when no results match the query.
+ *
+ * @see search_help()
+ */
+function theme_apachesolr_search_noresults() {
+ return t('
+
Check if your spelling is correct, or try removing filters.
+
Remove quotes around phrases to match each word individually: "blue drop" will match less than blue drop.
+
You can require or exclude terms using + and -: big +blue drop will require a match on blue while big blue -drop will exclude results that contain drop.
+
');
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/apachesolr_search.pages.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/apachesolr_search.pages.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,128 @@
+ 'container',
+ '#attributes' => array('class' => array('container-inline')),
+ );
+ $form['basic']['keys'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Enter terms'),
+ '#default_value' => $keys,
+ '#size' => 20,
+ '#maxlength' => 255,
+ );
+ $form['basic']['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Search'),
+ );
+
+ $form['basic']['get'] = array(
+ '#type' => 'hidden',
+ '#default_value' => json_encode(array_diff_key($_GET, array('q' => 1, 'page' => 1, 'solrsort' => 1, 'retain-filters' => 1))),
+ );
+
+ $fq = NULL;
+
+ if (apachesolr_has_searched($search_page['env_id'])) {
+ $query = apachesolr_current_query($search_page['env_id']);
+ // We use the presence of filter query params as a flag for the retain filters checkbox.
+ $fq = $query->getParam('fq');
+ }
+
+ if ($fq || isset($form_state['input']['retain-filters'])) {
+ $form['basic']['retain-filters'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Retain current filters'),
+ '#default_value' => (int) !empty($_GET['retain-filters']),
+ );
+ }
+
+ return $form;
+}
+
+/**
+ * Processes apachesolr_search_custom_page_search_form submissions.
+ */
+function apachesolr_search_custom_page_search_form_submit(&$form, &$form_state) {
+ $search_page = $form['#search_page'];
+ $redirect = $search_page['search_path'];
+
+ // Also encode slashes so we don't get akward situations when obtaining the
+ // search key. We can't use drupal_encode_path because for "aestetic" reasons
+ // they don't encode slashes...
+ $redirect_value = rawurlencode($form_state['values']['keys']);
+
+ if (strlen($form_state['values']['keys'])) {
+ $redirect .= '/' . $redirect_value;
+ }
+
+ $get = array();
+ if (isset($form_state['values']['get'])) {
+ $get = json_decode($form_state['values']['get'], TRUE);
+ }
+ if (!empty($form_state['values']['retain-filters'])) {
+ // Add our saved values
+ $get['retain-filters'] = '1';
+ }
+ else {
+ // Remove all filters
+ if (!empty($search_page['settings']['apachesolr_search_allow_user_input'])) {
+ unset($get['fq']);
+ }
+ if (module_exists('facetapi')) {
+ unset($get['f']);
+ }
+ }
+
+ // Add the query values into the redirect.
+ $form_state['redirect'] = array($redirect, array('query' => $get));
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/drush/apachesolr.drush.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/drush/apachesolr.drush.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,642 @@
+ 'apachesolr_drush_solr_delete_index',
+ 'description' => dt('Deletes the content from the index. Can take content types as parameters.'),
+ 'arguments' => array(
+ 'types' => dt('Optional. A space delimited list of content types to be deleted from the index.'),
+ ),
+ 'options' => array(
+ 'environment-id' => 'The environment ID',
+ ),
+ 'examples' => array(
+ 'drush solr-delete-index node' => 'Delete all node content from the index.',
+ 'drush solr-delete-index node:article' => 'Delete all content of the article content type from the index.',
+ 'drush solr-delete-index node:article node:blog' => 'Delete all content of the article and blog content types from the index.',
+ ),
+ );
+ $items['solr-mark-all'] = array(
+ 'callback' => 'apachesolr_drush_solr_mark_for_reindex',
+ 'description' => dt('Marks content for reindexing. Can take content types as parameters.'),
+ 'arguments' => array(
+ 'types' => dt('Optional. A space delimited list of content types to be marked for reindexing.'),
+ ),
+ 'options' => array(
+ 'environment-id' => 'The environment ID',
+ ),
+ );
+ $items['solr-index'] = array(
+ 'callback' => 'apachesolr_drush_solr_index',
+ 'description' => dt('Reindexes content marked for (re)indexing.'),
+ 'options' => array(
+ 'environment-id' => 'The environment ID',
+ 'limit' => 'The total number of documents to index',
+ ),
+ );
+ $items['solr-get-last-indexed'] = array(
+ 'callback' => 'apachesolr_drush_solr_get_last_indexed',
+ 'description' => dt('Get the ID of the last document indexed.'),
+ 'arguments' => array(
+ 'environment-id' => dt('Optional. The environment ID, uses the default if not passed.'),
+ 'entity-type' => dt('Optional. The machine name of the entity, defaults to "node".'),
+ ),
+ );
+ $items['solr-get-next-indexed'] = array(
+ 'callback' => 'apachesolr_drush_solr_get_next_indexed',
+ 'description' => dt('Get the ID of the next document to be indexed.'),
+ 'arguments' => array(
+ 'environment-id' => dt('Optional. The environment ID, uses the default if not passed.'),
+ 'entity-type' => dt('Optional. The machine name of the entity, defaults to "node".'),
+ ),
+ );
+ $items['solr-search'] = array(
+ 'callback' => 'apachesolr_drush_solr_search',
+ 'description' => dt('Search the site for keywords using Apache Solr'),
+ 'arguments' => array(
+ 'keywords' => dt('One or more keywords, separated by spaces.'),
+ ),
+ );
+ $items['solr-get-env-id'] = array(
+ 'callback' => 'apachesolr_drush_solr_get_env_id',
+ 'description' => dt('Get the default Apache Solr environment ID, or all IDs and names'),
+ 'arguments' => array(),
+ 'options' => array(
+ 'all' => array(
+ 'description' => 'List all environment IDs',
+ ),
+ ),
+ );
+ $items['solr-get-env-name'] = array(
+ 'callback' => 'apachesolr_drush_solr_get_env_name',
+ 'description' => dt('Get the Apache Solr environment name.'),
+ 'options' => array(
+ 'id' => array(
+ 'description' => 'Apache Solr environment ID to use (uses the default environment if not specified)',
+ ),
+ ),
+ );
+ $items['solr-get-env-url'] = array(
+ 'callback' => 'apachesolr_drush_solr_get_env_url',
+ 'description' => dt('Get the Apache Solr environment url.'),
+ 'options' => array(
+ 'id' => array(
+ 'description' => 'Apache Solr environment ID to use (uses the default environment if not specified)',
+ ),
+ ),
+ );
+ $items['solr-set-env-url'] = array(
+ 'callback' => 'apachesolr_drush_solr_set_env_url',
+ 'description' => dt('Set the url for an Apache Solr environment.'),
+ 'arguments' => array(
+ 'url' => dt('Apache Solr server url string.'),
+ ),
+ 'required-arguments' => TRUE,
+ 'options' => array(
+ 'id' => array(
+ 'description' => 'Apache Solr environment ID to use (uses the default environment if not specified)',
+ ),
+ ),
+ );
+ $items['solr-variable-get'] = array(
+ 'description' => 'Get a list of Apache Solr environment variable names and values.',
+ 'arguments' => array(
+ 'name' => 'A string to filter the variables by. Variables that have any part of their name matching the string will b listed.',
+ ),
+ 'examples' => array(
+ 'drush solr-vget' => 'List all variables and values.',
+ 'drush solr-vget user' => 'List all variables containing the string "user".',
+ ),
+ 'options' => array(
+ 'id' => 'Apache Solr environment ID to use (uses the default environment if not specified)',
+ 'format' => 'Format to output the object. Use "print_r" for print_r (default), "export" for var_export, and "json" for JSON.',
+ 'pipe' => 'A synonym for --format=export. Useful for pasting into code.',
+ ),
+ 'aliases' => array('solr-vget'),
+ );
+ $items['solr-variable-set'] = array(
+ 'description' => "Set an Apache Solr environment variable.",
+ 'arguments' => array(
+ 'name' => 'The name of a variable or the first few letters of its name.',
+ 'value' => 'The value to assign to the variable. Use \'-\' to read the object from STDIN.',
+ ),
+ 'required-arguments' => TRUE,
+ 'options' => array(
+ 'id' => 'Apache Solr environment ID to use (uses the default environment if not specified)',
+ 'yes' => 'Skip confirmation if only one variable name matches.',
+ 'always-set' => 'Always skip confirmation.',
+ 'format' => 'Format to parse the object. Use "auto" to detect format from value (default), "string", "integer" or "boolean" for corresponding primitive type, and "json" for JSON.',
+ ),
+ 'examples' => array(
+ 'drush solr-vset --yes apachesolr_read_only 1' => 'Set the apachesolr_read_only variable to 1. Skip confirmation if variable already exists.',
+ 'drush solr-vset pr TRUE' => 'Choose from a list of variables beginning with "pr" to set to (bool)true.',
+ 'php -r "print json_encode(array(\'drupal\', \'simpletest\'));" | drush solr-vset --format=json project_dependency_excluded_dependencies -'=> 'Set a variable to a complex value (e.g. array)',
+ ),
+ 'aliases' => array('solr-vset'),
+ );
+ $items['solr-variable-delete'] = array(
+ 'description' => "Delete an Apache Solr environment variable.",
+ 'arguments' => array(
+ 'name' => 'The name of a variable or the first few letters of its name.',
+ ),
+ 'required-arguments' => TRUE,
+ 'options' => array(
+ 'id' => array(
+ 'description' => 'Apaches Solr environment ID to use (uses the default environment if not specified)',
+ ),
+ 'yes' => 'Skip confirmation if only one variable name matches.',
+ 'exact' => 'Only delete the one variable that exactly matches the specified name.',
+ ),
+ 'examples' => array(
+ 'drush solr-vdel apachesolr_read_only --id=solr2' => 'Delete the apachesolr_read_only variable for the solr2 environment.',
+ 'drush solr-vdel apa' => 'Choose from a list of variables beginning with "u" to delete.',
+ 'drush solr-vdel -y --exact apachesolr_read_only' => 'Delete variable, skipping confirmation.',
+ ),
+ 'aliases' => array('solr-vdel'),
+ );
+ return $items;
+}
+
+/**
+ * Implements hook_drush_help().
+ *
+ * This function is called whenever a drush user calls
+ * 'drush help '
+ *
+ * @param string $section
+ * A string with the help section (prepend with 'drush:')
+ *
+ * @return string
+ * A string with the help text for your command.
+ */
+function apachesolr_drush_help($section) {
+ switch ($section) {
+ case 'drush:solr-delete-index':
+ return dt("Used without parameters, this command deletes the entire Solr index.
+ Used with parameters for content type, it deletes just the content types that are specified.
+ After the index has been deleted, all content will be indexed again on future cron runs.");
+ case 'drush:solr-mark-all':
+ return dt("Used without parameters, this command marks all of the content in the Solr index for
+ reindexing. Used with parameters for content type, it marks just the content types that are specified.
+ Reindexing is different than deleting as the content is still searchable while it is in queue to be reindexed.
+ Reindexing is done on future cron runs.");
+ case 'drush:solr-index':
+ return dt("Reindexes content marked for (re)indexing. If you want to reindex all content or content
+ of a specific type, use solr-reindex first to mark that content.");
+ case 'drush:solr-search':
+ return dt('Executes a search against the site\'s Apache Solr search index and returns the results.');
+ case 'error:APACHESOLR_ENV_ID_ERROR':
+ return dt('Not a valid environment ID.');
+ }
+ return '';
+}
+
+/**
+ * Selectively delete content from the apachesolr index.
+ *
+ * Each argument is a filter on what to delete from the index.
+ * They are of the form entity (to delete all content of that
+ * entity) or entity:bundle (to delete all content of that
+ * bundle).
+ */
+function apachesolr_drush_solr_delete_index() {
+ module_load_include('inc', 'apachesolr', 'apachesolr.index');
+ $args = func_get_args();
+ $env_id = drush_get_option('environment-id');
+ if (empty($env_id)) {
+ $env_id = apachesolr_default_environment();
+ }
+
+ if (count($args) > 0) {
+ foreach ($args as $type) {
+ $parts = explode(':', $type);
+ if (count($parts) === 1) {
+ apachesolr_index_delete_index($env_id, $type);
+ }
+ elseif (count($parts) == 2) {
+ apachesolr_index_delete_index($env_id, $parts[0], $parts[1]);
+ }
+ else {
+ drush_set_error('The syntax for each type is either entity or entity:bundle');
+ }
+ }
+ }
+ else {
+ apachesolr_index_delete_index($env_id);
+ }
+
+ drush_print(t('Deleted the Solr index'));
+}
+
+/**
+ * Mark all of a specific environment id for reindexing
+ */
+function apachesolr_drush_solr_mark_for_reindex() {
+ module_load_include('inc', 'apachesolr', 'apachesolr.index');
+ $args = func_get_args();
+ $env_id = drush_get_option('environment-id');
+ if (empty($env_id)) {
+ $env_id = apachesolr_default_environment();
+ }
+ if (count($args) > 0) {
+ foreach ($args as $type) {
+ apachesolr_index_mark_for_reindex($env_id, $type);
+ }
+ }
+ else {
+ apachesolr_index_mark_for_reindex($env_id);
+ }
+ drush_print(t('Marked content for reindexing'));
+}
+
+/**
+ * Index all the items in the queue using a batch command
+ */
+function apachesolr_drush_solr_index() {
+ module_load_include('inc', 'apachesolr', 'apachesolr.admin');
+ module_load_include('inc', 'apachesolr', 'apachesolr.index');
+ $env_id = drush_get_option('environment-id');
+ if (empty($env_id)) {
+ $env_id = apachesolr_default_environment();
+ }
+ $total_limit = intval(drush_get_option('limit'));
+ apachesolr_index_batch_index_remaining($env_id, $total_limit);
+ drush_backend_batch_process();
+}
+
+/**
+ * Get the last indexed document
+ *
+ * @param string $env_id
+ * @param string $entity_type
+ */
+function apachesolr_drush_solr_get_last_indexed($env_id = NULL, $entity_type = 'node') {
+ if (NULL === $env_id) {
+ $env_id = apachesolr_default_environment();
+ }
+ $return = apachesolr_get_last_index_position($env_id, $entity_type);
+ drush_print($return['last_entity_id']);
+}
+
+function apachesolr_drush_solr_get_next_indexed($env_id = NULL, $entity_type = 'node') {
+ module_load_include('inc', 'apachesolr', 'apachesolr.index');
+ if (NULL === $env_id) {
+ $env_id = apachesolr_default_environment();
+ }
+ $return = apachesolr_index_get_entities_to_index($env_id, $entity_type, 1);
+ $output = (isset($return[0]->entity_id)) ? $return[0]->entity_id : '0';
+ drush_print($output);
+}
+
+/**
+ * Search the solr index using Drush
+ */
+function apachesolr_drush_solr_search() {
+ $args = func_get_args();
+ $keys = implode(' ', $args);
+ foreach (apachesolr_search_search_execute($keys) as $result) {
+ $output = $result['fields']['path'];
+ if(isset($result['user']) && isset($result['node']->is_uid)) {
+ $output .= ' ' . dt('by @name (user/@uid)', array('@name' => strip_tags($result['user']), '@uid' => $result['node']->is_uid));
+ }
+ $output .= "\n";
+ $output .= dt('title: ') . $result['title'] . "\n";
+ $output .= trim(preg_replace('/\s+/', ' ', strip_tags($result['snippet']))) . "\n\n";
+ drush_print($output);
+ }
+}
+
+/**
+ * Get all the environments (using option all) or get the default environment id
+ */
+function apachesolr_drush_solr_get_env_id() {
+ $all = drush_get_option('all');
+
+ if ($all) {
+ foreach (apachesolr_load_all_environments() as $id => $env) {
+ drush_print(drush_format($env['name'], $id));
+ }
+ }
+ else {
+ $solr_env_id = apachesolr_default_environment();
+ drush_print($solr_env_id);
+ }
+}
+
+/**
+ * Get the environment name based on the environment ID
+ *
+ * @print The environment name
+ *
+ * @return mixed APACHESOLR_ENV_ID_ERROR
+ * Only return error if the environment can't be found
+ */
+function apachesolr_drush_solr_get_env_name() {
+ $env_id = drush_get_option('id', apachesolr_default_environment());
+ try {
+ $environment = _apachesolr_drush_environment_load_and_validate($env_id);
+ }
+ catch (Exception $e) {
+ return drush_set_error('APACHESOLR_ENV_ID_ERROR', $e->getMessage());
+ }
+ drush_print($environment['name']);
+}
+
+/**
+ * Get the environment url based on the environment ID
+ *
+ * @print The environment url
+ *
+ * @return mixed APACHESOLR_ENV_ID_ERROR
+ * Only return error if the environment can't be found
+ */
+function apachesolr_drush_solr_get_env_url() {
+ $env_id = drush_get_option('id', apachesolr_default_environment());
+ try {
+ $environment = _apachesolr_drush_environment_load_and_validate($env_id);
+ }
+ catch (Exception $e) {
+ return drush_set_error('APACHESOLR_ENV_ID_ERROR', $e->getMessage());
+ }
+ drush_print($environment['url']);
+}
+
+/**
+ * Set the environment url based on the environment ID
+ *
+ * @param $url
+ *
+ * @return mixed APACHESOLR_ENV_ID_ERROR
+ * Only return error if the environment can't be found
+ */
+function apachesolr_drush_solr_set_env_url($url) {
+ $env_id = drush_get_option('id', apachesolr_default_environment());
+ try {
+ $environment = _apachesolr_drush_environment_load_and_validate($env_id);
+ }
+ catch (Exception $e) {
+ return drush_set_error('APACHESOLR_ENV_ID_ERROR', $e->getMessage());
+ }
+ $environment['url'] = $url;
+ apachesolr_environment_save($environment);
+}
+
+/**
+ * Command callback.
+ *
+ * List your site's variables.
+ * much of it copied from drush core
+ *
+ * @param string $arg_name
+ *
+ * @return array|mixed Could be the variable or a drush error
+ */
+function drush_apachesolr_solr_variable_get($arg_name = NULL) {
+ $output = NULL;
+
+ $found = array();
+
+ $env_id = drush_get_option('id', apachesolr_default_environment());
+ try {
+ $found = _apachesolr_drush_variable_like($env_id, $arg_name);
+ }
+ catch (Exception $e) {
+ return drush_set_error('APACHESOLR_ENV_ID_ERROR', $e->getMessage());
+ }
+
+ foreach ($found as $name => $value) {
+ drush_print_pipe(drush_format($value, $name, 'export'));
+ drush_print(drush_format($value, $name));
+ }
+
+ if (empty($found)) {
+ return drush_set_error('DRUSH_VARIABLE_ERROR', 'No matching variable found.');
+ }
+ else {
+ return $found;
+ }
+}
+
+/**
+ * Command callback.
+ * Set a variable.
+ *
+ * @param string $arg_name
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+function drush_apachesolr_solr_variable_set($arg_name, $value) {
+ $args = func_get_args();
+
+ if (!isset($value)) {
+ return drush_set_error('DRUSH_VARIABLE_ERROR', dt('No value specified.'));
+ }
+
+ $env_id = drush_get_option('id', apachesolr_default_environment());
+ try {
+ $found = _apachesolr_drush_variable_like($env_id, $arg_name, TRUE);
+ }
+ catch (Exception $e) {
+ return drush_set_error('APACHESOLR_ENV_ID_ERROR', $e->getMessage());
+ }
+
+ $options[] = "$arg_name ". dt('(new variable)');
+ $match = isset($found[$arg_name]);
+ if (!$match && $found) {
+ $options = array_merge($options, array_keys($found));
+ }
+
+ if ($value == '-') {
+ $value = stream_get_contents(STDIN);
+ }
+
+ // If the value is a string (usual case, unless we are called from code),
+ // then format the input
+ if (is_string($value)) {
+ $value = _apachesolr_drush_variable_format($value, drush_get_option('format', 'auto'));
+ }
+
+ // Format the output for display
+ if (is_array($value)) {
+ $display = "\n" . var_export($value, TRUE);
+ }
+ elseif (is_integer($value)) {
+ $display = $value;
+ }
+ elseif (is_bool($value)) {
+ $display = $value ? "TRUE" : "FALSE";
+ }
+ else {
+ $display = '"' . $value . '"';
+ }
+
+ $name = NULL;
+ if (drush_get_option('always-set', FALSE) || $match) {
+ $name = $arg_name;
+ }
+ else {
+ $choice = drush_choice($options, 'Enter a number to choose which variable to set.');
+ if ($choice !== FALSE) {
+ $name = ($choice == 0) ? $arg_name : $options[$choice];
+ }
+ }
+ if ($name) {
+ drush_op('apachesolr_environment_variable_set', $env_id, $name, $value);
+ drush_log(dt('!name was set to !value', array('!name' => $name, '!value' => $display)), 'success');
+ }
+}
+
+/**
+ *
+ * Format a specific variable
+ *
+ * @param $value
+ * @param $format
+ *
+ * @return bool|int|string
+ */
+function _apachesolr_drush_variable_format($value, $format) {
+ if ($format == 'auto') {
+ if (is_numeric($value)) {
+ $format = 'integer';
+ }
+ elseif (($value == 'TRUE') || ($value == 'FALSE')) {
+ $format = 'bool';
+ }
+ }
+
+ // Now, we parse the object.
+ switch ($format) {
+ case 'integer':
+ $value = (integer)$value;
+ break;
+
+ case 'bool':
+ case 'boolean':
+ if ($value == 'TRUE') {
+ $value = TRUE;
+ }
+ elseif ($value == 'FALSE') {
+ $value = FALSE;
+ }
+ else {
+ $value = (bool)$value;
+ }
+ break;
+
+ case 'json':
+ $value = drush_json_decode($value);
+ break;
+ }
+ return $value;
+}
+
+/**
+ * Command callback.
+ * Delete a variable.
+ * @param $arg_name
+ *
+ * @return string
+ */
+function drush_apachesolr_solr_variable_delete($arg_name) {
+
+ $env_id = drush_get_option('id', apachesolr_default_environment());
+ // Look for similar variable names.
+ try {
+ $found = _apachesolr_drush_variable_like($env_id, $arg_name, TRUE);
+ }
+ catch (Exception $e) {
+ return drush_set_error('APACHESOLR_ENV_ID_ERROR', $e->getMessage());
+ }
+ drush_log(dt('Using environment ID "!env_id"', array('!env_id' => $env_id)), 'success');
+ $options = array_keys($found);
+
+ if (drush_get_option('exact', FALSE)) {
+ $options = isset($found[$arg_name]) ? array($arg_name) : array();
+ }
+
+ if (empty($options)) {
+ drush_print(dt('!name not found.', array('!name' => $arg_name)));
+ return '';
+ }
+
+ $name = NULL;
+ if ((count($options) == 1) && drush_get_context('DRUSH_AFFIRMATIVE')) {
+ $name = $arg_name;
+ }
+ else {
+ $choice = drush_choice($options, 'Enter a number to choose which variable to delete.');
+ if ($choice !== FALSE) {
+ $name = $options[$choice];
+ }
+ }
+ if ($name) {
+ drush_op('apachesolr_environment_variable_del', $env_id, $name);
+ drush_log(dt('!choice was deleted.', array('!choice' => $name)), 'success');
+ }
+}
+
+/**
+ * Load an environment from an id and validate the result.
+ *
+ * @param string $env_id
+ *
+ * @return array $environment
+ * @throws Exception
+ */
+function _apachesolr_drush_environment_load_and_validate($env_id) {
+ $environment = apachesolr_environment_load($env_id);
+ if (!$environment) {
+ throw new Exception(dt('!env_id is not a valid environment ID.', array('!env_id' => $env_id)));
+ }
+ drush_log(dt('Using environment ID: "!env_id"', array('!env_id' => $env_id)), 'success');
+ return $environment;
+}
+
+/**
+ * Search for similar variable names.
+ *
+ * @param string $env_id
+ * @param string $arg
+ * @param bool|string $starts_with
+ *
+ * @throws Exception
+ *
+ * @return array $variable
+ * Only return it if found
+ */
+function _apachesolr_drush_variable_like($env_id, $arg = NULL, $starts_with = FALSE) {
+ $found = array();
+ $environment = _apachesolr_drush_environment_load_and_validate($env_id);
+ if (!isset($arg)) {
+ return $environment['conf'];
+ }
+ if ($starts_with) {
+ $pattern = "/^{$arg}/i";
+ }
+ else {
+ $pattern = "/{$arg}/i";
+ }
+ foreach ($environment['conf'] as $name => $value) {
+ // Find all variable that start with $arg.
+ if (preg_match($pattern, $name)) {
+ $found[$name] = $value;
+ }
+ }
+ return $found;
+}
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/plugins/facetapi/adapter.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/plugins/facetapi/adapter.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,151 @@
+getSearcher(), '@'), '@');
+ $path .= '/' . $env_id . '/facets';
+ // Add the realm name to the path if it is not the first one in the list.
+ if (key(facetapi_get_realm_info()) != $realm_name) {
+ $path .= '/' . $realm_name;
+ }
+ }
+ return $path;
+ }
+
+ /**
+ * Allows the backend to initialize its query object before adding the facet
+ * filters.
+ *
+ * @param mixed $query
+ * The backend's native object.
+ */
+ function initActiveFilters($query) {
+ $enabled_facets = facetapi_get_enabled_facets($this->info['name']);
+ if ($enabled_facets) {
+ $query->addParam('facet', 'true');
+ $query->addParam('facet.sort', 'count');
+ $query->addParam('facet.mincount', '1');
+ }
+ }
+
+ /**
+ * Returns a boolean flagging whether $this->_searcher executed a search.
+ */
+ public function searchExecuted() {
+ // Initial check - has ANY solr query run in our environment.
+ $env_id = $this->info['instance'];
+ $this_has_searched = apachesolr_has_searched($env_id);
+ // Secondary check - do we have results for this searcher?
+ $this_has_searched = $this_has_searched && apachesolr_static_response_cache($this->getSearcher());
+ return $this_has_searched;
+ }
+
+ /**
+ * Suppress output of the realm
+ *
+ * @param string $realm_name
+ *
+ * @return bool $flag
+ * Returns if it was suppressed or not
+ */
+ public function suppressOutput($realm_name) {
+ $flag = FALSE;
+ if ($realm_name == 'block') {
+ $env_id = $this->info['instance'];
+ $flag = apachesolr_suppress_blocks($env_id);
+ }
+ return $flag || !$this->searchExecuted();
+ }
+
+ /**
+ * Returns the search keys.
+ *
+ * @return string
+ */
+ public function getSearchKeys() {
+ if (NULL === $this->keys) {
+ $env_id = $this->info['instance'];
+ if ($query = apachesolr_current_query($env_id)) {
+ return $query->getParam('q');
+ }
+ }
+ else {
+ return $this->keys;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the search path.
+ *
+ * @return string
+ * A string containing the search path.
+ *
+ * @todo D8 should provide an API function for this.
+ */
+ public function getSearchPath() {
+ $env_id = $this->info['instance'];
+ $query = apachesolr_current_query($env_id);
+ if (!$query || (NULL === $this->searchPath && NULL === $query->getPath())) {
+ if ($path = module_invoke($this->info['module'] . '_search', 'search_info')) {
+ $this->searchPath = 'search/' . $path['path'];
+ if (!isset($_GET['keys']) && ($keys = $this->getSearchKeys())) {
+ $this->searchPath .= '/' . $keys;
+ }
+ }
+ }
+ if (!$query || NULL === $query->getPath()) {
+ return $this->searchPath;
+ }
+ else {
+ return $query->getPath();
+ }
+
+ }
+
+ /**
+ * Returns the number of total results found for the current search.
+ *
+ * @return bool|int
+ * Number of results or false if no search response was found
+ */
+ public function getResultCount() {
+ $response = apachesolr_static_response_cache($this->getSearcher());
+ if ($response) {
+ return $response->response->numFound;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Allows for backend specific overrides to the settings form.
+ *
+ * @param array $form
+ * @param array $form_state
+ */
+ public function settingsForm(&$form, &$form_state) {
+ $form['#validate'][] = 'apachesolr_facet_form_validate';
+ }
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_date.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_date.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,185 @@
+getDateRange($query);
+ if (empty($date_range)) {
+ return NULL;
+ }
+ list($start, $end, $gap) = $date_range;
+ $query->addParam('facet.date', $this->facet['field']);
+ $query->addParam('f.' . $this->facet['field'] . '.facet.date.start', $start);
+ $query->addParam('f.' . $this->facet['field'] . '.facet.date.end', $end);
+ $query->addParam('f.' . $this->facet['field'] . '.facet.date.gap', $gap);
+
+ // Adds "hard limit" parameter to prevent too many return values.
+ $settings = $this->adapter->getFacet($this->facet)->getSettings();
+ $limit = empty($settings->settings['hard_limit']) ? 20 : (int) $settings->settings['hard_limit'];
+ $query->addParam('f.' . $this->facet['field'] . '.facet.limit', $limit);
+
+ $active = $this->adapter->getActiveItems($this->facet);
+ // Date filters don't support OR operator.
+ foreach ($active as $value => $item) {
+ $query->addFilter($this->facet['field'], $value);
+ }
+ }
+
+ /**
+ * Gets the range of dates we are using.
+ *
+ * @param DrupalSolrQueryInterface $query
+ * A SolrBaseQuery object.
+ *
+ * @return bool|array
+ * An array containing the gap and range information or false if not present
+ */
+ function getDateRange(DrupalSolrQueryInterface $query) {
+ $return = NULL;
+ $gap = NULL;
+
+ // Attempts to get next gap from passed date filters.
+ foreach ($this->adapter->getActiveItems($this->facet) as $item) {
+ if ($gap = facetapi_get_date_gap($item['start'], $item['end'])) {
+ $next_gap = facetapi_get_next_date_gap($gap, FACETAPI_DATE_SECOND);
+ if ($next_gap == $gap) {
+ $next_gap = NULL;
+ return NULL;
+ }
+ $return = array(
+ "{$item['start']}/$next_gap",
+ "{$item['end']}+1$next_gap/$next_gap",
+ "+1$next_gap",
+ );
+ }
+ }
+
+ // If no filters were passed, get default range.
+ if (NULL === $return) {
+
+ // Builds SQL that gets minimum and maximum values from node table.
+ $minimum = $maximum = FALSE;
+ if ($this->facet['min callback'] && is_callable($this->facet['min callback'])) {
+ $minimum = $this->facet['min callback']($this->facet);
+ }
+ if ($this->facet['max callback'] && is_callable($this->facet['max callback'])) {
+ $maximum = $this->facet['max callback']($this->facet);
+ }
+
+ // Gets the default gap.
+ //$gap = FACETAPI_DATE_YEAR;
+ if ($minimum && $maximum) {
+ $gap = facetapi_get_timestamp_gap($minimum, $maximum);
+ $minimum = facetapi_isodate($minimum, $gap);
+ $maximum = facetapi_isodate($maximum, $gap);
+ $return = array(
+ "$minimum/$gap",
+ "$maximum+1$gap/$gap",
+ "+1$gap",
+ );
+ }
+ }
+ // Returns the range information.
+ return $return;
+ }
+
+ /**
+ * Initializes the facet's build array.
+ *
+ * @return array
+ * The initialized render array.
+ */
+ public function build() {
+
+ // Initializes build and gets static response.
+ if (!$response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
+ return array();
+ }
+ $build = array();
+
+ // Gets total number of documents matched in search.
+ $total = $response->response->numFound;
+
+ // Gets the active date facets, starts to builds the "parent - child"
+ // relationships.
+ $parent = NULL;
+ foreach ($this->adapter->getActiveItems($this->facet) as $value => $item) {
+ // Builds the raw facet "value", the count for selected items will be the
+ // total number of rows returned in the query.
+ $build[$value] = array('#count' => $total);
+
+ // If there is a previous item, there is a parent, uses a reference so the
+ // arrays are populated when they are updated.
+ if (NULL !== $parent) {
+ $build[$parent]['#item_children'][$value] = &$build[$value];
+ $build[$value]['#item_parents'][$parent] = $parent;
+ }
+
+ // Stores the last value iterated over.
+ $parent = $value;
+ }
+
+ // Gets raw facet data from the Solr server.
+ if (isset($response->facet_counts->facet_dates) && isset($response->facet_counts->facet_dates->{$this->facet['field']})) {
+ $raw_data = (array) $response->facet_counts->facet_dates->{$this->facet['field']};
+ }
+ else {
+ $raw_data = array();
+ }
+ //$end = (!empty($raw_data['end'])) ? $raw_data['end'] : '';
+ //$start = (!empty($raw_data['start'])) ? $raw_data['start'] : '';
+ $gap = (!empty($raw_data['gap'])) ? $raw_data['gap'] : '';
+
+ // We cannot list anything below a minute (range of 00 seconds till 59
+ // seconds. Milliseconds are not possible)
+ if ($gap != "+1SECOND") {
+ unset($raw_data['start']);
+ unset($raw_data['end']);
+ unset($raw_data['gap']);
+
+ // Treat each date facet as a range start, and use the next date facet
+ // as range end. Use 'end' for the final end.
+ $previous = NULL;
+
+ // Builds facet counts object used by the server.
+ foreach ($raw_data as $value => $count) {
+ if ($count) {
+ $from = $value;
+ $to = facetapi_isodate(strtotime($value . $gap));
+ $new_value = '[' . $from . ' TO ' . $to . ']';
+ $build[$new_value] = array('#count' => $count, '#active' => 0);
+ if (NULL !== $parent) {
+ $build[$parent]['#item_children'][$new_value] = &$build[$new_value];
+ $build[$new_value]['#item_parents'][$parent] = $parent;
+ }
+ }
+ }
+ }
+ return $build;
+ }
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_geo.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_geo.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,84 @@
+adapter->getFacet($this->facet)->getSettings();
+
+ $facet_distances = explode(',', $this->facet_options);
+
+ $active_items = $this->adapter->getActiveItems($this->facet);
+
+ if (empty($active_items)) {
+ $distance = $this->default_radius;
+ }
+ else {
+ $active_item = array_pop($active_items);
+ $distance = substr($active_item['value'], 1);
+ // Add current selected distance to have possibility to unselect it.
+ $facet_distances[] = 1;
+ }
+
+ // Search center point.
+ $query->addParam('pt', $this->center_point);
+
+ // Set location field name.
+ $query->addParam('sfield', $this->facet['field']);
+ $query->addParam('fq', '{!geofilt sfield=' . $this->facet['field'] . '}');
+
+ // Set search radius.
+ $query->addParam('d', $distance);
+
+ // Set facets.
+ foreach ($facet_distances as $facet_option) {
+ $facet_distance = $distance * $facet_option;
+ $query->addParam('facet.query', '{!geofilt d=' . $facet_distance . ' key=d' . $facet_distance . '}');
+ }
+ }
+
+ /**
+ * Initializes the facet's build array.
+ *
+ * @return array
+ * The initialized render array.
+ */
+ public function build() {
+ $build = array();
+ if ($response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
+ if (isset($response->facet_counts->facet_queries)) {
+ foreach ($response->facet_counts->facet_queries as $value => $count) {
+ // Skip zero results values.
+ if ($count > 0) {
+ $build[$value] = array('#count' => $count);
+ }
+ }
+ }
+ }
+ return $build;
+ }
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_numeric_range.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_numeric_range.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,101 @@
+adapter->getFacet($this->facet)->getSettings();
+ $active = $this->adapter->getActiveItems($this->facet);
+
+ $singular_field_info = $this->facet['map options'];
+ $singular_field_info['multiple'] = FALSE;
+ $this->single_key = apachesolr_index_key($singular_field_info);
+ // See: http://wiki.apache.org/solr/StatsComponent
+ $query->addParam('stats', 'true');
+ $query->addParam('stats.field', $this->single_key);
+ $query->addParam('stats.facet', $this->single_key);
+ // Range filters don't support OR operator.
+ foreach ($active as $value => $item) {
+ $query->addFilter($this->single_key, $value);
+ }
+ }
+
+ /**
+ * Initializes the facet's build array.
+ *
+ * Any calls to this method need to be wrapped in a try-catch block.
+ *
+ * @return array
+ * The initialized render array.
+ */
+ public function build() {
+ $build = array();
+ if (!isset($this->single_key)) {
+ return $build;
+ }
+
+ // Per key we save our statistics result
+ $cache = cache_get('stats_' . $this->single_key, 'cache_apachesolr');
+ $stats_minmax = array();
+
+ if (!isset($cache->data)) {
+ // we need an additional query for the statistics of the field
+ // We can optionally specify a Solr object.
+ $solr = apachesolr_get_solr();
+
+ // We possibly need some caching for this query
+ $query_stats = apachesolr_drupal_query('apachesolr_stats', array(), '', '', $solr);
+ $query_stats->addParam('stats', 'true');
+ $query_stats->addParam('stats.field', $this->single_key);
+ $query_stats->addParam('stats.facet', $this->single_key);
+ $response_stats = $query_stats->search();
+
+ if ($response_stats->response) {
+ $stats_minmax = $response_stats->stats->stats_fields->{$this->single_key};
+ cache_set('stats_' . $this->single_key, $stats_minmax, 'cache_apachesolr');
+ }
+ }
+ else {
+ // Set our statistics from the cache
+ $stats_minmax = $cache->data;
+ }
+
+ if ($response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
+ if (isset($response->stats->stats_fields->{$this->single_key})) {
+ $stats = (array) $response->stats->stats_fields->{$this->single_key};
+ foreach ($stats as $key => $val) {
+ $build[$this->facet['field']]['#range_' . $key] = $val;
+ $build[$this->facet['field']]['#global_range_' . $key] = $stats_minmax->$key;
+ }
+ }
+ }
+ return $build;
+ }
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_term.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/plugins/facetapi/query_type_term.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,101 @@
+adapter->getFacet($this->facet)->getSettings();
+ // Adds the operator parameter.
+ $operator = $settings->settings['operator'];
+ $ex = (FACETAPI_OPERATOR_OR != $operator) ? '' : "{!ex={$this->facet['field']}}";
+ $query->addParam('facet.field', $ex . $this->facet['field']);
+
+ if (!empty($settings->settings['facet_missing'])) {
+ $query->addParam('f.' . $this->facet['field'] . '.facet.missing', 'true');
+ }
+ // Adds "hard limit" parameter to prevent too many return values.
+ $limit = empty($settings->settings['hard_limit']) ? 20 : (int) $settings->settings['hard_limit'];
+ $query->addParam('f.' . $this->facet['field'] . '.facet.limit', $limit);
+
+ // Adds "facet mincount" parameter to limit the number of facets.
+ if (isset($settings->settings['facet_mincount'])) {
+ $count = $settings->settings['facet_mincount'];
+ $query->addParam('f.' . $this->facet['field'] . '.facet.mincount', $count);
+ }
+
+ $active = $this->adapter->getActiveItems($this->facet);
+
+ // Adds filter based on the operator.
+ if (FACETAPI_OPERATOR_OR != $operator) {
+ foreach ($active as $value => $item) {
+ // Handle facet missing:
+ if ($value == '_empty_' && !empty($settings->settings['facet_missing'])) {
+ $query->addFilter($this->facet['field'], '[* TO *]', TRUE);
+ }
+ else {
+ $query->addFilter($this->facet['field'], $value);
+ }
+ }
+ }
+ else {
+ // OR facet.
+ $local = "tag={$this->facet['field']}";
+ $values = array_keys($active);
+ if ($values) {
+ // Quote any values that have white space or colons.
+ foreach ($values as &$v) {
+ if (preg_match('/[:\s]/', $v)) {
+ $v = '"' . $v . '"';
+ }
+ }
+ $query->addFilter($this->facet['field'], '(' . implode(' OR ', $values) . ')', FALSE, $local);
+ }
+ }
+ }
+
+ /**
+ * Initializes the facet's build array.
+ *
+ * @return array
+ * The initialized render array.
+ */
+ public function build() {
+ $build = array();
+ if ($response = apachesolr_static_response_cache($this->adapter->getSearcher())) {
+ $settings = $this->adapter->getFacet($this->facet)->getSettings();
+ if (isset($response->facet_counts->facet_fields->{$this->facet['field']})) {
+ $values = (array) $response->facet_counts->facet_fields->{$this->facet['field']};
+ foreach ($values as $value => $count) {
+ // Facet missing may return 0 even if mincount is 1.
+ if (empty($settings->settings['facet_mincount']) || $count) {
+ $build[$value] = array('#count' => $count);
+ }
+ }
+ }
+ }
+ return $build;
+ }
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-1.4/protwords.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-1.4/protwords.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,8 @@
+#-----------------------------------------------------------------------
+# This file blocks words from being operated on by the stemmer and word delimiter.
+&
+<
+>
+'
+"
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-1.4/schema.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-1.4/schema.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,497 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+ content
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-1.4/solrconfig.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-1.4/solrconfig.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,736 @@
+
+
+
+
+
+ ${solr.abortOnConfigurationError:true}
+
+
+
+
+
+
+ false
+
+ 10
+
+
+
+ 32
+ 2147483647
+ 20000
+ 1000
+ 10000
+
+
+
+
+
+
+
+
+
+
+ single
+
+
+
+
+ false
+ 32
+ 4
+ 2147483647
+ 20000
+
+
+ false
+
+
+
+
+ false
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2000
+ 120000
+
+
+
+
+
+
+
+
+
+
+
+
+ 1024
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ 50
+
+
+ 200
+
+
+
+
+
+
+
+
+ solr010
+ rocks010
+ static newSearcher warming query from solrconfig.xml
+
+
+
+
+
+
+ fast_warm010
+ static firstSearcher warming query from solrconfig.xml
+
+
+
+
+ false
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ explicit
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ dismax
+ explicit
+ true
+
+
+
+
+
+
+ dismax
+ explicit
+ true
+ 0.01
+
+ content^2.0
+
+ 15
+
+
+ 1
+ *:*
+
+
+ true
+ content
+ 3
+ true
+
+ teaser
+ 256
+
+
+
+
+ false
+
+ true
+ false
+
+ 1
+
+
+ spellcheck
+
+
+
+
+
+
+ 1
+ 1
+ 3
+ 15
+ 20
+ false
+
+
+
+
+
+
+
+
+
+
+
+ textSpell
+
+
+ default
+ spell
+ ./spellchecker1
+ true
+
+
+ jarowinkler
+ spell
+
+ org.apache.lucene.search.spell.JaroWinklerDistance
+ ./spellchecker2
+ true
+
+
+
+
+
+
+
+
+
+ string
+ elevate.xml
+
+
+
+
+
+ explicit
+
+
+ elevator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ standard
+ solrpingquery
+ all
+
+
+
+
+
+
+ admin-extra.html
+ scripts.conf
+ xslt/example.xsl
+ xslt/example_atom.xsl
+ xslt/example_rss.xsl
+ xslt/luke.xsl
+
+
+
+
+
+
+ explicit
+ true
+
+
+
+
+
+
+
+
+ 100
+
+
+
+
+
+
+
+ 70
+
+ 0.5
+
+ [-\w ,/\n\"']{20,200}
+
+
+
+
+
+
+ ]]>
+ ]]>
+
+
+
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+ solr
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/protwords.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/protwords.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,8 @@
+#-----------------------------------------------------------------------
+# This file blocks words from being operated on by the stemmer and word delimiter.
+&
+<
+>
+'
+"
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/schema.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/schema.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,546 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+ content
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/schema_extra_fields.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/schema_extra_fields.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,23 @@
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/schema_extra_types.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/schema_extra_types.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,30 @@
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/solrconfig.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/solrconfig.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,1583 @@
+
+
+
+
+
+
+
+
+ ${solr.abortOnConfigurationError:true}
+
+
+ ${luceneVersion:LUCENE_35}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+ 4
+
+ 32
+
+
+
+ 2147483647
+ 100000
+ 1000
+
+
+
+
+
+
+
+
+ single
+
+
+
+
+
+
+
+
+ false
+ 32
+ 10
+
+
+ false
+
+
+ true
+
+
+
+
+ 1
+
+ 0
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10000
+ 120000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1024
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ 20
+
+
+ 200
+
+
+
+
+
+
+
+
+
+
+
+ solr rocks010
+
+
+
+
+
+ false
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edismax
+ explicit
+ true
+ 0.01
+
+ ${pinkPony.timeAllowed:-1}
+ *:*
+
+
+ false
+
+ true
+ false
+
+ 1
+
+
+ spellcheck
+
+
+
+
+
+
+ 1
+ 1
+ 3
+ 15
+ 20
+ false
+
+ ${mlt.timeAllowed:2000}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text
+ true
+ ignored_
+
+
+ true
+ links
+ ignored_
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pinkPony
+ solrpingquery
+
+
+ all
+
+
+
+
+
+
+ explicit
+ true
+
+
+
+
+
+
+ ${enable.master:false}
+ commit
+ startup
+ ${confFiles}
+
+
+ ${enable.slave:false}
+ ${masterCoreUrl}/replication
+ ${pollTime:00:00:60}
+
+
+
+
+
+
+
+
+ false
+ false
+ 1
+
+
+ spellcheck
+
+
+
+
+
+
+
+
+
+ true
+
+
+ tvComponent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ terms
+
+
+
+
+
+
+
+ string
+ elevate.xml
+
+
+
+
+
+ explicit
+
+
+ elevator
+
+
+
+
+
+
+
+
+
+
+ 100
+
+
+
+
+
+
+
+ 70
+
+ 0.5
+
+ [-\w ,/\n\"']{20,200}
+
+
+
+
+
+
+ ]]>
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,,
+ ,,
+ ,,
+ ,,
+ ,]]>
+ ]]>
+
+
+
+
+
+ 10
+ .,!?
+
+
+
+
+
+
+ WORD
+
+
+ en
+ US
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/plain; charset=UTF-8
+
+
+
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+
+
+ *:*
+
+
+
+
+
+
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/solrconfig_extra.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/solrconfig_extra.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,79 @@
+
+
+
+textSpell
+
+
+
+
+
+ default
+ content
+ spellchecker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/solrcore.properties
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-3.x/solrcore.properties Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,10 @@
+#solrcore.properties for this specific core
+enable.master=false
+enable.slave=false
+pollTime=00:00:60
+masterCoreUrl=http://localhost:8983/solr
+confFiles=schema.xml,mapping-ISOLatin1Accent.txt,protwords.txt,stopwords.txt,synonyms.txt,elevate.xml
+mlt.timeAllowed=2000
+# You should not set your luceneVersion to anything lower then your Solr Version
+luceneVersion=LUCENE_35
+pinkPony.timeAllowed=-1
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/protwords.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/protwords.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,8 @@
+#-----------------------------------------------------------------------
+# This file blocks words from being operated on by the stemmer and word delimiter.
+&
+<
+>
+'
+"
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/schema.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/schema.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,547 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+
+
+ content
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/schema_extra_fields.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/schema_extra_fields.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,23 @@
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/schema_extra_types.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/schema_extra_types.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,30 @@
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/solrconfig.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/solrconfig.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,1575 @@
+
+
+
+
+
+
+
+
+ ${solr.abortOnConfigurationError:true}
+
+
+ ${luceneVersion:LUCENE_35}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+ 4
+
+ 32
+
+
+
+ 2147483647
+ 100000
+ 1000
+
+
+
+
+
+
+
+
+ single
+
+
+
+
+ false
+ 32
+ 10
+
+
+ false
+
+
+ true
+
+
+
+
+ 1
+
+ 0
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10000
+ 120000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1024
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ 20
+
+
+ 200
+
+
+
+
+
+
+
+
+
+
+
+ solr rocks010
+
+
+
+
+
+ false
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edismax
+ explicit
+ true
+ 0.01
+
+ ${pinkPony.timeAllowed:-1}
+ *:*
+
+
+ false
+
+ true
+ false
+
+ 1
+
+
+ spellcheck
+
+
+
+
+
+
+ 1
+ 1
+ 3
+ 15
+ 20
+ false
+
+ ${mlt.timeAllowed:2000}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text
+ true
+ ignored_
+
+
+ true
+ links
+ ignored_
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pinkPony
+ solrpingquery
+
+
+ all
+
+
+
+
+
+
+ explicit
+ true
+
+
+
+
+
+
+ ${enable.master:false}
+ commit
+ startup
+ ${confFiles}
+
+
+ ${enable.slave:false}
+ ${masterCoreUrl}/replication
+ ${pollTime:00:00:60}
+
+
+
+
+
+
+
+
+ false
+ false
+ 1
+
+
+ spellcheck
+
+
+
+
+
+
+
+
+
+ true
+
+
+ tvComponent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ terms
+
+
+
+
+
+
+
+ string
+ elevate.xml
+
+
+
+
+
+ explicit
+
+
+ elevator
+
+
+
+
+
+
+
+
+
+
+ 100
+
+
+
+
+
+
+
+ 70
+
+ 0.5
+
+ [-\w ,/\n\"']{20,200}
+
+
+
+
+
+
+ ]]>
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,,
+ ,,
+ ,,
+ ,,
+ ,]]>
+ ]]>
+
+
+
+
+
+ 10
+ .,!?
+
+
+
+
+
+
+ WORD
+
+
+ en
+ US
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/plain; charset=UTF-8
+
+
+
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+
+
+ *:*
+
+
+
+
+
+
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/solrconfig_extra.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/solrconfig_extra.xml Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,79 @@
+
+
+
+textSpell
+
+
+
+
+
+ default
+ content
+ spellchecker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/solrcore.properties
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/solr-conf/solr-4.x/solrcore.properties Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,10 @@
+#solrcore.properties for this specific core
+enable.master=false
+enable.slave=false
+pollTime=00:00:60
+masterCoreUrl=http://localhost:8983/solr
+confFiles=schema.xml,mapping-ISOLatin1Accent.txt,protwords.txt,stopwords.txt,synonyms.txt,elevate.xml
+mlt.timeAllowed=2000
+# You should not set your luceneVersion to anything lower then your Solr Version
+luceneVersion=LUCENE_40
+pinkPony.timeAllowed=-1
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/task-check.png
Binary file sites/all/modules/custom/solrconnect/task-check.png has changed
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/tests/Dummy_Solr.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/tests/Dummy_Solr.php Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,474 @@
+
+ (object) array(
+ 'type' => 'long',
+ 'schema' => 'I-S----OF-----',
+ ),
+ 'content' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => 'ITS-V---------',
+ ),
+ 'im_3_field_tags' =>
+ (object) array(
+ 'type' => 'long',
+ 'schema' => 'I-SM---OF-----',
+ 'dynamicBase' => 'im_*',
+ ),
+ 'entity_type' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'ds_last_comment_or_change' =>
+ (object) array(
+ 'type' => 'tdate',
+ 'schema' => 'ITS----OF-----',
+ ),
+ 'nodeaccess_ari4jj_node_access_example_view' =>
+ (object) array(
+ 'type' => 'integer',
+ 'schema' => 'I--M---OF-----',
+ 'dynamicBase' => 'nodeaccess*',
+ ),
+ 'entity_id' =>
+ (object) array(
+ 'type' => 'tlong',
+ 'schema' => 'ITS----OF-----',
+ ),
+ 'ds_changed' =>
+ (object) array(
+ 'type' => 'tdate',
+ 'schema' => 'ITS----OF-----',
+ ),
+ 'id' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'timestamp' =>
+ (object) array(
+ 'type' => 'date',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'label' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => 'ITS-V--O------',
+ ),
+ 'nodeaccess_ari4jj_node_access_example_edit' =>
+ (object) array(
+ 'type' => 'integer',
+ 'schema' => 'I--M---OF-----',
+ 'dynamicBase' => 'nodeaccess*',
+ ),
+ 'ds_created' =>
+ (object) array(
+ 'type' => 'tdate',
+ 'schema' => 'ITS----OF-----',
+ ),
+ 'ss_name' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => 'ITS-V---------',
+ ),
+ 'path' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'taxonomy_names' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => 'IT-MV--O------',
+ ),
+ 'bundle' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'tid' =>
+ (object) array(
+ 'type' => 'long',
+ 'schema' => 'I-SM---OF-----',
+ ),
+ 'is_tnid' =>
+ (object) array(
+ 'type' => 'long',
+ 'schema' => 'I-S----OF-----',
+ ),
+ 'nodeaccess_ari4jj_node_access_example_author' =>
+ (object) array(
+ 'type' => 'integer',
+ 'schema' => 'I--M---OF-----',
+ 'dynamicBase' => 'nodeaccess*',
+ ),
+ 'tm_vid_1_names' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => 'ITSMV---------',
+ 'dynamicBase' => 'tm_*',
+ ),
+ 'spell' =>
+ (object) array(
+ 'type' => 'textSpell',
+ 'schema' => 'ITSM----------',
+ ),
+ 'site' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'is_comment_count' =>
+ (object) array(
+ 'type' => 'tint',
+ 'schema' => 'ITS----OF-----',
+ ),
+ 'bundle_name' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'hash' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'bs_status' =>
+ (object) array(
+ 'type' => 'boolean',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'entity_id' =>
+ (object) array(
+ 'type' => 'long',
+ 'schema' => 'I-S----OF-----',
+ ),
+ 'url' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'nodeaccess_all' =>
+ (object) array(
+ 'type' => 'integer',
+ 'schema' => 'I--M---OF-----',
+ 'dynamicBase' => 'nodeaccess*',
+ ),
+ 'sort_name' =>
+ (object) array(
+ 'type' => 'sortString',
+ 'schema' => 'IT-----O-----l',
+ ),
+ 'tags_a' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => 'IT-----O------',
+ 'dynamicBase' => 'tags_*',
+ ),
+ 'bs_sticky' =>
+ (object) array(
+ 'type' => 'boolean',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'bs_promote' =>
+ (object) array(
+ 'type' => 'boolean',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'teaser' =>
+ (object) array(
+ 'type' => 'text',
+ 'schema' => '-TS-----------',
+ ),
+ 'im_vid_1' =>
+ (object) array(
+ 'type' => 'long',
+ 'schema' => 'I-SM---OF-----',
+ 'dynamicBase' => 'im_*',
+ ),
+ 'bs_translate' =>
+ (object) array(
+ 'type' => 'boolean',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'sort_label' =>
+ (object) array(
+ 'type' => 'sortString',
+ 'schema' => 'IT-----O-----l',
+ ),
+ 'ss_language' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-S----OF----l',
+ ),
+ 'sm_vid_Tags' =>
+ (object) array(
+ 'type' => 'string',
+ 'schema' => 'I-SM---OF----l',
+ 'dynamicBase' => 'sm_*',
+ ),
+ );
+ }
+
+ protected $last_search = array();
+
+ public function search($query = '', array $params = array(), $method = 'GET') {
+ $this->last_search = array('query' => $query, 'params' => $params, 'method' => $method);
+ $response = new stdClass();
+ $response->response = new stdClass();
+ $response->response->numFound = 0;
+ $response->response->docs = array();
+
+ return $response;
+ }
+
+ public function getLastSearch() {
+ return $this->last_search;
+ }
+
+ /**
+ * Call the /admin/ping servlet, to test the connection to the server.
+ *
+ * @param $timeout
+ * maximum time to wait for ping in seconds, -1 for unlimited (default 2).
+ * @return
+ * (float) seconds taken to ping the server, FALSE if timeout occurs.
+ */
+ function ping($timeout = 2) {
+ }
+
+ /**
+ * Get information about the Solr Core.
+ *
+ * @return
+ * (string) system info encoded in json
+ */
+ function getSystemInfo() {
+ }
+
+ /**
+ * Get meta-data about the index.
+ */
+ function getLuke($num_terms = 0) {
+ }
+
+ /**
+ * Get information about the Solr Core.
+ *
+ * Returns a Simple XMl document
+ */
+ function getStats() {
+ }
+
+ /**
+ * Get summary information about the Solr Core.
+ */
+ function getStatsSummary() {
+ }
+
+ /**
+ * Clear cached Solr data.
+ */
+ function clearCache() {
+ }
+
+ /**
+ * Constructor
+ *
+ * @param $url
+ * The URL to the Solr server, possibly including a core name. E.g. http://localhost:8983/solr/
+ * or https://search.example.com/solr/core99/
+ * @param $env_id
+ * The machine name of a corresponding saved configuration used for loading
+ * data like which facets are enabled.
+ */
+ function __construct($url, $env_id = NULL) {
+ }
+
+ /**
+ * Make a request to a servlet (a path) that's not a standard path.
+ *
+ * @param string $servlet
+ * A path to be added to the base Solr path. e.g. 'extract/tika'
+ *
+ * @param array $params
+ * Any request parameters when constructing the URL.
+ *
+ * @param array $options
+ * @see drupal_http_request() $options.
+ *
+ * @return
+ * response object
+ *
+ * @thows Exception
+ */
+ function makeServletRequest($servlet, $params = array(), $options = array()) {
+ }
+
+ /**
+ * Get the Solr url
+ *
+ * @return string
+ */
+ function getUrl() {
+ }
+
+ /**
+ * Set the Solr url.
+ *
+ * @param $url
+ *
+ * @return $this
+ */
+ function setUrl($url) {
+ }
+
+ /**
+ * Raw update Method. Takes a raw post body and sends it to the update service. Post body
+ * should be a complete and well formed xml document.
+ *
+ * @param string $rawPost
+ * @param float $timeout Maximum expected duration (in seconds)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function update($rawPost, $timeout = FALSE) {
+ }
+
+ /**
+ * Add an array of Solr Documents to the index all at once
+ *
+ * @param array $documents Should be an array of ApacheSolrDocument instances
+ * @param boolean $allowDups
+ * @param boolean $overwritePending
+ * @param boolean $overwriteCommitted
+ *
+ * @return response objecte
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function addDocuments($documents, $overwrite = NULL, $commitWithin = NULL) {
+ }
+
+ /**
+ * Send a commit command. Will be synchronous unless both wait parameters are set to false.
+ *
+ * @param boolean $optimize Defaults to true
+ * @param boolean $waitFlush Defaults to true
+ * @param boolean $waitSearcher Defaults to true
+ * @param float $timeout Maximum expected duration (in seconds) of the commit operation on the server (otherwise, will throw a communication exception). Defaults to 1 hour
+ * @param boolean $softCommit optimize by using a softCommit
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function commit($optimize = TRUE, $waitFlush = TRUE, $waitSearcher = TRUE, $timeout = 3600, $softCommit = FALSE) {
+ }
+
+ /**
+ * Create a delete document based on document ID
+ *
+ * @param string $id Expected to be utf-8 encoded
+ * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function deleteById($id, $timeout = 3600) {
+ }
+
+ /**
+ * Create and post a delete document based on multiple document IDs.
+ *
+ * @param array $ids Expected to be utf-8 encoded strings
+ * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function deleteByMultipleIds($ids, $timeout = 3600) {
+ }
+
+ /**
+ * Create a delete document based on a query and submit it
+ *
+ * @param string $rawQuery Expected to be utf-8 encoded
+ * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+ * @return stdClass response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function deleteByQuery($rawQuery, $timeout = 3600) {
+ }
+
+ /**
+ * Send an optimize command. Will be synchronous unless both wait parameters are set
+ * to false.
+ *
+ * @param boolean $waitFlush
+ * @param boolean $waitSearcher
+ * @param float $timeout Maximum expected duration of the commit operation on the server (otherwise, will throw a communication exception)
+ * @param boolean $softCommit optimize by using a softCommit
+ *
+ * @return response object
+ *
+ * @throws Exception If an error occurs during the service call
+ */
+ function optimize($waitFlush = TRUE, $waitSearcher = TRUE, $timeout = 3600, $softCommit = FALSE) {
+ }
+
+ /**
+ * Get the current solr version. This could be 1, 3 or 4
+ *
+ * @return int
+ * 1, 3 or 4. Does not give a more details version, for that you need
+ * to get the system info.
+ */
+ function getSolrVersion() {
+ }
+
+ /**
+ * Get query name.
+ */
+ function getName() {
+ }
+
+ /**
+ * Get query searcher name (for facetapi, views, pages, etc).
+ */
+ function getSearcher() {
+ }
+
+ /**
+ * Get context values.
+ */
+ function getContext() {
+ }
+
+ /**
+ * Set context value.
+ */
+ function addContext(array $context) {
+ }
+}
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrconnect/tests/apachesolr_base.test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrconnect/tests/apachesolr_base.test Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,547 @@
+ $v) {
+ if (!isset($a2[$k])) {
+ debug("\$a2[$k] is not set");
+ return FALSE;
+ }
+ if (is_array($a1[$k]) && is_array($a2[$k])) {
+ if (!$this->_nestedCompare($a1[$k], $a2[$k])) {
+ debug("_nestedCompare(\$a1[$k], \$a2[$k]) is false");
+ return FALSE;
+ }
+ }
+ elseif ($a1[$k] !== $a2[$k]) {
+ debug("\$a1[$k] !== \$a2[$k] : " . var_export($a1[$k], TRUE) . " " . var_export($a2[$k], TRUE));
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+}
+
+/**
+ * @file
+ * Unit test class that provides tests for base functionality of the Apachesolr
+ * Module without having the need of a Solr Server
+ */
+class DrupalSolrOfflineEnvironmentWebTestCase extends DrupalSolrOfflineWebTestCase {
+ /**
+ * A global basic user who can search.
+ */
+ var $basic_user;
+
+ /**
+ * A global administrative user who can administer search.
+ */
+ var $admin_user;
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Solr Search Environments',
+ 'description' => 'Tests search environments functionality of the Solr module',
+ 'group' => 'ApacheSolr',
+ );
+ }
+ /**
+ * Implementation of setUp().
+ */
+ function setUp() {
+ parent::setUp('apachesolr', 'search', 'apachesolr_test');
+ // Create a basic user, which is subject to moderation.
+ $permissions = array(
+ 'access content',
+ 'search content',
+ );
+ $basic_user = $this->drupalCreateUser($permissions);
+
+ // Create an admin user that can bypass revision moderation.
+ $permissions = array(
+ 'access content',
+ 'search content',
+ 'administer nodes',
+ 'administer search',
+ );
+ $admin_user = $this->drupalCreateUser($permissions);
+
+ // Assign users to their test suite-wide properties.
+ $this->basic_user = $basic_user;
+ $this->admin_user = $admin_user;
+ }
+
+ /**
+ * Asserts that the module was installed and that a notice appears that the server is offline
+ */
+ function testServerOffline() {
+ // Load the default server.
+ $env_id = apachesolr_default_environment();
+ $environment = apachesolr_environment_load($env_id);
+ $environment['url'] = 'http://localhost/solr/core_that_should_not_exist';
+ apachesolr_environment_save($environment);
+ $status = apachesolr_server_status($environment['url']);
+ $this->assertFalse($status, t('A false URL could not be loaded and is offline'));
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr');
+ $text = t('The server seems to be unavailable. Please verify the server settings');
+ $this->assertText($text, t('When checking the status of the server it gives the correct message to inform the user that the server is not reachable'));
+ }
+
+ /**
+ * Asserts that the module was installed and that a notice appears that the server is offline
+ */
+ function testIndexFileIncluded() {
+ $env_id = apachesolr_default_environment();
+ $environment = apachesolr_environment_load($env_id);
+ $environment['url'] = 'http://localhost/solr/core_that_should_not_exist';
+ apachesolr_environment_save($environment);
+
+ $paths = array(
+ 'user',
+ 'node',
+ 'admin/config/search/apachesolr',
+ 'admin/config/search/apachesolr/search-pages',
+ 'admin/config/search/apachesolr/search-pages/core_search/edit',
+ 'admin/structure/block/manage/apachesolr_search/mlt-001/configure',
+ 'admin/config/search/apachesolr/settings/solr/bias',
+ 'admin/config/search/apachesolr/settings/solr/index',
+ 'admin/config/search/apachesolr/settings/solr/edit',
+ 'admin/reports/apachesolr',
+ 'admin/reports/apachesolr/conf',
+ 'search/site',
+ );
+ $this->drupalLogin($this->admin_user);
+ foreach ($paths as $path) {
+ $this->drupalGet($path);
+ $text = 'apachesolr.index.inc was included';
+ $this->assertNoText($text, t('Apachesolr.index.inc was not included'));
+ }
+ }
+
+ /**
+ * Asserts that we can edit a search environment
+ */
+ function testEditSearchEnvironment() {
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->clickLink(t('Edit'));
+ $this->assertText(t('Example: http://localhost:8983/solr'), t('Edit page was succesfully loaded'));
+ $edit = array('name' => 'new description foo bar', 'url' => 'http://localhost:8983/solr/core_does_not_exists');
+ $this->drupalPost($this->getUrl(), $edit, t('Save'));
+ $this->assertResponse(200);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText(t('new description foo bar'), t('Search environment description was succesfully edited'));
+ $this->assertText('http://localhost:8983/solr/core_does_not_exists', t('Search environment url was succesfully edited'));
+ }
+
+ /**
+ * Asserts that we can use various url forms for the search environment
+ */
+ function testEditSearchEnvironmentURLs() {
+ // Set the various url schemes that will be tested
+ $urls = array(
+ 'http://user@localhost:8983/solr/core_does_not_exists',
+ 'http://user:pass@localhost:8983/solr/core_does_not_exists',
+ 'http://user:pass@localhost/solr/core_does_not_exists',
+ 'https://localhost:8983/solr/core_does_not_exists'
+ );
+ $this->drupalLogin($this->admin_user);
+ foreach ($urls as $url) {
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->clickLink(t('Edit'));
+ $this->assertText(t('Example: http://localhost:8983/solr'), t('Edit page was succesfully loaded'));
+ $edit = array('url' => $url);
+ $this->drupalPost($this->getUrl(), $edit, t('Save'));
+ $this->assertResponse(200);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText($url, t('Search environment url was succesfully set to !url', array('!url' => $url)));
+ }
+ }
+
+ /**
+ * Asserts that we can clone a search environment
+ */
+ function testCloneSearchEnvironment() {
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText(t('Clone'), t('Clone button is available'));
+ $this->drupalGet('admin/config/search/apachesolr/settings/solr/clone');
+ $this->assertText(t('Are you sure you want to clone search environment localhost server'), t('Clone confirmation page was succesfully loaded'));
+ $this->drupalPost($this->getUrl(), array(), t('Clone'));
+ $this->assertResponse(200);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText(t('localhost server [cloned]'), t('Search Environment was succesfully cloned'));
+ // Check if the bundles and configurations are exactly the same
+ // after we clear the caches.
+ apachesolr_environments_clear_cache();
+ $envs = apachesolr_load_all_environments();
+ $this->assertEqual(count($envs), 2, 'Now we have 2 environments');
+ $orig_env = $envs['solr'];
+ unset($envs['solr']);
+ $cloned_env = array_pop($envs);
+ $this->assertTrue($this->_nestedCompare($orig_env['index_bundles'], $cloned_env['index_bundles']));
+ $this->assertTrue($this->_nestedCompare($orig_env['conf'], $cloned_env['conf']));
+ }
+
+ /**
+ * Asserts that we can edit a search environment
+ */
+ function testCreateNewSearchEnvironment() {
+ // Create a new environment
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText(t('Add search environment'), t('Create new environment link is available'));
+ $this->clickLink(t('Add search environment'));
+ $this->assertText(t('Make this Solr search environment the default'), t('Environment creation page succesfully added'));
+ $edit = array('url' => 'http://localhost:8983/solr', 'name' => 'my test description', 'env_id' => 'solr_test');
+ $this->drupalPost($this->getUrl(), $edit, t('Save'));
+ $this->assertResponse(200);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText(t('my test description'), t('Search Environment was succesfully created'));
+
+ // Make this new search environment the default
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ // Click on the second environment edit link
+ $this->clickLink(t('Edit'), 1);
+ $this->assertText(t('Example: http://localhost:8983/solr'), t('Edit page was succesfully loaded'));
+ $edit = array('make_default' => 1, 'conf[apachesolr_read_only]' => APACHESOLR_READ_ONLY);
+ $this->drupalPost($this->getUrl(), $edit, t('Save'));
+ $this->assertResponse(200);
+ $this->drupalGet('admin/config/search/apachesolr/settings');
+ $this->assertText(t('my test description (Default)'), t('New Search environment was succesfully changed to default environment'));
+ // Clear our cache.
+ apachesolr_environments_clear_cache();
+ $mode = apachesolr_environment_variable_get('solr_test', 'apachesolr_read_only', APACHESOLR_READ_WRITE);
+ $this->assertEqual($mode, APACHESOLR_READ_ONLY, 'Environment succesfully changed to read only');
+ }
+}
+
+/**
+ * @file
+ * Unit test class that provides tests for base functionality of the Apachesolr
+ * Module without having the need of a Solr Server
+ */
+class DrupalSolrOfflineSearchPagesWebTestCase extends DrupalSolrOfflineWebTestCase {
+ /**
+ * A global basic user who can search.
+ */
+ var $basic_user;
+
+ /**
+ * A global administrative user who can administer search.
+ */
+ var $admin_user;
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Solr Search Pages',
+ 'description' => 'Tests search pages functionality of the Solr module',
+ 'group' => 'ApacheSolr',
+ );
+ }
+ /**
+ * Implementation of setUp().
+ */
+ function setUp() {
+ parent::setUp('apachesolr', 'apachesolr_search', 'search', 'apachesolr_test');
+ // Create a basic user, which is subject to moderation.
+ $permissions = array(
+ 'access content',
+ 'search content',
+ );
+ $basic_user = $this->drupalCreateUser($permissions);
+
+ // Create an admin user that can bypass revision moderation.
+ $permissions = array(
+ 'access content',
+ 'search content',
+ 'administer nodes',
+ 'administer search',
+ );
+ $admin_user = $this->drupalCreateUser($permissions);
+
+ // Assign users to their test suite-wide properties.
+ $this->basic_user = $basic_user;
+ $this->admin_user = $admin_user;
+
+ // Make sure our environment does not exists
+ $env_id = apachesolr_default_environment(NULL, TRUE);
+ $environment = apachesolr_environment_load($env_id, TRUE);
+ $environment['url'] = 'http://localhost/solr/core_that_should_not_exist';
+ apachesolr_environment_save($environment);
+ // Reset all caches
+ apachesolr_load_all_environments(TRUE);
+ }
+
+ /**
+ * Asserts that we can edit a search environment
+ */
+ function testCheckCoreSearchPage() {
+ // Create a new environment
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertText(t('Core Search'), t('Core Search page is available'));
+ }
+
+ /**
+ * Asserts that we can edit a search environment
+ */
+ function testEditSearchPage() {
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->clickLink(t('Edit'));
+ $this->assertText(t('The human-readable name of the search page configuration'), t('Edit page was succesfully loaded'));
+ $edit = array(
+ 'label' => 'Test Search Page',
+ 'description' => 'Test Description',
+ 'page_title' => 'Test Title',
+ 'search_path' => 'search/searchdifferentpath',
+ );
+ $this->drupalPost($this->getUrl(), $edit, t('Save'));
+ $this->assertResponse(200);
+ // Make sure the menu is recognized
+ drupal_static_reset('apachesolr_search_load_all_search_pages');
+ menu_cache_clear_all();
+ menu_rebuild();
+
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertText(t('Test Search Page'), t('Search page was succesfully edited'));
+ $this->assertText('search/searchdifferentpath', t('Search path was updated'));
+ $this->drupalGet('search/searchdifferentpath');
+ $this->assertText(t('Search is temporarily unavailable. If the problem persists, please contact the site administrator.'), t('Search path was successfully created and is accessible'));
+ }
+
+ /**
+ * Asserts that we can clone a search page
+ */
+ function testCloneSearchPage() {
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertText(t('Clone'), t('Clone button is available'));
+ $this->drupalGet('admin/config/search/apachesolr/search-pages/core_search/clone');
+ $this->assertText(t('Are you sure you want to clone search page Core Search?'), t('Clone confirmation page was succesfully loaded'));
+ $this->drupalPost($this->getUrl(), array(), t('Clone'));
+ $this->assertResponse(200);
+ drupal_static_reset('apachesolr_search_load_all_search_pages');
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertText(t('Core Search [cloned]'), 'Search page was succesfully cloned');
+ }
+
+ /**
+ * Asserts that we can edit a search environment
+ */
+ function testNewAndRemoveSearchPage() {
+ // Create a new search page
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertText(t('Add search page'), t('Create new search page link is available'));
+ $this->clickLink(t('Add search page'));
+ $this->assertText(t('The human-readable name of the search page configuration.'), t('Search page creation page succesfully added'));
+ $edit = array(
+ 'page_id' => 'solr_testingsuite',
+ 'env_id' => 'solr',
+ 'label' => 'Test Search Page',
+ 'description' => 'Test Description',
+ 'page_title' => 'Test Title',
+ 'search_path' => 'search/searchdifferentpath',
+ );
+ $this->drupalPost($this->getUrl(), $edit, t('Save'));
+ $this->assertResponse(200);
+ // Make sure the menu is recognized
+ drupal_static_reset('apachesolr_search_load_all_search_pages');
+ menu_cache_clear_all();
+ menu_rebuild();
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertText(t('Test Search Page'), t('Search Page was succesfully created'));
+
+ // Remove the same environment
+ $this->clickLink(t('Delete'));
+ $this->assertText(t('search page configuration will be deleted.This action cannot be undone.'), t('Delete confirmation page was succesfully loaded'));
+ $this->drupalPost($this->getUrl(), array(), t('Delete'));
+ $this->assertResponse(200);
+ drupal_static_reset('apachesolr_search_load_all_search_pages');
+ $this->drupalGet('admin/config/search/apachesolr/search-pages');
+ $this->assertNoText(t('Test Search Page'), t('Search Environment was succesfully deleted'));
+ apachesolr_environment_save(array('env_id' => 'DummySolr', 'service_class' => 'DummySolr', 'name' => 'dummy server', 'url' => 'http://localhost:8983/solr'));
+ $solr = new DummySolr($url = NULL, $env_id = 'DummySolr');
+ $params = array(
+ 'rows' => 5,
+ );
+ $results = apachesolr_search_run('apachesolr_test', $params, '', '', 0, $solr);
+ $query = apachesolr_current_query('DummySolr');
+ $this->assertEqual($query->getParam('rows'), 5, 'Passed in rows param overrode default');
+ }
+}
+
+class DrupalSolrNodeTestCase extends DrupalWebTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Solr Node add and deletion tests',
+ 'description' => 'Tests if we can succesfully add and delete nodes',
+ 'group' => 'ApacheSolr',
+ );
+ }
+ /**
+ * Implementation of setUp().
+ */
+ function setUp() {
+ parent::setUp('apachesolr', 'apachesolr_search', 'search', 'apachesolr_test');
+ }
+
+ function testApacheSolrNodeAddDelete() {
+ // Login as basic user to perform initial content creation.
+ // Create an admin user that can bypass revision moderation.
+ $permissions = array(
+ 'access content',
+ 'search content',
+ 'administer nodes',
+ 'administer search',
+ 'access content overview',
+ 'bypass node access',
+ );
+ $admin_user = $this->drupalCreateUser($permissions);
+
+ $this->drupalLogin($admin_user);
+
+ // enable our bundles to be indexed, and clear caches
+ apachesolr_index_set_bundles('solr', 'node', array('page', 'article'));
+ entity_info_cache_clear();
+ apachesolr_environments_clear_cache();
+
+ // Define types of node bundles that we want to index
+ $types = array('page', 'article');
+
+ foreach ($types as $type) {
+ $edit = array();
+ // Create a node of the type $type.
+ $edit['uid'] = $admin_user->uid;
+ $edit['type'] = $type;
+ $edit['title'] = $this->randomName(16);
+ $node = $this->drupalCreateNode($edit);
+ $this->assertTrue(is_object($node) && isset($node->nid), t('Article type @type has been created.', array('@type' => $type)));
+
+ // Check that the node has been created.
+ $node = $this->drupalGetNodeByTitle($edit['title']);
+ $this->assertTrue($node, t('Created article @type found in database.', array('@type' => $type)));
+
+ // Check that the node has status 1
+ $indexer_table = apachesolr_get_indexer_table('node');
+ $query = db_select($indexer_table, 'aien')
+ ->condition('entity_id', $node->nid)
+ ->fields('aien', array('entity_id', 'status'));
+ $db_node = $query->execute()->fetchObject();
+ $this->assertEqual($db_node->status, 1, t('Node @entity_id has status 1', array('@entity_id' => $db_node->entity_id)));
+
+ // Delete the node
+ $this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
+
+ // check if the entity delete does its work. It should have set the
+ // status to 0 so it will be deleted when solr comes online
+ $indexer_table = apachesolr_get_indexer_table('node');
+ $query = db_select($indexer_table, 'aien')
+ ->condition('entity_id', $node->nid)
+ ->fields('aien', array('entity_id', 'status'));
+ $db_node = $query->execute()->fetchObject();
+
+ // Check that all of the nodes (should only have 1) have status 0, it
+ // is set as 0 because it is pending to be deleted
+ $this->assertEqual($db_node->status, 0, t('Node @entity_id has status 0', array('@entity_id' => $db_node->entity_id)));
+
+ // Check that all the nodes have been deleted.
+ $count = db_select('node', 'n')
+ ->condition('n.nid', $node->nid)
+ ->countQuery()
+ ->execute()
+ ->fetchField();
+ $this->assertEqual($count, 0, t('No more nodes left in the node table.'));
+ }
+ }
+}
+
+class DrupalSolrOfflineUnitTestCase extends DrupalUnitTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Solr Base Framework Tests Unit Test',
+ 'description' => 'Unit test functionality of the Solr module',
+ 'group' => 'ApacheSolr',
+ );
+ }
+
+ protected function setUp() {
+ parent::setUp();
+ require_once dirname(dirname(realpath(__FILE__))) . '/apachesolr.module';
+
+ $this->script_content = <<GOOD_CONTENT
+
+
+EOF;
+
+ $this->embed_content = <<GOOD_CONTENT
+
+OTHER_CONTENT
+
+EOF;
+
+ $this->iframe_content = <<
+
';
+ return $output;
+}
+
+/**
+ * Added form submit function to retain filters.
+ *
+ * @see solrsearch_search_form_search_form_alter()
+ */
+function solrsearch_search_form_search_submit($form, &$form_state) {
+ $fv = $form_state['values'];
+ // Replace keys with their rawurlencoded value
+ if (isset($fv['search_block_form'])) {
+ $raw_keys = str_replace("/","%2f",$fv['search_block_form']);
+ $form_state['redirect'] = str_replace($fv['search_block_form'], $raw_keys, $form_state['redirect']);
+ }
+}
+
+
+/**
+ * submit function for the delete_index form.
+ *
+ */
+function solrsearch_search_build_spellcheck($form, &$form_state) {
+ try {
+ $solr = solrsearch_get_solr();
+ $params['spellcheck'] = 'true';
+ $params['spellcheck.build'] = 'true';
+ $response = $solr->search('solr', 0, 0, $params);
+ }
+ catch (Exception $e) {
+ watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
+ }
+}
+
+/**
+ * Implements hook_form_[form_id]_alter().
+ *
+ * Adds settings to show facet blocks on non-search pages.
+ */
+function solrsearch_search_form_facetapi_realm_settings_form_alter(&$form, &$form_state) {
+
+ if ('solrsearch' == $form['#facetapi']['adapter']->getId() && 'block' == $form['#facetapi']['realm']['name']) {
+ // Gets the environment ID from the searcher, stores in #facetapi property.
+ $env_id = ltrim(strstr($form['#facetapi']['adapter']->getSearcher(), '@'), '@');
+
+ $show_facets = solrsearch_environment_variable_get($env_id, 'solrsearch_search_show_facets', 0);
+ $facet_pages = solrsearch_environment_variable_get($env_id, 'solrsearch_search_facet_pages', '');
+
+ $form['#facetapi']['env_id'] = $env_id;
+
+ $form['solrsearch_search_show_facets'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Show facets on non-search pages.'),
+ '#default_value' => $show_facets,
+ '#weight' => '-10',
+ );
+
+ $form['solrsearch_search_facet_pages'] = array(
+ '#title' => t('Non-search paths'),
+ '#type' => 'textarea',
+ '#default_value' => $facet_pages,
+ '#weight' => '-10',
+ '#dependency' => array(
+ 'edit-solrsearch-search-show-facets' => array(1),
+ ),
+ );
+
+ $form['#submit'][] = 'solrsearch_search_facetapi_realm_settings_form_submit';
+ }
+}
+
+/**
+ * Form submission handler for facetapi_realm_settings_form().
+ */
+function solrsearch_search_facetapi_realm_settings_form_submit(&$form, &$form_state) {
+ $env_id = $form['#facetapi']['env_id'];
+
+ // Adds the settings to the array keyed by environment ID, saves variables.
+ $show_facets = $form_state['values']['solrsearch_search_show_facets'];
+ $facet_pages = $form_state['values']['solrsearch_search_facet_pages'];
+ if ($show_facets) {
+ solrsearch_environment_variable_set($env_id, 'solrsearch_search_show_facets', $show_facets);
+ }
+ else {
+ // Due to performance reasons, we delete it from the vars so that our init
+ // process can react on environments that hae it set and not unset.
+ // See solrsearch_search_init().
+ solrsearch_environment_variable_del($env_id, 'solrsearch_search_show_facets');
+ }
+ solrsearch_environment_variable_set($env_id, 'solrsearch_search_facet_pages', $facet_pages);
+}
+
+/**
+ * Implements hook_theme().
+ */
+function solrsearch_search_theme() {
+ return array(
+ /**
+ * Shows the facets in blocks in the search result area
+ */
+ 'solrsearch_search_browse_blocks' => array(
+ 'render element' => 'content',
+ ),
+ /**
+ * Shows the search snippet
+ */
+ 'solrsearch_search_snippets' => array(
+ 'variables' => array('doc' => NULL, 'snippets' => array()),
+ ),
+ /**
+ * Shows a message when the search does not return any result
+ */
+ 'solrsearch_search_noresults' => array(
+ 'variables' => array(),
+ ),
+ /**
+ * Shows a list of suggestions
+ */
+ 'solrsearch_search_suggestions' => array(
+ 'variables' => array('links' => NULL),
+ ),
+ /**
+ * Shows a list of results (docs) in content recommendation block
+ */
+ 'solrsearch_search_mlt_recommendation_block' => array(
+ 'variables' => array('docs' => NULL, 'delta' => NULL),
+ ),
+ 'solrsearch_search_block_form' => array(
+ 'render element' => 'form',
+ 'template' => 'solrsearch-block-form',
+ ),
+
+ 'solrsearch_search_author_block_form' => array(
+ 'render element' => 'form',
+ 'template' => 'solrsearch-author-block-form',
+ ),
+
+ 'solrsearch_search_title_block_form' => array(
+ 'render element' => 'form',
+ 'template' => 'solrsearch-title-block-form',
+ ),
+ );
+}
+
+
+
+/**
+ * Implements hook_theme_registry_alter().
+ */
+function solrsearch_search_theme_registry_alter(&$theme_registry) {
+
+ if (isset($theme_registry['search_results'])) {
+ $theme_registry['search_results']['variables']['search_page'] = NULL;
+ }
+}
+
+/**
+ * Theme the highlighted snippet text for a search entry.
+ *
+ * @param array $vars
+ *
+ */
+function theme_solrsearch_search_snippets($vars) {
+ $result = '';
+ if (is_array($vars['snippets'])) {
+ $snippets = $vars['snippets'];
+ if (isset($snippets['content'])) {
+ $result .= implode(' ... ', $snippets['content']);
+ unset($snippets['content']);
+ }
+ if (isset($snippets['teaser'])) {
+ $result .= (strlen($result) > 0) ? ' ... ' : '';
+ $result .= implode(' ... ', $snippets['teaser']);
+ unset($snippets['teaser']);
+ }
+ if (count($snippets)) {
+ $result .= (strlen($result) > 0) ? ' ... ' : '';
+ foreach ($snippets as $snippet) {
+ $result .= implode(' ... ', $snippet);
+ }
+ }
+ }
+ return $result . ' ...';
+}
+
+/**
+ * Brief message to display when no results match the query.
+ *
+ * @see search_help()
+ */
+function theme_solrsearch_search_noresults() {
+ return t('
+
Check if your spelling is correct, or try removing filters.
+
Remove quotes around phrases to match each word individually: "blue drop" will match less than blue drop.
+
You can require or exclude terms using + and -: big +blue drop will require a match on blue while big blue -drop will exclude results that contain drop.
+
');
+}
+
+
+
+
+/**
+ * Implements hook_forms().
+ */
+function solrsearch_search_forms() {
+ $forms['solrsearch_search_block_form']= array(
+ 'callback' => 'solrsearch_search_box',
+ 'callback arguments' => array('solrsearch_search_block_form'),
+ );
+
+ $forms['solrsearch_search_author_block_form']= array(
+ 'callback' => 'solrsearch_search_author_box',
+ 'callback arguments' => array('solrsearch_search_author_block_form'),
+ );
+
+ $forms['solrsearch_search_title_block_form']= array(
+ 'callback' => 'solrsearch_search_title_box',
+ 'callback arguments' => array('solrsearch_search_title_block_form'),
+ );
+ return $forms;
+}
+
+
+
+
+
+
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch/solrsearch_search.pages.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch/solrsearch_search.pages.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,130 @@
+ 'container',
+ '#attributes' => array('class' => array('container-inline')),
+ );
+ $form['basic']['keys'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Enter terms'),
+ '#default_value' => $keys,
+ '#size' => 20,
+ '#maxlength' => 255,
+ );
+ $form['basic']['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Search'),
+ );
+
+ $form['basic']['get'] = array(
+ '#type' => 'hidden',
+ '#default_value' => json_encode(array_diff_key($_GET, array('q' => 1, 'page' => 1, 'solrsort' => 1, 'retain-filters' => 1))),
+ );
+
+ $fq = NULL;
+
+ if (solrsearch_has_searched($search_page['env_id'])) {
+ $query = solrsearch_current_query($search_page['env_id']);
+ // We use the presence of filter query params as a flag for the retain filters checkbox.
+ $fq = $query->getParam('fq');
+ }
+
+ if ($fq || isset($form_state['input']['retain-filters'])) {
+ $form['basic']['retain-filters'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Retain current filters'),
+ '#default_value' => (int) !empty($_GET['retain-filters']),
+ );
+ }
+
+ return $form;
+}
+
+/**
+ * Processes solrsearch_search_custom_page_search_form submissions.
+ */
+function solrsearch_search_custom_page_search_form_submit(&$form, &$form_state) {
+ $search_page = $form['#search_page'];
+ $redirect = $search_page['search_path'];
+
+ // Also encode slashes so we don't get akward situations when obtaining the
+ // search key. We can't use drupal_encode_path because for "aestetic" reasons
+ // they don't encode slashes...
+ $redirect_value = rawurlencode($form_state['values']['keys']);
+
+ if (strlen($form_state['values']['keys'])) {
+ $redirect .= '/' . $redirect_value;
+ }
+
+ $get = array();
+ if (isset($form_state['values']['get'])) {
+ $get = json_decode($form_state['values']['get'], TRUE);
+ }
+ if (!empty($form_state['values']['retain-filters'])) {
+ // Add our saved values
+ $get['retain-filters'] = '1';
+ }
+ else {
+ // Remove all filters
+ if (!empty($search_page['settings']['solrsearch_search_allow_user_input'])) {
+ unset($get['fq']);
+ }
+ if (module_exists('facetapi')) {
+ unset($get['f']);
+ }
+ }
+
+ // Add the query values into the redirect.
+ $form_state['redirect'] = array($redirect, array('query' => $get));
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch/solrsearch_search_author_block.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch/solrsearch_search_author_block.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,93 @@
+ 'textfield',
+ '#title' => t('Search'),
+ '#title_display' => 'invisible',
+ '#size' => 15,
+ '#default_value' => '',
+ '#attributes' => array('title' => t('Enter the terms you wish to search for.')),
+ );
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Search'));
+ $form['#submit'][] = 'solrsearch_search_author_box_form_submit';
+
+ return $form;
+}
+
+/**
+ * Process a block search form submission.
+ */
+function solrsearch_search_author_box_form_submit($form, &$form_state) {
+ // The search form relies on control of the redirect destination for its
+ // functionality, so we override any static destination set in the request,
+ // for example by drupal_access_denied() or drupal_not_found()
+ // (see http://drupal.org/node/292565).
+ if (isset($_GET['destination'])) {
+ unset($_GET['destination']);
+ }
+
+ // Check to see if the form was submitted empty.
+ // If it is empty, display an error message.
+ // (This method is used instead of setting #required to TRUE for this field
+ // because that results in a confusing error message. It would say a plain
+ // "field is required" because the search keywords field has no title.
+ // The error message would also complain about a missing #title field.)
+ if ($form_state['values']['solrsearch_search_author_block_form'] == '') {
+ form_set_error('keys', t('Please enter some keywords.'));
+ }
+
+ $form_id = $form['form_id']['#value'];
+ $info = search_get_default_module_info();
+ if ($info) {
+ $form_state['redirect'] = 'solrsearch/' . $info['path'] . '/IM_author:' . trim($form_state['values'][$form_id]);
+ }
+ else {
+ form_set_error(NULL, t('Search is currently disabled.'), 'error');
+ }
+}
+
+/**
+ * Process variables for search-block-form.tpl.php.
+ *
+ * The $variables array contains the following arguments:
+ * - $form
+ *
+ * @see search-block-form.tpl.php
+ */
+function template_preprocess_solrsearch_search_author_block_form(&$variables) {
+ $variables['search'] = array();
+ $hidden = array();
+ // Provide variables named after form keys so themers can print each element independently.
+ foreach (element_children($variables['form']) as $key) {
+ $type = $variables['form'][$key]['#type'];
+ if ($type == 'hidden' || $type == 'token') {
+ $hidden[] = drupal_render($variables['form'][$key]);
+ }
+ else {
+ $variables['search'][$key] = drupal_render($variables['form'][$key]);
+ }
+ }
+ // Hidden form elements have no value to themers. No need for separation.
+ $variables['search']['hidden'] = implode($hidden);
+ // Collect all form elements to make it easier to print the whole form.
+ $variables['solrsearch_search_form'] = implode($variables['search']);
+}
+
+
+
+function solrsearch_search_author_block(){
+
+ $block['content'] = drupal_get_form('solrsearch_search_author_block_form');
+ return $block;
+
+
+}
\ No newline at end of file
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch/solrsearch_search_blocks.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch/solrsearch_search_blocks.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,94 @@
+ 'textfield',
+ '#title' => t('Search'),
+ '#title_display' => 'invisible',
+ '#size' => 15,
+ '#default_value' => '',
+ '#attributes' => array('title' => t('Enter the terms you wish to search for.')),
+ );
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Search'));
+ $form['#submit'][] = 'solrsearch_search_box_form_submit';
+
+ return $form;
+}
+
+/**
+ * Process a block search form submission.
+ */
+function solrsearch_search_box_form_submit($form, &$form_state) {
+ // The search form relies on control of the redirect destination for its
+ // functionality, so we override any static destination set in the request,
+ // for example by drupal_access_denied() or drupal_not_found()
+ // (see http://drupal.org/node/292565).
+ if (isset($_GET['destination'])) {
+ unset($_GET['destination']);
+ }
+
+ // Check to see if the form was submitted empty.
+ // If it is empty, display an error message.
+ // (This method is used instead of setting #required to TRUE for this field
+ // because that results in a confusing error message. It would say a plain
+ // "field is required" because the search keywords field has no title.
+ // The error message would also complain about a missing #title field.)
+ if ($form_state['values']['solrsearch_search_block_form'] == '') {
+ form_set_error('keys', t('Please enter some keywords.'));
+ }
+
+ $form_id = $form['form_id']['#value'];
+ $info = search_get_default_module_info();
+ if ($info) {
+ $form_state['redirect'] = 'solrsearch/' . $info['path'] . '/' . trim($form_state['values'][$form_id]);
+ }
+ else {
+ form_set_error(NULL, t('Search is currently disabled.'), 'error');
+ }
+}
+
+
+
+
+function solrsearch_search_block(){
+
+ $block['content'] = drupal_get_form('solrsearch_search_block_form');
+ return $block;
+
+
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch/solrsearch_search_title_block.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch/solrsearch_search_title_block.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,93 @@
+ 'textfield',
+ '#title' => t('Search'),
+ '#title_display' => 'invisible',
+ '#size' => 15,
+ '#default_value' => '',
+ '#attributes' => array('title' => t('Enter the terms you wish to search for.')),
+ );
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Search'));
+ $form['#submit'][] = 'solrsearch_search_title_box_form_submit';
+
+ return $form;
+}
+
+/**
+ * Process a block search form submission.
+ */
+function solrsearch_search_title_box_form_submit($form, &$form_state) {
+ // The search form relies on control of the redirect destination for its
+ // functionality, so we override any static destination set in the request,
+ // for example by drupal_access_denied() or drupal_not_found()
+ // (see http://drupal.org/node/292565).
+ if (isset($_GET['destination'])) {
+ unset($_GET['destination']);
+ }
+
+ // Check to see if the form was submitted empty.
+ // If it is empty, display an error message.
+ // (This method is used instead of setting #required to TRUE for this field
+ // because that results in a confusing error message. It would say a plain
+ // "field is required" because the search keywords field has no title.
+ // The error message would also complain about a missing #title field.)
+ if ($form_state['values']['solrsearch_search_title_block_form'] == '') {
+ form_set_error('keys', t('Please enter some keywords.'));
+ }
+
+ $form_id = $form['form_id']['#value'];
+ $info = search_get_default_module_info();
+ if ($info) {
+ $form_state['redirect'] = 'solrsearch/' . $info['path'] . '/IM_title:' . trim($form_state['values'][$form_id]);
+ }
+ else {
+ form_set_error(NULL, t('Search is currently disabled.'), 'error');
+ }
+}
+
+/**
+ * Process variables for search-block-form.tpl.php.
+ *
+ * The $variables array contains the following arguments:
+ * - $form
+ *
+ * @see search-block-form.tpl.php
+ */
+function template_preprocess_solrsearch_search_title_block_form(&$variables) {
+ $variables['search'] = array();
+ $hidden = array();
+ // Provide variables named after form keys so themers can print each element independently.
+ foreach (element_children($variables['form']) as $key) {
+ $type = $variables['form'][$key]['#type'];
+ if ($type == 'hidden' || $type == 'token') {
+ $hidden[] = drupal_render($variables['form'][$key]);
+ }
+ else {
+ $variables['search'][$key] = drupal_render($variables['form'][$key]);
+ }
+ }
+ // Hidden form elements have no value to themers. No need for separation.
+ $variables['search']['hidden'] = implode($hidden);
+ // Collect all form elements to make it easier to print the whole form.
+ $variables['solrsearch_search_form'] = implode($variables['search']);
+}
+
+
+
+function solrsearch_search_title_block(){
+
+ $block['content'] = drupal_get_form('solrsearch_search_title_block_form');
+ return $block;
+
+
+}
\ No newline at end of file
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch/solrsearch_terms.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch/solrsearch_terms.inc Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,106 @@
+data);
+ $authorsAll=$data['terms'][$field];
+ return $authorsAll;
+}
+
+function solrsearch_load_data($field,$letter,$accessType="free"){
+ #todo cache this!
+ $env = solrsearch_environment_load('echosearch');
+ $searchStr = "/select?q=". $field. ":". $letter . "*%20and%20doc-type:indexMeta%20&json.nl=map&facet.sort=index&facet.mincount=1&wt=json&facet=true&facet.field=" . $field . "&facet.limit=100000&start=0&rows=9";
+
+ if ($accessType=="free")
+ {
+ $searchStr .="&fq=access-type:free";
+ }
+
+ $url = $env['url'];
+ $result = drupal_http_request($url . $searchStr);
+ $data = drupal_json_decode($result->data);
+ #return $data;
+
+ $resultsAll=$data['facet_counts']['facet_fields'][$field];
+
+ #result list ist zu lang, da hier alle werke gefunden werden, bei denene ein Autor mit dem Buchstaben beginnt.
+ $res=array();
+ foreach ($resultsAll as $author => $val){
+ if (drupal_substr($author, 0,1) == $letter){
+ $res[$author]=$val;
+ }
+
+ }
+
+ return $res;
+}
+
+#
+
+function solrsearch_term_select_field(){
+ $query = $_GET;
+ if (isset($query['browseField'])){
+ drupal_goto("solrsearch-terms/" .$query['browseField'] );
+ }
+
+}
+function solrsearch_term_list($field="",$letter="A",$numperpage=20){
+
+ if ($field==""){
+ return '';
+ }
+
+
+
+ #field z.b. author_c
+
+ if (!user_access("view restricted content")){
+ $accessType="free";
+ } else {
+ $accessType="";
+ }
+
+ $authorsAll=solrsearch_load_data($field,$letter,$accessType);
+ $cnt=count($authorsAll);
+
+ $page = pager_find_page();
+ $offset = $numperpage * $page;
+ $authors = array_slice($authorsAll, $offset,$slice_lenght=$numperpage);
+
+ pager_default_initialize($cnt, 10);
+
+ $rs = theme('solrsearch_term_selection_form',array('field' => $field));
+ $rs .=theme('pager', array('tags' => array('<<','<','..','>','>>'),'quantity' => 3));
+
+ if ($field=='author_c'){
+ $rs .= theme('solrsearch_term_list_author',array('authors' => $authors,'cnt' => $cnt,'letter' => $letter));
+ } else {
+ $rs .= theme('solrsearch_term_list_title',array('titles' => $authors,'cnt' => $cnt,'letter' => $letter));
+ }
+
+
+ $rs .=theme('pager', array('tags' => array('<<','<','..','>','>>'),'quantity' => 3));
+
+ return $rs;
+ }
+
+
+ function solrsearch_alphapager($field) {
+ $attributes = array( 'class' => 'alpha-page' );
+ $output = "";
+
+ foreach(range('A', 'Z') as $letter) {
+ $output .= "
+
";
+ }
+
+
+
+ return $output;
+ }
\ No newline at end of file
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/LICENSE.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/LICENSE.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/README.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/README.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,102 @@
+-- veraenderunge bisher
+DW
+
+An das Textinputfeld für die solr suche wird jeweils zusätzlich eine klasse:
+ "solrsearch-autocomplete.field.FIELDNAME" angeängt, FIELDName ist hierbei das Feld das für die autovervollständigung durchsucht werden soll.
+
+
+ daher hat die function:
+ solrsearch_autocomplete_do_alter
+
+ jetzt einen zusätzlichen parameter für den feldnamen
+
+ function solrsearch_autocomplete_do_alter(&$element,$field_name) {
+
+
+ solrsearch_autocomplete.js
+
+ is dementsprechend erweitert, dass die zusatzliche klasse ausgewertet wird
+ jquery fragt dann die autocompletion function von solrsearch (angehaengt bei /solrsearch_autocomplete") mit den paramtern "query" und "fieldName".
+
+ entsprechend wird dann solr abgefragt.
+
+TODO:
+--bisher ist fuer jedes such feld in der solrsuche
+die form-Veränderung hard codiert (korrespondierte dazu ist bisher ist auch noch fuer jedes suchfeld eine eigene such box in solrsearch angelegt.)
+
+das sollte so geändert werden, dass fuer jedes suchfeld ein parameter existiert.
+
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ */
+function solrsearch_autocomplete_form_solrsearch_search_block_form_alter(&$form, $form_state) {
+
+ $element = &$form['solrsearch_search_block_form'];
+ solrsearch_autocomplete_do_alter($element,"title");
+}
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ */
+function solrsearch_autocomplete_form_solrsearch_search_author_block_form_alter(&$form, $form_state) {
+
+ $element = &$form['solrsearch_search_author_block_form'];
+ solrsearch_autocomplete_do_alter($element,"author");
+}
+
+
+--die widgets funktioneren nicht
+
+---- original apachesolr_autocomplete README -- begin ----
+
+
+Apache Solr Autocomplete module for Drupal.
+
+-- SUMMARY --
+
+Add-on module to Apache Solr Search Integration that adds simple autocomplete
+functionality. It enforces node access, meaning that all suggestions are only
+from nodes that the user actually has access to.
+
+For a full description of the module, visit the project page:
+ http://drupal.org/project/apachesolr_autocomplete
+
+To submit bug reports and feature suggestions, or to track changes:
+ http://drupal.org/project/issues/apachesolr_autocomplete
+
+
+-- REQUIREMENTS --
+
+Apache Solr Search Integration module.
+See http://drupal.org/project/apachesolr
+
+
+-- INSTALLATION --
+
+* Install as usual, see http://drupal.org/node/70151 for further information.
+
+
+-- CONFIGURATION --
+
+For configuration, go to:
+
+ Administration >> Settings >> Apache Solr
+
+and look for the "Advanced Options" fieldset. The setting is:
+
+ "Autocomplete widget to use:"
+
+where you can choose between a custom Javascript widget (included with the
+module) or fall back to the core Drupal autocomplete widget. The default is to
+use the custom widget.
+
+-- TROUBLESHOOTING --
+
+If you are having trouble with the autocomplete suggestions not working correctly,
+try changing the configuration to use the core Drupal autocomplete widget.
+
+If you encounter other problems, please post to the project issue queue:
+ http://drupal.org/project/issues/apachesolr_autocomplete
+
+--
\ No newline at end of file
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/changelog.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/changelog.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,27 @@
+1.1
+---
+* Added matchContains: "word" option, match only the start of words instead of everywhere
+* Fixed mustMatch to trigger result event when no match was found
+* Fixed the issue where an autocomplete was applied after the field had focus
+* Extended multiple complete to enable editing words not at the end of the field (doesn't work in Opera)
+
+1.0.2
+-----
+* Fixed missing semicolon
+
+1.0.1
+-----
+* Fixed element creation (
to
and
to
)
+* Fixed ac_even class (was ac_event)
+* Fixed bgiframe usage: now its really optional
+* Removed the blur-on-return workaround, added a less obtrusive one only for Opera
+* Fixed hold cursor keys: Opera needs keypress, everyone else keydown to scroll through result list when holding cursor key
+* Updated package to jQuery 1.2.5, removing dimensions
+* Fixed multiple-mustMatch: Remove only the last term when no match is found
+* Fixed multiple without mustMatch: Don't select the last active when no match is found (on tab/return)
+* Fixed multiple cursor position: Put cursor at end of input after selecting a value
+
+1.0
+---
+
+* First release.
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/jquery.autocomplete.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/jquery.autocomplete.css Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,48 @@
+.ac_results {
+ padding: 0px;
+ border: 1px solid black;
+ background-color: white;
+ overflow: hidden;
+ z-index: 99999;
+}
+
+.ac_results ul {
+ width: 100%;
+ list-style-position: outside;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.ac_results li {
+ margin: 0px;
+ padding: 2px 5px;
+ cursor: default;
+ display: block;
+ /*
+ if width will be 100% horizontal scrollbar will apear
+ when scroll mode will be used
+ */
+ /*width: 100%;*/
+ font: menu;
+ font-size: 12px;
+ /*
+ it is very important, if line-height not setted or setted
+ in relative units scroll will be broken in firefox
+ */
+ line-height: 16px;
+ overflow: hidden;
+}
+
+.ac_loading {
+ background: white url('indicator.gif') right center no-repeat;
+}
+
+.ac_odd {
+ background-color: #eee;
+}
+
+.ac_over {
+ background-color: #0A246A;
+ color: white;
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/jquery.autocomplete.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/jquery.autocomplete.js Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,808 @@
+/*
+ * jQuery Autocomplete plugin 1.1
+ *
+ * Copyright (c) 2009 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+;(function($) {
+
+$.fn.extend({
+ autocomplete: function(urlOrData, options) {
+
+ var isUrl = typeof urlOrData == "string";
+ options = $.extend({}, $.Autocompleter.defaults, {
+ url: isUrl ? urlOrData : null,
+ data: isUrl ? null : urlOrData,
+ delay: isUrl ? $.Autocompleter.defaults.delay : 10,
+ max: options && !options.scroll ? 10 : 150
+ }, options);
+
+ // if highlight is set to false, replace it with a do-nothing function
+ options.highlight = options.highlight || function(value) { return value; };
+
+ // if the formatMatch option is not specified, then use formatItem for backwards compatibility
+ options.formatMatch = options.formatMatch || options.formatItem;
+
+ return this.each(function() {
+ new $.Autocompleter(this, options);
+ });
+ },
+ result: function(handler) {
+ return this.bind("result", handler);
+ },
+ search: function(handler) {
+ return this.trigger("search", [handler]);
+ },
+ flushCache: function() {
+ return this.trigger("flushCache");
+ },
+ setOptions: function(options){
+ return this.trigger("setOptions", [options]);
+ },
+ unautocomplete: function() {
+ return this.trigger("unautocomplete");
+ }
+});
+
+$.Autocompleter = function(input, options) {
+
+ var KEY = {
+ UP: 38,
+ DOWN: 40,
+ DEL: 46,
+ TAB: 9,
+ RETURN: 13,
+ ESC: 27,
+ COMMA: 188,
+ PAGEUP: 33,
+ PAGEDOWN: 34,
+ BACKSPACE: 8
+ };
+
+ // Create $ object for input element
+ var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
+
+ var timeout;
+ var previousValue = "";
+ var cache = $.Autocompleter.Cache(options);
+ var hasFocus = 0;
+ var lastKeyPressCode;
+ var config = {
+ mouseDownOnSelect: false
+ };
+ var select = $.Autocompleter.Select(options, input, selectCurrent, config);
+
+ var blockSubmit;
+
+ // prevent form submit in opera when selecting with return key
+ $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
+ if (blockSubmit) {
+ blockSubmit = false;
+ return false;
+ }
+ });
+
+ // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
+ $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
+ // a keypress means the input has focus
+ // avoids issue where input had focus before the autocomplete was applied
+ hasFocus = 1;
+ // track last key pressed
+ lastKeyPressCode = event.keyCode;
+ switch(event.keyCode) {
+
+ case KEY.UP:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.prev();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ case KEY.DOWN:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.next();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ case KEY.PAGEUP:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.pageUp();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ case KEY.PAGEDOWN:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.pageDown();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ // matches also semicolon
+ case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
+ case KEY.TAB:
+ case KEY.RETURN:
+ if( selectCurrent() ) {
+ // stop default to prevent a form submit, Opera needs special handling
+ event.preventDefault();
+ blockSubmit = true;
+ return false;
+ }
+ break;
+
+ case KEY.ESC:
+ select.hide();
+ break;
+
+ default:
+ clearTimeout(timeout);
+ timeout = setTimeout(onChange, options.delay);
+ break;
+ }
+ }).focus(function(){
+ // track whether the field has focus, we shouldn't process any
+ // results if the field no longer has focus
+ hasFocus++;
+ }).blur(function() {
+ hasFocus = 0;
+ if (!config.mouseDownOnSelect) {
+ hideResults();
+ }
+ }).click(function() {
+ // show select when clicking in a focused field
+ if ( hasFocus++ > 1 && !select.visible() ) {
+ onChange(0, true);
+ }
+ }).bind("search", function() {
+ // TODO why not just specifying both arguments?
+ var fn = (arguments.length > 1) ? arguments[1] : null;
+ function findValueCallback(q, data) {
+ var result;
+ if( data && data.length ) {
+ for (var i=0; i < data.length; i++) {
+ if( data[i].result.toLowerCase() == q.toLowerCase() ) {
+ result = data[i];
+ break;
+ }
+ }
+ }
+ if( typeof fn == "function" ) fn(result);
+ else $input.trigger("result", result && [result.data, result.value]);
+ }
+ $.each(trimWords($input.val()), function(i, value) {
+ request(value, findValueCallback, findValueCallback);
+ });
+ }).bind("flushCache", function() {
+ cache.flush();
+ }).bind("setOptions", function() {
+ $.extend(options, arguments[1]);
+ // if we've updated the data, repopulate
+ if ( "data" in arguments[1] )
+ cache.populate();
+ }).bind("unautocomplete", function() {
+ select.unbind();
+ $input.unbind();
+ $(input.form).unbind(".autocomplete");
+ });
+
+
+ function selectCurrent() {
+ var selected = select.selected();
+ if( !selected )
+ return false;
+
+ var v = selected.result;
+ previousValue = v;
+
+ if ( options.multiple ) {
+ var words = trimWords($input.val());
+ if ( words.length > 1 ) {
+ var seperator = options.multipleSeparator.length;
+ var cursorAt = $(input).selection().start;
+ var wordAt, progress = 0;
+ $.each(words, function(i, word) {
+ progress += word.length;
+ if (cursorAt <= progress) {
+ wordAt = i;
+ return false;
+ }
+ progress += seperator;
+ });
+ words[wordAt] = v;
+ // TODO this should set the cursor to the right position, but it gets overriden somewhere
+ //$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
+ v = words.join( options.multipleSeparator );
+ }
+ v += options.multipleSeparator;
+ }
+
+ $input.val(v);
+ hideResultsNow();
+ $input.trigger("result", [selected.data, selected.value]);
+ return true;
+ }
+
+ function onChange(crap, skipPrevCheck) {
+ if( lastKeyPressCode == KEY.DEL ) {
+ select.hide();
+ return;
+ }
+
+ var currentValue = $input.val();
+
+ if ( !skipPrevCheck && currentValue == previousValue )
+ return;
+
+ previousValue = currentValue;
+
+ currentValue = lastWord(currentValue);
+ if ( currentValue.length >= options.minChars) {
+ $input.addClass(options.loadingClass);
+ if (!options.matchCase)
+ currentValue = currentValue.toLowerCase();
+ request(currentValue, receiveData, hideResultsNow);
+ } else {
+ stopLoading();
+ select.hide();
+ }
+ };
+
+ function trimWords(value) {
+ if (!value)
+ return [""];
+ if (!options.multiple)
+ return [$.trim(value)];
+ return $.map(value.split(options.multipleSeparator), function(word) {
+ return $.trim(value).length ? $.trim(word) : null;
+ });
+ }
+
+ function lastWord(value) {
+ if ( !options.multiple )
+ return value;
+ var words = trimWords(value);
+ if (words.length == 1)
+ return words[0];
+ var cursorAt = $(input).selection().start;
+ if (cursorAt == value.length) {
+ words = trimWords(value)
+ } else {
+ words = trimWords(value.replace(value.substring(cursorAt), ""));
+ }
+ return words[words.length - 1];
+ }
+
+ // fills in the input box w/the first match (assumed to be the best match)
+ // q: the term entered
+ // sValue: the first matching result
+ function autoFill(q, sValue){
+ // autofill in the complete box w/the first match as long as the user hasn't entered in more data
+ // if the last user key pressed was backspace, don't autofill
+ if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
+ // fill in the value (keep the case the user has typed)
+ $input.val($input.val() + sValue.substring(lastWord(previousValue).length));
+ // select the portion of the value not typed by the user (so the next character will erase)
+ $(input).selection(previousValue.length, previousValue.length + sValue.length);
+ }
+ };
+
+ function hideResults() {
+ clearTimeout(timeout);
+ timeout = setTimeout(hideResultsNow, 200);
+ };
+
+ function hideResultsNow() {
+ var wasVisible = select.visible();
+ select.hide();
+ clearTimeout(timeout);
+ stopLoading();
+ if (options.mustMatch) {
+ // call search and run callback
+ $input.search(
+ function (result){
+ // if no value found, clear the input box
+ if( !result ) {
+ if (options.multiple) {
+ var words = trimWords($input.val()).slice(0, -1);
+ $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
+ }
+ else {
+ $input.val( "" );
+ $input.trigger("result", null);
+ }
+ }
+ }
+ );
+ }
+ };
+
+ function receiveData(q, data) {
+ if ( data && data.length && hasFocus ) {
+ stopLoading();
+ select.display(data, q);
+ autoFill(q, data[0].value);
+ select.show();
+ } else {
+ hideResultsNow();
+ }
+ };
+
+ function request(term, success, failure) {
+ if (!options.matchCase)
+ term = term.toLowerCase();
+ var data = cache.load(term);
+ // recieve the cached data
+ if (data && data.length) {
+ success(term, data);
+ // if an AJAX url has been supplied, try loading the data now
+ } else if( (typeof options.url == "string") && (options.url.length > 0) ){
+
+ var extraParams = {
+ timestamp: +new Date()
+ };
+ $.each(options.extraParams, function(key, param) {
+ extraParams[key] = typeof param == "function" ? param() : param;
+ });
+
+ $.ajax({
+ // try to leverage ajaxQueue plugin to abort previous requests
+ mode: "abort",
+ // limit abortion to this input
+ port: "autocomplete" + input.name,
+ dataType: options.dataType,
+ url: options.url,
+ data: $.extend({
+ query: lastWord(term),
+ limit: options.max
+ }, extraParams),
+ success: function(data) {
+ var parsed = options.parse && options.parse(data) || parse(data);
+ cache.add(term, parsed);
+ success(term, parsed);
+ }
+ });
+ } else {
+ // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
+ select.emptyList();
+ failure(term);
+ }
+ };
+
+ function parse(data) {
+ var parsed = [];
+ var rows = data.split("\n");
+ for (var i=0; i < rows.length; i++) {
+ var row = $.trim(rows[i]);
+ if (row) {
+ row = row.split("|");
+ parsed[parsed.length] = {
+ data: row,
+ value: row[0],
+ result: options.formatResult && options.formatResult(row, row[0]) || row[0]
+ };
+ }
+ }
+ return parsed;
+ };
+
+ function stopLoading() {
+ $input.removeClass(options.loadingClass);
+ };
+
+};
+
+$.Autocompleter.defaults = {
+ inputClass: "ac_input",
+ resultsClass: "ac_results",
+ loadingClass: "ac_loading",
+ minChars: 1,
+ delay: 400,
+ matchCase: false,
+ matchSubset: true,
+ matchContains: false,
+ cacheLength: 10,
+ max: 100,
+ mustMatch: false,
+ extraParams: {},
+ selectFirst: true,
+ formatItem: function(row) { return row[0]; },
+ formatMatch: null,
+ autoFill: false,
+ width: 0,
+ multiple: false,
+ multipleSeparator: ", ",
+ highlight: function(value, term) {
+ return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1");
+ },
+ scroll: true,
+ scrollHeight: 180
+};
+
+$.Autocompleter.Cache = function(options) {
+
+ var data = {};
+ var length = 0;
+
+ function matchSubset(s, sub) {
+ if (!options.matchCase)
+ s = s.toLowerCase();
+ var i = s.indexOf(sub);
+ if (options.matchContains == "word"){
+ i = s.toLowerCase().search("\\b" + sub.toLowerCase());
+ }
+ if (i == -1) return false;
+ return i == 0 || options.matchContains;
+ };
+
+ function add(q, value) {
+ if (length > options.cacheLength){
+ flush();
+ }
+ if (!data[q]){
+ length++;
+ }
+ data[q] = value;
+ }
+
+ function populate(){
+ if( !options.data ) return false;
+ // track the matches
+ var stMatchSets = {},
+ nullData = 0;
+
+ // no url was specified, we need to adjust the cache length to make sure it fits the local data store
+ if( !options.url ) options.cacheLength = 1;
+
+ // track all options for minChars = 0
+ stMatchSets[""] = [];
+
+ // loop through the array and create a lookup structure
+ for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
+ var rawValue = options.data[i];
+ // if rawValue is a string, make an array otherwise just reference the array
+ rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
+
+ var value = options.formatMatch(rawValue, i+1, options.data.length);
+ if ( value === false )
+ continue;
+
+ var firstChar = value.charAt(0).toLowerCase();
+ // if no lookup array for this character exists, look it up now
+ if( !stMatchSets[firstChar] )
+ stMatchSets[firstChar] = [];
+
+ // if the match is a string
+ var row = {
+ value: value,
+ data: rawValue,
+ result: options.formatResult && options.formatResult(rawValue) || value
+ };
+
+ // push the current match into the set list
+ stMatchSets[firstChar].push(row);
+
+ // keep track of minChars zero items
+ if ( nullData++ < options.max ) {
+ stMatchSets[""].push(row);
+ }
+ };
+
+ // add the data items to the cache
+ $.each(stMatchSets, function(i, value) {
+ // increase the cache size
+ options.cacheLength++;
+ // add to the cache
+ add(i, value);
+ });
+ }
+
+ // populate any existing data
+ setTimeout(populate, 25);
+
+ function flush(){
+ data = {};
+ length = 0;
+ }
+
+ return {
+ flush: flush,
+ add: add,
+ populate: populate,
+ load: function(q) {
+ if (!options.cacheLength || !length)
+ return null;
+ /*
+ * if dealing w/local data and matchContains than we must make sure
+ * to loop through all the data collections looking for matches
+ */
+ if( !options.url && options.matchContains ){
+ // track all matches
+ var csub = [];
+ // loop through all the data grids for matches
+ for( var k in data ){
+ // don't search through the stMatchSets[""] (minChars: 0) cache
+ // this prevents duplicates
+ if( k.length > 0 ){
+ var c = data[k];
+ $.each(c, function(i, x) {
+ // if we've got a match, add it to the array
+ if (matchSubset(x.value, q)) {
+ csub.push(x);
+ }
+ });
+ }
+ }
+ return csub;
+ } else
+ // if the exact item exists, use it
+ if (data[q]){
+ return data[q];
+ } else
+ if (options.matchSubset) {
+ for (var i = q.length - 1; i >= options.minChars; i--) {
+ var c = data[q.substr(0, i)];
+ if (c) {
+ var csub = [];
+ $.each(c, function(i, x) {
+ if (matchSubset(x.value, q)) {
+ csub[csub.length] = x;
+ }
+ });
+ return csub;
+ }
+ }
+ }
+ return null;
+ }
+ };
+};
+
+$.Autocompleter.Select = function (options, input, select, config) {
+ var CLASSES = {
+ ACTIVE: "ac_over"
+ };
+
+ var listItems,
+ active = -1,
+ data,
+ term = "",
+ needsInit = true,
+ element,
+ list;
+
+ // Create results
+ function init() {
+ if (!needsInit)
+ return;
+ element = $("")
+ .hide()
+ .addClass(options.resultsClass)
+ .css("position", "absolute")
+ .appendTo(document.body);
+
+ list = $("
").appendTo(element).mouseover( function(event) {
+ if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
+ active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
+ $(target(event)).addClass(CLASSES.ACTIVE);
+ }
+ }).click(function(event) {
+ $(target(event)).addClass(CLASSES.ACTIVE);
+ select();
+ // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
+ input.focus();
+ return false;
+ }).mousedown(function() {
+ config.mouseDownOnSelect = true;
+ }).mouseup(function() {
+ config.mouseDownOnSelect = false;
+ });
+
+ if( options.width > 0 )
+ element.css("width", options.width);
+
+ needsInit = false;
+ }
+
+ function target(event) {
+ var element = event.target;
+ while(element && element.tagName != "LI")
+ element = element.parentNode;
+ // more fun with IE, sometimes event.target is empty, just ignore it then
+ if(!element)
+ return [];
+ return element;
+ }
+
+ function moveSelect(step) {
+ listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
+ movePosition(step);
+ var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
+ if(options.scroll) {
+ var offset = 0;
+ listItems.slice(0, active).each(function() {
+ offset += this.offsetHeight;
+ });
+ if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
+ list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
+ } else if(offset < list.scrollTop()) {
+ list.scrollTop(offset);
+ }
+ }
+ };
+
+ function movePosition(step) {
+ active += step;
+ if (active < 0) {
+ active = listItems.size() - 1;
+ } else if (active >= listItems.size()) {
+ active = 0;
+ }
+ }
+
+ function limitNumberOfItems(available) {
+ return options.max && options.max < available
+ ? options.max
+ : available;
+ }
+
+ function fillList() {
+ list.empty();
+ var max = limitNumberOfItems(data.length);
+ for (var i=0; i < max; i++) {
+ if (!data[i])
+ continue;
+ var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
+ if ( formatted === false )
+ continue;
+ var li = $("").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
+ $.data(li, "ac_data", data[i]);
+ }
+ listItems = list.find("li");
+ if ( options.selectFirst ) {
+ listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
+ active = 0;
+ }
+ // apply bgiframe if available
+ if ( $.fn.bgiframe )
+ list.bgiframe();
+ }
+
+ return {
+ display: function(d, q) {
+ init();
+ data = d;
+ term = q;
+ fillList();
+ },
+ next: function() {
+ moveSelect(1);
+ },
+ prev: function() {
+ moveSelect(-1);
+ },
+ pageUp: function() {
+ if (active != 0 && active - 8 < 0) {
+ moveSelect( -active );
+ } else {
+ moveSelect(-8);
+ }
+ },
+ pageDown: function() {
+ if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
+ moveSelect( listItems.size() - 1 - active );
+ } else {
+ moveSelect(8);
+ }
+ },
+ hide: function() {
+ element && element.hide();
+ listItems && listItems.removeClass(CLASSES.ACTIVE);
+ active = -1;
+ },
+ visible : function() {
+ return element && element.is(":visible");
+ },
+ current: function() {
+ return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
+ },
+ show: function() {
+ var offset = $(input).offset();
+ element.css({
+ width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
+ top: offset.top + input.offsetHeight,
+ left: offset.left
+ }).show();
+ if(options.scroll) {
+ list.scrollTop(0);
+ list.css({
+ maxHeight: options.scrollHeight,
+ overflow: 'auto'
+ });
+
+ if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
+ var listHeight = 0;
+ listItems.each(function() {
+ listHeight += this.offsetHeight;
+ });
+ var scrollbarsVisible = listHeight > options.scrollHeight;
+ list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
+ if (!scrollbarsVisible) {
+ // IE doesn't recalculate width when scrollbar disappears
+ listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
+ }
+ }
+
+ }
+ },
+ selected: function() {
+ var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
+ return selected && selected.length && $.data(selected[0], "ac_data");
+ },
+ emptyList: function (){
+ list && list.empty();
+ },
+ unbind: function() {
+ element && element.remove();
+ }
+ };
+};
+
+$.fn.selection = function(start, end) {
+ if (start !== undefined) {
+ return this.each(function() {
+ if( this.createTextRange ){
+ var selRange = this.createTextRange();
+ if (end === undefined || start == end) {
+ selRange.move("character", start);
+ selRange.select();
+ } else {
+ selRange.collapse(true);
+ selRange.moveStart("character", start);
+ selRange.moveEnd("character", end);
+ selRange.select();
+ }
+ } else if( this.setSelectionRange ){
+ this.setSelectionRange(start, end);
+ } else if( this.selectionStart ){
+ this.selectionStart = start;
+ this.selectionEnd = end;
+ }
+ });
+ }
+ var field = this[0];
+ if ( field.createTextRange ) {
+ var range = document.selection.createRange(),
+ orig = field.value,
+ teststring = "<->",
+ textLength = range.text.length;
+ range.text = teststring;
+ var caretAt = field.value.indexOf(teststring);
+ field.value = orig;
+ this.selection(caretAt, caretAt + textLength);
+ return {
+ start: caretAt,
+ end: caretAt + textLength
+ }
+ } else if( field.selectionStart !== undefined ){
+ return {
+ start: field.selectionStart,
+ end: field.selectionEnd
+ }
+ }
+};
+
+})(jQuery);
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/todo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/jquery-autocomplete/todo Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,166 @@
+TODO
+
+- test formatItem implementation that returns (clickable) anchors
+- bug: handle del key; eg. type a letter, remove it using del, type same letter again: nothing happens
+- handle up/down keys in textarea (prevent default while select is open?)
+- docs: max:0 works, too, "removing" it(??)
+- fix ac_loading/options.loadingClass
+- support/enable request urls like foo/bar/10 instead of foo/q=10
+- urlencode request term before passing to $.ajax/data; evaluate why $.ajax doesn't handle that itself, if at all; try with umlauts, russian/danish/chinese characeters (see validate)
+- test what happens when an element gets focused programmatically (maybe even before then autcomplete is applied)
+- check if blur on selecting can be removed
+- fix keyhandling to ignore metakeys, eg. shift; especially important for chinese characters that need more then one key
+- enhance mustMatch: provide event/callback when a value gets deleted
+- handle tab key different then enter, eg. don't blur field or prevent default, just let it move on; in any case, no need to blur the field when selecting a value via tab, unlike return
+- prevent redundant requests on
+ - superstring returned no result, no need to query again for substring, eg. pete returned nothing, peter won't either
+ - previous query mustn't be requested again, eg. pete returns 10 lines, peter nothing, backspace to pete should get the 10 lines from cache (may need TimeToLive setting for cache to invalidate it)
+- incorporate improvements and suggestions by Hector: http://beta.winserver.com/public/test/MultiSuggestTest.wct
+- json support: An optional JSON format, that assumes a certain JSON format as default and just looks for a dataType "json" to be activated; [records], where each record is { id:String, label:String, moreOptionalValues... }
+- accept callback as first argument to let users implement their own dynamic data (no caching) - consider async API
+- allow users to keep their incomplete value when pressing tab, just mimic the default-browser-autocomplete: tab doesn't select any proposed value -> tab closes the select and works normal otherwise
+- small bug in your autocomplete, When setting autoFill:true I would expect formatResult to be called on autofill, it seems not to be the case.
+- add a callback to allow decoding the response
+- allow modification of not-last value in multiple-fields
+@option Number size Limit the number of items to show at once. Default:
+@option Function parse - TEST AND DOCUMENT ME
+- add option to display selectbox on focus
+
+$input.bind("show", function() {
+ if ( !select.visible() ) {
+ onChange(0, true);
+ }
+});
+
+- reference: http://capxous.com/
+ - add "try ..." hints to demo
+ - check out demos
+- reference: http://createwebapp.com/demo/
+
+- add option to hide selectbox when no match is found - see comment by Ian on plugin page (14. Juli 2007 04:31)
+- add example for reinitializing an autocomplete using unbind()
+
+- Add option to pass through additional arguments to $.ajax, like type to use POST instead of GET
+
+ - I found out that the problem with UTF-8 not being correctly sent can be solved on the server side by applying (PHP) rawurldecode() function, which decodes the Unicode characters sent by GET method and therefore URL-encoded.
+-> add that hint to docs and examples
+
+But I am trying this with these three values: “foo bar”, “foo foo”, and “foo far”, and if I enter “b” (or “ba”) nothing matches, if I enter “f” all three do match, and if I enter “fa” the last one matches.
+The problem seems to be that the cache is implemented with a first-character hashtable, so only after matching the first character, the latter ones are searched for.
+
+xml example:
+
+
+
+
+
+ FreeNode: irc.freenode.net:6667]]>
+
+
+
+
+ irc.oftc.net:6667]]>
+
+
+
+
+ irc.undernet.org:6667]]>
+
+
+
+
+
+
+
+Hi all,
+
+I use Autocomplete 1.0 Alpha mostly for form inputs bound to foreign
+key columns. For instance I have a user_position table with two
+columns: user_id and position_id. On new appointment form I have two
+autocomplete text inputs with the following code:
+
+
+
+
+As you can see the inputs do not have a name attribute, and when the
+form is submitted their values are not sent, which is all right since
+they will contain strings like:
+
+ 'John Doe'
+ 'Sales Manager'
+
+whereas our backend expects something like:
+
+ 23
+ 14
+
+which are the user_id for John Doe and position_id for Sales Manager.
+To send these values I have two hidden inputs in the form like this:
+
+
+
+
+Also I have the following code in the $().ready function:
+
+ $("#user_id").result(function(event, data, formatted) {
+ $("input[@name=user_id]").val(data[1]);
+ });
+ $("#position_id").result(function(event, data, formatted) {
+ $("input[@name=position_id]").val(data[1]);
+ });
+
+As could be seen these functions stuff user_id and position_id values
+(in our example 23 and 14) into the hidden inputs, and when the form
+is submitted these values are sent:
+
+ user_id = 23
+ position_id = 14
+
+The backend script then takes care of adding a record to our
+user_position table containing those values.
+
+I wonder how could the plugin code be modified to simplify the setup
+by taking care of adding hidden inputs and updating the value of
+hidden inputs as default behavior. I have successfully attempted a
+simpler solution - writing a wrapper to perform these additional tasks
+and invoke autocomplete as well. I hope my intention is clear enough,
+if not, this is exactly the expected outcome:
+
+Before:
+
+
+
+
+After:
+
+
+
+
+
+Last word, I know this looks like a tall order, and I do not hope
+someone will make a complete working mod for me, but rather would very
+much appreciate helpful advise and directions.
+
+Many thanks in advance
+Majid
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/solrsearch_autocomplete.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/solrsearch_autocomplete.css Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,21 @@
+/**
+ * @file
+ * Adds some styles to the standard Drupal autocomplete widget.
+ */
+.apachesolr_autocomplete {
+}
+.apachesolr_autocomplete.message {
+ font-size:80%;
+ color:#888;
+}
+.apachesolr_autocomplete.count {
+ float:right;
+}
+div.apachesolr_autocomplete.suggestion {
+ display:inline;
+ float:left;
+}
+div.ac_results li {
+ list-style:none;
+ background-image: none !important;
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/solrsearch_autocomplete.info
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/solrsearch_autocomplete.info Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,13 @@
+name = Search Solr autocomplete
+description = Enables autocomplete on Search Solr search boxes
+dependencies[] = solrsearch
+dependencies[] = solrsearch_search
+package = SolrSearch
+core = "7.x"
+
+; Information added by drupal.org packaging script on 2012-08-29
+version = "7.x-1.3"
+core = "7.x"
+project = "solrsearch_autocomplete"
+datestamp = "1346272315"
+
diff -r 000000000000 -r 015d06b10d37 sites/all/modules/custom/solrsearch_autocomplete/solrsearch_autocomplete.install
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/custom/solrsearch_autocomplete/solrsearch_autocomplete.install Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,17 @@
+ array('path' => url('solrsearch_autocomplete'))), 'setting');
+ }
+}
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ */
+function solrsearch_autocomplete_form_search_form_alter(&$form, $form_state) {
+
+ if ($form['module']['#value'] == 'solrsearch_search' || $form['module']['#value'] == 'solrsearch_multisitesearch') {
+ $element = &$form['basic']['keys'];
+ solrsearch_autocomplete_do_alter($element);
+ }
+}
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ */
+function solrsearch_autocomplete_form_solrsearch_search_block_form_alter(&$form, $form_state) {
+
+ $element = &$form['solrsearch_search_block_form'];
+ solrsearch_autocomplete_do_alter($element,"title_s,title,author");
+}
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ */
+function solrsearch_autocomplete_form_solrsearch_search_author_block_form_alter(&$form, $form_state) {
+
+ $element = &$form['solrsearch_search_author_block_form'];
+
+ solrsearch_autocomplete_do_alter($element,"author");
+}
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ */
+function solrsearch_autocomplete_form_solrsearch_search_title_block_form_alter(&$form, $form_state) {
+
+ $element = &$form['solrsearch_search_title_block_form'];
+
+ solrsearch_autocomplete_do_alter($element,"title_s,title");
+}
+/**
+ * Helper function to do the actual altering of search forms.
+ *
+ * @param $element
+ * The element to alter. Should be passed by reference so that original form
+ * element will be altered.
+ * E.g.: solrsearch_autocomplete_do_alter(&$form['xyz'])
+ */
+function solrsearch_autocomplete_do_alter(&$element,$field_name) {
+
+ if (solrsearch_autocomplete_variable_get_widget() == 'custom') {
+ // Create elements if they do not exist.
+ if (!isset($element['#attributes'])) {
+ $element['#attributes'] = array();
+ }
+ if (!isset($element['#attributes']['class'])) {
+ $element['#attributes']['class'] = array();
+ }
+ array_push($element['#attributes']['class'], 'solrsearch-autocomplete', 'unprocessed','solrsearch-autocomplete.field.'.$field_name);
+
+ }
+ else {
+ $element['#autocomplete_path'] = 'solrsearch_autocomplete';
+ }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function solrsearch_autocomplete_menu() {
+ $items = array();
+
+ $items['solrsearch_autocomplete'] = array(
+ 'page callback' => 'solrsearch_autocomplete_callback',
+ 'access callback' => 'user_access',
+ 'access arguments' => array('search content'),
+ 'type' => MENU_CALLBACK,
+ );
+ return $items;
+}
+
+/**
+ * Callback for url solrsearch_autocomplete/autocomplete.
+ * @param $keys
+ * The user-entered query.
+ */
+function solrsearch_autocomplete_callback($keys = '', $field_name='') {
+
+
+ if (solrsearch_autocomplete_variable_get_widget() == 'custom') {
+ // Keys for custom widget come from $_GET.
+ $keys = $_GET['query'];
+ $field_names =$_GET['fieldName'];
+ }
+
+ /*
+ $res = split("\:",$keys);
+
+ if (count($res) == 2){
+ $keys=$res[1];
+ $field_name=$res[0];
+ } else {
+ $keys=$res[0];
+ $field_name="";
+ }
+ */
+
+ $suggestions = array();
+
+ foreach (explode(",",$field_names) as $field_name) {
+
+ $suggestions = array_merge($suggestions, solrsearch_autocomplete_suggest_word_completion($keys, 5,$field_name));
+ if (solrsearch_autocomplete_variable_get_suggest_keywords() || solrsearch_autocomplete_variable_get_suggest_spellcheck()) {
+ $suggestions = array_merge($suggestions, solrsearch_autocomplete_suggest_additional_term($keys, 5,$field_name));
+
+ }
+ }
+ $result = array();
+ if (solrsearch_autocomplete_variable_get_widget() == 'custom') {
+ // Place suggestions into new array for returning as JSON.
+ foreach ($suggestions as $key => $display) {
+ $result[] = array(
+ "key" => substr($key,1),
+ "display" => $display
+ );
+ }
+ }
+ else {
+ foreach ($suggestions as $key => $display) {
+ $result[substr($key,1)] =$display;
+ }
+ }
+ drupal_json_output($result);
+ exit();
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function solrsearch_autocomplete_theme() {
+ return array(
+ 'solrsearch_autocomplete_highlight' => array(
+ 'file' => 'solrsearch_autocomplete.module',
+ 'arguments' => array(
+ 'keys' => NULL,
+ 'suggestion' => NULL,
+ 'count' => NULL,
+ ),
+ ),
+ 'solrsearch_autocomplete_spellcheck' => array(
+ 'file' => 'solrsearch_autocomplete.module',
+ 'arguments' => array(
+ 'suggestion' => NULL,
+ ),
+ ),
+ );
+}
+
+/**
+ * Themes each returned suggestion.
+ */
+function theme_solrsearch_autocomplete_highlight($variables) {
+ static $first = true;
+ $html = '';
+ $html .= '
";
+ }
+ }
+ return $html;
+}
+
+/**
+ * Themes the spellchecker's suggestion.
+ */
+function theme_solrsearch_autocomplete_spellcheck($variables) {
+ return '' . t('Did you mean') .': ' . $variables['suggestion'];
+}
+
+/**
+ * Return the basic set of parameters for the Solr query.
+ *
+ * @param $suggestions_to_return
+ * Number of facets to return.
+ * @return array
+ */
+function solrsearch_autocomplete_basic_params($suggestions_to_return,$facet_name) {
+ return array(
+ 'facet' => 'true',
+ 'facet.field' => array($facet_name),
+ // We ask for $suggestions_to_return * 5 facets, because we want
+ // not-too-frequent terms (will be filtered below). 5 is just my best guess.
+ 'facet.limit' => $suggestions_to_return * 5,
+ 'facet.mincount' => 1,
+ 'start' => 0,
+ 'rows' => 0,
+ );
+}
+
+/**
+ * Helper function that suggests ways to complete partial words.
+ *
+ * For example, if $keys = "learn", this might return suggestions like:
+ * learn, learning, learner, learnability.
+ * The suggested terms are returned in order of frequency (most frequent first).
+ *
+ */
+function solrsearch_autocomplete_suggest_word_completion($keys, $suggestions_to_return = 5, $facet_name="author") {
+ /**
+ * Split $keys into two:
+ * $first_part will contain all complete words (delimited by spaces). Can be empty.
+ * $last_part is the (assumed incomplete) last word. If this is empty, don't suggest.
+ * Example:
+ * $keys = "learning dis" : $first_part = "learning", $last_part = "dis"
+ */
+ preg_match('/^(:?(.* |))([^ ]+)$/', $keys, $matches);
+ $first_part = @$matches[2];
+ // Make sure $last_part contains meaningful characters
+ $last_part = preg_replace('/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . ']+/u', '', @$matches[3]);
+ if ($last_part == '') {
+ return array();
+ }
+ // Ask Solr to return facets that begin with $last_part; these will be the suggestions.
+ $params = solrsearch_autocomplete_basic_params($suggestions_to_return,$facet_name);
+ $params['facet.prefix'] = $last_part;
+ // Get array of themed suggestions.
+ $result = solrsearch_autocomplete_suggest($first_part, $params, 'solrsearch_autocomplete_highlight', $keys, $suggestions_to_return);
+ if ($result && $result['suggestions']) {
+ return $result['suggestions'];
+ } else {
+ return array();
+ }
+}
+
+/**
+ * Helper function that suggests additional terms to search for.
+ *
+ * For example, if $keys = "learn", this might return suggestions like:
+ * learn student, learn school, learn mathematics.
+ * The suggested terms are returned in order of frequency (most frequent first).
+ */
+function solrsearch_autocomplete_suggest_additional_term($keys, $suggestions_to_return = 5, $facet_name="author") {
+ $keys = trim($keys);
+ $keys = check_plain($keys);
+ if ($keys == '') {
+ return array();
+ }
+ // Return no suggestions when $keys consists of only word delimiters
+ if (drupal_strlen(preg_replace('/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . ']+/u', '', $keys)) < 1) {
+ return array();
+ }
+
+ // Ask Solr to return facets from the 'spell' field to use as suggestions.
+ $params = solrsearch_autocomplete_basic_params($suggestions_to_return,$facet_name);
+
+ // Initialize arrays
+ $suggestions = array();
+ $replacements = array();
+
+ // Get array of themed suggestions.
+ $result = solrsearch_autocomplete_suggest($keys, $params, 'solrsearch_autocomplete_highlight', $keys, $suggestions_to_return);
+ if ($result && solrsearch_autocomplete_variable_get_suggest_keywords()) {
+ if (isset($result['suggestions']) && sizeof($result['suggestions'])) {
+ $suggestions = array_merge($suggestions, $result['suggestions']);
+ }
+ }
+
+ // Suggest using the spellchecker
+ if (solrsearch_autocomplete_variable_get_suggest_spellcheck()) {
+ if (isset($result['response']->spellcheck) && isset($result['response']->spellcheck->suggestions)) {
+ $spellcheck_suggestions = get_object_vars($result['response']->spellcheck->suggestions);
+ foreach($spellcheck_suggestions as $word => $value) {
+ $replacements[$word] = $value->suggestion[0];
+ }
+ if (count($replacements)) {
+ $new_keywords = strtr($keys, $replacements);
+ if ($new_keywords != $keys) {
+ // Place spellchecker suggestion before others
+ $suggestions = array_merge(array('*' . $new_keywords => theme('solrsearch_autocomplete_spellcheck', array('suggestion' => $new_keywords))), $suggestions);
+ }
+ }
+ }
+ }
+
+ return $suggestions;
+}
+
+
+function solrsearch_autocomplete_suggest($keys, $params, $theme_callback, $orig_keys, $suggestions_to_return = 5) {
+ $matches = array();
+ $suggestions = array();
+ $keys = trim($keys);
+ $show_counts = solrsearch_autocomplete_variable_get_counts();
+
+ // We need the keys array to make sure we don't suggest words that are already
+ // in the search terms.
+ $keys_array = explode(' ', $keys);
+ $keys_array = array_filter($keys_array);
+
+ // Query Solr for $keys so that suggestions will always return results.
+ $query = solrsearch_drupal_query($keys);
+
+ // This hook allows modules to modify the query and params objects.
+ drupal_alter('solrsearch_query', $query);
+ if (!$query) {
+ return array();
+ }
+ solrsearch_search_add_spellcheck_params($query);
+ foreach ($params as $param => $paramValue) {
+ $query->addParam($param, $paramValue);
+ }
+ solrsearch_search_add_boost_params($query);
+
+ // Query Solr
+ $response = $query->search($keys);
+ // Loop through requested fields and get suggestions.
+ foreach ($params['facet.field'] as $field) {
+ foreach ($response->facet_counts->facet_fields->{$field} as $terms => $count) {
+
+
+
+ $terms = preg_replace('/[_-]+/', ' ', $terms);
+ $term=$terms;
+ if ($term) {
+
+ if (isset($matches[$term])) {
+ $matches[$term] += $count;
+ }
+ else {
+ $matches[$term] = $count;
+ }
+ }
+
+ }
+ }
+
+ if (sizeof($matches) > 0) {
+ // Eliminate suggestions that are stopwords or are already in the query.
+ $matches_clone = $matches;
+ $stopwords = solrsearch_autocomplete_get_stopwords();
+ foreach ($matches_clone as $term => $count) {
+ if ((strlen($term) > 3) && !in_array($term, $stopwords) && !array_search($term, $keys_array)) {
+ // Longer strings get higher ratings.
+ #$matches_clone[$term] += strlen($term);
+ }
+ else {
+ unset($matches_clone[$term]);
+ unset($matches[$term]);
+ }
+ }
+
+ // Don't suggest terms that are too frequent (in >90% of results).
+ $max_occurence = $response->response->numFound * 0.90;
+ foreach ($matches_clone as $match => $count) {
+ if ($count > $max_occurence) {
+ unset($matches_clone[$match]);
+ }
+ }
+
+ // The $count in this array is actually a score. We want the highest ones first.
+ arsort($matches_clone);
+
+ // Shorten the array to the right ones.
+ $matches_clone = array_slice($matches_clone, 0, $suggestions_to_return, TRUE);
+
+ // Add current search as suggestion if results > 0
+ if ($response->response->numFound > 0 && $keys != '') {
+ // Add * to array element key to force into a string, else PHP will
+ // renumber keys that look like numbers on the returned array.
+ $suggestions['*' . $keys] = theme('solrsearch_autocomplete_highlight', array('keys' => $keys, 'suggestion' => $keys, 'count' => $response->response->numFound, 'show_counts' => $show_counts));
+ }
+
+ // Build suggestions using returned facets
+ foreach ($matches_clone as $match => $count) {
+ if ($keys != $match) {
+ $suggestion = trim($keys . ' ' . $match);
+ // On cases where there are more than 3 keywords, omit displaying
+ // the count because of the mm settings in solrconfig.xml
+ if (substr_count($suggestion, ' ') >= 2) {
+ $count = 0;
+ }
+ if ($suggestion != '') {
+ // Add * to array element key to force into a string, else PHP will
+ // renumber keys that look like numbers on the returned array.
+ $suggestions['*' . $suggestion] = theme('solrsearch_autocomplete_highlight', array('keys' => $orig_keys, 'suggestion' => $suggestion, 'count' => $count, 'show_counts' => $show_counts));
+ }
+ }
+ }
+ }
+
+ return array(
+ 'suggestions' => $suggestions,
+ 'response' => &$response
+ );
+}
+
+/**
+ * Gets the current stopwords list configured in Solr.
+ */
+function solrsearch_autocomplete_get_stopwords() {
+ static $words = array(), $flag = false;
+ if ($flag) {
+ return $words;
+ }
+ $stopwords_url = "/admin/file/?file=stopwords.txt";
+ $host = variable_get('solrsearch_host', 'localhost');
+ $port = variable_get('solrsearch_port', 8983);
+ $path = variable_get('solrsearch_path', '/solr');
+ $url = "http://{$host}:{$port}{$path}{$stopwords_url}";
+ $result = drupal_http_request($url);
+ if ($result->code != 200) {
+ return array();
+ }
+ $words = array();
+ foreach (explode("\n", $result->data) as $line) {
+ if (drupal_substr($line, 0, 1) == "#") {
+ continue;
+ }
+ if ($word = trim($line)) {
+ $words[] = $word;
+ }
+ }
+ $flag = true;
+ return $words;
+}
+
+/**
+ * Wrapper around variable_get() for variable solrsearch_autocomplete_widget.
+ */
+function solrsearch_autocomplete_variable_get_widget() {
+ return variable_get('solrsearch_autocomplete_widget', 'custom');
+}
+
+/**
+ * Wrapper around variable_get() for variable solrsearch_autocomplete_suggest_keywords.
+ */
+function solrsearch_autocomplete_variable_get_suggest_keywords() {
+ return variable_get('solrsearch_autocomplete_suggest_keywords', 1);
+}
+
+/**
+ * Wrapper around variable_get() for variable solrsearch_autocomplete_suggest_spellcheck.
+ */
+function solrsearch_autocomplete_variable_get_suggest_spellcheck() {
+ return variable_get('solrsearch_autocomplete_suggest_spellcheck', 1);
+}
+
+/**
+ * Wrapper around variable_get() for variable solrsearch_autocomplete_counts.
+ */
+function solrsearch_autocomplete_variable_get_counts() {
+ return variable_get('solrsearch_autocomplete_counts', TRUE);
+}
+
+/**
+ * Alter the solrsearch.module "advanced settings" form.
+ */
+function solrsearch_autocomplete_form_solrsearch_settings_alter(&$form, $form_state) {
+ $form['advanced']['solrsearch_autocomplete_widget'] = array(
+ '#type' => 'radios',
+ '#title' => t('Autocomplete widget to use'),
+ '#description' => t('The custom widget provides instant search upon selection, whereas the Drupal widget needs the user to hit Enter or click on the Search button. If you are having problems, try switching to the default Drupal autocomplete widget.'),
+ '#options' => array('custom' => t('Custom autocomplete widget'), 'drupal' => t('Drupal core autocomplete widget')),
+ '#default_value' => solrsearch_autocomplete_variable_get_widget(),
+ );
+ $form['advanced']['solrsearch_autocomplete_suggest_keywords'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Enable additional keyword suggestions on the autocomplete widget'),
+ '#description' => t('Suggest words to add to the currently typed-in words. E.g.: typing "blue" might suggest "blue bike" or "blue shirt".'),
+ '#default_value' => solrsearch_autocomplete_variable_get_suggest_keywords(),
+ );
+ $form['advanced']['solrsearch_autocomplete_suggest_spellcheck'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Enable spellchecker suggestions on the autocomplete widget'),
+ '#description' => t('Suggest corrections to the currently typed-in words. E.g.: typing "rec" or "redd" might suggest "red".'),
+ '#default_value' => solrsearch_autocomplete_variable_get_suggest_spellcheck(),
+ );
+ $form['advanced']['solrsearch_autocomplete_counts'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Enable counts in autocomplete widget suggestions'),
+ '#description' => t('WARNING: Counts shown alongside suggestions might be lower than the actual result count due to stemming and minimum match (mm) settings in solrconfig.xml.'),
+ '#default_value' => solrsearch_autocomplete_variable_get_counts(),
+ );
+}
diff -r 000000000000 -r 015d06b10d37 sites/all/themes/mpiwgDev/README.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/themes/mpiwgDev/README.txt Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,25 @@
+
+ABOUT STARK
+-----------
+
+The Stark theme is provided for demonstration purposes; it uses Drupal's default
+HTML markup and CSS styles. It can be used as a troubleshooting tool to
+determine whether module-related CSS and JavaScript are interfering with a more
+complex theme, and can be used by designers interested in studying Drupal's
+default markup without the interference of changes commonly made by more complex
+themes.
+
+To avoid obscuring CSS added to the page by Drupal or a contrib module, the
+Stark theme itself has no styling, except just enough CSS to arrange the page in
+a traditional "Header, sidebars, content, and footer" layout. See the layout.css
+file for more information.
+
+
+ABOUT DRUPAL THEMING
+--------------------
+
+To learn how to build your own custom theme and override Drupal's default code,
+see the Theming Guide: http://drupal.org/theme-guide
+
+See the sites/all/themes/README.txt for more information on where to place your
+custom themes to ensure easy maintenance and upgrades.
diff -r 000000000000 -r 015d06b10d37 sites/all/themes/mpiwgDev/block.tpl.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/themes/mpiwgDev/block.tpl.php Wed Jul 31 13:49:13 2013 +0200
@@ -0,0 +1,56 @@
+subject: Block title.
+ * - $content: Block content.
+ * - $block->module: Module that generated the block.
+ * - $block->delta: An ID for the block, unique within each module.
+ * - $block->region: The block region embedding the current block.
+ * - $classes: String of classes that can be used to style contextually through
+ * CSS. It can be manipulated through the variable $classes_array from
+ * preprocess functions. The default values can be one or more of the
+ * following:
+ * - block: The current template type, i.e., "theming hook".
+ * - block-[module]: The module generating the block. For example, the user
+ * module is responsible for handling the default user navigation block. In
+ * that case the class would be 'block-user'.
+ * - $title_prefix (array): An array containing additional output populated by
+ * modules, intended to be displayed in front of the main title tag that
+ * appears in the template.
+ * - $title_suffix (array): An array containing additional output populated by
+ * modules, intended to be displayed after the main title tag that appears in
+ * the template.
+ *
+ * Helper variables:
+ * - $classes_array: Array of html class attribute values. It is flattened
+ * into a string within the variable $classes.
+ * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region.
+ * - $zebra: Same output as $block_zebra but independent of any block region.
+ * - $block_id: Counter dependent on each block region.
+ * - $id: Same output as $block_id but independent of any block region.
+ * - $is_front: Flags true when presented in the front page.
+ * - $logged_in: Flags true when the current user is a logged-in member.
+ * - $is_admin: Flags true when the current user is an administrator.
+ * - $block_html_id: A valid HTML ID and guaranteed unique.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_block()
+ * @see template_process()
+ *
+ * @ingroup themeable
+ */
+?>
+
+ Maecenas id porttitor Ut enim ad minim veniam, quis nostrudfelis.
+ Laboris nisi ut aliquip ex ea.
+
+
+
+
+
Lorem ipsum dolor
+
+
+ Sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
+ nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+ commodo consequat. Maecenas id porttitor Ut enim ad minim veniam, quis nostr udfelis.
+