diff --git a/vendor/plugins/acts_as_solr/.gitignore b/vendor/plugins/acts_as_solr/.gitignore
new file mode 100644
index 0000000..d295b20
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/.gitignore
@@ -0,0 +1,8 @@
+*.log
+*.log
+*_pid
+coverage/*
+coverage.data
+solr/solr/data/*
+.svn
+test/db/*.db
diff --git a/vendor/plugins/acts_as_solr/CHANGE_LOG b/vendor/plugins/acts_as_solr/CHANGE_LOG
new file mode 100644
index 0000000..6f4588b
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/CHANGE_LOG
@@ -0,0 +1,233 @@
+== CHANGE_LOG
+=== Development
+NEW:: A unit test suite based on Shoulda, not requiring a running Solr or a Rails environment. (Mathias Meyer)
+NEW:: Added the :offline option to the acts_as_solr method. (Mathias Meyer)
+NEW:: Added :lazy flag to find_by_solr, and with that support to load records lazily. (Mathias Meyer)
+FIX:: Added test: to solr.yml so you don't need to do this by hand. (Ken Harris)
+FIX:: Updated bundled Solr to 1.3. (Mathias Meyer)
+FIX:: Updated bundled solr-ruby to 0.0.6 which comes bundled with Solr 1.3. (Mathias Meyer)
+FIX:: Improved logging of the reindex rake task. (David Stevenson)
+FIX:: Added requirement for libxml-ruby > 0.7, if libxml-ruby is installed. (David Stevenson)
+FIX:: Ruby 1.9 compatibility fixes. (David Palm)
+FIX:: Fixed compatibility with Desert by renaming environment.rb to solr_environment.rb. (David Stevenson)
+FIX:: Moved the require of solr_environment only into tasks that need it. (David Stevenson)
+NEW:: Added support to alias fields and includes using the option :as for acts_as_solr. See the RDoc for details. (Nick Hengeveld)
+NEW:: Added support to attach the score to multi search results. (Mathias Meyer)
+NEW:: Added support for facets on date fields. (Curtis Hatter)
+
+=== 06-18-2007: Version 0.9
+NEW:: Added the option :scores when doing a search. If set to true this will return the score as a 'solr_score' attribute or each one of the instances found
+ books = Book.find_by_solr 'ruby OR splinter', :scores => true
+ books.records.first.solr_score
+ => 1.21321397
+ books.records.last.solr_score
+ => 0.12321548
+
+NEW:: Major change on the way the results returned are accessed.
+ books = Book.find_by_solr 'ruby'
+ # the above will return a SearchResults class with 4 methods:
+ # docs|results|records: will return an array of records found
+ #
+ # books.records.is_a?(Array)
+ # => true
+ #
+ # total|num_found|total_hits: will return the total number of records found
+ #
+ # books.total
+ # => 2
+ #
+ # facets: will return the facets when doing a faceted search
+ #
+ # max_score|highest_score: returns the highest score found
+ #
+ # books.max_score
+ # => 1.3213213
+
+NEW:: Integrating acts_as_solr to use solr-ruby as the 'backend'. Integration based on the patch submitted by Erik Hatcher
+NEW:: Re-factoring rebuild_solr_index to allow adds to be done in batch; and if a finder block is given, it will be called to retrieve the items to index. (thanks Daniel E.)
+NEW:: Adding the option to specify the port Solr should start when using rake solr:start
+ rake solr:start RAILS_ENV=your_env PORT=XX
+
+NEW:: Adding deprecation warning for the :background configuration option. It will no longer be updated.
+NEW:: Adding support for models that use a primary key other than integer
+ class Posting < ActiveRecord::Base
+ set_primary_key 'guid' #string
+ #make sure you set the :primary_key_field => 'pk_s' if you wish to use a string field as the primary key
+ acts_as_solr({},{:primary_key_field => 'pk_s'})
+ end
+
+FIX:: Disabling of storing most fields. Storage isn't useful for acts_as_solr in any field other than the pk and id fields. It just takes up space and time. (thanks Daniel E.)
+FIX:: Re-factoring code submitted by Daniel E.
+NEW:: Adding an :auto_commit option that will only send the commit command to Solr if it is set to true
+ class Author < ActiveRecord::Base
+ acts_as_solr :auto_commit => false
+ end
+
+FIX:: Fixing bug on rake's test task
+FIX:: Making acts_as_solr's Post class compatible with Solr 1.2 (thanks Si)
+NEW:: Adding Solr 1.2
+FIX:: Removing Solr 1.1
+NEW:: Adding a conditional :if option to the acts_as_solr call. It behaves the same way ActiveRecord's :if argument option does.
+ class Electronic < ActiveRecord::Base
+ acts_as_solr :if => proc{|record| record.is_active?}
+ end
+
+NEW:: Adding fixtures to Solr index when using rake db:fixtures:load
+FIX:: Fixing boost warning messages
+FIX:: Fixing bug when adding a facet to a field that contains boost
+NEW:: Deprecating find_with_facet and combining functionality with find_by_solr
+NEW:: Adding the option to :exclude_fields when indexing a model
+ class User < ActiveRecord::Base
+ acts_as_solr :exclude_fields => [:password, :login, :credit_card_number]
+ end
+
+FIX:: Fixing branch bug on older ruby version
+NEW:: Adding boost support for fields and documents being indexed:
+ class Electronic < ActiveRecord::Base
+ # You can add boosting on a per-field basis or on the entire document
+ acts_as_solr :fields => [{:price => {:boost => 5.0}}], :boost => 5.0
+ end
+
+FIX:: Fixed the acts_as_solr limitation to only accept test|development|production environments.
+
+=== 05-16-2007: Version 0.8.5
+FIX:: There's no need to specify the :field_types anymore when doing a search in a model that specifies a field type for a field.
+FIX:: Better handling of nil values from indexed fields. Solr complained when indexing fields with field type and the field values being passed as nils.
+NEW:: Adding Solr sort (order by) option to the search query (thanks Kevin Hunt)
+FIX:: Applying patch suggested for increasing the Solr commit speed (thanks Mourad Hammiche)
+FIX:: Updated documentation
+
+=== 05-10-2007: Version 0.8
+NEW: New video tutorial
+NEW: Faceted search has been implemented and its possible to 'drill-down' on the facets
+NEW: New rake tasks you can use to start/stop the solr server in test, development and production environments: (thanks Matt Clark)
+ rake solr:start|stop RAILS_ENV=test|development|production (defaults to development if none given)
+
+NEW: Changes to the plugin's test framework and it now supports Sqlite as well (thanks Matt Clark)
+FIX: Patch applied (thanks Micah) that allows one to have multiple solr instances in the same servlet
+FIX: Patch applied (thanks Micah) that allows indexing of STIs
+FIX: Patch applied (thanks Gordon) that allows the plugin to use a table's primary key different than 'id'
+FIX: Returning empty array instead of empty strings when no records are found
+FIX: Problem with unit tests failing due to order of the tests and speed of the commits
+
+=== 02-16-2007: Version 0.7
+NEW: You can now specify the field types when indexing and searching if
+you'd like to preserve its original type:
+
+Indexing
+
+Each field passed can also be a hash with the value being a field type
+
+ class Electronic < ActiveRecord::Base
+ acts_as_solr :fields => [{:price => :range_float}, {:current_time => :date}]
+ def current_time
+ Time.now
+ end
+ end
+
+Searching
+ Electronic.find_by_solr "ipod AND price:[* TO 59.99]",
+ :field_types => [{:price => :range_float}]
+
+The field types accepted are:
+:float:: Index the field value as a float (ie.: 12.87)
+:integer:: Index the field value as an integer (ie.: 31)
+:boolean:: Index the field value as a boolean (ie.: true/false)
+:date:: Index the field value as a date (ie.: Wed Nov 15 23:13:03 PST 2006)
+:string:: Index the field value as a text string, not applying the same indexing filters as a regular text field
+:range_integer:: Index the field value for integer range queries (ie.:[5 TO 20])
+:range_float:: Index the field value for float range queries (ie.:[14.56 TO 19.99])
+
+Setting the field type preserves its original type when indexed
+
+FIX: Fixing sorting bug. Thanks for the catch Laurel
+
+FIX: Fixing small bug when installing the plugin
+
+NEW: Adding the :additional_fields option to the acts_as_solr method
+
+=== 02-05-2007: Version 0.6.5
+NEW:: Added multi-model search, which can be used to execute a search across multiple models:
+ Book.multi_solr_search "Napoleon OR Tom", :models => [Movie]
+
+====options:
+Accepts the same options as find_by_solr plus:
+models:: The additional models you'd like to include in the search
+results_format:: Specify the format of the results found
+ :objects :: Will return an array with the results being objects (default). Example:
+ Book.multi_solr_search "Napoleon OR Tom", :models => [Movie], :results_format => :objects
+ :ids :: Will return an array with the ids of each entry found. Example:
+ Book.multi_solr_search "Napoleon OR Tom", :models => [Movie], :results_format => :ids
+ => [{"id" => "Movie:1"},{"id" => Book:1}]
+ Where the value of each array is as Model:instance_id
+
+=== 02-03-2007: Version 0.6
+NEW:: Added basic faceted search functionality for indexing and searching:
+
+==== Indexing:
+
+ class Electronic < ActiveRecord::Base
+ acts_as_solr :facets => [:category, :manufacturer]
+ end
+
+==== Searching:
+
+ Electronic.find_with_facet "memory", :facets => {:fields =>[:category]}
+
+=== 01-15-2007: Version 0.5
+NEW:: Added model association indexing, which means you can include any :has_one, :has_many,
+:belongs_to and :has_and_belongs_to_many association to be indexed:
+
+ class Category < ActiveRecord::Base
+ has_many :books
+ acts_as_solr :include => [:books]
+ end
+
+ class Book < ActiveRecord::Base
+ belongs_to :category
+ acts_as_solr :include => [:category]
+ end
+
+=== 01-11-2007:
+NEW:: Added the acts_as_solr's plugin tests
+
+=== 11-07-2006: Version 0.4
+NEW:: Added :background option, which takes and integer value (in minutes) to wait before committing the changes to Solr. This depends on rail_cron being installed. By setting up the background job we prevent the users from having to wait for Solr records to be created, and we keep from updating the index over and over for quickly successive changes. (Rob Kaufman)
+
+=== 11-02-2006: Version 0.3
+NEW:: Added a method (Model.count_by_solr) that returns the total number of documents found based on query passed
+NEW:: Added configuration for production and development environments
+
+=== 10-21-2006: Version 0.2
+PLUGIN
+FIX:: Fixed bug when mixing search-by-field and 'free' search: Model.find_by_solr 'solr AND name:Thiago'
+FIX:: Fixed bug with multi-terms search: Book.find_by_solr 'anteater john'
+FIX:: Fixed bug when including more than one search field: Model.find_by_solr 'name:Thiago AND engine:Solr'
+FIX:: Fixed bug when rebuilding the index, it wasn't saving the data
+NEW:: Added the ability to index custom methods from a model as search fields
+NEW:: Added a search method (Model.find_id_by_solr) that will return only the id of the results
+
+SCHEMA.XML
+NEW:: Added a new field:
+NEW:: Added a default search field: default
+FIX:: Changed the defaultOperator to AND instead of OR
+
+=== 09-29-2006: Version 0.1
+PLUGIN
+NEW:: Included the option of having a Solr config file inside the rails env.
+NEW:: Added the ability of indexing only certain fields, if you chose to.
+NEW:: Added configuration options
+NEW:: Changed the way the search was done:
+ Old: You were forced the specify the field you wanted to look for
+ ('field:value') and you had to specify a default search field as
+ well, for when you didn't include the 'field' in the search term
+ New: The new search features include:
+ - You don't have to specify a default search field;
+ - You are not forced to include the field name in the search term,
+ unless you choose to search for a specific field ('name:Thiago');
+ - You can pass the starting row and the number of rows per page,
+ which is usefull for pagination
+NEW:: Included a method to rebuild the index files
+
+SCHEMA.XML
+NEW:: Created an optimized version of the config file to better work with this plugin
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/LICENSE b/vendor/plugins/acts_as_solr/LICENSE
new file mode 100644
index 0000000..e4a2ef5
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2006 Erik Hatcher, Thiago Jackiw
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/README.markdown b/vendor/plugins/acts_as_solr/README.markdown
new file mode 100644
index 0000000..6dcae24
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/README.markdown
@@ -0,0 +1,94 @@
+`acts_as_solr` Rails plugin
+======
+This plugin adds full text search capabilities and many other nifty features from Apache's [Solr](http://lucene.apache.org/solr/) to any Rails model.
+It was based on the first draft by Erik Hatcher.
+
+Current Release
+======
+The current stable release is v0.9 and was released on 06-18-2007.
+
+Changes
+======
+Please refer to the CHANGE_LOG
+
+Installation
+======
+
+For Rails >= 2.1:
+
+ script/plugin install git://github.com/mattmatt/acts_as_solr.git
+
+For Rails < 2.1:
+
+ cd vendor/plugins
+ git clone git://github.com/mattmatt/acts_as_solr.git
+ rm -rf acts_as_solr/.git
+
+Make sure you copy `vendor/plugins/acts_as_solr/config/solr.yml` to your Rails
+application's config directory, when you install via `git clone`.
+
+Requirements
+------
+* Java Runtime Environment(JRE) 1.5 aka 5.0 [http://www.java.com/en/download/index.jsp](http://www.java.com/en/download/index.jsp)
+* If you have libxml-ruby installed, make sure it's at least version 0.7
+
+Configuration
+======
+Basically everything is configured to work out of the box. You can use `rake solr:start` and `rake solr:stop`
+to start and stop the Solr web server (an embedded Jetty). If the default JVM options aren't suitable for
+your environment, you can configure them in solr.yml with the option `jvm_options`. There is a default
+set for the production environment to have some more memory available for the JVM than the defaults, but
+feel free to change them to your liking.
+
+Basic Usage
+======
+
+# Just include the line below to any of your ActiveRecord models:
+ acts_as_solr
+
+# Or if you want, you can specify only the fields that should be indexed:
+ acts_as_solr :fields => [:name, :author]
+
+# Then to find instances of your model, just do:
+ Model.find_by_solr(query) #query is a string representing your query
+
+# Please see ActsAsSolr::ActsMethods for a complete info
+
+
+
+
+`acts_as_solr` in your tests
+======
+To test code that uses `acts_as_solr` you must start a Solr server for the test environment. You can do that with `rake solr:start RAILS_ENV=test`
+
+However, if you would like to mock out Solr calls so that a Solr server is not needed (and your tests will run much faster), just add this to your `test_helper.rb` or similar:
+
+
+
+([via](http://www.subelsky.com/2007/10/actsassolr-capistranhttpwwwbloggercomim.html#c1646308013209805416))
+
+Authors
+======
+Erik Hatcher: First draft
+Thiago Jackiw: Previous developer
+Luke Francl: Current developer
+Mathias Meyer: Current developer
+
+Support
+=======
+
+Check the [project website](http://mattmatt.github.com/acts_as_solr) or stop by the [Google Group](http://groups.google.com/group/acts_as_solr). Send bug reports through [GitHub Issues](http://github.com/mattmatt/acts_as_solr/issues).
+
+Release Information
+======
+Released under the MIT license.
+
+More info
+======
+The old [acts_as_solr homepage](http://acts-as-solr.railsfreaks.com) is no more. For more up-to-date information, check out the project page of the current mainline on [GitHub](http://github.com/mattmatt/acts_as_solr/wikis).
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/README.rdoc b/vendor/plugins/acts_as_solr/README.rdoc
new file mode 100644
index 0000000..5ec08d8
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/README.rdoc
@@ -0,0 +1,84 @@
+= acts_as_solr Rails plugin
+
+This plugin adds full text search capabilities and many other nifty features from Apache's Solr[http://lucene.apache.org/solr/] to any Rails model.
+It was based on the first draft by Erik Hatcher.
+
+== Current Release
+
+There is no numbered release yet, but the master branch is always considered stable.
+
+== Support
+
+Check the project website[http://mattmatt.github.com/acts_as_solr] or stop by the Google Group[http://groups.google.com/group/acts_as_solr]. Send bug reports through GitHub[http://github.com/mattmatt/acts_as_solr/issues].
+
+== Changes
+
+Please refer to the CHANGELOG[http://github.com/mattmatt/acts_as_solr/blob/master/CHANGE_LOG]
+
+== Installation
+
+For Rails >= 2.1:
+
+ script/plugin install git://github.com/mattmatt/acts_as_solr.git
+
+For Rails < 2.1:
+
+ cd vendor/plugins
+ git clone git://github.com/mattmatt/acts_as_solr.git
+ rm -rf acts_as_solr/.git
+
+Make sure you copy vendor/plugins/acts_as_solr/config/solr.yml to your Rails
+application's config directory, when you install via git clone.
+
+== Requirements
+
+* Java Runtime Environment(JRE) 1.5 aka 5.0 [http://www.java.com/en/download/index.jsp](http://www.java.com/en/download/index.jsp)
+* If you have libxml-ruby installed, make sure it's at least version 0.7
+
+== Configuration
+
+Basically everything is configured to work out of the box. You can use `rake solr:start` and `rake solr:stop`
+to start and stop the Solr web server (an embedded Jetty). If the default JVM options aren't suitable for
+your environment, you can configure them in solr.yml with the option `jvm_options`. There is a default
+set for the production environment to have some more memory available for the JVM than the defaults, but
+feel free to change them to your liking.
+
+== Basic Usage
+
+# Just include the line below to any of your ActiveRecord models:
+ acts_as_solr
+
+# Or if you want, you can specify only the fields that should be indexed:
+ acts_as_solr :fields => [:name, :author]
+
+# Then to find instances of your model, just do:
+ Model.find_by_solr(query) #query is a string representing your query
+
+# Please see ActsAsSolr::ActsMethods for a complete info
+
+== acts_as_solr in your tests
+
+To test code that uses acts_as_solr you must start a Solr server for the test environment. You can do that with
+
+ rake solr:start RAILS_ENV=test
+
+However, if you would like to mock out Solr calls so that a Solr server is not needed (and your tests will run much faster), just add this to your `test_helper.rb` or similar:
+
+ class ActsAsSolr::Post
+ def self.execute(request)
+ true
+ end
+ end
+
+(via[http://www.subelsky.com/2007/10/actsassolr-capistranhttpwwwbloggercomim.html#c1646308013209805416])
+
+== Authors
+
+Erik Hatcher: First draft
+Thiago Jackiw: Previous developer
+Luke Francl: Current developer
+Mathias Meyer: Current developer
+
+== Release Information
+
+Released under the MIT license.
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/Rakefile b/vendor/plugins/acts_as_solr/Rakefile
new file mode 100644
index 0000000..54b1744
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/Rakefile
@@ -0,0 +1,53 @@
+require 'rubygems'
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+Dir["#{File.dirname(__FILE__)}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
+
+desc "Default Task"
+task :default => [:test]
+
+desc "Runs the unit tests"
+task :test => "test:unit"
+
+namespace :test do
+ task :setup do
+ ENV['RAILS_ENV'] = "test"
+ require File.dirname(__FILE__) + '/config/solr_environment'
+ puts "Using " + DB
+ %x(mysql -u#{MYSQL_USER} < #{File.dirname(__FILE__) + "/test/fixtures/db_definitions/mysql.sql"}) if DB == 'mysql'
+
+ Rake::Task["test:migrate"].invoke
+ end
+
+ desc 'Measures test coverage using rcov'
+ task :rcov => :setup do
+ rm_f "coverage"
+ rm_f "coverage.data"
+ rcov = "rcov --rails --aggregate coverage.data --text-summary -Ilib"
+
+ system("#{rcov} --html #{Dir.glob('test/**/*_test.rb').join(' ')}")
+ system("open coverage/index.html") if PLATFORM['darwin']
+ end
+
+ desc 'Runs the functional tests, testing integration with Solr'
+ Rake::TestTask.new('functional' => :setup) do |t|
+ t.pattern = "test/functional/*_test.rb"
+ t.verbose = true
+ end
+
+ desc "Unit tests"
+ Rake::TestTask.new(:unit) do |t|
+ t.libs << 'test/unit'
+ t.pattern = "test/unit/*_shoulda.rb"
+ t.verbose = true
+ end
+end
+
+Rake::RDocTask.new do |rd|
+ rd.main = "README.rdoc"
+ rd.rdoc_dir = "rdoc"
+ rd.rdoc_files.exclude("lib/solr/**/*.rb", "lib/solr.rb")
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/TESTING_THE_PLUGIN b/vendor/plugins/acts_as_solr/TESTING_THE_PLUGIN
new file mode 100644
index 0000000..06d5d76
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/TESTING_THE_PLUGIN
@@ -0,0 +1,25 @@
+acts_as_solr comes with a quick and fast unit test suite, and with a longer-running
+functional test suite, the latter testing the actual integration with Solr.
+
+The unit test suite is written using Shoulda, so make sure you have a recent version
+installed.
+
+Running `rake test` or just `rake` will run both test suites. Use `rake test:unit` to
+just run the unit test suite.
+
+== How to run functional tests for this plugin:
+To run the acts_as_solr's plugin tests run the following steps:
+
+- create a MySQL database called "actsassolr_test" (if you want to use MySQL)
+
+- create a new Rails project, if needed (the plugin can only be tested from within a Rails project); move/checkout acts_as_solr into its vendor/plugins/, as usual
+
+- copy vendor/plugins/acts_as_solr/config/solr.yml to config/ (the Rails config folder)
+
+- rake solr:start RAILS_ENV=test
+
+- rake test:functional (Accepts the following arguments: DB=sqlite|mysql and MYSQL_USER=user)
+
+== Troubleshooting:
+If for some reason the tests don't run and you get MySQL errors, make sure you edit the MYSQL_USER entry under
+config/environment.rb. It's recommended to create or use a MySQL user with no password.
diff --git a/vendor/plugins/acts_as_solr/config/solr.yml b/vendor/plugins/acts_as_solr/config/solr.yml
new file mode 100644
index 0000000..84550f5
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/config/solr.yml
@@ -0,0 +1,15 @@
+# Config file for the acts_as_solr plugin.
+#
+# If you change the host or port number here, make sure you update
+# them in your Solr config file
+
+development:
+ url: http://127.0.0.1:8982/solr
+
+production:
+ url: http://127.0.0.1:8983/solr
+ jvm_options: -server -d64 -Xmx1024M -Xms64M
+
+test:
+ url: http://127.0.0.1:8981/solr
+
diff --git a/vendor/plugins/acts_as_solr/config/solr_environment.rb b/vendor/plugins/acts_as_solr/config/solr_environment.rb
new file mode 100644
index 0000000..3d4aeb7
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/config/solr_environment.rb
@@ -0,0 +1,22 @@
+ENV['RAILS_ENV'] = (ENV['RAILS_ENV'] || 'development').dup
+# RAILS_ROOT isn't defined yet, so figure it out.
+rails_root_dir = "#{File.dirname(File.expand_path(__FILE__))}/../../../../"
+SOLR_PATH = "#{File.dirname(File.expand_path(__FILE__))}/../solr" unless defined? SOLR_PATH
+
+SOLR_LOGS_PATH = "#{rails_root_dir}/log" unless defined? SOLR_LOGS_PATH
+SOLR_PIDS_PATH = "#{rails_root_dir}/tmp/pids" unless defined? SOLR_PIDS_PATH
+SOLR_DATA_PATH = "#{rails_root_dir}/solr/#{ENV['RAILS_ENV']}" unless defined? SOLR_DATA_PATH
+
+unless defined? SOLR_PORT
+ config = YAML::load_file(rails_root_dir+'/config/solr.yml')
+
+ SOLR_PORT = ENV['PORT'] || URI.parse(config[ENV['RAILS_ENV']]['url']).port
+end
+
+SOLR_JVM_OPTIONS = config[ENV['RAILS_ENV']]['jvm_options'] unless defined? SOLR_JVM_OPTIONS
+
+if ENV['RAILS_ENV'] == 'test'
+ DB = (ENV['DB'] ? ENV['DB'] : 'mysql') unless defined?(DB)
+ MYSQL_USER = (ENV['MYSQL_USER'].nil? ? 'root' : ENV['MYSQL_USER']) unless defined? MYSQL_USER
+ require File.join(File.dirname(File.expand_path(__FILE__)), '..', 'test', 'db', 'connections', DB, 'connection.rb')
+end
diff --git a/vendor/plugins/acts_as_solr/init.rb b/vendor/plugins/acts_as_solr/init.rb
new file mode 100644
index 0000000..fcbeb75
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/init.rb
@@ -0,0 +1,21 @@
+# Copyright (c) 2006 Erik Hatcher, Thiago Jackiw
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+require 'acts_as_solr'
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/install.rb b/vendor/plugins/acts_as_solr/install.rb
new file mode 100644
index 0000000..99ad8ff
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/install.rb
@@ -0,0 +1,11 @@
+require 'fileutils'
+
+def install(file)
+ puts "Installing: #{file}"
+ target = File.join(File.dirname(__FILE__), '..', '..', '..', file)
+ FileUtils.cp File.join(File.dirname(__FILE__), file), target
+ dir_to_rename = File.dirname(__FILE__) + '/../trunk'
+ FileUtils.mv(dir_to_rename, File.dirname(__FILE__) + '/../acts_as_solr') if File.exists? dir_to_rename
+end
+
+install File.join( 'config', 'solr.yml' )
diff --git a/vendor/plugins/acts_as_solr/lib/acts_as_solr.rb b/vendor/plugins/acts_as_solr/lib/acts_as_solr.rb
new file mode 100644
index 0000000..b8d44a9
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/acts_as_solr.rb
@@ -0,0 +1,59 @@
+# Copyright (c) 2006 Erik Hatcher, Thiago Jackiw
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+require 'active_record'
+require 'rexml/document'
+require 'net/http'
+require 'yaml'
+
+require File.dirname(__FILE__) + '/solr'
+require File.dirname(__FILE__) + '/acts_methods'
+require File.dirname(__FILE__) + '/class_methods'
+require File.dirname(__FILE__) + '/instance_methods'
+require File.dirname(__FILE__) + '/common_methods'
+require File.dirname(__FILE__) + '/deprecation'
+require File.dirname(__FILE__) + '/search_results'
+require File.dirname(__FILE__) + '/lazy_document'
+module ActsAsSolr
+
+ class Post
+ def self.execute(request)
+ begin
+ if File.exists?(RAILS_ROOT+'/config/solr.yml')
+ config = YAML::load_file(RAILS_ROOT+'/config/solr.yml')
+ url = config[RAILS_ENV]['url']
+ # for backwards compatibility
+ url ||= "http://#{config[RAILS_ENV]['host']}:#{config[RAILS_ENV]['port']}/#{config[RAILS_ENV]['servlet_path']}"
+ else
+ url = 'http://localhost:8982/solr'
+ end
+ connection = Solr::Connection.new(url)
+ return connection.send(request)
+ rescue
+ raise "Couldn't connect to the Solr server at #{url}. #{$!}"
+ false
+ end
+ end
+ end
+
+end
+
+# reopen ActiveRecord and include the acts_as_solr method
+ActiveRecord::Base.extend ActsAsSolr::ActsMethods
diff --git a/vendor/plugins/acts_as_solr/lib/acts_methods.rb b/vendor/plugins/acts_as_solr/lib/acts_methods.rb
new file mode 100644
index 0000000..20bed88
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/acts_methods.rb
@@ -0,0 +1,279 @@
+module ActsAsSolr #:nodoc:
+
+ module ActsMethods
+
+ # declares a class as solr-searchable
+ #
+ # ==== options:
+ # fields:: This option can be used to specify only the fields you'd
+ # like to index. If not given, all the attributes from the
+ # class will be indexed. You can also use this option to
+ # include methods that should be indexed as fields
+ #
+ # class Movie < ActiveRecord::Base
+ # acts_as_solr :fields => [:name, :description, :current_time]
+ # def current_time
+ # Time.now.to_s
+ # end
+ # end
+ #
+ # Each field passed can also be a hash with the value being a field type
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :fields => [{:price => :range_float}]
+ # def current_time
+ # Time.now
+ # end
+ # end
+ #
+ # The field types accepted are:
+ #
+ # :float:: Index the field value as a float (ie.: 12.87)
+ # :integer:: Index the field value as an integer (ie.: 31)
+ # :boolean:: Index the field value as a boolean (ie.: true/false)
+ # :date:: Index the field value as a date (ie.: Wed Nov 15 23:13:03 PST 2006)
+ # :string:: Index the field value as a text string, not applying the same indexing
+ # filters as a regular text field
+ # :range_integer:: Index the field value for integer range queries (ie.:[5 TO 20])
+ # :range_float:: Index the field value for float range queries (ie.:[14.56 TO 19.99])
+ #
+ # Setting the field type preserves its original type when indexed
+ #
+ # The field may also be passed with a hash value containing options
+ #
+ # class Author < ActiveRecord::Base
+ # acts_as_solr :fields => [{:full_name => {:type => :text, :as => :name}}]
+ # def full_name
+ # self.first_name + ' ' + self.last_name
+ # end
+ # end
+ #
+ # The options accepted are:
+ #
+ # :type:: Index the field using the specified type
+ # :as:: Index the field using the specified field name
+ #
+ # additional_fields:: This option takes fields to be include in the index
+ # in addition to those derived from the database. You
+ # can also use this option to include custom fields
+ # derived from methods you define. This option will be
+ # ignored if the :fields option is given. It also accepts
+ # the same field types as the option above
+ #
+ # class Movie < ActiveRecord::Base
+ # acts_as_solr :additional_fields => [:current_time]
+ # def current_time
+ # Time.now.to_s
+ # end
+ # end
+ #
+ # exclude_fields:: This option taks an array of fields that should be ignored from indexing:
+ #
+ # class User < ActiveRecord::Base
+ # acts_as_solr :exclude_fields => [:password, :login, :credit_card_number]
+ # end
+ #
+ # include:: This option can be used for association indexing, which
+ # means you can include any :has_one, :has_many, :belongs_to
+ # and :has_and_belongs_to_many association to be indexed:
+ #
+ # class Category < ActiveRecord::Base
+ # has_many :books
+ # acts_as_solr :include => [:books]
+ # end
+ #
+ # Each association may also be specified as a hash with an option hash as a value
+ #
+ # class Book < ActiveRecord::Base
+ # belongs_to :author
+ # has_many :distribution_companies
+ # has_many :copyright_dates
+ # has_many :media_types
+ # acts_as_solr(
+ # :fields => [:name, :description],
+ # :include => [
+ # {:author => {:using => :fullname, :as => :name}},
+ # {:media_types => {:using => lambda{|media| type_lookup(media.id)}}}
+ # {:distribution_companies => {:as => :distributor, :multivalued => true}},
+ # {:copyright_dates => {:as => :copyright, :type => :date}}
+ # ]
+ # ]
+ #
+ # The options accepted are:
+ #
+ # :type:: Index the associated objects using the specified type
+ # :as:: Index the associated objects using the specified field name
+ # :using:: Index the associated objects using the value returned by the specified method or proc. If a method
+ # symbol is supplied, it will be sent to each object to look up the value to index; if a proc is
+ # supplied, it will be called once for each object with the object as the only argument
+ # :multivalued:: Index the associated objects using one field for each object rather than joining them
+ # all into a single field
+ #
+ # facets:: This option can be used to specify the fields you'd like to
+ # index as facet fields
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :facets => [:category, :manufacturer]
+ # end
+ #
+ # boost:: You can pass a boost (float) value that will be used to boost the document and/or a field. To specify a more
+ # boost for the document, you can either pass a block or a symbol. The block will be called with the record
+ # as an argument, a symbol will result in the according method being called:
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :fields => [{:price => {:boost => 5.0}}], :boost => 10.0
+ # end
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :fields => [{:price => {:boost => 5.0}}], :boost => proc {|record| record.id + 120*37}
+ # end
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :fields => [{:price => {:boost => :price_rating}}], :boost => 10.0
+ # end
+ #
+ # if:: Only indexes the record if the condition evaluated is true. The argument has to be
+ # either a symbol, string (to be eval'ed), proc/method, or class implementing a static
+ # validation method. It behaves the same way as ActiveRecord's :if option.
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :if => proc{|record| record.is_active?}
+ # end
+ #
+ # offline:: Assumes that your using an outside mechanism to explicitly trigger indexing records, e.g. you only
+ # want to update your index through some asynchronous mechanism. Will accept either a boolean or a block
+ # that will be evaluated before actually contacting the index for saving or destroying a document. Defaults
+ # to false. It doesn't refer to the mechanism of an offline index in general, but just to get a centralized point
+ # where you can control indexing. Note: This is only enabled for saving records. acts_as_solr doesn't always like
+ # it, if you have a different number of results coming from the database and the index. This might be rectified in
+ # another patch to support lazy loading.
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :offline => proc {|record| record.automatic_indexing_disabled?}
+ # end
+ #
+ # auto_commit:: The commit command will be sent to Solr only if its value is set to true:
+ #
+ # class Author < ActiveRecord::Base
+ # acts_as_solr :auto_commit => false
+ # end
+ #
+ def acts_as_solr(options={}, solr_options={})
+
+ extend ClassMethods
+ include InstanceMethods
+ include CommonMethods
+ include ParserMethods
+
+ cattr_accessor :configuration
+ cattr_accessor :solr_configuration
+
+ self.configuration = {
+ :fields => nil,
+ :additional_fields => nil,
+ :exclude_fields => [],
+ :auto_commit => true,
+ :include => nil,
+ :facets => nil,
+ :boost => nil,
+ :if => "true",
+ :offline => false
+ }
+ self.solr_configuration = {
+ :type_field => "type_s",
+ :primary_key_field => "pk_i",
+ :default_boost => 1.0
+ }
+
+ configuration.update(options) if options.is_a?(Hash)
+ solr_configuration.update(solr_options) if solr_options.is_a?(Hash)
+ Deprecation.validate_index(configuration)
+
+ configuration[:solr_fields] = {}
+ configuration[:solr_includes] = {}
+
+ after_save :solr_save
+ after_destroy :solr_destroy
+
+ if configuration[:fields].respond_to?(:each)
+ process_fields(configuration[:fields])
+ else
+ process_fields(self.new.attributes.keys.map { |k| k.to_sym })
+ process_fields(configuration[:additional_fields])
+ end
+
+ if configuration[:include].respond_to?(:each)
+ process_includes(configuration[:include])
+ end
+ end
+
+ private
+ def get_field_value(field)
+ field_name, options = determine_field_name_and_options(field)
+ configuration[:solr_fields][field_name] = options
+
+ define_method("#{field_name}_for_solr".to_sym) do
+ begin
+ value = self[field_name] || self.instance_variable_get("@#{field_name.to_s}".to_sym) || self.send(field_name.to_sym)
+ case options[:type]
+ # format dates properly; return nil for nil dates
+ when :date
+ value ? (value.respond_to?(:utc) ? value.utc : value).strftime("%Y-%m-%dT%H:%M:%SZ") : nil
+ else value
+ end
+ rescue
+ puts $!
+ logger.debug "There was a problem getting the value for the field '#{field_name}': #{$!}"
+ value = ''
+ end
+ end
+ end
+
+ def process_fields(raw_field)
+ if raw_field.respond_to?(:each)
+ raw_field.each do |field|
+ next if configuration[:exclude_fields].include?(field)
+ get_field_value(field)
+ end
+ end
+ end
+
+ def process_includes(includes)
+ if includes.respond_to?(:each)
+ includes.each do |assoc|
+ field_name, options = determine_field_name_and_options(assoc)
+ configuration[:solr_includes][field_name] = options
+ end
+ end
+ end
+
+ def determine_field_name_and_options(field)
+ if field.is_a?(Hash)
+ name = field.keys.first
+ options = field.values.first
+ if options.is_a?(Hash)
+ [name, {:type => type_for_field(field)}.merge(options)]
+ else
+ [name, {:type => options}]
+ end
+ else
+ [field, {:type => type_for_field(field)}]
+ end
+ end
+
+ def type_for_field(field)
+ if configuration[:facets] && configuration[:facets].include?(field)
+ :facet
+ elsif column = columns_hash[field.to_s]
+ case column.type
+ when :string then :text
+ when :datetime then :date
+ when :time then :date
+ else column.type
+ end
+ else
+ :text
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/class_methods.rb b/vendor/plugins/acts_as_solr/lib/class_methods.rb
new file mode 100644
index 0000000..6e8613c
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/class_methods.rb
@@ -0,0 +1,239 @@
+require File.dirname(__FILE__) + '/common_methods'
+require File.dirname(__FILE__) + '/parser_methods'
+
+module ActsAsSolr #:nodoc:
+
+ module ClassMethods
+ include CommonMethods
+ include ParserMethods
+
+ # Finds instances of a model. Terms are ANDed by default, can be overwritten
+ # by using OR between terms
+ #
+ # Here's a sample (untested) code for your controller:
+ #
+ # def search
+ # results = Book.find_by_solr params[:query]
+ # end
+ #
+ # You can also search for specific fields by searching for 'field:value'
+ #
+ # ====options:
+ # offset:: - The first document to be retrieved (offset)
+ # limit:: - The number of rows per page
+ # order:: - Orders (sort by) the result set using a given criteria:
+ #
+ # Book.find_by_solr 'ruby', :order => 'description asc'
+ #
+ # field_types:: This option is deprecated and will be obsolete by version 1.0.
+ # There's no need to specify the :field_types anymore when doing a
+ # search in a model that specifies a field type for a field. The field
+ # types are automatically traced back when they're included.
+ #
+ # class Electronic < ActiveRecord::Base
+ # acts_as_solr :fields => [{:price => :range_float}]
+ # end
+ #
+ # facets:: This option argument accepts the following arguments:
+ # fields:: The fields to be included in the faceted search (Solr's facet.field)
+ # query:: The queries to be included in the faceted search (Solr's facet.query)
+ # zeros:: Display facets with count of zero. (true|false)
+ # sort:: Sorts the faceted resuls by highest to lowest count. (true|false)
+ # browse:: This is where the 'drill-down' of the facets work. Accepts an array of
+ # fields in the format "facet_field:term"
+ # mincount:: Replacement for zeros (it has been deprecated in Solr). Specifies the
+ # minimum count necessary for a facet field to be returned. (Solr's
+ # facet.mincount) Overrides :zeros if it is specified. Default is 0.
+ #
+ # dates:: Run date faceted queries using the following arguments:
+ # fields:: The fields to be included in the faceted date search (Solr's facet.date).
+ # It may be either a String/Symbol or Hash. If it's a hash the options are the
+ # same as date_facets minus the fields option (i.e., :start:, :end, :gap, :other,
+ # :between). These options if provided will override the base options.
+ # (Solr's f..date.=).
+ # start:: The lower bound for the first date range for all Date Faceting. Required if
+ # :fields is present
+ # end:: The upper bound for the last date range for all Date Faceting. Required if
+ # :fields is prsent
+ # gap:: The size of each date range expressed as an interval to be added to the lower
+ # bound using the DateMathParser syntax. Required if :fields is prsent
+ # hardend:: A Boolean parameter instructing Solr what do do in the event that
+ # facet.date.gap does not divide evenly between facet.date.start and facet.date.end.
+ # other:: This param indicates that in addition to the counts for each date range
+ # constraint between facet.date.start and facet.date.end, other counds should be
+ # calculated. May specify more then one in an Array. The possible options are:
+ # before:: - all records with lower bound less than start
+ # after:: - all records with upper bound greater than end
+ # between:: - all records with field values between start and end
+ # none:: - compute no other bounds (useful in per field assignment)
+ # all:: - shortcut for before, after, and between
+ # filter:: Similar to :query option provided by :facets, in that accepts an array of
+ # of date queries to limit results. Can not be used as a part of a :field hash.
+ # This is the only option that can be used if :fields is not present.
+ #
+ # Example:
+ #
+ # Electronic.find_by_solr "memory", :facets => {:zeros => false, :sort => true,
+ # :query => ["price:[* TO 200]",
+ # "price:[200 TO 500]",
+ # "price:[500 TO *]"],
+ # :fields => [:category, :manufacturer],
+ # :browse => ["category:Memory","manufacturer:Someone"]}
+ #
+ #
+ # Examples of date faceting:
+ #
+ # basic:
+ # Electronic.find_by_solr "memory", :facets => {:dates => {:fields => [:updated_at, :created_at],
+ # :start => 'NOW-10YEARS/DAY', :end => 'NOW/DAY', :gap => '+2YEARS', :other => :before}}
+ #
+ # advanced:
+ # Electronic.find_by_solr "memory", :facets => {:dates => {:fields => [:updated_at,
+ # {:created_at => {:start => 'NOW-20YEARS/DAY', :end => 'NOW-10YEARS/DAY', :other => [:before, :after]}
+ # }], :start => 'NOW-10YEARS/DAY', :end => 'NOW/DAY', :other => :before, :filter =>
+ # ["created_at:[NOW-10YEARS/DAY TO NOW/DAY]", "updated_at:[NOW-1YEAR/DAY TO NOW/DAY]"]}}
+ #
+ # filter only:
+ # Electronic.find_by_solr "memory", :facets => {:dates => {:filter => "updated_at:[NOW-1YEAR/DAY TO NOW/DAY]"}}
+ #
+ #
+ #
+ # scores:: If set to true this will return the score as a 'solr_score' attribute
+ # for each one of the instances found. Does not currently work with find_id_by_solr
+ #
+ # books = Book.find_by_solr 'ruby OR splinter', :scores => true
+ # books.records.first.solr_score
+ # => 1.21321397
+ # books.records.last.solr_score
+ # => 0.12321548
+ #
+ # lazy:: If set to true the search will return objects that will touch the database when you ask for one
+ # of their attributes for the first time. Useful when you're using fragment caching based solely on
+ # types and ids.
+ #
+ def find_by_solr(query, options={})
+ data = parse_query(query, options)
+ return parse_results(data, options) if data
+ end
+
+ # Finds instances of a model and returns an array with the ids:
+ # Book.find_id_by_solr "rails" => [1,4,7]
+ # The options accepted are the same as find_by_solr
+ #
+ def find_id_by_solr(query, options={})
+ data = parse_query(query, options)
+ return parse_results(data, {:format => :ids}) if data
+ end
+
+ # This method can be used to execute a search across multiple models:
+ # Book.multi_solr_search "Napoleon OR Tom", :models => [Movie]
+ #
+ # ====options:
+ # Accepts the same options as find_by_solr plus:
+ # models:: The additional models you'd like to include in the search
+ # results_format:: Specify the format of the results found
+ # :objects :: Will return an array with the results being objects (default). Example:
+ # Book.multi_solr_search "Napoleon OR Tom", :models => [Movie], :results_format => :objects
+ # :ids :: Will return an array with the ids of each entry found. Example:
+ # Book.multi_solr_search "Napoleon OR Tom", :models => [Movie], :results_format => :ids
+ # => [{"id" => "Movie:1"},{"id" => Book:1}]
+ # Where the value of each array is as Model:instance_id
+ # scores:: If set to true this will return the score as a 'solr_score' attribute
+ # for each one of the instances found. Does not currently work with find_id_by_solr
+ #
+ # books = Book.multi_solr_search 'ruby OR splinter', :scores => true
+ # books.records.first.solr_score
+ # => 1.21321397
+ # books.records.last.solr_score
+ # => 0.12321548
+ #
+ def multi_solr_search(query, options = {})
+ models = multi_model_suffix(options)
+ options.update(:results_format => :objects) unless options[:results_format]
+ data = parse_query(query, options, models)
+
+ if data.nil? or data.total_hits == 0
+ return SearchResults.new(:docs => [], :total => 0)
+ end
+
+ result = find_multi_search_objects(data, options)
+ if options[:scores] and options[:results_format] == :objects
+ add_scores(result, data)
+ end
+ SearchResults.new :docs => result, :total => data.total_hits
+ end
+
+ def find_multi_search_objects(data, options)
+ result = []
+ if options[:results_format] == :objects
+ data.hits.each do |doc|
+ k = doc.fetch('id').first.to_s.split(':')
+ result << k[0].constantize.find_by_id(k[1])
+ end
+ elsif options[:results_format] == :ids
+ data.hits.each{|doc| result << {"id" => doc.values.pop.to_s}}
+ end
+ result
+ end
+
+ def multi_model_suffix(options)
+ models = "AND (#{solr_configuration[:type_field]}:#{self.name}"
+ models << " OR " + options[:models].collect {|m| "#{solr_configuration[:type_field]}:" + m.to_s}.join(" OR ") if options[:models].is_a?(Array)
+ models << ")"
+ end
+
+ # returns the total number of documents found in the query specified:
+ # Book.count_by_solr 'rails' => 3
+ #
+ def count_by_solr(query, options = {})
+ data = parse_query(query, options)
+ data.total_hits
+ end
+
+ # It's used to rebuild the Solr index for a specific model.
+ # Book.rebuild_solr_index
+ #
+ # If batch_size is greater than 0, adds will be done in batches.
+ # NOTE: If using sqlserver, be sure to use a finder with an explicit order.
+ # Non-edge versions of rails do not handle pagination correctly for sqlserver
+ # without an order clause.
+ #
+ # If a finder block is given, it will be called to retrieve the items to index.
+ # This can be very useful for things such as updating based on conditions or
+ # using eager loading for indexed associations.
+ def rebuild_solr_index(batch_size=100, &finder)
+ finder ||= lambda { |ar, options| ar.find(:all, options.merge({:order => self.primary_key})) }
+ start_time = Time.now
+
+ if batch_size > 0
+ items_processed = 0
+ limit = batch_size
+ offset = 0
+ begin
+ iteration_start = Time.now
+ items = finder.call(self, {:limit => limit, :offset => offset})
+ add_batch = items.collect { |content| content.to_solr_doc }
+
+ if items.size > 0
+ solr_add add_batch
+ solr_commit
+ end
+
+ items_processed += items.size
+ last_id = items.last.id if items.last
+ time_so_far = Time.now - start_time
+ iteration_time = Time.now - iteration_start
+ logger.info "#{Process.pid}: #{items_processed} items for #{self.name} have been batch added to index in #{'%.3f' % time_so_far}s at #{'%.3f' % (items_processed / time_so_far)} items/sec (#{'%.3f' % (items.size / iteration_time)} items/sec for the last batch). Last id: #{last_id}"
+ offset += items.size
+ end while items.nil? || items.size > 0
+ else
+ items = finder.call(self, {})
+ items.each { |content| content.solr_save }
+ items_processed = items.size
+ end
+ solr_optimize
+ logger.info items_processed > 0 ? "Index for #{self.name} has been rebuilt" : "Nothing to index for #{self.name}"
+ end
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/common_methods.rb b/vendor/plugins/acts_as_solr/lib/common_methods.rb
new file mode 100644
index 0000000..1854a35
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/common_methods.rb
@@ -0,0 +1,89 @@
+module ActsAsSolr #:nodoc:
+
+ module CommonMethods
+
+ # Converts field types into Solr types
+ def get_solr_field_type(field_type)
+ if field_type.is_a?(Symbol)
+ case field_type
+ when :float
+ return "f"
+ when :integer
+ return "i"
+ when :boolean
+ return "b"
+ when :string
+ return "s"
+ when :date
+ return "d"
+ when :range_float
+ return "rf"
+ when :range_integer
+ return "ri"
+ when :facet
+ return "facet"
+ when :text
+ return "t"
+ else
+ raise "Unknown field_type symbol: #{field_type}"
+ end
+ elsif field_type.is_a?(String)
+ return field_type
+ else
+ raise "Unknown field_type class: #{field_type.class}: #{field_type}"
+ end
+ end
+
+ # Sets a default value when value being set is nil.
+ def set_value_if_nil(field_type)
+ case field_type
+ when "b", :boolean
+ return "false"
+ when "s", "t", "d", :date, :string, :text
+ return ""
+ when "f", "rf", :float, :range_float
+ return 0.00
+ when "i", "ri", :integer, :range_integer
+ return 0
+ else
+ return ""
+ end
+ end
+
+ # Sends an add command to Solr
+ def solr_add(add_xml)
+ ActsAsSolr::Post.execute(Solr::Request::AddDocument.new(add_xml))
+ end
+
+ # Sends the delete command to Solr
+ def solr_delete(solr_ids)
+ ActsAsSolr::Post.execute(Solr::Request::Delete.new(:id => solr_ids))
+ end
+
+ # Sends the commit command to Solr
+ def solr_commit
+ ActsAsSolr::Post.execute(Solr::Request::Commit.new)
+ end
+
+ # Optimizes the Solr index. Solr says:
+ #
+ # Optimizations can take nearly ten minutes to run.
+ # We are presuming optimizations should be run once following large
+ # batch-like updates to the collection and/or once a day.
+ #
+ # One of the solutions for this would be to create a cron job that
+ # runs every day at midnight and optmizes the index:
+ # 0 0 * * * /your_rails_dir/script/runner -e production "Model.solr_optimize"
+ #
+ def solr_optimize
+ ActsAsSolr::Post.execute(Solr::Request::Optimize.new)
+ end
+
+ # Returns the id for the given instance
+ def record_id(object)
+ eval "object.#{object.class.primary_key}"
+ end
+
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/deprecation.rb b/vendor/plugins/acts_as_solr/lib/deprecation.rb
new file mode 100644
index 0000000..94d2194
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/deprecation.rb
@@ -0,0 +1,61 @@
+module ActsAsSolr #:nodoc:
+
+ class Post
+ def initialize(body, mode = :search)
+ @body = body
+ @mode = mode
+ puts "The method ActsAsSolr::Post.new(body, mode).execute_post is depracated. " +
+ "Use ActsAsSolr::Post.execute(body, mode) instead!"
+ end
+
+ def execute_post
+ ActsAsSolr::Post.execute(@body, @mode)
+ end
+ end
+
+ module ClassMethods
+ def find_with_facet(query, options={})
+ Deprecation.plog "The method find_with_facet is deprecated. Use find_by_solr instead, passing the " +
+ "arguments the same way you used to do with find_with_facet."
+ find_by_solr(query, options)
+ end
+ end
+
+ class Deprecation
+ # Validates the options passed during query
+ def self.validate_query options={}
+ if options[:field_types]
+ plog "The option :field_types for searching is deprecated. " +
+ "The field types are automatically traced back when you specify a field type in your model."
+ end
+ if options[:sort_by]
+ plog "The option :sort_by is deprecated, use :order instead!"
+ options[:order] ||= options[:sort_by]
+ end
+ if options[:start]
+ plog "The option :start is deprecated, use :offset instead!"
+ options[:offset] ||= options[:start]
+ end
+ if options[:rows]
+ plog "The option :rows is deprecated, use :limit instead!"
+ options[:limit] ||= options[:rows]
+ end
+ end
+
+ # Validates the options passed during indexing
+ def self.validate_index options={}
+ if options[:background]
+ plog "The :background option is being deprecated. There are better and more efficient " +
+ "ways to handle delayed saving of your records."
+ end
+ end
+
+ # This will print the text to stdout and log the text
+ # if rails logger is available
+ def self.plog text
+ puts text
+ RAILS_DEFAULT_LOGGER.warn text if defined? RAILS_DEFAULT_LOGGER
+ end
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/instance_methods.rb b/vendor/plugins/acts_as_solr/lib/instance_methods.rb
new file mode 100644
index 0000000..aab6a0e
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/instance_methods.rb
@@ -0,0 +1,166 @@
+module ActsAsSolr #:nodoc:
+
+ module InstanceMethods
+
+ # Solr id is : to be unique across all models
+ def solr_id
+ "#{self.class.name}:#{record_id(self)}"
+ end
+
+ # saves to the Solr index
+ def solr_save
+ return true if indexing_disabled?
+ if evaluate_condition(:if, self)
+ logger.debug "solr_save: #{self.class.name} : #{record_id(self)}"
+ solr_add to_solr_doc
+ solr_commit if configuration[:auto_commit]
+ true
+ else
+ solr_destroy
+ end
+ end
+
+ def indexing_disabled?
+ evaluate_condition(:offline, self) || !configuration[:if]
+ end
+
+ # remove from index
+ def solr_destroy
+ return true if indexing_disabled?
+ logger.debug "solr_destroy: #{self.class.name} : #{record_id(self)}"
+ solr_delete solr_id
+ solr_commit if configuration[:auto_commit]
+ true
+ end
+
+ # convert instance to Solr document
+ def to_solr_doc
+ logger.debug "to_solr_doc: creating doc for class: #{self.class.name}, id: #{record_id(self)}"
+ doc = Solr::Document.new
+ doc.boost = validate_boost(configuration[:boost]) if configuration[:boost]
+
+ doc << {:id => solr_id,
+ solr_configuration[:type_field] => self.class.name,
+ solr_configuration[:primary_key_field] => record_id(self).to_s}
+
+ # iterate through the fields and add them to the document,
+ configuration[:solr_fields].each do |field_name, options|
+ #field_type = configuration[:facets] && configuration[:facets].include?(field) ? :facet : :text
+
+ field_boost = options[:boost] || solr_configuration[:default_boost]
+ field_type = get_solr_field_type(options[:type])
+ solr_name = options[:as] || field_name
+
+ value = self.send("#{field_name}_for_solr")
+ value = set_value_if_nil(field_type) if value.to_s == ""
+
+ # add the field to the document, but only if it's not the id field
+ # or the type field (from single table inheritance), since these
+ # fields have already been added above.
+ if field_name.to_s != self.class.primary_key and field_name.to_s != "type"
+ suffix = get_solr_field_type(field_type)
+ # This next line ensures that e.g. nil dates are excluded from the
+ # document, since they choke Solr. Also ignores e.g. empty strings,
+ # but these can't be searched for anyway:
+ # http://www.mail-archive.com/solr-dev@lucene.apache.org/msg05423.html
+ next if value.nil? || value.to_s.strip.empty?
+ [value].flatten.each do |v|
+ v = set_value_if_nil(suffix) if value.to_s == ""
+ field = Solr::Field.new("#{solr_name}_#{suffix}" => ERB::Util.html_escape(v.to_s))
+ field.boost = validate_boost(field_boost)
+ doc << field
+ end
+ end
+ end
+
+ add_includes(doc)
+ logger.debug doc.to_xml
+ doc
+ end
+
+ private
+ def add_includes(doc)
+ if configuration[:solr_includes].respond_to?(:each)
+ configuration[:solr_includes].each do |association, options|
+ data = options[:multivalued] ? [] : ""
+ field_name = options[:as] || association.to_s.singularize
+ field_type = get_solr_field_type(options[:type])
+ field_boost = options[:boost] || solr_configuration[:default_boost]
+ suffix = get_solr_field_type(field_type)
+ case self.class.reflect_on_association(association).macro
+ when :has_many, :has_and_belongs_to_many
+ records = self.send(association).to_a
+ unless records.empty?
+ records.each {|r| data << include_value(r, options)}
+ [data].flatten.each do |value|
+ field = Solr::Field.new("#{field_name}_#{suffix}" => value)
+ field.boost = validate_boost(field_boost)
+ doc << field
+ end
+ end
+ when :has_one, :belongs_to
+ record = self.send(association)
+ unless record.nil?
+ doc["#{field_name}_#{suffix}"] = include_value(record, options)
+ end
+ end
+ end
+ end
+ end
+
+ def include_value(record, options)
+ if options[:using].is_a? Proc
+ options[:using].call(record)
+ elsif options[:using].is_a? Symbol
+ record.send(options[:using])
+ else
+ record.attributes.inject([]){|k,v| k << "#{v.first}=#{ERB::Util.html_escape(v.last)}"}.join(" ")
+ end
+ end
+
+ def validate_boost(boost)
+ boost_value = case boost
+ when Float
+ return solr_configuration[:default_boost] if boost < 0
+ boost
+ when Proc
+ boost.call(self)
+ when Symbol
+ if self.respond_to?(boost)
+ self.send(boost)
+ end
+ end
+
+ boost_value || solr_configuration[:default_boost]
+ end
+
+ def condition_block?(condition)
+ condition.respond_to?("call") && (condition.arity == 1 || condition.arity == -1)
+ end
+
+ def evaluate_condition(which_condition, field)
+ condition = configuration[which_condition]
+ case condition
+ when Symbol
+ field.send(condition)
+ when String
+ eval(condition, binding)
+ when FalseClass, NilClass
+ false
+ when TrueClass
+ true
+ else
+ if condition_block?(condition)
+ condition.call(field)
+ else
+ raise(
+ ArgumentError,
+ "The :#{which_condition} option has to be either a symbol, string (to be eval'ed), proc/method, true/false, or " +
+ "class implementing a static validation method"
+ )
+ end
+ end
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/lazy_document.rb b/vendor/plugins/acts_as_solr/lib/lazy_document.rb
new file mode 100644
index 0000000..8cf8960
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/lazy_document.rb
@@ -0,0 +1,18 @@
+module ActsAsSolr
+ class LazyDocument
+ attr_reader :id, :clazz
+
+ def initialize(id, clazz)
+ @id = id
+ @clazz = clazz
+ end
+
+ def method_missing(name, *args)
+ unless @__instance
+ @__instance = @clazz.find(@id)
+ end
+
+ @__instance.send(name, *args)
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/parser_methods.rb b/vendor/plugins/acts_as_solr/lib/parser_methods.rb
new file mode 100644
index 0000000..dd0b6ba
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/parser_methods.rb
@@ -0,0 +1,201 @@
+module ActsAsSolr #:nodoc:
+ module ParserMethods
+ protected
+
+ # Method used by mostly all the ClassMethods when doing a search
+ def parse_query(query=nil, options={}, models=nil)
+ valid_options = [:offset, :limit, :facets, :models, :results_format, :order, :scores, :operator, :include, :lazy]
+ query_options = {}
+
+ return nil if (query.nil? || query.strip == '')
+
+ raise "Invalid parameters: #{(options.keys - valid_options).join(',')}" unless (options.keys - valid_options).empty?
+ begin
+ Deprecation.validate_query(options)
+ query_options[:start] = options[:offset]
+ query_options[:rows] = options[:limit]
+ query_options[:operator] = options[:operator]
+
+ # first steps on the facet parameter processing
+ if options[:facets]
+ query_options[:facets] = {}
+ query_options[:facets][:limit] = -1 # TODO: make this configurable
+ query_options[:facets][:sort] = :count if options[:facets][:sort]
+ query_options[:facets][:mincount] = 0
+ query_options[:facets][:mincount] = 1 if options[:facets][:zeros] == false
+ # override the :zeros (it's deprecated anyway) if :mincount exists
+ query_options[:facets][:mincount] = options[:facets][:mincount] if options[:facets][:mincount]
+ query_options[:facets][:fields] = options[:facets][:fields].collect{|k| "#{k}_facet"} if options[:facets][:fields]
+ query_options[:filter_queries] = replace_types([*options[:facets][:browse]].collect{|k| "#{k.sub!(/ *: */,"_facet:")}"}) if options[:facets][:browse]
+ query_options[:facets][:queries] = replace_types(options[:facets][:query].collect{|k| "#{k.sub!(/ *: */,"_t:")}"}) if options[:facets][:query]
+
+
+ if options[:facets][:dates]
+ query_options[:date_facets] = {}
+ # if options[:facets][:dates][:fields] exists then :start, :end, and :gap must be there
+ if options[:facets][:dates][:fields]
+ [:start, :end, :gap].each { |k| raise "#{k} must be present in faceted date query" unless options[:facets][:dates].include?(k) }
+ query_options[:date_facets][:fields] = []
+ options[:facets][:dates][:fields].each { |f|
+ if f.kind_of? Hash
+ key = f.keys[0]
+ query_options[:date_facets][:fields] << {"#{key}_d" => f[key]}
+ validate_date_facet_other_options(f[key][:other]) if f[key][:other]
+ else
+ query_options[:date_facets][:fields] << "#{f}_d"
+ end
+ }
+ end
+
+ query_options[:date_facets][:start] = options[:facets][:dates][:start] if options[:facets][:dates][:start]
+ query_options[:date_facets][:end] = options[:facets][:dates][:end] if options[:facets][:dates][:end]
+ query_options[:date_facets][:gap] = options[:facets][:dates][:gap] if options[:facets][:dates][:gap]
+ query_options[:date_facets][:hardend] = options[:facets][:dates][:hardend] if options[:facets][:dates][:hardend]
+ query_options[:date_facets][:filter] = replace_types([*options[:facets][:dates][:filter]].collect{|k| "#{k.sub!(/ *:(?!\d) */,"_d:")}"}) if options[:facets][:dates][:filter]
+
+ if options[:facets][:dates][:other]
+ validate_date_facet_other_options(options[:facets][:dates][:other])
+ query_options[:date_facets][:other] = options[:facets][:dates][:other]
+ end
+
+ end
+ end
+
+ if models.nil?
+ # TODO: use a filter query for type, allowing Solr to cache it individually
+ models = "AND #{solr_type_condition}"
+ field_list = solr_configuration[:primary_key_field]
+ else
+ field_list = "id"
+ end
+
+ query_options[:field_list] = [field_list, 'score']
+ query = "(#{query.gsub(/ *: */,"_t:")}) #{models}"
+ order = options[:order].split(/\s*,\s*/).collect{|e| e.gsub(/\s+/,'_t ').gsub(/\bscore_t\b/, 'score') }.join(',') if options[:order]
+ query_options[:query] = replace_types([query])[0] # TODO adjust replace_types to work with String or Array
+
+ if options[:order]
+ # TODO: set the sort parameter instead of the old ;order. style.
+ query_options[:query] << ';' << replace_types([order], false)[0]
+ end
+
+ ActsAsSolr::Post.execute(Solr::Request::Standard.new(query_options))
+ rescue
+ raise "There was a problem executing your search: #{$!} in #{$!.backtrace.first}"
+ end
+ end
+
+ def solr_type_condition
+ subclasses.inject("(#{solr_configuration[:type_field]}:#{self.name}") do |condition, subclass|
+ condition << " OR #{solr_configuration[:type_field]}:#{subclass.name}"
+ end << ')'
+ end
+
+ # Parses the data returned from Solr
+ def parse_results(solr_data, options = {})
+ results = {
+ :docs => [],
+ :total => 0
+ }
+
+ configuration = {
+ :format => :objects
+ }
+ results.update(:facets => {'facet_fields' => []}) if options[:facets]
+ return SearchResults.new(results) if (solr_data.nil? || solr_data.total_hits == 0)
+
+ configuration.update(options) if options.is_a?(Hash)
+
+ ids = solr_data.hits.collect {|doc| doc["#{solr_configuration[:primary_key_field]}"]}.flatten
+
+ result = find_objects(ids, options, configuration)
+
+ add_scores(result, solr_data) if configuration[:format] == :objects && options[:scores]
+
+ results.update(:facets => solr_data.data['facet_counts']) if options[:facets]
+ results.update({:docs => result, :total => solr_data.total_hits, :max_score => solr_data.max_score, :query_time => solr_data.data['responseHeader']['QTime']})
+ SearchResults.new(results)
+ end
+
+
+ def find_objects(ids, options, configuration)
+ result = if configuration[:lazy] && configuration[:format] != :ids
+ ids.collect {|id| ActsAsSolr::LazyDocument.new(id, self)}
+ elsif configuration[:format] == :objects
+ conditions = [ "#{self.table_name}.#{primary_key} in (?)", ids ]
+ find_options = {:conditions => conditions}
+ find_options[:include] = options[:include] if options[:include]
+ result = reorder(self.find(:all, find_options), ids)
+ else
+ ids
+ end
+
+ result
+ end
+
+ # Reorders the instances keeping the order returned from Solr
+ def reorder(things, ids)
+ ordered_things = Array.new(things.size)
+ raise "Out of sync! Found #{ids.size} items in index, but only #{things.size} were found in database!" unless things.size == ids.size
+ things.each do |thing|
+ position = ids.index(thing.id)
+ ordered_things[position] = thing
+ end
+ ordered_things
+ end
+
+ # Replaces the field types based on the types (if any) specified
+ # on the acts_as_solr call
+ def replace_types(strings, include_colon=true)
+ suffix = include_colon ? ":" : ""
+ if configuration[:solr_fields]
+ configuration[:solr_fields].each do |name, options|
+ solr_name = options[:as] || name.to_s
+ solr_type = get_solr_field_type(options[:type])
+ field = "#{solr_name}_#{solr_type}#{suffix}"
+ strings.each_with_index {|s,i| strings[i] = s.gsub(/#{solr_name.to_s}_t#{suffix}/,field) }
+ end
+ end
+ if configuration[:solr_includes]
+ configuration[:solr_includes].each do |association, options|
+ solr_name = options[:as] || association.to_s.singularize
+ solr_type = get_solr_field_type(options[:type])
+ field = "#{solr_name}_#{solr_type}#{suffix}"
+ strings.each_with_index {|s,i| strings[i] = s.gsub(/#{solr_name.to_s}_t#{suffix}/,field) }
+ end
+ end
+ strings
+ end
+
+ # Adds the score to each one of the instances found
+ def add_scores(results, solr_data)
+ with_score = []
+ solr_data.hits.each do |doc|
+ with_score.push([doc["score"],
+ results.find {|record| scorable_record?(record, doc) }])
+ end
+ with_score.each do |score, object|
+ class << object; attr_accessor :solr_score; end
+ object.solr_score = score
+ end
+ end
+
+ def scorable_record?(record, doc)
+ doc_id = doc["#{solr_configuration[:primary_key_field]}"]
+ if doc_id.nil?
+ doc_id = doc["id"]
+ "#{record.class.name}:#{record_id(record)}" == doc_id.first.to_s
+ else
+ record_id(record).to_s == doc_id.to_s
+ end
+ end
+
+ def validate_date_facet_other_options(options)
+ valid_other_options = [:after, :all, :before, :between, :none]
+ options = [options] unless options.kind_of? Array
+ bad_options = options.map {|x| x.to_sym} - valid_other_options
+ raise "Invalid option#{'s' if bad_options.size > 1} for faceted date's other param: #{bad_options.join(', ')}. May only be one of :after, :all, :before, :between, :none" if bad_options.size > 0
+ end
+
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/search_results.rb b/vendor/plugins/acts_as_solr/lib/search_results.rb
new file mode 100644
index 0000000..b81a119
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/search_results.rb
@@ -0,0 +1,68 @@
+module ActsAsSolr #:nodoc:
+
+ # TODO: Possibly looking into hooking it up with Solr::Response::Standard
+ #
+ # Class that returns the search results with four methods.
+ #
+ # books = Book.find_by_solr 'ruby'
+ #
+ # the above will return a SearchResults class with 4 methods:
+ #
+ # docs|results|records: will return an array of records found
+ #
+ # books.records.empty?
+ # => false
+ #
+ # total|num_found|total_hits: will return the total number of records found
+ #
+ # books.total
+ # => 2
+ #
+ # facets: will return the facets when doing a faceted search
+ #
+ # max_score|highest_score: returns the highest score found
+ #
+ # books.max_score
+ # => 1.3213213
+ #
+ #
+ class SearchResults
+ def initialize(solr_data={})
+ @solr_data = solr_data
+ end
+
+ # Returns an array with the instances. This method
+ # is also aliased as docs and records
+ def results
+ @solr_data[:docs]
+ end
+
+ # Returns the total records found. This method is
+ # also aliased as num_found and total_hits
+ def total
+ @solr_data[:total]
+ end
+
+ # Returns the facets when doing a faceted search
+ def facets
+ @solr_data[:facets]
+ end
+
+ # Returns the highest score found. This method is
+ # also aliased as highest_score
+ def max_score
+ @solr_data[:max_score]
+ end
+
+ def query_time
+ @solr_data[:query_time]
+ end
+
+ alias docs results
+ alias records results
+ alias num_found total
+ alias total_hits total
+ alias highest_score max_score
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr.rb b/vendor/plugins/acts_as_solr/lib/solr.rb
new file mode 100755
index 0000000..aea686f
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr.rb
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Solr; end
+require 'solr/exception'
+require 'solr/request'
+require 'solr/connection'
+require 'solr/response'
+require 'solr/util'
+require 'solr/xml'
+require 'solr/importer'
+require 'solr/indexer'
diff --git a/vendor/plugins/acts_as_solr/lib/solr/connection.rb b/vendor/plugins/acts_as_solr/lib/solr/connection.rb
new file mode 100755
index 0000000..6e1aadc
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/connection.rb
@@ -0,0 +1,179 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'net/http'
+
+# TODO: add a convenience method to POST a Solr .xml file, like Solr's example post.sh
+
+class Solr::Connection
+ attr_reader :url, :autocommit, :connection
+
+ # create a connection to a solr instance using the url for the solr
+ # application context:
+ #
+ # conn = Solr::Connection.new("http://example.com:8080/solr")
+ #
+ # if you would prefer to have all adds/updates autocommitted,
+ # use :autocommit => :on
+ #
+ # conn = Solr::Connection.new('http://example.com:8080/solr',
+ # :autocommit => :on)
+
+ def initialize(url="http://localhost:8983/solr", opts={})
+ @url = URI.parse(url)
+ unless @url.kind_of? URI::HTTP
+ raise "invalid http url: #{url}"
+ end
+
+ # TODO: Autocommit seems nice at one level, but it currently is confusing because
+ # only calls to Connection#add/#update/#delete, though a Connection#send(AddDocument.new(...))
+ # does not autocommit. Maybe #send should check for the request types that require a commit and
+ # commit in #send instead of the individual methods?
+ @autocommit = opts[:autocommit] == :on
+
+ # Not actually opening the connection yet, just setting up the persistent connection.
+ @connection = Net::HTTP.new(@url.host, @url.port)
+
+ @connection.read_timeout = opts[:timeout] if opts[:timeout]
+ end
+
+ # add a document to the index. you can pass in either a hash
+ #
+ # conn.add(:id => 123, :title => 'Tlon, Uqbar, Orbis Tertius')
+ #
+ # or a Solr::Document
+ #
+ # conn.add(Solr::Document.new(:id => 123, :title = 'On Writing')
+ #
+ # true/false will be returned to designate success/failure
+
+ def add(doc)
+ request = Solr::Request::AddDocument.new(doc)
+ response = send(request)
+ commit if @autocommit
+ return response.ok?
+ end
+
+ # update a document in the index (really just an alias to add)
+
+ def update(doc)
+ return add(doc)
+ end
+
+ # performs a standard query and returns a Solr::Response::Standard
+ #
+ # response = conn.query('borges')
+ #
+ # alternative you can pass in a block and iterate over hits
+ #
+ # conn.query('borges') do |hit|
+ # puts hit
+ # end
+ #
+ # options include:
+ #
+ # :sort, :default_field, :rows, :filter_queries, :debug_query,
+ # :explain_other, :facets, :highlighting, :mlt,
+ # :operator => :or / :and
+ # :start => defaults to 0
+ # :field_list => array, defaults to ["*", "score"]
+
+ def query(query, options={}, &action)
+ # TODO: Shouldn't this return an exception if the Solr status is not ok? (rather than true/false).
+ create_and_send_query(Solr::Request::Standard, options.update(:query => query), &action)
+ end
+
+ # performs a dismax search and returns a Solr::Response::Standard
+ #
+ # response = conn.search('borges')
+ #
+ # options are same as query, but also include:
+ #
+ # :tie_breaker, :query_fields, :minimum_match, :phrase_fields,
+ # :phrase_slop, :boost_query, :boost_functions
+
+ def search(query, options={}, &action)
+ create_and_send_query(Solr::Request::Dismax, options.update(:query => query), &action)
+ end
+
+ # sends a commit message to the server
+ def commit(options={})
+ response = send(Solr::Request::Commit.new(options))
+ return response.ok?
+ end
+
+ # sends an optimize message to the server
+ def optimize
+ response = send(Solr::Request::Optimize.new)
+ return response.ok?
+ end
+
+ # pings the connection and returns true/false if it is alive or not
+ def ping
+ begin
+ response = send(Solr::Request::Ping.new)
+ return response.ok?
+ rescue
+ return false
+ end
+ end
+
+ # delete a document from the index using the document id
+ def delete(document_id)
+ response = send(Solr::Request::Delete.new(:id => document_id))
+ commit if @autocommit
+ response.ok?
+ end
+
+ # delete using a query
+ def delete_by_query(query)
+ response = send(Solr::Request::Delete.new(:query => query))
+ commit if @autocommit
+ response.ok?
+ end
+
+ def info
+ send(Solr::Request::IndexInfo.new)
+ end
+
+ # send a given Solr::Request and return a RubyResponse or XmlResponse
+ # depending on the type of request
+ def send(request)
+ data = post(request)
+ Solr::Response::Base.make_response(request, data)
+ end
+
+ # send the http post request to solr; for convenience there are shortcuts
+ # to some requests: add(), query(), commit(), delete() or send()
+ def post(request)
+ response = @connection.post(@url.path + "/" + request.handler,
+ request.to_s,
+ { "Content-Type" => request.content_type })
+
+ case response
+ when Net::HTTPSuccess then response.body
+ else
+ response.error!
+ end
+
+ end
+
+private
+
+ def create_and_send_query(klass, options = {}, &action)
+ request = klass.new(options)
+ response = send(request)
+ return response unless action
+ response.each {|hit| action.call(hit)}
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/document.rb b/vendor/plugins/acts_as_solr/lib/solr/document.rb
new file mode 100644
index 0000000..79a3428
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/document.rb
@@ -0,0 +1,78 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+require 'solr/field'
+
+class Solr::Document
+ include Enumerable
+ attr_accessor :boost
+ attr_reader :fields
+
+ # Create a new Solr::Document, optionally passing in a hash of
+ # key/value pairs for the fields
+ #
+ # doc = Solr::Document.new(:creator => 'Jorge Luis Borges')
+ def initialize(hash={})
+ @fields = []
+ self << hash
+ end
+
+ # Append a Solr::Field
+ #
+ # doc << Solr::Field.new(:creator => 'Jorge Luis Borges')
+ #
+ # If you are truly lazy you can simply pass in a hash:
+ #
+ # doc << {:creator => 'Jorge Luis Borges'}
+ def <<(fields)
+ case fields
+ when Hash
+ fields.each_pair do |name,value|
+ if value.respond_to?(:each) && !value.is_a?(String)
+ value.each {|v| @fields << Solr::Field.new(name => v)}
+ else
+ @fields << Solr::Field.new(name => value)
+ end
+ end
+ when Solr::Field
+ @fields << fields
+ else
+ raise "must pass in Solr::Field or Hash"
+ end
+ end
+
+ # shorthand to allow hash lookups
+ # doc['name']
+ def [](name)
+ field = @fields.find {|f| f.name == name.to_s}
+ return field.value if field
+ return nil
+ end
+
+ # shorthand to assign as a hash
+ def []=(name,value)
+ @fields << Solr::Field.new(name => value)
+ end
+
+ # convert the Document to a REXML::Element
+ def to_xml
+ e = Solr::XML::Element.new 'doc'
+ e.attributes['boost'] = @boost.to_s if @boost
+ @fields.each {|f| e.add_element(f.to_xml)}
+ return e
+ end
+
+ def each(*args, &blk)
+ fields.each(&blk)
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/exception.rb b/vendor/plugins/acts_as_solr/lib/solr/exception.rb
new file mode 100644
index 0000000..a439e67
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/exception.rb
@@ -0,0 +1,13 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Exception < Exception; end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/field.rb b/vendor/plugins/acts_as_solr/lib/solr/field.rb
new file mode 100644
index 0000000..0731d0e
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/field.rb
@@ -0,0 +1,39 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+require 'time'
+
+class Solr::Field
+ VALID_PARAMS = [:boost]
+ attr_accessor :name
+ attr_accessor :value
+ attr_accessor :boost
+
+ # Accepts an optional :boost parameter, used to boost the relevance of a particular field.
+ def initialize(params)
+ @boost = params[:boost]
+ name_key = (params.keys - VALID_PARAMS).first
+ @name, @value = name_key.to_s, params[name_key]
+ # Convert any Time values into UTC/XML schema format (which Solr requires).
+ @value = @value.respond_to?(:utc) ? @value.utc.xmlschema : @value.to_s
+ end
+
+ def to_xml
+ e = Solr::XML::Element.new 'field'
+ e.attributes['name'] = @name
+ e.attributes['boost'] = @boost.to_s if @boost
+ e.text = @value
+ return e
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer.rb b/vendor/plugins/acts_as_solr/lib/solr/importer.rb
new file mode 100755
index 0000000..d607b2c
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer.rb
@@ -0,0 +1,19 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Solr; module Importer; end; end
+require 'solr/importer/mapper'
+require 'solr/importer/array_mapper'
+require 'solr/importer/delimited_file_source'
+require 'solr/importer/hpricot_mapper'
+require 'solr/importer/xpath_mapper'
+require 'solr/importer/solr_source'
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer/array_mapper.rb b/vendor/plugins/acts_as_solr/lib/solr/importer/array_mapper.rb
new file mode 100755
index 0000000..abef907
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer/array_mapper.rb
@@ -0,0 +1,26 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+
+class Solr::Importer::ArrayMapper < Solr::Importer::Mapper
+ # TODO document that initializer takes an array of Mappers [mapper1, mapper2, ... mapperN]
+
+ # TODO: make merge conflict handling configurable. as is, the last map fields win.
+ def map(orig_data_array)
+ mapped_data = {}
+ orig_data_array.each_with_index do |data,i|
+ mapped_data.merge!(@mapping[i].map(data))
+ end
+ mapped_data
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer/delimited_file_source.rb b/vendor/plugins/acts_as_solr/lib/solr/importer/delimited_file_source.rb
new file mode 100755
index 0000000..70f226a
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer/delimited_file_source.rb
@@ -0,0 +1,38 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# For files with the first line containing field names
+# Currently not designed for enormous files, as all lines are
+# read into an array
+class Solr::Importer::DelimitedFileSource
+ include Enumerable
+
+ def initialize(filename, splitter=/\t/)
+ @filename = filename
+ @splitter = splitter
+ end
+
+ def each
+ lines = IO.readlines(@filename)
+ headers = lines[0].split(@splitter).collect{|h| h.chomp}
+
+ lines[1..-1].each do |line|
+ data = headers.zip(line.split(@splitter).collect{|s| s.chomp})
+ def data.[](key)
+ self.assoc(key.to_s)[1]
+ end
+
+ yield(data)
+ end
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer/hpricot_mapper.rb b/vendor/plugins/acts_as_solr/lib/solr/importer/hpricot_mapper.rb
new file mode 100644
index 0000000..53a48e4
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer/hpricot_mapper.rb
@@ -0,0 +1,27 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+begin
+ require 'hpricot'
+
+ class Solr::Importer::HpricotMapper < Solr::Importer::Mapper
+ def field_data(doc, path)
+ doc.search(path.to_s).collect { |e| e.inner_html }
+ end
+ end
+rescue LoadError => e # If we can't load hpricot
+ class Solr::Importer::HpricotMapper
+ def initialize(mapping, options={})
+ raise "Hpricot not installed."
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer/mapper.rb b/vendor/plugins/acts_as_solr/lib/solr/importer/mapper.rb
new file mode 100755
index 0000000..55b199f
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer/mapper.rb
@@ -0,0 +1,51 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Importer::Mapper
+ def initialize(mapping, options={})
+ @mapping = mapping
+ @options = options
+ end
+
+ def field_data(orig_data, field_name)
+ orig_data[field_name]
+ end
+
+ def mapped_field_value(orig_data, field_mapping)
+ case field_mapping
+ when String
+ field_mapping
+ when Proc
+ field_mapping.call(orig_data) # TODO pass in more context, like self or a function for field_data, etc
+ when Symbol
+ field_data(orig_data, @options[:stringify_symbols] ? field_mapping.to_s : field_mapping)
+ when Enumerable
+ field_mapping.collect {|orig_field_name| mapped_field_value(orig_data, orig_field_name)}.flatten
+ else
+ raise "Unknown mapping for #{field_mapping}"
+ end
+ end
+
+ def map(orig_data)
+ mapped_data = {}
+ @mapping.each do |solr_name, field_mapping|
+ value = mapped_field_value(orig_data, field_mapping)
+ mapped_data[solr_name] = value if value
+ end
+
+ mapped_data
+ end
+
+
+
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer/solr_source.rb b/vendor/plugins/acts_as_solr/lib/solr/importer/solr_source.rb
new file mode 100755
index 0000000..fe2f4f6
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer/solr_source.rb
@@ -0,0 +1,43 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr'
+
+class Solr::Importer::SolrSource
+ def initialize(solr_url, query, filter_queries=nil, options={})
+ @connection = Solr::Connection.new(solr_url)
+ @query = query
+ @filter_queries = filter_queries
+
+ @page_size = options[:page_size] || 1000
+ @field_list = options[:field_list] || ["*"]
+ end
+
+ def each
+ done = false
+ start = 0
+ until done do
+ # request N documents from a starting point
+ request = Solr::Request::Standard.new(:query => @query,
+ :rows => @page_size,
+ :start => start,
+ :field_list => @field_list,
+ :filter_queries => @filter_queries)
+ response = @connection.send(request)
+ response.each do |doc|
+ yield doc # TODO: perhaps convert to HashWithIndifferentAccess.new(doc), so stringify_keys isn't necessary
+ end
+ done = start + @page_size >= response.total_hits
+ start = start + @page_size
+ end
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/importer/xpath_mapper.rb b/vendor/plugins/acts_as_solr/lib/solr/importer/xpath_mapper.rb
new file mode 100755
index 0000000..772e1c3
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/importer/xpath_mapper.rb
@@ -0,0 +1,35 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+begin
+ require 'xml/libxml'
+
+ # For files with the first line containing field names
+ class Solr::Importer::XPathMapper < Solr::Importer::Mapper
+ def field_data(doc, xpath)
+ doc.find(xpath.to_s).collect do |node|
+ case node
+ when XML::Attr
+ node.value
+ when XML::Node
+ node.content
+ end
+ end
+ end
+ end
+rescue LoadError => e # If we can't load libxml
+ class Solr::Importer::XPathMapper
+ def initialize(mapping, options={})
+ raise "libxml not installed"
+ end
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/indexer.rb b/vendor/plugins/acts_as_solr/lib/solr/indexer.rb
new file mode 100755
index 0000000..5210f05
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/indexer.rb
@@ -0,0 +1,52 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Indexer
+ attr_reader :solr
+
+ # TODO: document options!
+ def initialize(data_source, mapper_or_mapping, options={})
+ solr_url = options[:solr_url] || ENV["SOLR_URL"] || "http://localhost:8983/solr"
+ @solr = Solr::Connection.new(solr_url, options) #TODO - these options contain the solr_url and debug keys also, so tidy up what gets passed
+
+ @data_source = data_source
+ @mapper = mapper_or_mapping.is_a?(Hash) ? Solr::Importer::Mapper.new(mapper_or_mapping) : mapper_or_mapping
+
+ @buffer_docs = options[:buffer_docs]
+ @debug = options[:debug]
+ end
+
+ def index
+ buffer = []
+ @data_source.each do |record|
+ document = @mapper.map(record)
+
+ # TODO: check arrity of block, if 3, pass counter as 3rd argument
+ yield(record, document) if block_given? # TODO check return of block, if not true then don't index, or perhaps if document.empty?
+
+ buffer << document
+
+ if !@buffer_docs || buffer.size == @buffer_docs
+ add_docs(buffer)
+ buffer.clear
+ end
+ end
+ add_docs(buffer) if !buffer.empty?
+
+ @solr.commit unless @debug
+ end
+
+ def add_docs(documents)
+ @solr.add(documents) unless @debug
+ puts documents.inspect if @debug
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request.rb b/vendor/plugins/acts_as_solr/lib/solr/request.rb
new file mode 100755
index 0000000..a3ce7da
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request.rb
@@ -0,0 +1,26 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Solr; module Request; end; end
+require 'solr/request/add_document'
+require 'solr/request/modify_document'
+require 'solr/request/base'
+require 'solr/request/commit'
+require 'solr/request/delete'
+require 'solr/request/ping'
+require 'solr/request/select'
+require 'solr/request/standard'
+require 'solr/request/spellcheck'
+require 'solr/request/dismax'
+require 'solr/request/update'
+require 'solr/request/index_info'
+require 'solr/request/optimize'
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/add_document.rb b/vendor/plugins/acts_as_solr/lib/solr/request/add_document.rb
new file mode 100644
index 0000000..bb3d018
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/add_document.rb
@@ -0,0 +1,63 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+require 'solr/request/base'
+require 'solr/document'
+require 'solr/request/update'
+
+class Solr::Request::AddDocument < Solr::Request::Update
+
+ # create the request, optionally passing in a Solr::Document
+ #
+ # request = Solr::Request::AddDocument.new doc
+ #
+ # as a short cut you can pass in a Hash instead:
+ #
+ # request = Solr::Request::AddDocument.new :creator => 'Jorge Luis Borges'
+ #
+ # or an array, to add multiple documents at the same time:
+ #
+ # request = Solr::Request::AddDocument.new([doc1, doc2, doc3])
+
+ def initialize(doc={})
+ @docs = []
+ if doc.is_a?(Array)
+ doc.each { |d| add_doc(d) }
+ else
+ add_doc(doc)
+ end
+ end
+
+ # returns the request as a string suitable for posting
+
+ def to_s
+ e = Solr::XML::Element.new 'add'
+ for doc in @docs
+ e.add_element doc.to_xml
+ end
+ return e.to_s
+ end
+
+ private
+ def add_doc(doc)
+ case doc
+ when Hash
+ @docs << Solr::Document.new(doc)
+ when Solr::Document
+ @docs << doc
+ else
+ raise "must pass in Solr::Document or Hash"
+ end
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/base.rb b/vendor/plugins/acts_as_solr/lib/solr/request/base.rb
new file mode 100644
index 0000000..4b65b1f
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/base.rb
@@ -0,0 +1,36 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Request::Base
+
+
+ #TODO : Add base support for the debugQuery flag, and such that the response provides debug output easily
+
+ # returns either :xml or :ruby depending on what the
+ # response type is for a given request
+
+ def response_format
+ raise "unknown request type: #{self.class}"
+ end
+
+ def content_type
+ 'text/xml; charset=utf-8'
+ end
+
+ # returns the solr handler or url fragment that can
+ # respond to this type of request
+
+ def handler
+ raise "unknown request type: #{self.class}"
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/commit.rb b/vendor/plugins/acts_as_solr/lib/solr/request/commit.rb
new file mode 100644
index 0000000..bcf1308
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/commit.rb
@@ -0,0 +1,31 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+
+class Solr::Request::Commit < Solr::Request::Update
+
+ def initialize(options={})
+ @wait_searcher = options[:wait_searcher] || true
+ @wait_flush = options[:wait_flush] || true
+ end
+
+
+ def to_s
+ e = Solr::XML::Element.new('commit')
+ e.attributes['waitSearcher'] = @wait_searcher ? 'true' : 'false'
+ e.attributes['waitFlush'] = @wait_flush ? 'true' : 'false'
+
+ e.to_s
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/delete.rb b/vendor/plugins/acts_as_solr/lib/solr/request/delete.rb
new file mode 100644
index 0000000..916b44a
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/delete.rb
@@ -0,0 +1,50 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+
+class Solr::Request::Delete < Solr::Request::Update
+
+ # A delete request can be for a specific document id
+ #
+ # request = Solr::Request::Delete.new(:id => 1234)
+ #
+ # or by query:
+ #
+ # request = Solr::Request::Delete.new(:query =>
+ #
+ def initialize(options)
+ unless options.kind_of?(Hash) and (options[:id] or options[:query])
+ raise Solr::Exception.new("must pass in :id or :query")
+ end
+ if options[:id] and options[:query]
+ raise Solr::Exception.new("can't pass in both :id and :query")
+ end
+ @document_id = options[:id]
+ @query = options[:query]
+ end
+
+ def to_s
+ delete_element = Solr::XML::Element.new('delete')
+ if @document_id
+ id_element = Solr::XML::Element.new('id')
+ id_element.text = @document_id
+ delete_element.add_element(id_element)
+ elsif @query
+ query = Solr::XML::Element.new('query')
+ query.text = @query
+ delete_element.add_element(query)
+ end
+ delete_element.to_s
+ end
+end
+
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/dismax.rb b/vendor/plugins/acts_as_solr/lib/solr/request/dismax.rb
new file mode 100644
index 0000000..13d1977
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/dismax.rb
@@ -0,0 +1,46 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Request::Dismax < Solr::Request::Standard
+
+ VALID_PARAMS.replace(VALID_PARAMS + [:tie_breaker, :query_fields, :minimum_match, :phrase_fields, :phrase_slop,
+ :boost_query, :boost_functions])
+
+ def initialize(params)
+ @alternate_query = params.delete(:alternate_query)
+ @sort_values = params.delete(:sort)
+
+ super
+
+ @query_type = "dismax"
+ end
+
+ def to_hash
+ hash = super
+ hash[:tie] = @params[:tie_breaker]
+ hash[:mm] = @params[:minimum_match]
+ hash[:qf] = @params[:query_fields]
+ hash[:pf] = @params[:phrase_fields]
+ hash[:ps] = @params[:phrase_slop]
+ hash[:bq] = @params[:boost_query]
+ hash[:bf] = @params[:boost_functions]
+ hash["q.alt"] = @alternate_query
+ # FIXME: 2007-02-13 -- This code is duplicated in
+ # Solr::Request::Standard. It should be refactored into a single location.
+ hash[:sort] = @sort_values.collect do |sort|
+ key = sort.keys[0]
+ "#{key.to_s} #{sort[key] == :descending ? 'desc' : 'asc'}"
+ end.join(',') if @sort_values
+ return hash
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/index_info.rb b/vendor/plugins/acts_as_solr/lib/solr/request/index_info.rb
new file mode 100755
index 0000000..d4eeea5
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/index_info.rb
@@ -0,0 +1,22 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Request::IndexInfo < Solr::Request::Select
+
+ def handler
+ 'admin/luke'
+ end
+
+ def to_hash
+ {:numTerms => 0}.merge(super.to_hash)
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/modify_document.rb b/vendor/plugins/acts_as_solr/lib/solr/request/modify_document.rb
new file mode 100644
index 0000000..6276d97
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/modify_document.rb
@@ -0,0 +1,51 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+require 'solr/request/base'
+require 'solr/document'
+require 'solr/request/update'
+
+class Solr::Request::ModifyDocument < Solr::Request::Update
+
+ # Example: ModifyDocument.new(:id => 10, :overwrite => {:field_name => "new value"})
+ def initialize(update_data)
+ modes = []
+ @doc = {}
+ [:overwrite, :append, :distinct, :increment, :delete].each do |mode|
+ field_data = update_data[mode]
+ if field_data
+ field_data.each do |field_name, field_value|
+ modes << "#{field_name}:#{mode.to_s.upcase}"
+ @doc[field_name] = field_value if field_value # if value is nil, omit so it can be removed
+ end
+ update_data.delete mode
+ end
+ end
+ @mode = modes.join(",")
+
+ # only one key should be left over, the id
+ @doc[update_data.keys[0].to_s] = update_data.values[0]
+ end
+
+ # returns the request as a string suitable for posting
+ def to_s
+ e = Solr::XML::Element.new 'add'
+ e.add_element(Solr::Document.new(@doc).to_xml)
+ return e.to_s
+ end
+
+ def handler
+ "update?mode=#{@mode}"
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/optimize.rb b/vendor/plugins/acts_as_solr/lib/solr/request/optimize.rb
new file mode 100755
index 0000000..3bd1fc4
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/optimize.rb
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'solr/xml'
+
+class Solr::Request::Optimize < Solr::Request::Update
+
+ def to_s
+ Solr::XML::Element.new('optimize').to_s
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/ping.rb b/vendor/plugins/acts_as_solr/lib/solr/request/ping.rb
new file mode 100644
index 0000000..6b420be
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/ping.rb
@@ -0,0 +1,36 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# TODO: Consider something lazy like this?
+# Solr::Request::Ping = Solr::Request.simple_request :format=>:xml, :handler=>'admin/ping'
+# class Solr::Request
+# def self.simple_request(options)
+# Class.new do
+# def response_format
+# options[:format]
+# end
+# def handler
+# options[:handler]
+# end
+# end
+# end
+# end
+
+class Solr::Request::Ping < Solr::Request::Base
+ def response_format
+ :xml
+ end
+
+ def handler
+ 'admin/ping'
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/select.rb b/vendor/plugins/acts_as_solr/lib/solr/request/select.rb
new file mode 100644
index 0000000..122c5b7
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/select.rb
@@ -0,0 +1,56 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'erb'
+
+# "Abstract" base class, only useful with subclasses that add parameters
+class Solr::Request::Select < Solr::Request::Base
+
+ attr_reader :query_type
+
+ def initialize(qt=nil, params={})
+ @query_type = qt
+ @select_params = params
+ end
+
+ def response_format
+ :ruby
+ end
+
+ def handler
+ 'select'
+ end
+
+ def content_type
+ 'application/x-www-form-urlencoded; charset=utf-8'
+ end
+
+ def to_hash
+ return {:qt => query_type, :wt => 'ruby'}.merge(@select_params)
+ end
+
+ def to_s
+ raw_params = self.to_hash
+
+ http_params = []
+ raw_params.each do |key,value|
+ if value.respond_to? :each
+ value.each { |v| http_params << "#{key}=#{ERB::Util::url_encode(v)}" unless v.nil?}
+ else
+ http_params << "#{key}=#{ERB::Util::url_encode(value)}" unless value.nil?
+ end
+ end
+
+ http_params.join("&")
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/spellcheck.rb b/vendor/plugins/acts_as_solr/lib/solr/request/spellcheck.rb
new file mode 100644
index 0000000..eab24eb
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/spellcheck.rb
@@ -0,0 +1,30 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Request::Spellcheck < Solr::Request::Select
+
+ def initialize(params)
+ super('spellchecker')
+ @params = params
+ end
+
+ def to_hash
+ hash = super
+ hash[:q] = @params[:query]
+ hash[:suggestionCount] = @params[:suggestion_count]
+ hash[:accuracy] = @params[:accuracy]
+ hash[:onlyMorePopular] = @params[:only_more_popular]
+ hash[:cmd] = @params[:command]
+ return hash
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/standard.rb b/vendor/plugins/acts_as_solr/lib/solr/request/standard.rb
new file mode 100755
index 0000000..03ec243
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/standard.rb
@@ -0,0 +1,402 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Request::Standard < Solr::Request::Select
+
+ VALID_PARAMS = [:query, :sort, :default_field, :operator, :start, :rows, :shards, :date_facets,
+ :filter_queries, :field_list, :debug_query, :explain_other, :facets, :highlighting, :mlt]
+
+ def initialize(params)
+ super('standard')
+
+ raise "Invalid parameters: #{(params.keys - VALID_PARAMS).join(',')}" unless
+ (params.keys - VALID_PARAMS).empty?
+
+ raise ":query parameter required" unless params[:query]
+
+ @params = params.dup
+
+ # Validate operator
+ if params[:operator]
+ raise "Only :and/:or operators allowed" unless
+ [:and, :or].include?(params[:operator])
+
+ @params[:operator] = params[:operator].to_s.upcase
+ end
+
+ # Validate start, rows can be transformed to ints
+ @params[:start] = params[:start].to_i if params[:start]
+ @params[:rows] = params[:rows].to_i if params[:rows]
+
+ @params[:field_list] ||= ["*","score"]
+
+ @params[:shards] ||= []
+ end
+
+ def to_hash
+ hash = {}
+
+ # standard request param processing
+ sort = @params[:sort].collect do |sort|
+ key = sort.keys[0]
+ "#{key.to_s} #{sort[key] == :descending ? 'desc' : 'asc'}"
+ end.join(',') if @params[:sort]
+ hash[:q] = sort ? "#{@params[:query]};#{sort}" : @params[:query]
+ hash["q.op"] = @params[:operator]
+ hash[:df] = @params[:default_field]
+
+ # common parameter processing
+ hash[:start] = @params[:start]
+ hash[:rows] = @params[:rows]
+ hash[:fq] = @params[:filter_queries]
+ hash[:fl] = @params[:field_list].join(',')
+ hash[:debugQuery] = @params[:debug_query]
+ hash[:explainOther] = @params[:explain_other]
+ hash[:shards] = @params[:shards].join(',') unless @params[:shards].empty?
+
+ # facet parameter processing
+ if @params[:facets]
+ # TODO need validation of all that is under the :facets Hash too
+ hash[:facet] = true
+ hash["facet.field"] = []
+ hash["facet.query"] = @params[:facets][:queries]
+ hash["facet.sort"] = (@params[:facets][:sort] == :count) if @params[:facets][:sort]
+ hash["facet.limit"] = @params[:facets][:limit]
+ hash["facet.missing"] = @params[:facets][:missing]
+ hash["facet.mincount"] = @params[:facets][:mincount]
+ hash["facet.prefix"] = @params[:facets][:prefix]
+ hash["facet.offset"] = @params[:facets][:offset]
+ if @params[:facets][:fields] # facet fields are optional (could be facet.query only)
+ @params[:facets][:fields].each do |f|
+ if f.kind_of? Hash
+ key = f.keys[0]
+ value = f[key]
+ hash["facet.field"] << key
+ hash["f.#{key}.facet.sort"] = (value[:sort] == :count) if value[:sort]
+ hash["f.#{key}.facet.limit"] = value[:limit]
+ hash["f.#{key}.facet.missing"] = value[:missing]
+ hash["f.#{key}.facet.mincount"] = value[:mincount]
+ hash["f.#{key}.facet.prefix"] = value[:prefix]
+ hash["f.#{key}.facet.offset"] = value[:offset]
+ else
+ hash["facet.field"] << f
+ end
+ end
+ end
+
+ if @params[:date_facets]
+ hash["facet.date"] = []
+ if @params[:date_facets][:fields]
+ @params[:date_facets][:fields].each do |f|
+ if f.kind_of? Hash
+ key = f.keys[0]
+ hash["facet.date"] << key
+ f[key].each { |k, v|
+ hash["f.#{key}.facet.date.#{k}"] = v
+ }
+ else
+ hash["facet.date"] << f
+ end
+ end
+ end
+ hash["facet.date.start"] = @params[:date_facets][:start]
+ hash["facet.date.end"] = @params[:date_facets][:end]
+ hash["facet.date.gap"] = @params[:date_facets][:gap]
+ hash["facet.date.other"] = @params[:date_facets][:other]
+ hash["facet.date.hardend"] = @params[:date_facets][:hardend]
+ if @params[:date_facets][:filter]
+ if hash[:fq]
+ hash[:fq] << @params[:date_facets][:filter]
+ else
+ hash[:fq] = @params[:date_facets][:filter]
+ end
+ end
+ end
+ end
+
+ # highlighting parameter processing - http://wiki.apache.org/solr/HighlightingParameters
+ if @params[:highlighting]
+ hash[:hl] = true
+ hash["hl.fl"] = @params[:highlighting][:field_list].join(',') if @params[:highlighting][:field_list]
+
+ snippets = @params[:highlighting][:max_snippets]
+ if snippets
+ if snippets.kind_of? Hash
+ if snippets[:default]
+ hash["hl.snippets"] = snippets[:default]
+ end
+ if snippets[:fields]
+ snippets[:fields].each do |k,v|
+ hash["f.#{k}.hl.snippets"] = v
+ end
+ end
+ else
+ hash["hl.snippets"] = snippets
+ end
+ end
+
+ fragsize = @params[:highlighting][:fragment_size]
+ if fragsize
+ if fragsize.kind_of? Hash
+ if fragsize[:default]
+ hash["hl.fragsize"] = fragsize[:default]
+ end
+ if fragsize[:fields]
+ fragsize[:fields].each do |k,v|
+ hash["f.#{k}.hl.fragsize"] = v
+ end
+ end
+ else
+ hash["hl.fragsize"] = fragsize
+ end
+ end
+
+ rfm = @params[:highlighting][:require_field_match]
+ if nil != rfm
+ if rfm.kind_of? Hash
+ if nil != rfm[:default]
+ hash["hl.requireFieldMatch"] = rfm[:default]
+ end
+ if rfm[:fields]
+ rfm[:fields].each do |k,v|
+ hash["f.#{k}.hl.requireFieldMatch"] = v
+ end
+ end
+ else
+ hash["hl.requireFieldMatch"] = rfm
+ end
+ end
+
+ mac = @params[:highlighting][:max_analyzed_chars]
+ if mac
+ if mac.kind_of? Hash
+ if mac[:default]
+ hash["hl.maxAnalyzedChars"] = mac[:default]
+ end
+ if mac[:fields]
+ mac[:fields].each do |k,v|
+ hash["f.#{k}.hl.maxAnalyzedChars"] = v
+ end
+ end
+ else
+ hash["hl.maxAnalyzedChars"] = mac
+ end
+ end
+
+ prefix = @params[:highlighting][:prefix]
+ if prefix
+ if prefix.kind_of? Hash
+ if prefix[:default]
+ hash["hl.simple.pre"] = prefix[:default]
+ end
+ if prefix[:fields]
+ prefix[:fields].each do |k,v|
+ hash["f.#{k}.hl.simple.pre"] = v
+ end
+ end
+ else
+ hash["hl.simple.pre"] = prefix
+ end
+ end
+
+ suffix = @params[:highlighting][:suffix]
+ if suffix
+ if suffix.kind_of? Hash
+ if suffix[:default]
+ hash["hl.simple.post"] = suffix[:default]
+ end
+ if suffix[:fields]
+ suffix[:fields].each do |k,v|
+ hash["f.#{k}.hl.simple.post"] = v
+ end
+ end
+ else
+ hash["hl.simple.post"] = suffix
+ end
+ end
+
+ formatter = @params[:highlighting][:formatter]
+ if formatter
+ if formatter.kind_of? Hash
+ if formatter[:default]
+ hash["hl.formatter"] = formatter[:default]
+ end
+ if formatter[:fields]
+ formatter[:fields].each do |k,v|
+ hash["f.#{k}.hl.formatter"] = v
+ end
+ end
+ else
+ hash["hl.formatter"] = formatter
+ end
+ end
+
+ fragmenter = @params[:highlighting][:fragmenter]
+ if fragmenter
+ if fragmenter.kind_of? Hash
+ if fragmenter[:default]
+ hash["hl.fragmenter"] = fragmenter[:default]
+ end
+ if fragmenter[:fields]
+ fragmenter[:fields].each do |k,v|
+ hash["f.#{k}.hl.fragmenter"] = v
+ end
+ end
+ else
+ hash["hl.fragmenter"] = fragmenter
+ end
+ end
+
+ merge_contiguous = @params[:highlighting][:merge_contiguous]
+ if nil != merge_contiguous
+ if merge_contiguous.kind_of? Hash
+ if nil != merge_contiguous[:default]
+ hash["hl.mergeContiguous"] = merge_contiguous[:default]
+ end
+ if merge_contiguous[:fields]
+ merge_contiguous[:fields].each do |k,v|
+ hash["f.#{k}.hl.mergeContiguous"] = v
+ end
+ end
+ else
+ hash["hl.mergeContiguous"] = merge_contiguous
+ end
+ end
+
+ increment = @params[:highlighting][:increment]
+ if increment
+ if increment.kind_of? Hash
+ if increment[:default]
+ hash["hl.increment"] = increment[:default]
+ end
+ if increment[:fields]
+ increment[:fields].each do |k,v|
+ hash["f.#{k}.hl.increment"] = v
+ end
+ end
+ else
+ hash["hl.increment"] = increment
+ end
+ end
+
+ # support "old style"
+ alternate_fields = @params[:highlighting][:alternate_fields]
+ if alternate_fields
+ alternate_fields.each do |f,v|
+ hash["f.#{f}.hl.alternateField"] = v
+ end
+ end
+
+ alternate_field = @params[:highlighting][:alternate_field]
+ if alternate_field
+ if alternate_field.kind_of? Hash
+ if alternate_field[:default]
+ hash["hl.alternateField"] = alternate_field[:default]
+ end
+ if alternate_field[:fields]
+ alternate_field[:fields].each do |k,v|
+ hash["f.#{k}.hl.alternateField"] = v
+ end
+ end
+ else
+ hash["hl.alternateField"] = alternate_field
+ end
+ end
+
+ mafl = @params[:highlighting][:max_alternate_field_length]
+ if mafl
+ if mafl.kind_of? Hash
+ if mafl[:default]
+ hash["hl.maxAlternateFieldLength"] = mafl[:default]
+ end
+ if mafl[:fields]
+ mafl[:fields].each do |k,v|
+ hash["f.#{k}.hl.maxAlternateFieldLength"] = v
+ end
+ else
+ # support "old style"
+ mafl.each do |k,v|
+ hash["f.#{k}.hl.maxAlternateFieldLength"] = v
+ end
+ end
+ else
+ hash["hl.maxAlternateFieldLength"] = mafl
+ end
+ end
+
+ hash["hl.usePhraseHighlighter"] = @params[:highlighting][:use_phrase_highlighter]
+
+ regex = @params[:highlighting][:regex]
+ if regex
+ if regex[:slop]
+ if regex[:slop].kind_of? Hash
+ if regex[:slop][:default]
+ hash["hl.regex.slop"] = regex[:slop][:default]
+ end
+ if regex[:slop][:fields]
+ regex[:slop][:fields].each do |k,v|
+ hash["f.#{k}.hl.regex.slop"] = v
+ end
+ end
+ else
+ hash["hl.regex.slop"] = regex[:slop]
+ end
+ end
+ if regex[:pattern]
+ if regex[:pattern].kind_of? Hash
+ if regex[:pattern][:default]
+ hash["hl.regex.pattern"] = regex[:pattern][:default]
+ end
+ if regex[:pattern][:fields]
+ regex[:pattern][:fields].each do |k,v|
+ hash["f.#{k}.hl.regex.pattern"] = v
+ end
+ end
+ else
+ hash["hl.regex.pattern"] = regex[:pattern]
+ end
+ end
+ if regex[:max_analyzed_chars]
+ if regex[:max_analyzed_chars].kind_of? Hash
+ if regex[:max_analyzed_chars][:default]
+ hash["hl.regex.maxAnalyzedChars"] = regex[:max_analyzed_chars][:default]
+ end
+ if regex[:max_analyzed_chars][:fields]
+ regex[:max_analyzed_chars][:fields].each do |k,v|
+ hash["f.#{k}.hl.regex.maxAnalyzedChars"] = v
+ end
+ end
+ else
+ hash["hl.regex.maxAnalyzedChars"] = regex[:max_analyzed_chars]
+ end
+ end
+ end
+
+ end
+
+ if @params[:mlt]
+ hash[:mlt] = true
+ hash["mlt.count"] = @params[:mlt][:count]
+ hash["mlt.fl"] = @params[:mlt][:field_list].join(',')
+ hash["mlt.mintf"] = @params[:mlt][:min_term_freq]
+ hash["mlt.mindf"] = @params[:mlt][:min_doc_freq]
+ hash["mlt.minwl"] = @params[:mlt][:min_word_length]
+ hash["mlt.maxwl"] = @params[:mlt][:max_word_length]
+ hash["mlt.maxqt"] = @params[:mlt][:max_query_terms]
+ hash["mlt.maxntp"] = @params[:mlt][:max_tokens_parsed]
+ hash["mlt.boost"] = @params[:mlt][:boost]
+ end
+
+ hash.merge(super.to_hash)
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/request/update.rb b/vendor/plugins/acts_as_solr/lib/solr/request/update.rb
new file mode 100644
index 0000000..8bd8448
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/request/update.rb
@@ -0,0 +1,23 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# a parent class for all requests that go through the solr update handler
+# TODO: Use new xml update handler for better error responses
+class Solr::Request::Update < Solr::Request::Base
+ def response_format
+ :xml
+ end
+
+ def handler
+ 'update'
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response.rb b/vendor/plugins/acts_as_solr/lib/solr/response.rb
new file mode 100755
index 0000000..72c55fe
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response.rb
@@ -0,0 +1,27 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Solr; module Response; end; end
+require 'solr/response/base'
+require 'solr/response/xml'
+require 'solr/response/ruby'
+require 'solr/response/ping'
+require 'solr/response/add_document'
+require 'solr/response/modify_document'
+require 'solr/response/standard'
+require 'solr/response/spellcheck'
+require 'solr/response/dismax'
+require 'solr/response/commit'
+require 'solr/response/delete'
+require 'solr/response/index_info'
+require 'solr/response/optimize'
+require 'solr/response/select'
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/add_document.rb b/vendor/plugins/acts_as_solr/lib/solr/response/add_document.rb
new file mode 100644
index 0000000..d1e1923
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/add_document.rb
@@ -0,0 +1,17 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::AddDocument < Solr::Response::Xml
+ def initialize(xml)
+ super
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/base.rb b/vendor/plugins/acts_as_solr/lib/solr/response/base.rb
new file mode 100644
index 0000000..a66d2a4
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/base.rb
@@ -0,0 +1,42 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Base
+ attr_reader :raw_response
+
+ def initialize(raw_response)
+ @raw_response = raw_response
+ end
+
+ # factory method for creating a Solr::Response::* from
+ # a request and the raw response content
+ def self.make_response(request, raw)
+
+ # make sure response format seems sane
+ unless [:xml, :ruby].include?(request.response_format)
+ raise Solr::Exception.new("unknown response format: #{request.response_format}" )
+ end
+
+ # TODO: Factor out this case... perhaps the request object should provide the response class instead? Or dynamically align by class name?
+ # Maybe the request itself could have the response handling features that get mixed in with a single general purpose response object?
+
+ begin
+ klass = eval(request.class.name.sub(/Request/,'Response'))
+ rescue NameError
+ raise Solr::Exception.new("unknown request type: #{request.class}")
+ else
+ klass.new(raw)
+ end
+
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/commit.rb b/vendor/plugins/acts_as_solr/lib/solr/response/commit.rb
new file mode 100644
index 0000000..ff937a3
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/commit.rb
@@ -0,0 +1,17 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'rexml/xpath'
+
+class Solr::Response::Commit < Solr::Response::Xml
+end
+
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/delete.rb b/vendor/plugins/acts_as_solr/lib/solr/response/delete.rb
new file mode 100644
index 0000000..0836128
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/delete.rb
@@ -0,0 +1,13 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Delete < Solr::Response::Xml; end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/dismax.rb b/vendor/plugins/acts_as_solr/lib/solr/response/dismax.rb
new file mode 100644
index 0000000..d495843
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/dismax.rb
@@ -0,0 +1,8 @@
+class Solr::Response::Dismax < Solr::Response::Standard
+ # no need for special processing
+
+ # FIXME: 2007-02-07 -- The existence of this class indicates that
+ # the Request/Response pair architecture is a little hinky. Perhaps we could refactor
+ # out some of the most common functionality -- Common Query Parameters, Highlighting Parameters,
+ # Simple Facet Parameters, etc. -- into modules?
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/index_info.rb b/vendor/plugins/acts_as_solr/lib/solr/response/index_info.rb
new file mode 100755
index 0000000..b8e215f
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/index_info.rb
@@ -0,0 +1,26 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::IndexInfo < Solr::Response::Ruby
+ def initialize(ruby_code)
+ super
+ end
+
+ def num_docs
+ return @data['index']['numDocs']
+ end
+
+ def field_names
+ return @data['fields'].keys
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/modify_document.rb b/vendor/plugins/acts_as_solr/lib/solr/response/modify_document.rb
new file mode 100644
index 0000000..44c4f5b
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/modify_document.rb
@@ -0,0 +1,17 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::ModifyDocument < Solr::Response::Xml
+ def initialize(xml)
+ super
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/optimize.rb b/vendor/plugins/acts_as_solr/lib/solr/response/optimize.rb
new file mode 100755
index 0000000..4594d90
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/optimize.rb
@@ -0,0 +1,14 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Optimize < Solr::Response::Commit
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/ping.rb b/vendor/plugins/acts_as_solr/lib/solr/response/ping.rb
new file mode 100644
index 0000000..1c40588
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/ping.rb
@@ -0,0 +1,28 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'rexml/xpath'
+
+class Solr::Response::Ping < Solr::Response::Xml
+
+ def initialize(xml)
+ super
+ @ok = REXML::XPath.first(@doc, './solr/ping') ? true : false
+ end
+
+ # returns true or false depending on whether the ping
+ # was successful or not
+ def ok?
+ @ok
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/ruby.rb b/vendor/plugins/acts_as_solr/lib/solr/response/ruby.rb
new file mode 100644
index 0000000..05424c1
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/ruby.rb
@@ -0,0 +1,42 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Ruby < Solr::Response::Base
+ attr_reader :data, :header
+
+ def initialize(ruby_code)
+ super
+ begin
+ #TODO: what about pulling up data/header/response to ResponseBase,
+ # or maybe a new middle class like SelectResponseBase since
+ # all Select queries return this same sort of stuff??
+ # XML (&wt=xml) and Ruby (&wt=ruby) responses contain exactly the same structure.
+ # a goal of solrb is to make it irrelevant which gets used under the hood,
+ # but favor Ruby responses.
+ @data = eval(ruby_code)
+ @header = @data['responseHeader']
+ raise "response should be a hash" unless @data.kind_of? Hash
+ raise "response header missing" unless @header.kind_of? Hash
+ rescue SyntaxError => e
+ raise Solr::Exception.new("invalid ruby code: #{e}")
+ end
+ end
+
+ def ok?
+ @header['status'] == 0
+ end
+
+ def query_time
+ @header['QTime']
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/select.rb b/vendor/plugins/acts_as_solr/lib/solr/response/select.rb
new file mode 100644
index 0000000..8e2185d
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/select.rb
@@ -0,0 +1,17 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Select < Solr::Response::Ruby
+ def initialize(ruby_code)
+ super
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/spellcheck.rb b/vendor/plugins/acts_as_solr/lib/solr/response/spellcheck.rb
new file mode 100644
index 0000000..a4842c5
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/spellcheck.rb
@@ -0,0 +1,20 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Spellcheck < Solr::Response::Ruby
+ attr_reader :suggestions
+
+ def initialize(ruby_code)
+ super
+ @suggestions = @data['suggestions']
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/standard.rb b/vendor/plugins/acts_as_solr/lib/solr/response/standard.rb
new file mode 100644
index 0000000..2e59fe9
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/standard.rb
@@ -0,0 +1,60 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Response::Standard < Solr::Response::Ruby
+ FacetValue = Struct.new(:name, :value)
+ include Enumerable
+
+ def initialize(ruby_code)
+ super
+ @response = @data['response']
+ raise "response section missing" unless @response.kind_of? Hash
+ end
+
+ def total_hits
+ @response['numFound']
+ end
+
+ def start
+ @response['start']
+ end
+
+ def hits
+ @response['docs']
+ end
+
+ def max_score
+ @response['maxScore']
+ end
+
+ # TODO: consider the use of json.nl parameter
+ def field_facets(field)
+ facets = []
+ values = @data['facet_counts']['facet_fields'][field]
+ Solr::Util.paired_array_each(values) do |key, value|
+ facets << FacetValue.new(key, value)
+ end
+
+ facets
+ end
+
+ def highlighted(id, field)
+ @data['highlighting'][id.to_s][field.to_s] rescue nil
+ end
+
+ # supports enumeration of hits
+ # TODO revisit - should this iterate through *all* hits by re-requesting more?
+ def each
+ @response['docs'].each {|hit| yield hit}
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/response/xml.rb b/vendor/plugins/acts_as_solr/lib/solr/response/xml.rb
new file mode 100644
index 0000000..f48de5d
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/response/xml.rb
@@ -0,0 +1,42 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'rexml/document'
+require 'solr/exception'
+
+class Solr::Response::Xml < Solr::Response::Base
+ attr_reader :doc, :status_code, :status_message
+
+ def initialize(xml)
+ super
+ # parse the xml
+ @doc = REXML::Document.new(xml)
+
+ # look for the result code and string
+ #
+ #
+ # 02
+ #
+ result = REXML::XPath.first(@doc, './response/lst[@name="responseHeader"]/int[@name="status"]')
+ if result
+ @status_code = result.text
+ @status_message = result.text # TODO: any need for a message?
+ end
+ rescue REXML::ParseException => e
+ raise Solr::Exception.new("invalid response xml: #{e}")
+ end
+
+ def ok?
+ return @status_code == '0'
+ end
+
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/solrtasks.rb b/vendor/plugins/acts_as_solr/lib/solr/solrtasks.rb
new file mode 100755
index 0000000..3a1f76a
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/solrtasks.rb
@@ -0,0 +1,27 @@
+#!/usr/bin/env ruby
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# TODO: fill out Solr tasks: start, stop, ping, optimize, etc.
+
+require 'rake'
+require 'rake/tasklib'
+
+module Solr
+ namespace :solr do
+ desc "Start Solr"
+ task :start do
+ # TODO: actually start it up!
+ puts "Starting..."
+ end
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/util.rb b/vendor/plugins/acts_as_solr/lib/solr/util.rb
new file mode 100755
index 0000000..bb134ee
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/util.rb
@@ -0,0 +1,32 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Solr::Util
+ # paired_array_each([key1,value1,key2,value2]) yields twice:
+ # |key1,value1| and |key2,value2|
+ def self.paired_array_each(a, &block)
+ 0.upto(a.size / 2 - 1) do |i|
+ n = i * 2
+ yield(a[n], a[n+1])
+ end
+ end
+
+ # paired_array_to_hash([key1,value1,key2,value2]) => {key1 => value1, key2, value2}
+ def self.paired_array_to_hash(a)
+ Hash[*a]
+ end
+
+ def self.query_parser_escape(string)
+ # backslash prefix everything that isn't a word character
+ string.gsub(/(\W)/,'\\\\\1')
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/lib/solr/xml.rb b/vendor/plugins/acts_as_solr/lib/solr/xml.rb
new file mode 100644
index 0000000..d449225
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr/xml.rb
@@ -0,0 +1,44 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Solr::XML
+end
+
+begin
+
+ # If we can load rubygems and libxml-ruby...
+ require 'rubygems'
+ require 'xml/libxml'
+ raise "acts_as_solr requires libxml-ruby 0.7 or greater" unless XML::Node.public_instance_methods.include?("attributes")
+
+ # then make a few modifications to XML::Node so it can stand in for REXML::Element
+ class XML::Node
+ # element.add_element(another_element) should work
+ alias_method :add_element, :<<
+
+
+ # element.text = "blah" should work
+ def text=(x)
+ self << x.to_s
+ end
+ end
+
+ # And use XML::Node for our XML generation
+ Solr::XML::Element = XML::Node
+
+rescue LoadError => e # If we can't load either rubygems or libxml-ruby
+ puts "Requiring REXML"
+ # Just use REXML.
+ require 'rexml/document'
+ Solr::XML::Element = REXML::Element
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/solr_fixtures.rb b/vendor/plugins/acts_as_solr/lib/solr_fixtures.rb
new file mode 100644
index 0000000..c16781e
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/solr_fixtures.rb
@@ -0,0 +1,13 @@
+module ActsAsSolr
+
+ class SolrFixtures
+ def self.load(table_names)
+ [table_names].flatten.map { |n| n.to_s }.each do |table_name|
+ klass = instance_eval(File.split(table_name.to_s).last.to_s.gsub('_',' ').split(" ").collect{|w| w.capitalize}.to_s.singularize)
+ klass.rebuild_solr_index if klass.respond_to?(:rebuild_solr_index)
+ end
+ ActsAsSolr::Post.execute(Solr::Request::Commit.new)
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/tasks/database.rake b/vendor/plugins/acts_as_solr/lib/tasks/database.rake
new file mode 100644
index 0000000..c02dd3b
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/tasks/database.rake
@@ -0,0 +1,18 @@
+require File.dirname(__FILE__) + '/../solr_fixtures'
+
+namespace :db do
+ namespace :fixtures do
+ desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y"
+ task :load => :environment do
+ begin
+ ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "*:*"))
+ ActsAsSolr::Post.execute(Solr::Request::Commit.new)
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
+ ActsAsSolr::SolrFixtures.load(File.basename(fixture_file, '.*'))
+ end
+ puts "The fixtures loaded have been added to Solr"
+ rescue
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/acts_as_solr/lib/tasks/solr.rake b/vendor/plugins/acts_as_solr/lib/tasks/solr.rake
new file mode 100644
index 0000000..fc139d3
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/tasks/solr.rake
@@ -0,0 +1,137 @@
+require 'rubygems'
+require 'rake'
+require 'net/http'
+require 'active_record'
+
+namespace :solr do
+
+ desc 'Starts Solr. Options accepted: RAILS_ENV=your_env, PORT=XX. Defaults to development if none.'
+ task :start do
+ require "#{File.dirname(__FILE__)}/../../config/solr_environment.rb"
+ begin
+ n = Net::HTTP.new('127.0.0.1', SOLR_PORT)
+ n.request_head('/').value
+
+ rescue Net::HTTPServerException #responding
+ puts "Port #{SOLR_PORT} in use" and return
+
+ rescue Errno::ECONNREFUSED #not responding
+ Dir.chdir(SOLR_PATH) do
+ pid = fork do
+ #STDERR.close
+ exec "java #{SOLR_JVM_OPTIONS} -Dsolr.data.dir=#{SOLR_DATA_PATH} -Djetty.logs=#{SOLR_LOGS_PATH} -Djetty.port=#{SOLR_PORT} -jar start.jar"
+ end
+ sleep(5)
+ File.open("#{SOLR_PIDS_PATH}/#{ENV['RAILS_ENV']}_pid", "w"){ |f| f << pid}
+ puts "#{ENV['RAILS_ENV']} Solr started successfully on #{SOLR_PORT}, pid: #{pid}."
+ end
+ end
+ end
+
+ desc 'Stops Solr. Specify the environment by using: RAILS_ENV=your_env. Defaults to development if none.'
+ task :stop do
+ require "#{File.dirname(__FILE__)}/../../config/solr_environment.rb"
+ fork do
+ file_path = "#{SOLR_PIDS_PATH}/#{ENV['RAILS_ENV']}_pid"
+ if File.exists?(file_path)
+ File.open(file_path, "r") do |f|
+ pid = f.readline
+ Process.kill('TERM', pid.to_i)
+ end
+ File.unlink(file_path)
+ Rake::Task["solr:destroy_index"].invoke if ENV['RAILS_ENV'] == 'test'
+ puts "Solr shutdown successfully."
+ else
+ puts "PID file not found at #{file_path}. Either Solr is not running or no PID file was written."
+ end
+ end
+ end
+
+ desc 'Remove Solr index'
+ task :destroy_index do
+ require "#{File.dirname(__FILE__)}/../../config/solr_environment.rb"
+ raise "In production mode. I'm not going to delete the index, sorry." if ENV['RAILS_ENV'] == "production"
+ if File.exists?("#{SOLR_DATA_PATH}")
+ Dir["#{SOLR_DATA_PATH}/index/*"].each{|f| File.unlink(f)}
+ Dir.rmdir("#{SOLR_DATA_PATH}/index")
+ puts "Index files removed under " + ENV['RAILS_ENV'] + " environment"
+ end
+ end
+
+ # this task is by Henrik Nyh
+ # http://henrik.nyh.se/2007/06/rake-task-to-reindex-models-for-acts_as_solr
+ desc %{Reindexes data for all acts_as_solr models. Clears index first to get rid of orphaned records and optimizes index afterwards. RAILS_ENV=your_env to set environment. ONLY=book,person,magazine to only reindex those models; EXCEPT=book,magazine to exclude those models. START_SERVER=true to solr:start before and solr:stop after. BATCH=123 to post/commit in batches of that size: default is 300. CLEAR=false to not clear the index first; OPTIMIZE=false to not optimize the index afterwards.}
+ task :reindex => :environment do
+ require "#{File.dirname(__FILE__)}/../../config/solr_environment.rb"
+
+ includes = env_array_to_constants('ONLY')
+ if includes.empty?
+ includes = Dir.glob("#{RAILS_ROOT}/app/models/*.rb").map { |path| File.basename(path, ".rb").camelize.constantize }
+ end
+ excludes = env_array_to_constants('EXCEPT')
+ includes -= excludes
+
+ optimize = env_to_bool('OPTIMIZE', true)
+ start_server = env_to_bool('START_SERVER', false)
+ clear_first = env_to_bool('CLEAR', true)
+ batch_size = ENV['BATCH'].to_i.nonzero? || 300
+ debug_output = env_to_bool("DEBUG", false)
+
+ RAILS_DEFAULT_LOGGER.level = ActiveSupport::BufferedLogger::INFO unless debug_output
+
+ if start_server
+ puts "Starting Solr server..."
+ Rake::Task["solr:start"].invoke
+ end
+
+ # Disable solr_optimize
+ module ActsAsSolr::CommonMethods
+ def blank() end
+ alias_method :deferred_solr_optimize, :solr_optimize
+ alias_method :solr_optimize, :blank
+ end
+
+ models = includes.select { |m| m.respond_to?(:rebuild_solr_index) }
+ models.each do |model|
+
+ if clear_first
+ puts "Clearing index for #{model}..."
+ ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "#{model.solr_configuration[:type_field]}:#{model}"))
+ ActsAsSolr::Post.execute(Solr::Request::Commit.new)
+ end
+
+ puts "Rebuilding index for #{model}..."
+ model.rebuild_solr_index(batch_size)
+
+ end
+
+ if models.empty?
+ puts "There were no models to reindex."
+ elsif optimize
+ puts "Optimizing..."
+ models.last.deferred_solr_optimize
+ end
+
+ if start_server
+ puts "Shutting down Solr server..."
+ Rake::Task["solr:stop"].invoke
+ end
+
+ end
+
+ def env_array_to_constants(env)
+ env = ENV[env] || ''
+ env.split(/\s*,\s*/).map { |m| m.singularize.camelize.constantize }.uniq
+ end
+
+ def env_to_bool(env, default)
+ env = ENV[env] || ''
+ case env
+ when /^true$/i then true
+ when /^false$/i then false
+ else default
+ end
+ end
+
+end
+
diff --git a/vendor/plugins/acts_as_solr/lib/tasks/test.rake b/vendor/plugins/acts_as_solr/lib/tasks/test.rake
new file mode 100644
index 0000000..6bb6caf
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/lib/tasks/test.rake
@@ -0,0 +1,7 @@
+require 'active_record'
+
+namespace :test do
+ task :migrate do
+ ActiveRecord::Migrator.migrate("test/db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
+ end
+end
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/admin-extra.html b/vendor/plugins/acts_as_solr/solr/solr/conf/admin-extra.html
new file mode 100644
index 0000000..aa739da
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/admin-extra.html
@@ -0,0 +1,31 @@
+
+
+
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/protwords.txt b/vendor/plugins/acts_as_solr/solr/solr/conf/protwords.txt
new file mode 100644
index 0000000..1dfc0ab
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/protwords.txt
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# Use a protected word file to protect against the stemmer reducing two
+# unrelated words to the same base word.
+
+# Some non-words that normally won't be encountered,
+# just to test that they won't be stemmed.
+dontstems
+zwhacky
+
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/schema.xml b/vendor/plugins/acts_as_solr/solr/solr/conf/schema.xml
new file mode 100644
index 0000000..e559039
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/schema.xml
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id
+ text
+
+
+
+
+
+
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/scripts.conf b/vendor/plugins/acts_as_solr/solr/solr/conf/scripts.conf
new file mode 100644
index 0000000..f58b262
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/scripts.conf
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+user=
+solr_hostname=localhost
+solr_port=8983
+rsyncd_port=18983
+data_dir=
+webapp_name=solr
+master_host=
+master_data_dir=
+master_status_dir=
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/solrconfig.xml b/vendor/plugins/acts_as_solr/solr/solr/conf/solrconfig.xml
new file mode 100644
index 0000000..f1c48cd
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/solrconfig.xml
@@ -0,0 +1,458 @@
+
+
+
+
+
+ ${solr.abortOnConfigurationError:true}
+
+
+
+ ${solr.data.dir:./solr/data}
+
+
+
+ false
+ 10
+ 1000
+ 2147483647
+ 10000
+ 1000
+ 10000
+
+
+
+
+ false
+ 10
+ 1000
+ 2147483647
+ 10000
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1024
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ explicit
+ map
+
+
+
+
+
+
+
+ explicit
+ 0.01
+
+ text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+
+
+ text^0.2 features^1.1 name^1.5 manu^1.4 manu_exact^1.9
+
+
+ ord(poplarity)^0.5 recip(rord(price),1,1000,1000)^0.3
+
+
+ id,name,price,score
+
+
+ 2<-1 5<-2 6<90%
+
+ 100
+ *:*
+
+
+
+
+
+
+ explicit
+ text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0
+ 2<-1 5<-2 6<90%
+
+ incubationdate_dt:[* TO NOW/DAY-1MONTH]^2.2
+
+
+
+ inStock:true
+
+
+
+ cat
+ manu_exact
+ price:[* TO 500]
+ price:[500 TO *]
+
+
+
+
+
+
+ inStock:true
+
+
+ text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+
+
+ 2<-1 5<-2 6<90%
+
+
+
+
+
+
+
+
+ 1
+ 0.5
+
+
+
+
+
+
+
+ spell
+
+
+
+
+ word
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ explicit
+ true
+
+
+
+
+
+
+
+ 5
+
+
+
+
+ solr
+ solrconfig.xml schema.xml admin-extra.html
+
+
+ qt=standard&q=solrpingquery
+
+
+
+
+
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/stopwords.txt b/vendor/plugins/acts_as_solr/solr/solr/conf/stopwords.txt
new file mode 100644
index 0000000..8433c83
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/stopwords.txt
@@ -0,0 +1,57 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# a couple of test stopwords to test that the words are really being
+# configured from this file:
+stopworda
+stopwordb
+
+#Standard english stop words taken from Lucene's StopAnalyzer
+an
+and
+are
+as
+at
+be
+but
+by
+for
+if
+in
+into
+is
+it
+no
+not
+of
+on
+or
+s
+such
+t
+that
+the
+their
+then
+there
+these
+they
+this
+to
+was
+will
+with
+
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/synonyms.txt b/vendor/plugins/acts_as_solr/solr/solr/conf/synonyms.txt
new file mode 100644
index 0000000..b0e31cb
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/synonyms.txt
@@ -0,0 +1,31 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+#some test synonym mappings unlikely to appear in real input text
+aaa => aaaa
+bbb => bbbb1 bbbb2
+ccc => cccc1,cccc2
+a\=>a => b\=>b
+a\,a => b\,b
+fooaaa,baraaa,bazaaa
+
+# Some synonym groups specific to this example
+GB,gib,gigabyte,gigabytes
+MB,mib,megabyte,megabytes
+Television, Televisions, TV, TVs
+#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming
+#after us won't split it into two words.
+
+# Synonym mappings can be used for spelling correction too
+pixima => pixma
+
diff --git a/vendor/plugins/acts_as_solr/solr/solr/conf/xslt/example.xsl b/vendor/plugins/acts_as_solr/solr/solr/conf/xslt/example.xsl
new file mode 100644
index 0000000..6832a1d
--- /dev/null
+++ b/vendor/plugins/acts_as_solr/solr/solr/conf/xslt/example.xsl
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This has been formatted by the sample "example.xsl" transform -
+ use your own XSLT to get a nicer page
+