diff --git a/config/application.config.php b/config/application.config.php
index bc68b9ec1fcd2fc5f522be15d31ab15f33b4e6f7..0a5657e6664bf3de4e48a0fcd1dac540638ae386 100644
--- a/config/application.config.php
+++ b/config/application.config.php
@@ -3,7 +3,7 @@ $config = array(
     'modules' => array(
         'VuFindHttp', 'VuFindTheme', 'VuFindSearch', 'VuFind',
     ),
-    'module_listener_options' => array( 
+    'module_listener_options' => array(
         'config_glob_paths'    => array(
             'config/autoload/{,*.}{global,local}.php',
         ),
@@ -29,7 +29,7 @@ if (APPLICATION_ENV == 'development') {
 if ($localModules = getenv('VUFIND_LOCAL_MODULES')) {
     $localModules = array_map('trim', explode(',', $localModules));
     foreach ($localModules as $current) {
-        if (!empty($current)) {
+        if (!empty($current) && !in_array($current, $config['modules'])) {
             $config['modules'][] = $current;
         }
     }
diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 9751fdb2b67c603bfd888965bd2799a00090ceb2..4de4b6a7590ce28f1012c0baa6bd9c0f5c30216e 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -90,6 +90,7 @@ lifetime                    = 3600 ; Session lasts for 1 hour
 ;
 ; Available drivers: Aleph, Amicus, ClaviusSQL, Evergreen, Horizon (basic database
 ;       access only), HorizonXMLAPI (more features via API), Innovative, Koha,
+;       MultiBackend (to chain together multiple drivers in a consortial setting),
 ;       NewGenLib, NoILS (for users without an ILS, or to disable ILS functionality
 ;       during maintenance), Unicorn (which also applies to SirsiDynix Symphony),
 ;       Virtua, Voyager (for Voyager 6+), VoyagerRestful (for Voyager 7+ w/ RESTful
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index e643e67b77b483fcf60051cf3bab78ca94bdf2f2..6aff258f76be8895d523c457a6da1a9cccc402f1 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -74,16 +74,35 @@ $config = array(
         ),
     ),
     'controllers' => array(
+        'factories' => array(
+            'browse' => function ($sm) {
+                return new \VuFind\Controller\BrowseController(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
+            'collection' => function ($sm) {
+                return new \VuFind\Controller\CollectionController(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
+            'collections' => function ($sm) {
+                return new \VuFind\Controller\CollectionsController(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
+            'record' => function ($sm) {
+                return new \VuFind\Controller\RecordController(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
+        ),
         'invokables' => array(
             'admin' => 'VuFind\Controller\AdminController',
             'ajax' => 'VuFind\Controller\AjaxController',
             'alphabrowse' => 'VuFind\Controller\AlphabrowseController',
             'author' => 'VuFind\Controller\AuthorController',
             'authority' => 'VuFind\Controller\AuthorityController',
-            'browse' => 'VuFind\Controller\BrowseController',
             'cart' => 'VuFind\Controller\CartController',
-            'collection' => 'VuFind\Controller\CollectionController',
-            'collections' => 'VuFind\Controller\CollectionsController',
             'cover' => 'VuFind\Controller\CoverController',
             'error' => 'VuFind\Controller\ErrorController',
             'help' => 'VuFind\Controller\HelpController',
@@ -93,7 +112,6 @@ $config = array(
             'missingrecord' => 'VuFind\Controller\MissingrecordController',
             'my-research' => 'VuFind\Controller\MyResearchController',
             'oai' => 'VuFind\Controller\OaiController',
-            'record' => 'VuFind\Controller\RecordController',
             'records' => 'VuFind\Controller\RecordsController',
             'search' => 'VuFind\Controller\SearchController',
             'summon' => 'VuFind\Controller\SummonController',
@@ -106,14 +124,30 @@ $config = array(
         ),
     ),
     'controller_plugins' => array(
+        'factories' => array(
+            'holds' => function ($sm) {
+                return new \VuFind\Controller\Plugin\Holds(
+                    $sm->getServiceLocator()->get('VuFind\HMAC')
+                );
+            },
+            'reserves' => function ($sm) {
+                $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+                $useIndex = isset($config->Reserves->search_enabled)
+                    && $config->Reserves->search_enabled;
+                return new \VuFind\Controller\Plugin\Reserves($useIndex);
+            },
+            'result-scroller' => function ($sm) {
+                $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+                $enabled = (isset($config->Record->next_prev_navigation)
+                    && $config->Record->next_prev_navigation);
+                return new \VuFind\Controller\Plugin\ResultScroller($enabled);
+            },
+        ),
         'invokables' => array(
             'db-upgrade' => 'VuFind\Controller\Plugin\DbUpgrade',
             'favorites' => 'VuFind\Controller\Plugin\Favorites',
             'followup' => 'VuFind\Controller\Plugin\Followup',
-            'holds' => 'VuFind\Controller\Plugin\Holds',
             'renewals' => 'VuFind\Controller\Plugin\Renewals',
-            'reserves' => 'VuFind\Controller\Plugin\Reserves',
-            'result-scroller' => 'VuFind\Controller\Plugin\ResultScroller',
         )
     ),
     'service_manager' => array(
@@ -123,6 +157,12 @@ $config = array(
                     $sm->get('VuFind\Config')->get('config')
                 );
             },
+            'VuFind\CacheManager' => function ($sm) {
+                return new \VuFind\Cache\Manager(
+                    $sm->get('VuFind\Config')->get('config'),
+                    $sm->get('VuFind\Config')->get('searches')
+                );
+            },
             'VuFind\Cart' => function ($sm) {
                 $config = $sm->get('VuFind\Config')->get('config');
                 $active = isset($config->Site->showBookBag)
@@ -139,7 +179,12 @@ $config = array(
                 );
             },
             'VuFind\DbAdapter' => function ($sm) {
-                return \VuFind\Db\AdapterFactory::getAdapter();
+                return $sm->get('VuFind\DbAdapterFactory')->getAdapter();
+            },
+            'VuFind\DbAdapterFactory' => function ($sm) {
+                return new \VuFind\Db\AdapterFactory(
+                    $sm->get('VuFind\Config')->get('config')
+                );
             },
             'VuFind\Export' => function ($sm) {
                 return new \VuFind\Export(
@@ -158,13 +203,35 @@ $config = array(
                 }
                 return new \VuFindHttp\HttpService($options);
             },
+            'VuFind\HMAC' => function ($sm) {
+                return new \VuFind\Crypt\HMAC(
+                    $sm->get('VuFind\Config')->get('config')->Security->HMACkey
+                );
+            },
             'VuFind\ILSConnection' => function ($sm) {
-                $catalog = new \VuFind\ILS\Connection();
-                return $catalog
-                    ->setConfig($sm->get('VuFind\Config')->get('config')->Catalog)
-                    ->initWithDriverManager(
-                        $sm->get('VuFind\ILSDriverPluginManager')
-                    );
+                $catalog = new \VuFind\ILS\Connection(
+                    $sm->get('VuFind\Config')->get('config')->Catalog,
+                    $sm->get('VuFind\ILSDriverPluginManager'),
+                    $sm->get('VuFind\Config')
+                );
+                return $catalog->setHoldConfig($sm->get('VuFind\ILSHoldSettings'));
+            },
+            'VuFind\ILSHoldLogic' => function ($sm) {
+                return new \VuFind\ILS\Logic\Holds(
+                    $sm->get('VuFind\AuthManager'), $sm->get('VuFind\ILSConnection'),
+                    $sm->get('VuFind\HMAC'), $sm->get('VuFind\Config')->get('config')
+                );
+            },
+            'VuFind\ILSHoldSettings' => function ($sm) {
+                return new \VuFind\ILS\HoldSettings(
+                    $sm->get('VuFind\Config')->get('config')->Catalog
+                );
+            },
+            'VuFind\ILSTitleHoldLogic' => function ($sm) {
+                return new \VuFind\ILS\Logic\TitleHolds(
+                    $sm->get('VuFind\AuthManager'), $sm->get('VuFind\ILSConnection'),
+                    $sm->get('VuFind\HMAC'), $sm->get('VuFind\Config')->get('config')
+                );
             },
             'VuFind\Logger' => function ($sm) {
                 $logger = new \VuFind\Log\Logger();
@@ -223,15 +290,20 @@ $config = array(
             },
             'VuFind\WorldCatConnection' => function ($sm) {
                 return new \VuFind\Connection\WorldCat(
+                    $sm->get('VuFind\Config')->get('config'),
                     $sm->get('VuFind\Http')->createClient()
                 );
             },
+            'VuFind\WorldCatUtils' => function ($sm) {
+                $config = $sm->get('VuFind\Config')->get('config');
+                $wcId = isset($config->WorldCat->id)
+                    ? $config->WorldCat->id : false;
+                return new \VuFind\Connection\WorldCatUtils($wcId);
+            },
         ),
         'invokables' => array(
-            'VuFind\CacheManager' => 'VuFind\Cache\Manager',
             'VuFind\RecordLoader' => 'VuFind\Record\Loader',
             'VuFind\SessionManager' => 'Zend\Session\SessionManager',
-            'VuFind\WorldCatUtils' => 'VuFind\Connection\WorldCatUtils',
         ),
         'initializers' => array(
             array('VuFind\ServiceManager\Initializer', 'initInstance'),
@@ -383,6 +455,11 @@ $config = array(
                             $sm->getServiceLocator()->get('VuFind\DateConverter')
                         );
                     },
+                    'multibackend' => function ($sm) {
+                        return new \VuFind\ILS\Driver\MultiBackend(
+                            $sm->getServiceLocator()->get('VuFind\Config')
+                        );
+                    },
                     'unicorn' => function ($sm) {
                         return new \VuFind\ILS\Driver\Unicorn(
                             $sm->getServiceLocator()->get('VuFind\DateConverter')
@@ -394,8 +471,10 @@ $config = array(
                         );
                     },
                     'voyagerrestful' => function ($sm) {
+                        $ils = $sm->getServiceLocator()->get('VuFind\ILSHoldSettings');
                         return new \VuFind\ILS\Driver\VoyagerRestful(
-                            $sm->getServiceLocator()->get('VuFind\DateConverter')
+                            $sm->getServiceLocator()->get('VuFind\DateConverter'),
+                            $ils->getHoldsMode(), $ils->getTitleHoldsMode()
                         );
                     },
                 ),
@@ -426,6 +505,37 @@ $config = array(
                             isset ($config->Content->authors) ? $config->Content->authors : ''
                         );
                     },
+                    'collectionsidefacets' => function ($sm) {
+                        return new \VuFind\Recommend\CollectionSideFacets(
+                            $sm->getServiceLocator()->get('VuFind\Config')
+                        );
+                    },
+                    'europeanaresults' => function ($sm) {
+                        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+                        return new \VuFind\Recommend\EuropeanaResults(
+                            $config->Content->europeanaAPI
+                        );
+                    },
+                    'expandfacets' => function ($sm) {
+                        return new \VuFind\Recommend\ExpandFacets(
+                            $sm->getServiceLocator()->get('VuFind\Config')
+                        );
+                    },
+                    'favoritefacets' => function ($sm) {
+                        return new \VuFind\Recommend\FavoriteFacets(
+                            $sm->getServiceLocator()->get('VuFind\Config')
+                        );
+                    },
+                    'sidefacets' => function ($sm) {
+                        return new \VuFind\Recommend\SideFacets(
+                            $sm->getServiceLocator()->get('VuFind\Config')
+                        );
+                    },
+                    'topfacets' => function ($sm) {
+                        return new \VuFind\Recommend\TopFacets(
+                            $sm->getServiceLocator()->get('VuFind\Config')
+                        );
+                    },
                     'worldcatidentities' => function ($sm) {
                         return new \VuFind\Recommend\WorldCatIdentities(
                             $sm->getServiceLocator()->get('VuFind\WorldCatUtils')
@@ -441,21 +551,15 @@ $config = array(
                     'authorfacets' => 'VuFind\Recommend\AuthorFacets',
                     'authorityrecommend' => 'VuFind\Recommend\AuthorityRecommend',
                     'catalogresults' => 'VuFind\Recommend\CatalogResults',
-                    'collectionsidefacets' => 'VuFind\Recommend\CollectionSideFacets',
-                    'europeanaresults' => 'VuFind\Recommend\EuropeanaResults',
                     'europeanaresultsdeferred' => 'VuFind\Recommend\EuropeanaResultsDeferred',
-                    'expandfacets' => 'VuFind\Recommend\ExpandFacets',
                     'facetcloud' => 'VuFind\Recommend\FacetCloud',
-                    'favoritefacets' => 'VuFind\Recommend\FavoriteFacets',
                     'openlibrarysubjects' => 'VuFind\Recommend\OpenLibrarySubjects',
                     'openlibrarysubjectsdeferred' => 'VuFind\Recommend\OpenLibrarySubjectsDeferred',
                     'pubdatevisajax' => 'VuFind\Recommend\PubDateVisAjax',
                     'resultgooglemapajax' => 'VuFind\Recommend\ResultGoogleMapAjax',
-                    'sidefacets' => 'VuFind\Recommend\SideFacets',
                     'summondatabases' => 'VuFind\Recommend\SummonDatabases',
                     'summonresults' => 'VuFind\Recommend\SummonResults',
                     'switchtype' => 'VuFind\Recommend\SwitchType',
-                    'topfacets' => 'VuFind\Recommend\TopFacets',
                 ),
             ),
             'recorddriver' => array(
@@ -481,11 +585,17 @@ $config = array(
                         );
                     },
                     'solrmarc' => function ($sm) {
-                        return new \VuFind\RecordDriver\SolrMarc(
+                        $driver = new \VuFind\RecordDriver\SolrMarc(
                             $sm->getServiceLocator()->get('VuFind\Config')->get('config'),
                             null,
                             $sm->getServiceLocator()->get('VuFind\Config')->get('searches')
                         );
+                        $driver->attachILS(
+                            $sm->getServiceLocator()->get('VuFind\ILSConnection'),
+                            $sm->getServiceLocator()->get('VuFind\ILSHoldLogic'),
+                            $sm->getServiceLocator()->get('VuFind\ILSTitleHoldLogic')
+                        );
+                        return $driver;
                     },
                     'solrreserves' => function ($sm) {
                         return new \VuFind\RecordDriver\SolrReserves(
@@ -525,6 +635,7 @@ $config = array(
                 'factories' => array(
                     'collectionhierarchytree' => function ($sm) {
                         return new \VuFind\RecordTab\CollectionHierarchyTree(
+                            $sm->getServiceLocator()->get('VuFind\Config')->get('config'),
                             $sm->getServiceLocator()->get('VuFind\RecordLoader')
                         );
                     },
@@ -534,6 +645,16 @@ $config = array(
                             $searchManager->setSearchClassId('SolrCollection')->getResults()
                         );
                     },
+                    'excerpt' => function ($sm) {
+                        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+                        $enabled = isset($config->Content->excerpts);
+                        return new \VuFind\RecordTab\Excerpt($enabled);
+                    },
+                    'hierarchytree' => function ($sm) {
+                        return new \VuFind\RecordTab\HierarchyTree(
+                            $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                        );
+                    },
                     'holdingsils' => function ($sm) {
                         // If VuFind is configured to suppress the holdings tab when the
                         // ILS driver specifies no holdings, we need to pass in a connection
@@ -548,14 +669,20 @@ $config = array(
                         }
                         return new \VuFind\RecordTab\HoldingsILS($catalog);
                     },
+                    'map' => function ($sm) {
+                        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+                        $enabled = isset($config->Content->recordMap);
+                        return new \VuFind\RecordTab\Map($enabled);
+                    },
+                    'reviews' => function ($sm) {
+                        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+                        $enabled = isset($config->Content->reviews);
+                        return new \VuFind\RecordTab\Reviews($enabled);
+                    },
                 ),
                 'invokables' => array(
                     'description' => 'VuFind\RecordTab\Description',
-                    'excerpt' => 'VuFind\RecordTab\Excerpt',
-                    'hierarchytree' => 'VuFind\RecordTab\HierarchyTree',
                     'holdingsworldcat' => 'VuFind\RecordTab\HoldingsWorldCat',
-                    'map' => 'VuFind\RecordTab\Map',
-                    'reviews' => 'VuFind\RecordTab\Reviews',
                     'staffviewarray' => 'VuFind\RecordTab\StaffViewArray',
                     'staffviewmarc' => 'VuFind\RecordTab\StaffViewMARC',
                     'toc' => 'VuFind\RecordTab\TOC',
diff --git a/module/VuFind/src/VuFind/Auth/AbstractBase.php b/module/VuFind/src/VuFind/Auth/AbstractBase.php
index b02b58597d3a113f02d26e62f7d2f05ce9248af5..df31681fab238456be91a84fc02fe1571e4690e8 100644
--- a/module/VuFind/src/VuFind/Auth/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Auth/AbstractBase.php
@@ -27,8 +27,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Auth;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\Auth as AuthException;
+use VuFind\Exception\Auth as AuthException;
 
 /**
  * Abstract authentication base class
@@ -72,11 +71,6 @@ abstract class AbstractBase implements \VuFind\Db\Table\DbTableAwareInterface
      */
     public function getConfig()
     {
-        // Load configuration if not already present:
-        if (is_null($this->config)) {
-            $this->setConfig(ConfigReader::getConfig());
-        }
-
         // Validate configuration if not already validated:
         if (!$this->configValidated) {
             $this->validateConfig();
diff --git a/module/VuFind/src/VuFind/Auth/Database.php b/module/VuFind/src/VuFind/Auth/Database.php
index 5f6b24de29135c937c90b006f787a9b39229c4d3..b9c6942e91b2a5a3462f140cf067a4722a80a891 100644
--- a/module/VuFind/src/VuFind/Auth/Database.php
+++ b/module/VuFind/src/VuFind/Auth/Database.php
@@ -43,7 +43,18 @@ use VuFind\Exception\Auth as AuthException, Zend\Crypt\Password\Bcrypt;
  */
 class Database extends AbstractBase
 {
+    /**
+     * Username
+     *
+     * @var string
+     */
     protected $username;
+
+    /**
+     * Password
+     *
+     * @var string
+     */
     protected $password;
 
     /**
@@ -81,8 +92,9 @@ class Database extends AbstractBase
      */
     protected function passwordHashingEnabled()
     {
-        return isset($this->config->Authentication->hash_passwords)
-            ? $this->config->Authentication->hash_passwords : false;
+        $config = $this->getConfig();
+        return isset($config->Authentication->hash_passwords)
+            ? $config->Authentication->hash_passwords : false;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Auth/ILS.php b/module/VuFind/src/VuFind/Auth/ILS.php
index fdbfe22cd773922bb3f208a20c03a9969ff80eec..b05ea77d42a626f61a4427a3591596ffe32214d6 100644
--- a/module/VuFind/src/VuFind/Auth/ILS.php
+++ b/module/VuFind/src/VuFind/Auth/ILS.php
@@ -41,6 +41,11 @@ use VuFind\Exception\Auth as AuthException;
  */
 class ILS extends AbstractBase
 {
+    /**
+     * Catalog connection
+     *
+     * @var \VuFind\ILS\Connection
+     */
     protected $catalog = null;
 
     /**
diff --git a/module/VuFind/src/VuFind/Auth/LDAP.php b/module/VuFind/src/VuFind/Auth/LDAP.php
index c907870bd3ea64f9a8895b1146086670798edc52..4730d240d4f92eb5e8c5c982fbad9cfcabdb9f48 100644
--- a/module/VuFind/src/VuFind/Auth/LDAP.php
+++ b/module/VuFind/src/VuFind/Auth/LDAP.php
@@ -41,7 +41,18 @@ use VuFind\Exception\Auth as AuthException;
  */
 class LDAP extends AbstractBase
 {
+    /**
+     * Username
+     *
+     * @var string
+     */
     protected $username;
+
+    /**
+     * Password
+     *
+     * @var string
+     */
     protected $password;
 
     /**
diff --git a/module/VuFind/src/VuFind/Autocomplete/PluginManager.php b/module/VuFind/src/VuFind/Autocomplete/PluginManager.php
index 90a9b3854d977d7833399eecdcfe9eb7e3677f83..f965b6906da6593b27cc51867f72e1da96d4541c 100644
--- a/module/VuFind/src/VuFind/Autocomplete/PluginManager.php
+++ b/module/VuFind/src/VuFind/Autocomplete/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:autosuggesters Wiki
  */
 namespace VuFind\Autocomplete;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Autocomplete handler plugin manager
@@ -75,7 +74,8 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
         $searcher = $request->get('searcher', 'Solr');
         $options = $this->getServiceLocator()->get('SearchManager')
             ->setSearchClassId($searcher)->getOptionsInstance();
-        $config = ConfigReader::getConfig($options->getSearchIni());
+        $config = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($options->getSearchIni());
         $types = isset($config->Autocomplete_Types) ?
             $config->Autocomplete_Types->toArray() : array();
 
diff --git a/module/VuFind/src/VuFind/Cache/Manager.php b/module/VuFind/src/VuFind/Cache/Manager.php
index 605fa700a232a819186fd5f7a5dc7da12b1bdbee..11e36be0d408870aabad0454d709a2c00b16fca9 100644
--- a/module/VuFind/src/VuFind/Cache/Manager.php
+++ b/module/VuFind/src/VuFind/Cache/Manager.php
@@ -26,7 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Cache;
-use VuFind\Config\Reader as ConfigReader, Zend\Cache\StorageFactory;
+use Zend\Cache\StorageFactory, Zend\Config\Config;
 
 /**
  * VuFind Cache Manager
@@ -71,12 +71,12 @@ class Manager
 
     /**
      * Constructor
+     *
+     * @param Config $config       Main VuFind configuration
+     * @param Config $searchConfig Search configuration
      */
-    public function __construct()
+    public function __construct(Config $config, Config $searchConfig)
     {
-        // Get global cache options
-        $config = ConfigReader::getConfig('config');
-
         // $config and $config->Cache are Zend\Config\Config objects
         // $cache is created immutable, so get the array, it will be modified
         // downstream.
@@ -95,9 +95,8 @@ class Manager
         $this->createFileCache('language', $cacheBase . 'languages');
 
         // Set up search specs cache based on config settings:
-        $config = ConfigReader::getConfig('searches');
-        $searchCacheType = isset($config->Cache->type)
-            ? $config->Cache->type : false;
+        $searchCacheType = isset($searchConfig->Cache->type)
+            ? $searchConfig->Cache->type : false;
         switch ($searchCacheType) {
         case 'APC':
             $this->createAPCCache('searchspecs');
diff --git a/module/VuFind/src/VuFind/Config/Locator.php b/module/VuFind/src/VuFind/Config/Locator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d19008764eabce3439c8745ca09a83780e9da734
--- /dev/null
+++ b/module/VuFind/src/VuFind/Config/Locator.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * VF Configuration Locator
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Config
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org   Main Site
+ */
+namespace VuFind\Config;
+
+/**
+ * Class to find VuFind configuration files
+ *
+ * @category VuFind2
+ * @package  Config
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org   Main Site
+ */
+class Locator
+{
+    /**
+     * Get the file path to the local configuration file (null if none found).
+     *
+     * @param string $filename config file name
+     * @param string $path     path relative to VuFind base (optional; defaults
+     * to config/vufind if set to null)
+     * @param bool   $force    force method to return path even if file does not
+     * exist (default = false, do not force)
+     *
+     * @return string
+     */
+    public static function getLocalConfigPath($filename, $path = null,
+        $force = false
+    ) {
+        if (is_null($path)) {
+            $path = 'config/vufind';
+        }
+        if (defined('LOCAL_OVERRIDE_DIR') && strlen(trim(LOCAL_OVERRIDE_DIR)) > 0) {
+            $path = LOCAL_OVERRIDE_DIR . '/' . $path . '/' . $filename;
+            if ($force || file_exists($path)) {
+                return $path;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get the file path to the base configuration file.
+     *
+     * @param string $filename config file name
+     * @param string $path     path relative to VuFind base (optional; defaults
+     * to config/vufind
+     *
+     * @return string
+     */
+    public static function getBaseConfigPath($filename, $path='config/vufind')
+    {
+        return APPLICATION_PATH . '/' . $path . '/' . $filename;
+    }
+
+    /**
+     * Get the file path to a config file.
+     *
+     * @param string $filename config file name
+     * @param string $path     path relative to VuFind base (optional; defaults
+     * to config/vufind
+     *
+     * @return string
+     */
+    public static function getConfigPath($filename, $path = 'config/vufind')
+    {
+        // Check if config exists in local dir:
+        $local = static::getLocalConfigPath($filename, $path);
+        if (!empty($local)) {
+            return $local;
+        }
+
+        // No local version?  Return default core version:
+        return static::getBaseConfigPath($filename, $path);
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Config/PluginFactory.php b/module/VuFind/src/VuFind/Config/PluginFactory.php
index 27bb59f5704c56b2e60688892d6d0e118ea71506..cc2aec3054f7176cc68aca09185be179e21ee6b9 100644
--- a/module/VuFind/src/VuFind/Config/PluginFactory.php
+++ b/module/VuFind/src/VuFind/Config/PluginFactory.php
@@ -26,7 +26,8 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\Config;
-use Zend\ServiceManager\AbstractFactoryInterface,
+use Zend\Config\Config, Zend\Config\Reader\Ini as IniReader,
+    Zend\ServiceManager\AbstractFactoryInterface,
     Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
@@ -40,6 +41,82 @@ use Zend\ServiceManager\AbstractFactoryInterface,
  */
 class PluginFactory implements AbstractFactoryInterface
 {
+    /**
+     * .ini reader
+     *
+     * @var IniReader
+     */
+    protected $iniReader;
+
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        // Use ASCII 0 as a nest separator; otherwise some of the unusual key names
+        // we have (i.e. in WorldCat.ini search options) will get parsed in
+        // unexpected ways.
+        $this->iniReader = new IniReader();
+        $this->iniReader->setNestSeparator(chr(0));
+    }
+
+    /**
+     * Load the specified configuration file.
+     *
+     * @param string $filename config file name
+     * @param string $path     path relative to VuFind base (optional; defaults
+     * to config/vufind
+     *
+     * @return \Zend\Config\Config
+     */
+    protected function loadConfigFile($filename, $path = 'config/vufind')
+    {
+        $configs = array();
+
+        $fullpath = Locator::getConfigPath($filename, $path);
+
+        // Retrieve and parse at least one configuration file, and possibly a whole
+        // chain of them if the Parent_Config setting is used:
+        do {
+            $configs[]
+                = new Config($this->iniReader->fromFile($fullpath), true);
+
+            $i = count($configs) - 1;
+            $fullpath = isset($configs[$i]->Parent_Config->path)
+                ? $configs[$i]->Parent_Config->path : false;
+        } while ($fullpath);
+
+        // The last element in the array will be the top of the inheritance tree.
+        // Let's establish a baseline:
+        $config = array_pop($configs);
+
+        // Now we'll pull all the children down one at a time and override settings
+        // as appropriate:
+        while (!is_null($child = array_pop($configs))) {
+            $overrideSections = isset($child->Parent_Config->override_full_sections)
+                ? explode(
+                    ',', str_replace(
+                        ' ', '', $child->Parent_Config->override_full_sections
+                    )
+                )
+                : array();
+            foreach ($child as $section => $contents) {
+                if (in_array($section, $overrideSections)
+                    || !isset($config->$section)
+                ) {
+                    $config->$section = $child->$section;
+                } else {
+                    foreach ($contents as $key => $value) {
+                        $config->$section->$key = $child->$section->$key;
+                    }
+                }
+            }
+        }
+
+        $config->setReadOnly();
+        return $config;
+    }
+
     /**
      * Can we create a service for the specified name?
      *
@@ -68,6 +145,6 @@ class PluginFactory implements AbstractFactoryInterface
     public function createServiceWithName(ServiceLocatorInterface $serviceLocator,
         $name, $requestedName
     ) {
-        return \VuFind\Config\Reader::getConfig($requestedName);
+        return $this->loadConfigFile($requestedName . '.ini');
     }
 }
diff --git a/module/VuFind/src/VuFind/Config/PluginManager.php b/module/VuFind/src/VuFind/Config/PluginManager.php
index d19396509f5a70a0ccd6ab50aad5a6d0833304da..5e89f3b95b7066a95c7a5895bda0f6976dc4bef5 100644
--- a/module/VuFind/src/VuFind/Config/PluginManager.php
+++ b/module/VuFind/src/VuFind/Config/PluginManager.php
@@ -54,4 +54,20 @@ class PluginManager extends Base
     {
         // Assume everything is okay.
     }
+
+    /**
+     * Reload a configuration and return the new version
+     *
+     * @param string $id Service identifier
+     *
+     * @return \Zend\Config\Config
+     */
+    public function reload($id)
+    {
+        $oldOverrideSetting = $this->getAllowOverride();
+        $this->setAllowOverride(true);
+        $this->setService($id, $this->create($id));
+        $this->setAllowOverride($oldOverrideSetting);
+        return $this->get($id);
+    }
 }
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Config/Reader.php b/module/VuFind/src/VuFind/Config/Reader.php
deleted file mode 100644
index 7d5324fb9b05632164d13332cbaed8e524514673..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Config/Reader.php
+++ /dev/null
@@ -1,302 +0,0 @@
-<?php
-/**
- * VF Configuration Reader
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * @category VuFind2
- * @package  Config
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     http://vufind.org   Main Site
- */
-namespace VuFind\Config;
-use Zend\Config\Config, Zend\Config\Reader\Ini as IniReader;
-
-/**
- * Class to digest VuFind configuration settings
- *
- * @category VuFind2
- * @package  Config
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     http://vufind.org   Main Site
- */
-class Reader
-{
-    protected static $configs = array();
-
-    /**
-     * Load the proper config file
-     *
-     * @param string $name        Config file name (no .ini; null for main config)
-     * @param bool   $forceReload Reload config from disk even if already in cache
-     *
-     * @return \Zend\Config\Config
-     */
-    public static function getConfig($name = null, $forceReload = false)
-    {
-        if (is_null($name)) {
-            $name = 'config';
-        }
-        // Not already cached?  Load it now.
-        if ($forceReload || !isset(self::$configs[$name])) {
-            self::$configs[$name] = self::loadConfigFile($name . '.ini');
-        }
-        return self::$configs[$name];
-    }
-
-    /**
-     * Get the file path to the local configuration file (null if none found).
-     *
-     * @param string $filename config file name
-     * @param string $path     path relative to VuFind base (optional; defaults
-     * to config/vufind if set to null)
-     * @param bool   $force    force method to return path even if file does not
-     * exist (default = false, do not force)
-     *
-     * @return string
-     */
-    public static function getLocalConfigPath($filename, $path = null,
-        $force = false
-    ) {
-        if (is_null($path)) {
-            $path = 'config/vufind';
-        }
-        if (defined('LOCAL_OVERRIDE_DIR') && strlen(trim(LOCAL_OVERRIDE_DIR)) > 0) {
-            $path = LOCAL_OVERRIDE_DIR . '/' . $path . '/' . $filename;
-            if ($force || file_exists($path)) {
-                return $path;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Get the file path to the base configuration file.
-     *
-     * @param string $filename config file name
-     * @param string $path     path relative to VuFind base (optional; defaults
-     * to config/vufind
-     *
-     * @return string
-     */
-    public static function getBaseConfigPath($filename, $path='config/vufind')
-    {
-        return APPLICATION_PATH . '/' . $path . '/' . $filename;
-    }
-
-    /**
-     * Get the file path to a config file.
-     *
-     * @param string $filename config file name
-     * @param string $path     path relative to VuFind base (optional; defaults
-     * to config/vufind
-     *
-     * @return string
-     */
-    public static function getConfigPath($filename, $path = 'config/vufind')
-    {
-        // Check if config exists in local dir:
-        $local = self::getLocalConfigPath($filename, $path);
-        if (!empty($local)) {
-            return $local;
-        }
-
-        // No local version?  Return default core version:
-        return self::getBaseConfigPath($filename, $path);
-    }
-
-    /**
-     * Get the Ini Reader.
-     *
-     * @return \Zend\Config\Reader\Ini
-     */
-    protected static function getIniReader()
-    {
-        static $iniReader = false;
-
-        // Set up reader if it is not already present in the static variable:
-        if (!$iniReader) {
-            // Use ASCII 0 as a nest separator; otherwise some of the unusual
-            // key names we have (i.e. in WorldCat.ini search options) will get
-            // parsed in unexpected ways.
-            $iniReader = new IniReader();
-            $iniReader->setNestSeparator(chr(0));
-        }
-
-        return $iniReader;
-    }
-
-    /**
-     * Load the specified configuration file.
-     *
-     * @param string $filename config file name
-     * @param string $path     path relative to VuFind base (optional; defaults
-     * to config/vufind
-     *
-     * @return \Zend\Config\Config
-     */
-    public static function loadConfigFile($filename, $path = 'config/vufind')
-    {
-        $configs = array();
-
-        $fullpath = self::getConfigPath($filename, $path);
-
-        // Retrieve and parse at least one configuration file, and possibly a whole
-        // chain of them if the Parent_Config setting is used:
-        do {
-            $configs[]
-                = new Config(static::getIniReader()->fromFile($fullpath), true);
-
-            $i = count($configs) - 1;
-            $fullpath = isset($configs[$i]->Parent_Config->path)
-                ? $configs[$i]->Parent_Config->path : false;
-        } while ($fullpath);
-
-        // The last element in the array will be the top of the inheritance tree.
-        // Let's establish a baseline:
-        $config = array_pop($configs);
-
-        // Now we'll pull all the children down one at a time and override settings
-        // as appropriate:
-        while (!is_null($child = array_pop($configs))) {
-            $overrideSections = isset($child->Parent_Config->override_full_sections)
-                ? explode(
-                    ',', str_replace(
-                        ' ', '', $child->Parent_Config->override_full_sections
-                    )
-                )
-                : array();
-            foreach ($child as $section => $contents) {
-                if (in_array($section, $overrideSections)
-                    || !isset($config->$section)
-                ) {
-                    $config->$section = $child->$section;
-                } else {
-                    foreach ($contents as $key => $value) {
-                        $config->$section->$key = $child->$section->$key;
-                    }
-                }
-            }
-        }
-
-        $config->setReadOnly();
-        return $config;
-    }
-
-    /**
-     * readIniComments
-     *
-     * Read the specified file and return an associative array of this format
-     * containing all comments extracted from the file:
-     *
-     * array =>
-     *   'sections' => array
-     *     'section_name_1' => array
-     *       'before' => string ("Comments found at the beginning of this section")
-     *       'inline' => string ("Comments found at the end of the section's line")
-     *       'settings' => array
-     *         'setting_name_1' => array
-     *           'before' => string ("Comments found before this setting")
-     *           'inline' => string ("Comments found at the end of setting's line")
-     *           ...
-     *         'setting_name_n' => array (same keys as setting_name_1)
-     *        ...
-     *      'section_name_n' => array (same keys as section_name_1)
-     *   'after' => string ("Comments found at the very end of the file")
-     *
-     * @param string $filename Name of ini file to read.
-     *
-     * @return array           Associative array as described above.
-     */
-    public static function extractComments($filename)
-    {
-        $lines = file($filename);
-
-        // Initialize our return value:
-        $retVal = array('sections' => array(), 'after' => '');
-
-        // Initialize variables for tracking status during parsing:
-        $section = $comments = '';
-
-        foreach ($lines as $line) {
-            // To avoid redundant processing, create a trimmed version of the current
-            // line:
-            $trimmed = trim($line);
-
-            // Is the current line a comment?  If so, add to the currentComments
-            // string. Note that we treat blank lines as comments.
-            if (substr($trimmed, 0, 1) == ';' || empty($trimmed)) {
-                $comments .= $line;
-            } else if (substr($trimmed, 0, 1) == '['
-                && ($closeBracket = strpos($trimmed, ']')) > 1
-            ) {
-                // Is the current line the start of a section?  If so, create the
-                // appropriate section of the return value:
-                $section = substr($trimmed, 1, $closeBracket - 1);
-                if (!empty($section)) {
-                    // Grab comments at the end of the line, if any:
-                    if (($semicolon = strpos($trimmed, ';')) !== false) {
-                        $inline = trim(substr($trimmed, $semicolon));
-                    } else {
-                        $inline = '';
-                    }
-                    $retVal['sections'][$section] = array(
-                        'before' => $comments,
-                        'inline' => $inline,
-                        'settings' => array());
-                    $comments = '';
-                }
-            } else if (($equals = strpos($trimmed, '=')) !== false) {
-                // Is the current line a setting?  If so, add to the return value:
-                $set = trim(substr($trimmed, 0, $equals));
-                $set = trim(str_replace('[]', '', $set));
-                if (!empty($section) && !empty($set)) {
-                    // Grab comments at the end of the line, if any:
-                    if (($semicolon = strpos($trimmed, ';')) !== false) {
-                        $inline = trim(substr($trimmed, $semicolon));
-                    } else {
-                        $inline = '';
-                    }
-                    // Currently, this data structure doesn't support arrays very
-                    // well, since it can't distinguish which line of the array
-                    // corresponds with which comments.  For now, we just append all
-                    // the preceding and inline comments together for arrays.  Since
-                    // we rarely use arrays in the config.ini file, this isn't a big
-                    // concern, but we should improve it if we ever need to.
-                    if (!isset($retVal['sections'][$section]['settings'][$set])) {
-                        $retVal['sections'][$section]['settings'][$set]
-                            = array('before' => $comments, 'inline' => $inline);
-                    } else {
-                        $retVal['sections'][$section]['settings'][$set]['before']
-                            .= $comments;
-                        $retVal['sections'][$section]['settings'][$set]['inline']
-                            .= "\n" . $inline;
-                    }
-                    $comments = '';
-                }
-            }
-        }
-
-        // Store any leftover comments following the last setting:
-        $retVal['after'] = $comments;
-
-        return $retVal;
-    }
-}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Config/SearchSpecsReader.php b/module/VuFind/src/VuFind/Config/SearchSpecsReader.php
index ab382df37a8ab1fe38150eb0ed3a90cb25ff5017..752c70b36908ff7438bd80cf232b589256e92f73 100644
--- a/module/VuFind/src/VuFind/Config/SearchSpecsReader.php
+++ b/module/VuFind/src/VuFind/Config/SearchSpecsReader.php
@@ -79,8 +79,8 @@ class SearchSpecsReader
                 ? $this->cacheManager->getCache('searchspecs') : false;
 
             // Determine full configuration file path:
-            $fullpath = Reader::getBaseConfigPath($filename);
-            $local = Reader::getLocalConfigPath($filename);
+            $fullpath = Locator::getBaseConfigPath($filename);
+            $local = Locator::getLocalConfigPath($filename);
 
             // Generate cache key:
             $key = $filename . '-' . filemtime($fullpath);
diff --git a/module/VuFind/src/VuFind/Config/Upgrade.php b/module/VuFind/src/VuFind/Config/Upgrade.php
index 9c463d3acfbfe349d08eff9e13277f27d7a6d5aa..54b334a29ceb9f82c8f4ae502051bbb7dafeac37 100644
--- a/module/VuFind/src/VuFind/Config/Upgrade.php
+++ b/module/VuFind/src/VuFind/Config/Upgrade.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Config;
-use VuFind\Config\Reader as ConfigReader, VuFind\Config\Writer as ConfigWriter,
+use VuFind\Config\Writer as ConfigWriter,
     VuFind\Exception\FileAccess as FileAccessException;
 
 /**
@@ -285,7 +285,7 @@ class Upgrade
             $this->newConfigs[$config]
                 = parse_ini_file($this->rawDir . '/' . $config, true);
             $this->comments[$config]
-                = ConfigReader::extractComments($this->rawDir . '/' . $config);
+                = $this->extractComments($this->rawDir . '/' . $config);
         }
     }
 
@@ -873,4 +873,102 @@ class Upgrade
             unset($this->oldConfigs['facets.ini']['StripFacets']);
         }
     }
+
+    /**
+     * Read the specified file and return an associative array of this format
+     * containing all comments extracted from the file:
+     *
+     * array =>
+     *   'sections' => array
+     *     'section_name_1' => array
+     *       'before' => string ("Comments found at the beginning of this section")
+     *       'inline' => string ("Comments found at the end of the section's line")
+     *       'settings' => array
+     *         'setting_name_1' => array
+     *           'before' => string ("Comments found before this setting")
+     *           'inline' => string ("Comments found at the end of setting's line")
+     *           ...
+     *         'setting_name_n' => array (same keys as setting_name_1)
+     *        ...
+     *      'section_name_n' => array (same keys as section_name_1)
+     *   'after' => string ("Comments found at the very end of the file")
+     *
+     * @param string $filename Name of ini file to read.
+     *
+     * @return array           Associative array as described above.
+     */
+    protected function extractComments($filename)
+    {
+        $lines = file($filename);
+
+        // Initialize our return value:
+        $retVal = array('sections' => array(), 'after' => '');
+
+        // Initialize variables for tracking status during parsing:
+        $section = $comments = '';
+
+        foreach ($lines as $line) {
+            // To avoid redundant processing, create a trimmed version of the current
+            // line:
+            $trimmed = trim($line);
+
+            // Is the current line a comment?  If so, add to the currentComments
+            // string. Note that we treat blank lines as comments.
+            if (substr($trimmed, 0, 1) == ';' || empty($trimmed)) {
+                $comments .= $line;
+            } else if (substr($trimmed, 0, 1) == '['
+                && ($closeBracket = strpos($trimmed, ']')) > 1
+            ) {
+                // Is the current line the start of a section?  If so, create the
+                // appropriate section of the return value:
+                $section = substr($trimmed, 1, $closeBracket - 1);
+                if (!empty($section)) {
+                    // Grab comments at the end of the line, if any:
+                    if (($semicolon = strpos($trimmed, ';')) !== false) {
+                        $inline = trim(substr($trimmed, $semicolon));
+                    } else {
+                        $inline = '';
+                    }
+                    $retVal['sections'][$section] = array(
+                        'before' => $comments,
+                        'inline' => $inline,
+                        'settings' => array());
+                    $comments = '';
+                }
+            } else if (($equals = strpos($trimmed, '=')) !== false) {
+                // Is the current line a setting?  If so, add to the return value:
+                $set = trim(substr($trimmed, 0, $equals));
+                $set = trim(str_replace('[]', '', $set));
+                if (!empty($section) && !empty($set)) {
+                    // Grab comments at the end of the line, if any:
+                    if (($semicolon = strpos($trimmed, ';')) !== false) {
+                        $inline = trim(substr($trimmed, $semicolon));
+                    } else {
+                        $inline = '';
+                    }
+                    // Currently, this data structure doesn't support arrays very
+                    // well, since it can't distinguish which line of the array
+                    // corresponds with which comments.  For now, we just append all
+                    // the preceding and inline comments together for arrays.  Since
+                    // we rarely use arrays in the config.ini file, this isn't a big
+                    // concern, but we should improve it if we ever need to.
+                    if (!isset($retVal['sections'][$section]['settings'][$set])) {
+                        $retVal['sections'][$section]['settings'][$set]
+                            = array('before' => $comments, 'inline' => $inline);
+                    } else {
+                        $retVal['sections'][$section]['settings'][$set]['before']
+                            .= $comments;
+                        $retVal['sections'][$section]['settings'][$set]['inline']
+                            .= "\n" . $inline;
+                    }
+                    $comments = '';
+                }
+            }
+        }
+
+        // Store any leftover comments following the last setting:
+        $retVal['after'] = $comments;
+
+        return $retVal;
+    }
 }
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Connection/Manager.php b/module/VuFind/src/VuFind/Connection/Manager.php
index 8e13b84201c4b383ea00da2b497550fef6d79e1a..526716cd2ff5286c65b3c879578f3f42f097fcca 100644
--- a/module/VuFind/src/VuFind/Connection/Manager.php
+++ b/module/VuFind/src/VuFind/Connection/Manager.php
@@ -27,8 +27,7 @@
  */
 namespace VuFind\Connection;
 
-use VuFind\Config\Reader as ConfigReader, VuFind\ILS\Connection as ILSConnection,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Central class for connecting to resources used by VuFind.
@@ -66,7 +65,7 @@ class Manager
      */
     public static function connectToIndex($type = null, $core = null, $url = null)
     {
-        $configArray = ConfigReader::getConfig();
+        $configArray = self::$serviceLocator->get('VuFind\Config')->get('config');
 
         // Load config.ini settings for missing parameters:
         if ($type == null) {
diff --git a/module/VuFind/src/VuFind/Connection/Solr.php b/module/VuFind/src/VuFind/Connection/Solr.php
index 096ead893849a797c7129dd0f1127fef21371d15..24675f59c264b3b401cf073431187d8d85a13432 100644
--- a/module/VuFind/src/VuFind/Connection/Solr.php
+++ b/module/VuFind/src/VuFind/Connection/Solr.php
@@ -27,7 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\Connection;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\Solr as SolrException,
+use VuFind\Exception\Solr as SolrException,
     VuFind\Solr\Utils as SolrUtils, Zend\Log\LoggerInterface,
     Zend\ServiceManager\ServiceLocatorAwareInterface,
     Zend\ServiceManager\ServiceLocatorInterface;
@@ -1756,7 +1756,7 @@ class Solr implements ServiceLocatorAwareInterface,
      */
     public function getHttpTimeout()
     {
-        $config = ConfigReader::getConfig();
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
         return isset($config->Index->timeout) ? $config->Index->timeout : 30;
     }
 
diff --git a/module/VuFind/src/VuFind/Connection/Summon.php b/module/VuFind/src/VuFind/Connection/Summon.php
index eeca54ab8692693b5082d871b9fdba47d5cff7ef..4fd985a6ea48f82eb59e42224235dd4cf72aa1d9 100644
--- a/module/VuFind/src/VuFind/Connection/Summon.php
+++ b/module/VuFind/src/VuFind/Connection/Summon.php
@@ -28,8 +28,7 @@
  */
 namespace VuFind\Connection;
 use SerialsSolutions\Summon\Zend2 as BaseSummon,
-    VuFind\Config\Reader as ConfigReader, VuFind\Solr\Utils as SolrUtils,
-    Zend\Log\LoggerInterface;
+    VuFind\Solr\Utils as SolrUtils, Zend\Log\LoggerInterface;
 
 /**
  * Summon Search API Interface (VuFind implementation)
@@ -70,9 +69,10 @@ class Summon extends BaseSummon implements \Zend\Log\LoggerAwareInterface
      *
      * Sets up the Summon API Client
      *
-     * @param string            $apiId   Summon API ID
-     * @param string            $apiKey  Summon API Key
-     * @param array             $options Associative array of additional options;
+     * @param \Zend\Config\Config $config  Configuration representing Summon.ini
+     * @param string              $apiId   Summon API ID
+     * @param string              $apiKey  Summon API Key
+     * @param array               $options Associative array of additional options;
      * legal keys:
      *    <ul>
      *      <li>authedUser - is the end-user authenticated?</li>
@@ -81,13 +81,11 @@ class Summon extends BaseSummon implements \Zend\Log\LoggerAwareInterface
      *      <li>sessionId - Summon session ID to apply</li>
      *      <li>version - API version to use</li>
      *    </ul>
-     * @param \Zend\Http\Client $client  HTTP client
+     * @param \Zend\Http\Client   $client  HTTP client
      */
-    public function __construct($apiId, $apiKey, $options = array(),
-        \Zend\Http\Client $client = null
+    public function __construct(\Zend\Config\Config $config, $apiId, $apiKey,
+        $options = array(), \Zend\Http\Client $client = null
     ) {
-        $config = ConfigReader::getConfig('Summon');
-
         // Store preferred boolean behavior:
         if (!isset($options['caseSensitiveBooleans'])
             && isset($config->General->case_sensitive_bools)
diff --git a/module/VuFind/src/VuFind/Connection/Summon/Query.php b/module/VuFind/src/VuFind/Connection/Summon/Query.php
index c0326788a96221a9621841be7832bc036fb23098..b7f490ebf5542512995a4091169c53d2ecbc7b43 100644
--- a/module/VuFind/src/VuFind/Connection/Summon/Query.php
+++ b/module/VuFind/src/VuFind/Connection/Summon/Query.php
@@ -27,7 +27,7 @@
  * @link     http://api.summon.serialssolutions.com/help/api/ API Documentation
  */
 namespace VuFind\Connection\Summon;
-use VuFind\Config\Reader as ConfigReader, VuFind\Solr\Utils as SolrUtils;
+use VuFind\Solr\Utils as SolrUtils;
 
 /**
  * Summon REST API Interface (query model - VuFind implementation)
@@ -41,6 +41,11 @@ use VuFind\Config\Reader as ConfigReader, VuFind\Solr\Utils as SolrUtils;
  */
 class Query extends \SerialsSolutions_Summon_Query
 {
+    /**
+     * Summon configuration object
+     *
+     * @var \Zend\Config\Config
+     */
     protected $config;
 
     /**
@@ -48,13 +53,14 @@ class Query extends \SerialsSolutions_Summon_Query
      *
      * Sets up the Summon API Client
      *
-     * @param string $query   Search query
-     * @param array  $options Other options to set (associative array)
+     * @param string              $query   Search query
+     * @param array               $options Other options to set (associative array)
+     * @param \Zend\Config\Config $config  Summon configuration object (optional)
      */
-    public function __construct($query = null, $options = array())
+    public function __construct($query = null, $options = array(), $config = null)
     {
         parent::__construct($query, $options);
-        $this->config = ConfigReader::getConfig('Summon');
+        $this->config = $config;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Connection/WorldCat.php b/module/VuFind/src/VuFind/Connection/WorldCat.php
index 862c939454e6a672af414e543566a13ffeefd626..e4e2f86b6bc5895c1c4f9b3213c62a476792dd55 100644
--- a/module/VuFind/src/VuFind/Connection/WorldCat.php
+++ b/module/VuFind/src/VuFind/Connection/WorldCat.php
@@ -27,7 +27,6 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\Connection;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * WorldCat SRU Search Interface
@@ -57,14 +56,15 @@ class WorldCat extends SRU
     /**
      * Constructor
      *
-     * @param \Zend\Http\Client $client An HTTP client object
+     * @param \Zend\Config\Config $config VuFind configuration
+     * @param \Zend\Http\Client   $client An HTTP client object
      */
-    public function __construct(\Zend\Http\Client $client)
-    {
+    public function __construct(\Zend\Config\Config $config,
+        \Zend\Http\Client $client
+    ) {
         parent::__construct(
             'http://www.worldcat.org/webservices/catalog/search/sru', $client
         );
-        $config = ConfigReader::getConfig();
         $this->wskey = isset($config->WorldCat->apiKey)
             ? $config->WorldCat->apiKey : null;
         $this->limitCodes = isset($config->WorldCat->LimitCodes)
diff --git a/module/VuFind/src/VuFind/Connection/WorldCatUtils.php b/module/VuFind/src/VuFind/Connection/WorldCatUtils.php
index a5668984969cd84fd0b541fcc89dd5afb9bbfb10..c25f0a0bd1145019c1eec1a84e13d5b863fc379d 100644
--- a/module/VuFind/src/VuFind/Connection/WorldCatUtils.php
+++ b/module/VuFind/src/VuFind/Connection/WorldCatUtils.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\Connection;
-use File_MARCXML, VuFind\Config\Reader as ConfigReader,
-    VuFind\XSLT\Processor as XSLTProcessor, Zend\Log\LoggerInterface;
+use File_MARCXML, VuFind\XSLT\Processor as XSLTProcessor, Zend\Log\LoggerInterface;
 
 /**
  * World Cat Utilities
@@ -49,6 +48,23 @@ class WorldCatUtils implements \Zend\Log\LoggerAwareInterface
      */
     protected $logger = false;
 
+    /**
+     * WorldCat ID
+     *
+     * @var string
+     */
+    protected $worldCatId;
+
+    /**
+     * Constructor
+     *
+     * @param string $worldCatId WorldCat ID
+     */
+    public function __construct($worldCatId)
+    {
+        $this->worldCatId = $worldCatId;
+    }
+
     /**
      * Set the logger
      *
@@ -82,13 +98,7 @@ class WorldCatUtils implements \Zend\Log\LoggerAwareInterface
      */
     protected function getWorldCatId()
     {
-        static $wcId = null;
-        if (is_null($wcId)) {
-            $config = ConfigReader::getConfig();
-            $wcId = isset($config->WorldCat->id)
-                ? $config->WorldCat->id : false;
-        }
-        return $wcId;
+        return $this->worldCatId;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php
index 106dd6e4a9f106d1e353e5ffdb74cd38badc00c9..b2dfb7efd18deb9ed863039c3d157d0a0acff1a8 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php
@@ -176,6 +176,18 @@ class AbstractBase extends AbstractActionController
         return $patron;
     }
 
+    /**
+     * Get a VuFind configuration.
+     *
+     * @param string $id Configuration identifier (default = main VuFind config)
+     *
+     * @return \Zend\Config\Config
+     */
+    public function getConfig($id = 'config')
+    {
+        return $this->getServiceLocator()->get('VuFind\Config')->get($id);
+    }
+
     /**
      * Get the ILS connection.
      *
diff --git a/module/VuFind/src/VuFind/Controller/AbstractRecord.php b/module/VuFind/src/VuFind/Controller/AbstractRecord.php
index fdd84b6db3bf1dc1a708885384ab96eaa94efa9f..1b5bd949c8ba5acbc31a4bb90a3b87ce3718692b 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractRecord.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractRecord.php
@@ -345,7 +345,7 @@ class AbstractRecord extends AbstractBase
     public function emailAction()
     {
         // Force login if necessary:
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         if ((!isset($config->Mail->require_login) || $config->Mail->require_login)
             && !$this->getUser()
         ) {
diff --git a/module/VuFind/src/VuFind/Controller/AdminController.php b/module/VuFind/src/VuFind/Controller/AdminController.php
index 8097f5c89659575dc4374e3273f1421a9de3c615..1de7e7c5b0fe7bc9fa2971e362a529c8515d7aab 100644
--- a/module/VuFind/src/VuFind/Controller/AdminController.php
+++ b/module/VuFind/src/VuFind/Controller/AdminController.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\Forbidden as ForbiddenException, Zend\Mvc\MvcEvent;
+use VuFind\Exception\Forbidden as ForbiddenException, Zend\Mvc\MvcEvent;
 
 /**
  * Class controls VuFind administration.
@@ -61,7 +60,7 @@ class AdminController extends AbstractBase
         }
 
         // Block access to everyone when module is disabled:
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         if (!isset($config->Site->admin_enabled) || !$config->Site->admin_enabled) {
             $routeMatch->setParam('action', 'disabled');
             return;
@@ -127,7 +126,7 @@ class AdminController extends AbstractBase
      */
     public function homeAction()
     {
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $xml = false;
         if (isset($config->Index->url)) {
             $response = $this->getServiceLocator()->get('VuFind\Http')
@@ -162,7 +161,7 @@ class AdminController extends AbstractBase
     {
         $view = $this->createViewModel();
 
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $statsFilled = array(
             'search' => false,
             'record' => false
@@ -239,8 +238,8 @@ class AdminController extends AbstractBase
     public function configAction()
     {
         $view = $this->createViewModel();
-        $view->baseConfigPath = ConfigReader::getBaseConfigPath('');
-        $conf = ConfigReader::getConfig();
+        $view->baseConfigPath = \VuFind\Config\Locator::getBaseConfigPath('');
+        $conf = $this->getConfig();
         $view->showInstallLink
             = isset($conf->System->autoConfigure) && $conf->System->autoConfigure;
         return $view;
@@ -253,7 +252,7 @@ class AdminController extends AbstractBase
      */
     public function enableautoconfigAction()
     {
-        $configFile = ConfigReader::getConfigPath('config.ini');
+        $configFile = \VuFind\Config\Locator::getConfigPath('config.ini');
         $writer = new \VuFind\Config\Writer($configFile);
         $writer->set('System', 'autoConfigure', 1);
         if ($writer->save()) {
@@ -262,7 +261,7 @@ class AdminController extends AbstractBase
 
             // Reload config now that it has been edited (otherwise, old setting
             // will persist in cache):
-            ConfigReader::getConfig(null, true);
+            $this->getServiceLocator()->get('VuFind\Config')->reload('config');
         } else {
             $this->flashMessenger()->setNamespace('error')
                 ->addMessage(
diff --git a/module/VuFind/src/VuFind/Controller/AjaxController.php b/module/VuFind/src/VuFind/Controller/AjaxController.php
index 6f64c5d850810e54ec359442ce6dfb9915fab93f..12ae62c9ce1681896e5fbd6efb705ae19605559e 100644
--- a/module/VuFind/src/VuFind/Controller/AjaxController.php
+++ b/module/VuFind/src/VuFind/Controller/AjaxController.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_a_controller Wiki
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\Auth as AuthException;
+use VuFind\Exception\Auth as AuthException;
 
 /**
  * This controller handles global AJAX functionality
@@ -45,8 +44,18 @@ class AjaxController extends AbstractBase
     const STATUS_ERROR = 'ERROR';            // bad
     const STATUS_NEED_AUTH = 'NEED_AUTH';    // must login first
 
+    /**
+     * Type of output to use
+     *
+     * @var string
+     */
     protected $outputMode;
-    protected $account;
+
+    /**
+     * Array of PHP errors captured during execution
+     *
+     * @var array
+     */
     protected static $php_errors = array();
 
     /**
@@ -147,17 +156,15 @@ class AjaxController extends AbstractBase
      * Support method for getItemStatuses() -- filter suppressed locations from the
      * array of item information for a particular bib record.
      *
-     * @param array                  $record  Information on items linked to a single
-     * bib record
-     * @param \VuFind\ILS\Connection $catalog ILS connection
+     * @param array $record Information on items linked to a single bib record
      *
      * @return array        Filtered version of $record
      */
-    protected function filterSuppressedLocations($record, $catalog)
+    protected function filterSuppressedLocations($record)
     {
         static $hideHoldings = false;
         if ($hideHoldings === false) {
-            $logic = new \VuFind\ILS\Logic\Holds($this->getAuthManager(), $catalog);
+            $logic = $this->getServiceLocator()->get('VuFind\ILSHoldLogic');
             $hideHoldings = $logic->getSuppressedLocations();
         }
 
@@ -210,7 +217,7 @@ class AjaxController extends AbstractBase
         );
 
         // Load callnumber and location settings:
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $callnumberSetting = isset($config->Item_Status->multiple_call_nos)
             ? $config->Item_Status->multiple_call_nos : 'msg';
         $locationSetting = isset($config->Item_Status->multiple_locations)
@@ -222,7 +229,7 @@ class AjaxController extends AbstractBase
         $statuses = array();
         foreach ($results as $recordNumber=>$record) {
             // Filter out suppressed locations:
-            $record = $this->filterSuppressedLocations($record, $catalog);
+            $record = $this->filterSuppressedLocations($record);
 
             // Skip empty records:
             if (count($record)) {
@@ -977,7 +984,7 @@ class AjaxController extends AbstractBase
         $this->writeSession();  // avoid session write timing bug
 
         // Force login if necessary:
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         if ((!isset($config->Mail->require_login) || $config->Mail->require_login)
             && !$this->getUser()
         ) {
@@ -1018,7 +1025,7 @@ class AjaxController extends AbstractBase
         $this->writeSession();  // avoid session write timing bug
 
         // Force login if necessary:
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         if ((!isset($config->Mail->require_login) || $config->Mail->require_login)
             && !$this->getUser()
         ) {
@@ -1258,7 +1265,7 @@ class AjaxController extends AbstractBase
         $this->writeSession();  // avoid session write timing bug
         $openUrl = $this->params()->fromQuery('openurl', '');
 
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $resolverType = isset($config->OpenURL->resolver)
             ? $config->OpenURL->resolver : 'other';
         $pluginManager = $this->getServiceLocator()
diff --git a/module/VuFind/src/VuFind/Controller/AlphabrowseController.php b/module/VuFind/src/VuFind/Controller/AlphabrowseController.php
index 0c91ade93bceba1d1845206d255f9a3dc26a8ec7..48746be06c83f0a9c8c51f3993bd100686e7800e 100644
--- a/module/VuFind/src/VuFind/Controller/AlphabrowseController.php
+++ b/module/VuFind/src/VuFind/Controller/AlphabrowseController.php
@@ -27,8 +27,7 @@
  * @link     http://vufind.org/wiki/alphabetical_heading_browse Wiki
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Connection\Manager as ConnectionManager,
+use VuFind\Connection\Manager as ConnectionManager,
     VuFind\Exception\Solr as SolrException;
 
 /**
@@ -52,7 +51,7 @@ class AlphabrowseController extends AbstractBase
      */
     public function homeAction()
     {
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
 
         // Load browse types from config file, or use defaults if unavailable:
         if (isset($config->AlphaBrowse_Types)
diff --git a/module/VuFind/src/VuFind/Controller/BrowseController.php b/module/VuFind/src/VuFind/Controller/BrowseController.php
index 36738cd5e89f53a5c3e4abf6f4c853fab588993a..bffd94c18fa4a0fa3899ba61de164d55d69cb4f9 100644
--- a/module/VuFind/src/VuFind/Controller/BrowseController.php
+++ b/module/VuFind/src/VuFind/Controller/BrowseController.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:building_a_controller Wiki
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * BrowseController Class
@@ -41,15 +40,35 @@ use VuFind\Config\Reader as ConfigReader;
  */
 class BrowseController extends AbstractBase
 {
+    /**
+     * VuFind configuration
+     *
+     * @var \Zend\Config\Config
+     */
+    protected $config;
 
-    protected $config, $currentAction = null, $disabledFacets;
+    /**
+     * Current browse mode
+     *
+     * @var string
+     */
+    protected $currentAction = null;
+
+    /**
+     * Browse options disabled in configuration
+     *
+     * @var array
+     */
+    protected $disabledFacets;
 
     /**
      * Constructor
+     *
+     * @param \Zend\Config\Config $config VuFind configuration
      */
-    public function __construct()
+    public function __construct(\Zend\Config\Config $config)
     {
-        $this->config = ConfigReader::getConfig();
+        $this->config = $config;
 
         $this->disabledFacets = array();
         foreach ($this->config->Browse as $key => $setting) {
diff --git a/module/VuFind/src/VuFind/Controller/CartController.php b/module/VuFind/src/VuFind/Controller/CartController.php
index cd8895959c9e3d5fe01a606af3c00a2556624668..f2fb501a8d82aa77a8c9f02c158be30cebc5f344 100644
--- a/module/VuFind/src/VuFind/Controller/CartController.php
+++ b/module/VuFind/src/VuFind/Controller/CartController.php
@@ -167,7 +167,7 @@ class CartController extends AbstractBase
     public function emailAction()
     {
         // Force login if necessary:
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         if ((!isset($config->Mail->require_login) || $config->Mail->require_login)
             && !$this->getUser()
         ) {
diff --git a/module/VuFind/src/VuFind/Controller/CollectionController.php b/module/VuFind/src/VuFind/Controller/CollectionController.php
index 380af3f1ed08bbe840ad4528bc44fab33379ee7e..eff46209f5e8c9c9b1348260689389b38585f83c 100644
--- a/module/VuFind/src/VuFind/Controller/CollectionController.php
+++ b/module/VuFind/src/VuFind/Controller/CollectionController.php
@@ -40,14 +40,15 @@ class CollectionController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param \Zend\Config\Config $config VuFind configuration
      */
-    public function __construct()
+    public function __construct(\Zend\Config\Config $config)
     {
         // Call standard record controller initialization:
         parent::__construct();
 
         // Set default tab, if specified:
-        $config = \VuFind\Config\Reader::getConfig();
         if (isset($config->Collections->defaultTab)) {
             $this->defaultTab = $config->Collections->defaultTab;
         }
diff --git a/module/VuFind/src/VuFind/Controller/CollectionsController.php b/module/VuFind/src/VuFind/Controller/CollectionsController.php
index 579593815ddd7519d493ed9fe6a38b0088f144df..dd45c58ff60df28cf6d4c3c1dfd32396fbbbbef7 100644
--- a/module/VuFind/src/VuFind/Controller/CollectionsController.php
+++ b/module/VuFind/src/VuFind/Controller/CollectionsController.php
@@ -47,10 +47,12 @@ class CollectionsController extends AbstractBase
 
     /**
      * Constructor
+     *
+     * @param \Zend\Config\Config $config VuFind configuration
      */
-    public function __construct()
+    public function __construct(\Zend\Config\Config $config)
     {
-        $this->config = \VuFind\Config\Reader::getConfig();
+        $this->config = $config;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/CoverController.php b/module/VuFind/src/VuFind/Controller/CoverController.php
index 60508d259ac92c76ad312a2a6fca9aa18b18a9eb..2efe5dae265f3422f5b07f7637b66fa16b2c62bc 100644
--- a/module/VuFind/src/VuFind/Controller/CoverController.php
+++ b/module/VuFind/src/VuFind/Controller/CoverController.php
@@ -26,7 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader, VuFind\Cover\Loader;
+use VuFind\Cover\Loader;
 
 /**
  * Generates covers for book entries
@@ -51,7 +51,7 @@ class CoverController extends AbstractBase
         // Construct object for loading cover images if it does not already exist:
         if (!$this->loader) {
             $this->loader = new Loader(
-                ConfigReader::getConfig(),
+                $this->getConfig(),
                 $this->getServiceLocator()->get('VuFindTheme\ThemeInfo'),
                 $this->getServiceLocator()->get('VuFind\Http')->createClient(),
                 $this->getServiceLocator()->get('VuFind\CacheManager')->getCacheDir()
diff --git a/module/VuFind/src/VuFind/Controller/HelpController.php b/module/VuFind/src/VuFind/Controller/HelpController.php
index 8880a2ed6b024e39ddc028eaff77964e459df067..fe6ea409d23c72dbf86653ea3b2e207e9b36d1a7 100644
--- a/module/VuFind/src/VuFind/Controller/HelpController.php
+++ b/module/VuFind/src/VuFind/Controller/HelpController.php
@@ -28,7 +28,6 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Home action for Help module
@@ -51,7 +50,6 @@ class HelpController extends AbstractBase
      */
     public function homeAction()
     {
-        $config = ConfigReader::getConfig();
         $this->layout()->setTemplate('layout/help');
 
         // Sanitize the topic name to include only alphanumeric characters
diff --git a/module/VuFind/src/VuFind/Controller/HierarchyController.php b/module/VuFind/src/VuFind/Controller/HierarchyController.php
index a1b6c5a3c3f772ff833ad695c8bb427588003683..0fae2b3587e43e1b00eb08f9e80fee1e2bc412d1 100644
--- a/module/VuFind/src/VuFind/Controller/HierarchyController.php
+++ b/module/VuFind/src/VuFind/Controller/HierarchyController.php
@@ -79,7 +79,7 @@ class HierarchyController extends AbstractBase
     public function searchtreeAction()
     {
         $this->writeSession();  // avoid session write timing bug
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         $limit = isset($config->Hierarchy->treeSearchLimit)
             ? $config->Hierarchy->treeSearchLimit : -1;
         $resultIDs = array();
diff --git a/module/VuFind/src/VuFind/Controller/IndexController.php b/module/VuFind/src/VuFind/Controller/IndexController.php
index 17c52e526e84790f2a2f4d118f730ecdf4e6a0b5..ac6f7a3d2fa293047ade64e510ae8a4b000421d3 100644
--- a/module/VuFind/src/VuFind/Controller/IndexController.php
+++ b/module/VuFind/src/VuFind/Controller/IndexController.php
@@ -27,8 +27,6 @@
  */
 namespace VuFind\Controller;
 
-use VuFind\Config\Reader as ConfigReader;
-
 /**
  * Redirects the user to the appropriate default VuFind action.
  *
@@ -48,7 +46,7 @@ class IndexController extends AbstractBase
      */
     public function homeAction()
     {
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $loggedInModule = isset($config->Site->defaultLoggedInModule)
             ? $config->Site->defaultLoggedInModule : 'MyResearch';
         $loggedOutModule = isset($config->Site->defaultModule)
diff --git a/module/VuFind/src/VuFind/Controller/InstallController.php b/module/VuFind/src/VuFind/Controller/InstallController.php
index 0cb93d909fa64fb2b7cb01f749ef258da541033a..67048a360b6cddca5f74d1c09600deb5e963588f 100644
--- a/module/VuFind/src/VuFind/Controller/InstallController.php
+++ b/module/VuFind/src/VuFind/Controller/InstallController.php
@@ -26,10 +26,9 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader,
+use VuFind\Config\Locator as ConfigLocator,
     VuFind\Config\Writer as ConfigWriter,
     VuFind\Connection\Manager as ConnectionManager,
-    VuFind\Db\AdapterFactory,
     Zend\Mvc\MvcEvent,
     Zend\Crypt\Password\Bcrypt;
 
@@ -56,7 +55,7 @@ class InstallController extends AbstractBase
     {
         // If auto-configuration is disabled, prevent any other action from being
         // accessed:
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         if (!isset($config->System->autoConfigure)
             || !$config->System->autoConfigure
         ) {
@@ -95,9 +94,9 @@ class InstallController extends AbstractBase
      */
     protected function installBasicConfig()
     {
-        $config = ConfigReader::getLocalConfigPath('config.ini', null, true);
+        $config = ConfigLocator::getLocalConfigPath('config.ini', null, true);
         if (!file_exists($config)) {
-            return copy(ConfigReader::getBaseConfigPath('config.ini'), $config);
+            return copy(ConfigLocator::getBaseConfigPath('config.ini'), $config);
         }
         return true;        // report success if file already exists
     }
@@ -115,7 +114,7 @@ class InstallController extends AbstractBase
         // See if the URL setting remains at the default (unless we already
         // know we've failed):
         if ($status) {
-            $config = ConfigReader::getConfig();
+            $config = $this->getConfig();
             if (stristr($config->Site->url, 'myuniversity.edu')) {
                 $status = false;
             }
@@ -135,7 +134,7 @@ class InstallController extends AbstractBase
     public function fixbasicconfigAction()
     {
         $view = $this->createViewModel();
-        $config = ConfigReader::getLocalConfigPath('config.ini', null, true);
+        $config = ConfigLocator::getLocalConfigPath('config.ini', null, true);
         try {
             if (!$this->installBasicConfig()) {
                 throw new \Exception('Cannot copy file into position.');
@@ -338,9 +337,8 @@ class InstallController extends AbstractBase
                     . $this->params()->fromPost('dbrootpass') . '@'
                     . $view->dbhost;
                 try {
-                    $db = AdapterFactory::getAdapterFromConnectionString(
-                        $connection . '/mysql'
-                    );
+                    $db = $this->getServiceLocator()->get('VuFind\DbAdapterFactory')
+                        ->getAdapterFromConnectionString($connection . '/mysql');
                 } catch (\Exception $e) {
                     $this->flashMessenger()->setNamespace('error')
                         ->addMessage(
@@ -370,7 +368,9 @@ class InstallController extends AbstractBase
                         $db->query($query, $db::QUERY_MODE_EXECUTE);
                         $db->query($grant, $db::QUERY_MODE_EXECUTE);
                         $db->query('FLUSH PRIVILEGES', $db::QUERY_MODE_EXECUTE);
-                        $db = AdapterFactory::getAdapterFromConnectionString(
+                        $dbFactory = $this->getServiceLocator()
+                            ->get('VuFind\DbAdapterFactory');
+                        $db = $dbFactory->getAdapterFromConnectionString(
                             $connection . '/' . $view->dbname
                         );
                         $statements = explode(';', $sql);
@@ -385,7 +385,7 @@ class InstallController extends AbstractBase
                         // forward back to the home action!
                         $string = "mysql://{$view->dbuser}:{$newpass}@"
                             . $view->dbhost . '/' . $view->dbname;
-                        $config = ConfigReader::getLocalConfigPath(
+                        $config = ConfigLocator::getLocalConfigPath(
                             'config.ini', null, true
                         );
                         $writer = new ConfigWriter($config);
@@ -428,7 +428,7 @@ class InstallController extends AbstractBase
      */
     protected function checkILS()
     {
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         if (in_array($config->Catalog->driver, array('Sample', 'Demo'))) {
             $status = false;
         } else {
@@ -453,16 +453,17 @@ class InstallController extends AbstractBase
         // Process incoming parameter -- user may have selected a new driver:
         $newDriver = $this->params()->fromPost('driver');
         if (!empty($newDriver)) {
-            $configPath = ConfigReader::getLocalConfigPath('config.ini', null, true);
+            $configPath
+                = ConfigLocator::getLocalConfigPath('config.ini', null, true);
             $writer = new ConfigWriter($configPath);
             $writer->set('Catalog', 'driver', $newDriver);
             if (!$writer->save()) {
                 return $this->forwardTo('Install', 'fixbasicconfig');
             }
             // Copy configuration, if applicable:
-            $ilsIni = ConfigReader::getBaseConfigPath($newDriver . '.ini');
+            $ilsIni = ConfigLocator::getBaseConfigPath($newDriver . '.ini');
             $localIlsIni
-                = ConfigReader::getLocalConfigPath("{$newDriver}.ini", null, true);
+                = ConfigLocator::getLocalConfigPath("{$newDriver}.ini", null, true);
             if (file_exists($ilsIni) && !file_exists($localIlsIni)) {
                 if (!copy($ilsIni, $localIlsIni)) {
                     return $this->forwardTo('Install', 'fixbasicconfig');
@@ -473,7 +474,7 @@ class InstallController extends AbstractBase
 
         // If we got this far, check whether we have an error with a real driver
         // or if we need to warn the user that they have selected a fake driver:
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $view = $this->createViewModel();
         if (in_array($config->Catalog->driver, array('Sample', 'Demo'))) {
             $view->demo = true;
@@ -494,7 +495,7 @@ class InstallController extends AbstractBase
             sort($drivers);
             $view->drivers = $drivers;
         } else {
-            $view->configPath = ConfigReader::getLocalConfigPath(
+            $view->configPath = ConfigLocator::getLocalConfigPath(
                 "{$config->Catalog->driver}.ini", null, true
             );
         }
@@ -526,8 +527,8 @@ class InstallController extends AbstractBase
     public function fixsolrAction()
     {
         // In Windows, localhost may fail -- see if switching to 127.0.0.1 helps:
-        $config = ConfigReader::getConfig();
-        $configFile = ConfigReader::getLocalConfigPath('config.ini', null, true);
+        $config = $this->getConfig();
+        $configFile = ConfigLocator::getLocalConfigPath('config.ini', null, true);
         if (stristr($config->Index->url, 'localhost')) {
             $newUrl = str_replace('localhost', '127.0.0.1', $config->Index->url);
             try {
@@ -569,7 +570,7 @@ class InstallController extends AbstractBase
     protected function checkSecurity()
     {
         // Are configuration settings missing?
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         if (!isset($config->Authentication->hash_passwords)
             || !$config->Authentication->hash_passwords
             || !isset($config->Authentication->encrypt_ils_password)
@@ -665,8 +666,8 @@ class InstallController extends AbstractBase
     public function performsecurityfixAction()
     {
         // First, set encryption/hashing to true, and set the key
-        $config = ConfigReader::getConfig();
-        $configPath = ConfigReader::getLocalConfigPath('config.ini', null, true);
+        $config = $this->getConfig();
+        $configPath = ConfigLocator::getLocalConfigPath('config.ini', null, true);
         $writer = new ConfigWriter($configPath);
         if ($this->fixSecurityConfiguration($config, $writer)) {
             // Problem writing? Show the user an error:
@@ -709,7 +710,7 @@ class InstallController extends AbstractBase
      */
     public function doneAction()
     {
-        $config = ConfigReader::getLocalConfigPath('config.ini', null, true);
+        $config = ConfigLocator::getLocalConfigPath('config.ini', null, true);
         $writer = new ConfigWriter($config);
         $writer->set('System', 'autoConfigure', 0);
         if (!$writer->save()) {
diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php
index 23daa5ddf49bf2cb45b6af936eaa4c0a41b062c4..ed5699b92317e1e976e384139f782e3c8a0cfd11 100644
--- a/module/VuFind/src/VuFind/Controller/MyResearchController.php
+++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php
@@ -27,8 +27,7 @@
  */
 namespace VuFind\Controller;
 
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\Auth as AuthException,
+use VuFind\Exception\Auth as AuthException,
     VuFind\Exception\ListPermission as ListPermissionException,
     VuFind\Exception\RecordMissing as RecordMissingException,
     Zend\Stdlib\Parameters;
@@ -81,7 +80,7 @@ class MyResearchController extends AbstractBase
             return $this->redirect()->toUrl($url);
         }
 
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $page = isset($config->Site->defaultAccountPage)
             ? $config->Site->defaultAccountPage : 'Favorites';
         return $this->forwardTo('MyResearch', $page);
diff --git a/module/VuFind/src/VuFind/Controller/OaiController.php b/module/VuFind/src/VuFind/Controller/OaiController.php
index 653d714df0c868296062bd84ed685ff8e0be725a..1f4466ca2bd850fe929928ddb28cf16f6d1e5806 100644
--- a/module/VuFind/src/VuFind/Controller/OaiController.php
+++ b/module/VuFind/src/VuFind/Controller/OaiController.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:building_a_controller Wiki
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * OAIController Class
@@ -82,7 +81,7 @@ class OaiController extends AbstractBase
     protected function handleOAI($serverClass)
     {
         // Check if the OAI Server is enabled before continuing
-        $config = ConfigReader::getConfig();
+        $config = $this->getConfig();
         $response = $this->getResponse();
         if (!isset($config->OAI)) {
             $response->setStatusCode(404);
@@ -97,7 +96,7 @@ class OaiController extends AbstractBase
         // Build OAI response or die trying:
         try {
             $server = new $serverClass(
-                $this->getSearchManager(),
+                $this->getSearchManager(), $config,
                 $baseURL, $this->getRequest()->getQuery()->toArray()
             );
             $xml = $server->getResponse();
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Holds.php b/module/VuFind/src/VuFind/Controller/Plugin/Holds.php
index 1b6e3f31353430611d86351b07d0b10eeff714d0..763a86fb5ba150d1f2a44827ccfe07adaf421f65 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Holds.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Holds.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Controller\Plugin;
-use VuFind\Crypt\HMAC, Zend\Mvc\Controller\Plugin\AbstractPlugin,
-    Zend\Session\Container;
+use Zend\Mvc\Controller\Plugin\AbstractPlugin, Zend\Session\Container;
 
 /**
  * Zend action helper to perform renewal-related actions
@@ -40,8 +39,30 @@ use VuFind\Crypt\HMAC, Zend\Mvc\Controller\Plugin\AbstractPlugin,
  */
 class Holds extends AbstractPlugin
 {
+    /**
+     * Session data
+     *
+     * @var Container
+     */
     protected $session;
 
+    /**
+     * HMAC generator
+     *
+     * @var \VuFind\Crypt\HMAC
+     */
+    protected $hmac;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Crypt\HMAC $hmac HMAC generator
+     */
+    public function __construct(\VuFind\Crypt\HMAC $hmac)
+    {
+        $this->hmac = $hmac;
+    }
+
     /**
      * Grab the Container object for storing helper-specific session
      * data.
@@ -193,7 +214,7 @@ class Holds extends AbstractPlugin
         foreach ($linkData as $details) {
             $keyValueArray[$details] = $params->fromQuery($details);
         }
-        $hashKey = HMAC::generate($linkData, $keyValueArray);
+        $hashKey = $this->hmac->generate($linkData, $keyValueArray);
 
         if ($params->fromQuery('hashKey') != $hashKey) {
             return false;
@@ -212,7 +233,7 @@ class Holds extends AbstractPlugin
         $gatheredDetails['id'] = $params->fromRoute('id');
 
         // Get Values Passed from holdings.php
-        $gatheredDetails += $keyValueArray;
+        $gatheredDetails = array_merge($gatheredDetails, $keyValueArray);
 
         return $gatheredDetails;
     }
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php b/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php
index b64ad16a068b6fbdd71ad1e01305582ef267d1f6..55c82cb04faa437c140cda4ded03e5b640836f6b 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Controller\Plugin;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Connection\Manager as ConnectionManager,
+use VuFind\Connection\Manager as ConnectionManager,
     Zend\Mvc\Controller\Plugin\AbstractPlugin;
 
 /**
@@ -41,6 +40,25 @@ use VuFind\Config\Reader as ConfigReader,
  */
 class Reserves extends AbstractPlugin
 {
+    /**
+     * Do we need to use the Solr index for reserves (true) or the ILS driver
+     * (false)?
+     *
+     * @var bool
+     */
+    protected $useIndex;
+
+    /**
+     * Constructor
+     *
+     * @param bool $useIndex Do we need to use the Solr index for reserves (true)
+     * or the ILS driver (false)?
+     */
+    public function __construct($useIndex = false)
+    {
+        $this->useIndex = $useIndex;
+    }
+
     /**
      * Do we need to use the Solr index for reserves (true) or the ILS driver
      * (false)?
@@ -49,9 +67,7 @@ class Reserves extends AbstractPlugin
      */
     public function useIndex()
     {
-        $config = ConfigReader::getConfig();
-        return isset($config->Reserves->search_enabled)
-            && $config->Reserves->search_enabled;
+        return $this->useIndex;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php b/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php
index cfa60d88d2ee2866b13c3ef16f43887b333f80fa..40724ad602b1b14fe35c5d42c05a65949b5c167f 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\Controller\Plugin;
-use VuFind\Config\Reader as ConfigReader, VuFind\Search\Memory,
-    Zend\Mvc\Controller\Plugin\AbstractPlugin,
+use VuFind\Search\Memory, Zend\Mvc\Controller\Plugin\AbstractPlugin,
     Zend\Session\Container as SessionContainer;
 
 /**
@@ -41,18 +40,28 @@ use VuFind\Config\Reader as ConfigReader, VuFind\Search\Memory,
  */
 class ResultScroller extends AbstractPlugin
 {
+    /**
+     * Is scroller enabled?
+     *
+     * @var bool
+     */
     protected $enabled;
+
+    /**
+     * Session data used by scroller
+     *
+     * @var SessionContainer
+     */
     protected $data;
 
     /**
      * Constructor. Create a new search result scroller.
+     *
+     * @param bool $enabled Is the scroller enabled?
      */
-    public function __construct()
+    public function __construct($enabled = true)
     {
-        // Is this functionality enabled in config.ini?
-        $config = ConfigReader::getConfig();
-        $this->enabled = (isset($config->Record->next_prev_navigation)
-            && $config->Record->next_prev_navigation);
+        $this->enabled = $enabled;
 
         // Set up session namespace for the class.
         $this->data = new SessionContainer('ResultScroller');
diff --git a/module/VuFind/src/VuFind/Controller/RecordController.php b/module/VuFind/src/VuFind/Controller/RecordController.php
index c7d416ad22c8ed2926a119ba39245815b7c3ac0a..bfa7bc0a93b23b5b453bb6e9a1c6602b276cd53f 100644
--- a/module/VuFind/src/VuFind/Controller/RecordController.php
+++ b/module/VuFind/src/VuFind/Controller/RecordController.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Controller;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Record Controller
@@ -41,14 +40,15 @@ class RecordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param \Zend\Config\Config $config VuFind configuration
      */
-    public function __construct()
+    public function __construct(\Zend\Config\Config $config)
     {
         // Call standard record controller initialization:
         parent::__construct();
 
         // Load default tab setting:
-        $config = ConfigReader::getConfig();
         $this->defaultTab = isset($config->Site->defaultRecordTab)
             ? $config->Site->defaultRecordTab : 'Holdings';
     }
diff --git a/module/VuFind/src/VuFind/Controller/SearchController.php b/module/VuFind/src/VuFind/Controller/SearchController.php
index fcf2fadb56e2d3b965b26d50c339c568c58254ec..316cb18a6967e51e8b874bc1ad61262490158729 100644
--- a/module/VuFind/src/VuFind/Controller/SearchController.php
+++ b/module/VuFind/src/VuFind/Controller/SearchController.php
@@ -27,8 +27,7 @@
  */
 namespace VuFind\Controller;
 
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\Mail as MailException, VuFind\Search\Memory,
+use VuFind\Exception\Mail as MailException, VuFind\Search\Memory,
     VuFind\Solr\Utils as SolrUtils;
 
 /**
@@ -85,7 +84,7 @@ class SearchController extends AbstractSearch
         );
 
         // Force login if necessary:
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         if ((!isset($config->Mail->require_login) || $config->Mail->require_login)
             && !$this->getUser()
         ) {
@@ -311,7 +310,7 @@ class SearchController extends AbstractSearch
         // Find out if there are user configured range options; if not,
         // default to the standard 1/5/30 days:
         $ranges = array();
-        $searchSettings = ConfigReader::getConfig('searches');
+        $searchSettings = $this->getConfig('searches');
         if (isset($searchSettings->NewItem->ranges)) {
             $tmp = explode(',', $searchSettings->NewItem->ranges);
             foreach ($tmp as $range) {
@@ -342,7 +341,21 @@ class SearchController extends AbstractSearch
         $range = $this->params()->fromQuery('range');
         $dept = $this->params()->fromQuery('department');
 
-        $searchSettings = ConfigReader::getConfig('searches');
+        // Validate the range parameter -- it should not exceed the greatest
+        // configured value:
+        $searchSettings = $this->getConfig('searches');
+        $maxAge = 0;
+        if (isset($searchSettings->NewItem->ranges)) {
+            $tmp = explode(',', $searchSettings->NewItem->ranges);
+            foreach ($tmp as $current) {
+                if (intval($current) > $maxAge) {
+                    $maxAge = intval($current);
+                }
+            }
+        }
+        if ($maxAge > 0 && $range > $maxAge) {
+            $range = $maxAge;
+        }
 
         // The code always pulls in enough catalog results to get a fixed number
         // of pages worth of Solr results.  Note that if the Solr index is out of
@@ -583,7 +596,7 @@ class SearchController extends AbstractSearch
     {
         switch ($this->params()->fromQuery('method')) {
         case 'describe':
-            $config = ConfigReader::getConfig();
+            $config = $this->getConfig();
             $xml = $this->getViewRenderer()->render(
                 'search/opensearch-describe.phtml', array('site' => $config->Site)
             );
diff --git a/module/VuFind/src/VuFind/Controller/UpgradeController.php b/module/VuFind/src/VuFind/Controller/UpgradeController.php
index b959bb02ed2c3468d757eb0dbfcbd665e4731b2d..977599cd7981373becc2d82b680cbf4e79b3b953 100644
--- a/module/VuFind/src/VuFind/Controller/UpgradeController.php
+++ b/module/VuFind/src/VuFind/Controller/UpgradeController.php
@@ -26,8 +26,8 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Controller;
-use ArrayObject, VuFind\Config\Reader as ConfigReader,
-    VuFind\Cookie\Container as CookieContainer, VuFind\Db\AdapterFactory,
+use ArrayObject, VuFind\Config\Locator as ConfigLocator,
+    VuFind\Cookie\Container as CookieContainer,
     VuFind\Exception\RecordMissing as RecordMissingException,
     Zend\Session\Container as SessionContainer;
 
@@ -143,8 +143,8 @@ class UpgradeController extends AbstractBase
         $upgrader = new \VuFind\Config\Upgrade(
             $this->cookie->oldVersion, $this->cookie->newVersion,
             $this->cookie->sourceDir . '/web/conf',
-            dirname(ConfigReader::getBaseConfigPath('config.ini')),
-            dirname(ConfigReader::getLocalConfigPath('config.ini', null, true))
+            dirname(ConfigLocator::getBaseConfigPath('config.ini')),
+            dirname(ConfigLocator::getLocalConfigPath('config.ini', null, true))
         );
         try {
             $upgrader->run();
@@ -171,7 +171,8 @@ class UpgradeController extends AbstractBase
         // subsequent calls.
         static $adapter = false;
         if (!$adapter) {
-            $adapter = AdapterFactory::getAdapter(
+            $factory = $this->getServiceLocator()->get('VuFind\DbAdapterFactory');
+            $adapter = $factory->getAdapter(
                 $this->session->dbRootUser, $this->session->dbRootPass
             );
         }
@@ -199,7 +200,7 @@ class UpgradeController extends AbstractBase
      */
     protected function setDbEncodingConfiguration($charset)
     {
-        $config = ConfigReader::getLocalConfigPath('config.ini', null, true);
+        $config = ConfigLocator::getLocalConfigPath('config.ini', null, true);
         $writer = new \VuFind\Config\Writer($config);
         $writer->set('Database', 'charset', $charset);
         if (!$writer->save()) {
@@ -369,7 +370,9 @@ class UpgradeController extends AbstractBase
                 // Test the connection:
                 try {
                     // Query a table known to exist
-                    $db = AdapterFactory::getAdapter($dbrootuser, $pass);
+                    $factory = $this->getServiceLocator()
+                        ->get('VuFind\DbAdapterFactory');
+                    $db = $factory->getAdapter($dbrootuser, $pass);
                     $db->query("SELECT * FROM user;");
                     $this->session->dbRootUser = $dbrootuser;
                     $this->session->dbRootPass = $pass;
@@ -576,7 +579,7 @@ class UpgradeController extends AbstractBase
         return $this->createViewModel(
             array(
                 'configDir' => dirname(
-                    ConfigReader::getLocalConfigPath('config.ini', null, true)
+                    ConfigLocator::getLocalConfigPath('config.ini', null, true)
                 ),
                 'importDir' => LOCAL_OVERRIDE_DIR . '/import'
             )
diff --git a/module/VuFind/src/VuFind/Crypt/HMAC.php b/module/VuFind/src/VuFind/Crypt/HMAC.php
index 0725c8a9ae1649009c8b6c74d00d30fb5423174e..0423833835a49aeb1699bafb579af7e771867db1 100644
--- a/module/VuFind/src/VuFind/Crypt/HMAC.php
+++ b/module/VuFind/src/VuFind/Crypt/HMAC.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\Crypt;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * HMAC hash generator wrapper
@@ -39,6 +38,23 @@ use VuFind\Config\Reader as ConfigReader;
  */
 class HMAC
 {
+    /**
+     * Hash key
+     *
+     * @var string
+     */
+    protected $hashKey;
+
+    /**
+     * Constructor
+     *
+     * @param string $key Hash key
+     */
+    public function __construct($key)
+    {
+        $this->hashKey = $key;
+    }
+
     /**
      * Accepts $keysToHash, a list of array keys, and $keyValueArray, a keyed array
      *
@@ -47,14 +63,13 @@ class HMAC
      *
      * @return sting A hash_hmac string using md5
      */
-    public static function generate($keysToHash, $keyValueArray)
+    public function generate($keysToHash, $keyValueArray)
     {
-        $config = ConfigReader::getConfig();
         $str = '';
         foreach ($keysToHash as $key) {
             $value = isset($keyValueArray[$key]) ? $keyValueArray[$key] : '';
             $str .= $key . '=' . $value . '|';
         }
-        return hash_hmac('md5', $str, $config->Security->HMACkey);
+        return hash_hmac('md5', $str, $this->hashKey);
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/AdapterFactory.php b/module/VuFind/src/VuFind/Db/AdapterFactory.php
index 513381b8c3a8dae3922d5e284d29f3a9dfb1beb8..8a32d721d726f430aeded011aa6d596d191209d4 100644
--- a/module/VuFind/src/VuFind/Db/AdapterFactory.php
+++ b/module/VuFind/src/VuFind/Db/AdapterFactory.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Db;
-use VuFind\Config\Reader as ConfigReader, Zend\Db\Adapter\Adapter;
+use Zend\Db\Adapter\Adapter;
 
 /**
  * Database utility class.
@@ -39,6 +39,23 @@ use VuFind\Config\Reader as ConfigReader, Zend\Db\Adapter\Adapter;
  */
 class AdapterFactory
 {
+    /**
+     * VuFind configuration
+     *
+     * @var \Zend\Config\Config
+     */
+    protected $config;
+
+    /**
+     * Constructor
+     *
+     * @param \Zend\Config\Config $config VuFind configuration
+     */
+    public function __construct(\Zend\Config\Config $config)
+    {
+        $this->config = $config;
+    }
+
     /**
      * Obtain a Zend\DB connection using standard VuFind configuration.
      *
@@ -49,12 +66,11 @@ class AdapterFactory
      *
      * @return object
      */
-    public static function getAdapter($overrideUser = null, $overridePass = null)
+    public function getAdapter($overrideUser = null, $overridePass = null)
     {
         // Parse details from connection string:
-        $config = ConfigReader::getConfig();
-        return static::getAdapterFromConnectionString(
-            $config->Database->database, $overrideUser, $overridePass
+        return $this->getAdapterFromConnectionString(
+            $this->config->Database->database, $overrideUser, $overridePass
         );
     }
 
@@ -65,7 +81,7 @@ class AdapterFactory
      *
      * @return string
      */
-    public static function getDriverName($type)
+    public function getDriverName($type)
     {
         switch (strtolower($type)) {
         case 'mysql':
@@ -85,14 +101,13 @@ class AdapterFactory
      *
      * @return object
      */
-    public static function getAdapterFromOptions($options)
+    public function getAdapterFromOptions($options)
     {
         // Set up custom options by database type:
         switch (strtolower($options['driver'])) {
         case 'mysqli':
-            $config = ConfigReader::getConfig();
-            $options['charset'] = isset($config->Database->charset)
-                ? $config->Database->charset : 'utf8';
+            $options['charset'] = isset($this->config->Database->charset)
+                ? $this->config->Database->charset : 'utf8';
             $options['options'] = array('buffer_results' => true);
             break;
         }
@@ -113,7 +128,7 @@ class AdapterFactory
      *
      * @return object
      */
-    public static function getAdapterFromConnectionString($connectionString,
+    public function getAdapterFromConnectionString($connectionString,
         $overrideUser = null, $overridePass = null
     ) {
         list($type, $details) = explode('://', $connectionString);
@@ -132,13 +147,13 @@ class AdapterFactory
 
         // Set up default options:
         $options = array(
-            'driver' => static::getDriverName($type),
+            'driver' => $this->getDriverName($type),
             'hostname' => $host,
             'username' => $username,
             'password' => $password,
             'database' => $dbName
         );
 
-        return static::getAdapterFromOptions($options);
+        return $this->getAdapterFromOptions($options);
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php
index 7e90a3a196cc4c9e6ced82dab366273a6dc8f317..ce91fc12d71d3dd2173c79eb17289080ff061df6 100644
--- a/module/VuFind/src/VuFind/Db/Row/User.php
+++ b/module/VuFind/src/VuFind/Db/Row/User.php
@@ -31,8 +31,7 @@ use Zend\Db\Sql\Expression,
     Zend\Db\Sql\Sql,
     Zend\Crypt\Symmetric\Mcrypt,
     Zend\Crypt\Password\Bcrypt,
-    Zend\Crypt\BlockCipher as BlockCipher,
-    VuFind\Config\Reader as ConfigReader;
+    Zend\Crypt\BlockCipher as BlockCipher;
 
 /**
  * Row Definition for user
@@ -45,6 +44,13 @@ use Zend\Db\Sql\Expression,
  */
 class User extends ServiceLocatorAwareGateway
 {
+    /**
+     * Is encryption enabled?
+     *
+     * @var bool
+     */
+    protected $encryptionEnabled = null;
+
     /**
      * Encryption key used for catalog passwords (null if encryption disabled):
      *
@@ -60,19 +66,6 @@ class User extends ServiceLocatorAwareGateway
     public function __construct($adapter)
     {
         parent::__construct('id', 'user', $adapter);
-        $config = ConfigReader::getConfig();
-        $encryption = isset($config->Authentication->encrypt_ils_password)
-            ? $config->Authentication->encrypt_ils_password : false;
-        if ($encryption) {
-            if (!isset($config->Authentication->ils_encryption_key)
-                || empty($config->Authentication->ils_encryption_key)
-            ) {
-                throw new \VuFind\Exception\PasswordSecurity(
-                    'ILS password encryption on, but no key set.'
-                );
-            }
-            $this->encryptionKey = $config->Authentication->ils_encryption_key;
-        }
     }
 
     /**
@@ -131,6 +124,7 @@ class User extends ServiceLocatorAwareGateway
      * @param string $password Password to save
      *
      * @return mixed           The output of the save method.
+     * @throws \VuFind\Exception\PasswordSecurity
      */
     public function saveCredentials($username, $password)
     {
@@ -146,10 +140,11 @@ class User extends ServiceLocatorAwareGateway
     }
 
     /**
-     *  This is a getter for the Catalog Password. It will return a plaintext version
-     *  of the password.
+     * This is a getter for the Catalog Password. It will return a plaintext version
+     * of the password.
      *
-     *  @return string The Catalog password in plain text
+     * @return string The Catalog password in plain text
+     * @throws \VuFind\Exception\PasswordSecurity
      */
     public function getCatPassword()
     {
@@ -165,7 +160,14 @@ class User extends ServiceLocatorAwareGateway
      */
     protected function passwordEncryptionEnabled()
     {
-        return null !== $this->encryptionKey;
+        if (null === $this->encryptionEnabled) {
+            $config = $this->getServiceLocator()->getServiceLocator()
+                ->get('VuFind\Config')->get('config');
+            $this->encryptionEnabled
+                = isset($config->Authentication->encrypt_ils_password)
+                ? $config->Authentication->encrypt_ils_password : false;
+        }
+        return $this->encryptionEnabled;
     }
 
     /**
@@ -177,9 +179,25 @@ class User extends ServiceLocatorAwareGateway
      * decrypt text.
      *
      * @return string|bool    The encrypted/decrypted string
+     * @throws \VuFind\Exception\PasswordSecurity
      */
     protected function encryptOrDecrypt($text, $encrypt = true)
     {
+        // Load encryption key from configuration if not already present:
+        if (null === $this->encryptionKey) {
+            $config = $this->getServiceLocator()->getServiceLocator()
+                ->get('VuFind\Config')->get('config');
+            if (!isset($config->Authentication->ils_encryption_key)
+                || empty($config->Authentication->ils_encryption_key)
+            ) {
+                throw new \VuFind\Exception\PasswordSecurity(
+                    'ILS password encryption on, but no key set.'
+                );
+            }
+            $this->encryptionKey = $config->Authentication->ils_encryption_key;
+        }
+
+        // Perform encryption:
         $cipher = new BlockCipher(new Mcrypt(array('algorithm' => 'blowfish')));
         $cipher->setKey($this->encryptionKey);
         return $encrypt ? $cipher->encrypt($text) : $cipher->decrypt($text);
diff --git a/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php b/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php
index e7f2feef12baee000ac7f28a74f51febab4adeb4..e808f4d1f3bfba048685f58bcc6cc76e60d8d92a 100644
--- a/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php
+++ b/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php
@@ -53,14 +53,15 @@ class Factory
         $class = 'VuFind\Hierarchy\Driver\ConfigurationBased'
     ) {
         // Set up options based on global VuFind settings:
-        $globalConfig = \VuFind\Config\Reader::getConfig();
+        $configReader = $sm->get('VuFind\Config');
+        $globalConfig = $configReader->get('config');
         $options = array(
             'enabled' => isset($globalConfig->Hierarchy->showTree)
                 ? $globalConfig->Hierarchy->showTree : false
         );
 
         // Load driver-specific configuration:
-        $driverConfig = \VuFind\Config\Reader::getConfig($config);
+        $driverConfig = $configReader->get($config);
 
         // Build object:
         return new $class(
diff --git a/module/VuFind/src/VuFind/ILS/Connection.php b/module/VuFind/src/VuFind/ILS/Connection.php
index d53bf586486718eff9d0daa063797b4e0ab27d45..8d0f88bdb78bda751ad227642c4a6fafff609b5a 100644
--- a/module/VuFind/src/VuFind/ILS/Connection.php
+++ b/module/VuFind/src/VuFind/ILS/Connection.php
@@ -30,8 +30,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException,
-    VuFind\ILS\Driver\DriverInterface;
+use VuFind\Exception\ILS as ILSException, VuFind\ILS\Driver\DriverInterface;
 
 /**
  * Catalog Connection Class
@@ -70,30 +69,40 @@ class Connection
     protected $config;
 
     /**
-     * Set the configuration of the connection.
+     * Holds mode
      *
-     * @param \Zend\Config\Config $config Configuration representing the [Catalog]
-     * section of config.ini
+     * @var string
+     */
+    protected $holdsMode = 'disabled';
+
+    /**
+     * Title-level holds mode
      *
-     * @return Connection
+     * @var string
      */
-    public function setConfig($config)
-    {
-        $this->config = $config;
-        return $this;
-    }
+    protected $titleHoldsMode = 'disabled';
 
     /**
-     * Initialize the driver using the ILS driver plugin manager.
+     * Configuration loader
      *
-     * @param \VuFind\ILS\Driver\PluginManager $driverManager Driver plugin manager
+     * @var \VuFind\Config\PluginManager
+     */
+    protected $configReader;
+
+    /**
+     * Constructor
      *
-     * @throws \Exception
-     * @return Connection
+     * @param \Zend\Config\Config              $config        Configuration
+     * representing the [Catalog] section of config.ini
+     * @param \VuFind\ILS\Driver\PluginManager $driverManager Driver plugin manager
+     * @param \VuFind\Config\PluginManager     $configReader  Configuration loader
      */
-    public function initWithDriverManager(
-        \VuFind\ILS\Driver\PluginManager $driverManager
+    public function __construct(\Zend\Config\Config $config,
+        \VuFind\ILS\Driver\PluginManager $driverManager,
+        \VuFind\Config\PluginManager $configReader
     ) {
+        $this->config = $config;
+        $this->configReader = $configReader;
         if (!isset($this->config->driver)) {
             throw new \Exception('ILS driver setting missing.');
         }
@@ -114,6 +123,19 @@ class Connection
                 $this->setDriver($driverManager->get('NoILS'));
             }
         }
+    }
+
+    /**
+     * Set the hold configuration for the connection.
+     *
+     * @param \VuFind\ILS\HoldSettings $settings Hold settings
+     *
+     * @return Connection
+     */
+    public function setHoldConfig($settings)
+    {
+        $this->holdsMode = $settings->getHoldsMode();
+        $this->titleHoldsMode = $settings->getTitleHoldsMode();
         return $this;
     }
 
@@ -172,13 +194,13 @@ class Connection
         // Determine config file name based on class name:
         $parts = explode('\\', $this->getDriverClass());
         try {
-            $config = ConfigReader::getConfig(end($parts));
+            $config = $this->configReader->get(end($parts));
         } catch (\Zend\Config\Exception\RuntimeException $e) {
             // Configuration loading failed; probably means file does not
             // exist -- just return an empty array in that case:
             return array();
         }
-        return $config->toArray();
+        return is_object($config) ? $config->toArray() : array();
     }
 
     /**
@@ -331,11 +353,9 @@ class Connection
      *
      * @return string The Holds mode
      */
-    public static function getHoldsMode()
+    public function getHoldsMode()
     {
-        $config = ConfigReader::getConfig();
-        return isset($config->Catalog->holds_mode)
-            ? $config->Catalog->holds_mode : 'all';
+        return $this->holdsMode;
     }
 
     /**
@@ -360,11 +380,9 @@ class Connection
      *
      * @return string The Title Holds mode
      */
-    public static function getTitleHoldsMode()
+    public function getTitleHoldsMode()
     {
-        $config = ConfigReader::getConfig();
-        return isset($config->Catalog->title_level_holds_mode)
-            ? $config->Catalog->title_level_holds_mode : 'disabled';
+        return $this->titleHoldsMode;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
index 182c0b4f67f2a3975d564dc685545e1804797587..a86b39d3ee51b2aa5dda51d171ed544428c18625 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
@@ -36,7 +36,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * Aleph Translator Class
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Amicus.php b/module/VuFind/src/VuFind/ILS/Driver/Amicus.php
index 2fc91b6fc7ecb5e22714869909a9e468b8393d87..89fdcf74817871d55a80b540d208e7be75818fb2 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Amicus.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Amicus.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use PDO, PDOException, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException,
+use PDO, PDOException, VuFind\Exception\ILS as ILSException,
     VuFind\I18n\Translator\TranslatorAwareInterface;
 
 /**
diff --git a/module/VuFind/src/VuFind/ILS/Driver/ClaviusSQL.php b/module/VuFind/src/VuFind/ILS/Driver/ClaviusSQL.php
index 5c93ba809a7105fc944f8124617a057e1aabd796..162176efc184f910415d07865cd88ece058627a8 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/ClaviusSQL.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/ClaviusSQL.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use PDO, PDOException, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use PDO, PDOException, VuFind\Exception\ILS as ILSException;
 
 /**
  * VuFind Driver for Clavius SQL (version: 0.1 dev)
diff --git a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
index fe5af6040ee37b8c5a13791d8ea6b6a426035c5f..b23e74a3ba72b272cbd3a6c9a740715ad133c631 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
@@ -28,8 +28,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use DOMDocument, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use DOMDocument, VuFind\Exception\ILS as ILSException;
 
 /**
  * ILS Driver for VuFind to query availability information via DAIA.
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Demo.php b/module/VuFind/src/VuFind/ILS/Driver/Demo.php
index 273c2d64ae347c7a85eb524cf570083efd4a377a..8f95438e52addb39463f64825bdebdc0170ceac9 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Demo.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Demo.php
@@ -30,8 +30,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use ArrayObject, VuFind\Config\Reader as ConfigReader,
-    VuFind\Connection\Manager as ConnectionManager,
+use ArrayObject, VuFind\Connection\Manager as ConnectionManager,
     VuFind\Exception\Date as DateException,
     VuFind\Exception\ILS as ILSException,
     Zend\Session\Container as SessionContainer;
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php b/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php
index dfda2d7b21f47f1a00e59841f9f4af175fa54385..02bd855a74a4d45837b2573f3fe564d44877fd7f 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Evergreen.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use PDO, PDOException, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use PDO, PDOException, VuFind\Exception\ILS as ILSException;
 
 /**
  * VuFind Connector for Evergreen
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Horizon.php b/module/VuFind/src/VuFind/ILS/Driver/Horizon.php
index f86b1eac8d61e21d75e9dd02ec63c926dc935b76..fe4c4569a81fde9c1f864c5ec87c28a825806f59 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Horizon.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Horizon.php
@@ -27,7 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * Horizon ILS Driver
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Innovative.php b/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
index bbe7ebb9a8baebd84fb651e27e78f990d98deef4..f68194944bbf4c4fa0c66f491f9f600ac045a7fd 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * VuFind Connector for Innovative
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Koha.php b/module/VuFind/src/VuFind/ILS/Driver/Koha.php
index add59c55bc9d681a9875c70210003068e99e5c1e..43acea89d0a8aa9eab004af0478a09d72decd981 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Koha.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Koha.php
@@ -27,8 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use PDO, PDOException, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use PDO, PDOException, VuFind\Exception\ILS as ILSException;
 
 /**
  * VuFind Driver for Koha (version: 3.02)
diff --git a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
index 16b112273194d27c0f86ce05af85e47a96de6b14..faad56af6d3acc818247f6ddac02698a1f81c58d 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
@@ -28,8 +28,7 @@
  */
 namespace VuFind\ILS\Driver;
 
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException,
+use VuFind\Exception\ILS as ILSException,
     Zend\ServiceManager\ServiceLocatorAwareInterface,
     Zend\ServiceManager\ServiceLocatorInterface;
 
@@ -90,7 +89,6 @@ class MultiBackend extends AbstractBase implements ServiceLocatorAwareInterface
      */
     protected $config = array();
 
-
     /**
      * The seperating values to be used for each ILS.
      * Not yet implemented
@@ -98,6 +96,22 @@ class MultiBackend extends AbstractBase implements ServiceLocatorAwareInterface
      */
     protected $delimiters = array();
 
+    /**
+     * Configuration loader
+     *
+     * @var \VuFind\Config\PluginManager
+     */
+    protected $configLoader;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Config\PluginManager $configLoader Configuration loader
+     */
+    public function __construct(\VuFind\Config\PluginManager $configLoader)
+    {
+        $this->configLoader = $configLoader;
+    }
 
     /**
      * Set the driver configuration.
@@ -314,7 +328,7 @@ class MultiBackend extends AbstractBase implements ServiceLocatorAwareInterface
     {
         // Determine config file name based on class name:
         try {
-            $config = ConfigReader::getConfig($source);
+            $config = $this->configLoader->get($source);
         } catch (\Zend\Config\Exception\RuntimeException $e) {
             // Configuration loading failed; probably means file does not
             // exist -- just return an empty array in that case:
diff --git a/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php b/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php
index e6034cafca2c8ef1b793f1d487f42d8286f19a36..58764a67d06018b0138df4fc431e3e92005f3b9b 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/NewGenLib.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use PDO, PDOException, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use PDO, PDOException, VuFind\Exception\ILS as ILSException;
 
 /**
  * ILS Driver for NewGenLib
diff --git a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
index 84fa0730bc1b62ab66b02a1ee121cb4f59a27ea1..48904939db3b60e86222270ade0618342290e0a2 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
@@ -27,7 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException,
+use VuFind\Exception\ILS as ILSException,
     VuFind\I18n\Translator\TranslatorAwareInterface,
     Zend\ServiceManager\ServiceLocatorAwareInterface,
     Zend\ServiceManager\ServiceLocatorInterface;
diff --git a/module/VuFind/src/VuFind/ILS/Driver/PICA.php b/module/VuFind/src/VuFind/ILS/Driver/PICA.php
index 3fff7cc4b11e1681dba915875fa62336b1fc2cef..60898ff817c38eda635285608f4a6305f319edbc 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/PICA.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/PICA.php
@@ -30,8 +30,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use DOMDocument, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use DOMDocument, VuFind\Exception\ILS as ILSException;
 
 /**
  * ILS Driver for VuFind to get information from PICA
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
index c0e31ef62f690b6e5fc578f90aa74305eaa49a01..526ed62a09ddcd5c7b64aa04d33fad108f65b1f0 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
@@ -27,8 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use SoapClient, SoapFault, SoapHeader, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException,
+use SoapClient, SoapFault, SoapHeader, VuFind\Exception\ILS as ILSException,
     Zend\ServiceManager\ServiceLocatorAwareInterface,
     Zend\ServiceManager\ServiceLocatorInterface;
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php b/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php
index e15fee4dd11788d8c371cfcc1251084566a98569..53c1e50e27813644e465647d9c1dd61adc9c3f26 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Unicorn.php
@@ -25,8 +25,7 @@
  * @link     http://code.google.com/p/vufind-unicorn/ vufind-unicorn project
  */
 namespace VuFind\ILS\Driver;
-use File_MARC, VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\ILS as ILSException;
+use File_MARC, VuFind\Exception\ILS as ILSException;
 
 /**
  * SirsiDynix Unicorn ILS Driver (VuFind side)
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Virtua.php b/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
index 41cb98b64ed2fcc580d093f87abe3daf251bebc0..ab42e5f5f09151d674c1f1767f9aead770c02b51 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * VTLS Virtua Driver
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
index a4b70a9dc1d34320ad2ec54b0b07fd33daef6ccb..41f1153df33b269c966ccc8d9e6d89d062ee7f54 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
@@ -27,7 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use File_MARC, PDO, PDOException, VuFind\Config\Reader as ConfigReader,
+use File_MARC, PDO, PDOException,
     VuFind\Exception\Date as DateException,
     VuFind\Exception\ILS as ILSException,
     VuFind\I18n\Translator\TranslatorAwareInterface,
@@ -1551,22 +1551,6 @@ class Voyager extends AbstractBase implements TranslatorAwareInterface
     {
         $items = array();
 
-        // Prevent unnecessary load on Voyager -- no point in exceeding the maximum
-        // configured date range.
-        $maxAge = 30;
-        $searchSettings = ConfigReader::getConfig('searches');
-        if (isset($searchSettings->NewItem->ranges)) {
-            $tmp = explode(',', $searchSettings->NewItem->ranges);
-            foreach ($tmp as $current) {
-                if (intval($current) > $maxAge) {
-                    $maxAge = intval($current);
-                }
-            }
-        }
-        if ($daysOld > $maxAge) {
-            $daysOld = $maxAge;
-        }
-
         $bindParams = array(
             ':enddate' => date('d-m-Y', strtotime('now')),
             ':startdate' => date('d-m-Y', strtotime("-$daysOld day"))
diff --git a/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php b/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php
index 92d06d534b81d2c927f48f50abc35bb04c305f90..459ecd390eb00e12ed5ea1c33e9f4666912e5f08 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php
@@ -29,7 +29,7 @@
  */
 namespace VuFind\ILS\Driver;
 use PDOException, VuFind\Exception\Date as DateException,
-    VuFind\Exception\ILS as ILSException, VuFind\ILS\Connection as ILSConnection;
+    VuFind\Exception\ILS as ILSException;
 
 /**
  * Voyager Restful ILS Driver
@@ -44,14 +44,68 @@ use PDOException, VuFind\Exception\Date as DateException,
  */
 class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInterface
 {
+    /**
+     * Web services host
+     *
+     * @var string
+     */
     protected $ws_host;
+
+    /**
+     * Web services port
+     *
+     * @var string
+     */
     protected $ws_port;
+
+    /**
+     * Web services app
+     *
+     * @var string
+     */
     protected $ws_app;
+
+    /**
+     * Web services database key
+     *
+     * @var string
+     */
     protected $ws_dbKey;
+
+    /**
+     * Web services patron home UB ID
+     *
+     * @var string
+     */
     protected $ws_patronHomeUbId;
+
+    /**
+     * Legal pickup locations
+     *
+     * @var array
+     */
     protected $ws_pickUpLocations;
+
+    /**
+     * Default pickup location
+     *
+     * @var string
+     */
     protected $defaultPickUpLocation;
+
+    /**
+     * The maximum number of holds to check at a time (0 = no limit)
+     *
+     * @var int
+     */
     protected $holdCheckLimit;
+
+    /**
+     * Should we check renewal status before presenting a list of items or only
+     * after user requests renewal?
+     *
+     * @var bool
+     */
     protected $checkRenewalsUpFront;
 
     /**
@@ -61,6 +115,35 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
      */
     protected $httpService = null;
 
+    /**
+     * Holds mode
+     *
+     * @var string
+     */
+    protected $holdsMode;
+
+    /**
+     * Title-level holds mode
+     *
+     * @var string
+     */
+    protected $titleHoldsMode;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Date\Converter $dateConverter  Date converter object
+     * @param string                 $holdsMode      Holds mode setting
+     * @param string                 $titleHoldsMode Title holds mode setting
+     */
+    public function __construct(\VuFind\Date\Converter $dateConverter,
+        $holdsMode = 'disabled', $titleHoldsMode = 'disabled'
+    ) {
+        parent::__construct($dateConverter);
+        $this->holdsMode = $holdsMode;
+        $this->titleHoldsMode = $titleHoldsMode;
+    }
+
     /**
      * Set the HTTP service to be used for HTTP requests.
      *
@@ -214,7 +297,6 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
     protected function processHoldingData($data, $patron = false)
     {
         $holding = parent::processHoldingData($data, $patron);
-        $mode = ILSConnection::getHoldsMode();
 
         foreach ($holding as $i => $row) {
             $is_borrowable = isset($row['_fullRow']['ITEM_TYPE_ID'])
@@ -231,7 +313,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
 
             // Hold Type - If we have patron data, we can use it to determine if a
             // hold link should be shown
-            if ($patron && $mode == "driver") {
+            if ($patron && $this->holdsMode == "driver") {
                 // This limit is set as the api is slow to return results
                 if ($i < $this->holdCheckLimit && $this->holdCheckLimit != "0") {
                     $holdType = $this->determineHoldType(
@@ -272,8 +354,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
     {
         $holdType = isset($data['holdtype']) ? $data['holdtype'] : "auto";
         $level = isset($data['level']) ? $data['level'] : "copy";
-        $mode = ("title" == $level) ? ILSConnection::getTitleHoldsMode()
-            : ILSConnection::getHoldsMode();
+        $mode = ("title" == $level) ? $this->titleHoldsMode : $this->holdsMode;
         if ("driver" == $mode && "auto" == $holdType) {
             $itemID = isset($data['item_id']) ? $data['item_id'] : false;
             $result = $this->determineHoldType($patron['id'], $id, $itemID);
diff --git a/module/VuFind/src/VuFind/ILS/Driver/XCNCIP.php b/module/VuFind/src/VuFind/ILS/Driver/XCNCIP.php
index 024f2c3686f54263b50e296081364f9883dadc5f..4bdc43797d977be10236a51174672008f1f2217e 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/XCNCIP.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/XCNCIP.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * XC NCIP Toolkit ILS Driver
diff --git a/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php b/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php
index 6285f3393b6cea7054fba68b192040a2875ae49a..940f9118df2da5174dc92c7fb03185329c1c2127 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/XCNCIP2.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
  */
 namespace VuFind\ILS\Driver;
-use VuFind\Config\Reader as ConfigReader, VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * XC NCIP Toolkit (v2) ILS Driver
diff --git a/module/VuFind/src/VuFind/ILS/HoldSettings.php b/module/VuFind/src/VuFind/ILS/HoldSettings.php
new file mode 100644
index 0000000000000000000000000000000000000000..669679db08ac552d53ef78d4c52498860718e88f
--- /dev/null
+++ b/module/VuFind/src/VuFind/ILS/HoldSettings.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * ILS Hold Settings Class
+ *
+ * This class is responsible for determining hold settings for VuFind based
+ * on configuration and defaults.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  ILS_Drivers
+ * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
+ */
+namespace VuFind\ILS;
+
+/**
+ * ILS Hold Settings Class
+ *
+ * This class is responsible for determining hold settings for VuFind based
+ * on configuration and defaults.
+ *
+ * @category VuFind2
+ * @package  ILS_Drivers
+ * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
+ */
+class HoldSettings
+{
+    /**
+     * ILS configuration
+     *
+     * @var \Zend\Config\Config
+     */
+    protected $config;
+
+    /**
+     * Constructor
+     *
+     * @param \Zend\Config\Config $config Configuration representing the [Catalog]
+     * section of config.ini
+     */
+    public function __construct(\Zend\Config\Config $config)
+    {
+        $this->config = $config;
+    }
+
+    /**
+     * Get Holds Mode
+     *
+     * This is responsible for returning the holds mode
+     *
+     * @return string The Holds mode
+     */
+    public function getHoldsMode()
+    {
+        return isset($this->config->holds_mode) ? $this->config->holds_mode : 'all';
+    }
+
+    /**
+     * Get Title Holds Mode
+     *
+     * This is responsible for returning the Title holds mode
+     *
+     * @return string The Title Holds mode
+     */
+    public function getTitleHoldsMode()
+    {
+        return isset($this->config->title_level_holds_mode)
+            ? $this->config->title_level_holds_mode : 'disabled';
+    }
+}
diff --git a/module/VuFind/src/VuFind/ILS/Logic/Holds.php b/module/VuFind/src/VuFind/ILS/Logic/Holds.php
index 1e1aabdf2d628fd11d03b3f7ccb50d4152a4ec68..2bba28794278f932c71977d77388b5c7151babe2 100644
--- a/module/VuFind/src/VuFind/ILS/Logic/Holds.php
+++ b/module/VuFind/src/VuFind/ILS/Logic/Holds.php
@@ -27,8 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\ILS\Logic;
-use VuFind\Config\Reader as ConfigReader, VuFind\Crypt\HMAC,
-    VuFind\ILS\Connection as ILSConnection;
+use VuFind\ILS\Connection as ILSConnection;
 
 /**
  * Hold Logic Class
@@ -42,9 +41,39 @@ use VuFind\Config\Reader as ConfigReader, VuFind\Crypt\HMAC,
  */
 class Holds
 {
+    /**
+     * Auth manager object
+     *
+     * @var \VuFind\Auth\Manager
+     */
     protected $account;
+
+    /**
+     * Catalog connection object
+     *
+     * @var ILSConnection
+     */
     protected $catalog;
+
+    /**
+     * HMAC generator
+     *
+     * @var \VuFind\Crypt\HMAC
+     */
+    protected $hmac;
+
+    /**
+     * VuFind configuration
+     *
+     * @var \Zend\Config\Config
+     */
     protected $config;
+
+    /**
+     * Holding locations to hide from display
+     *
+     * @var array
+     */
     protected $hideHoldings = array();
 
     /**
@@ -52,11 +81,15 @@ class Holds
      *
      * @param \VuFind\Auth\Manager $account Auth manager object
      * @param ILSConnection        $ils     A catalog connection
+     * @param \VuFind\Crypt\HMAC   $hmac    HMAC generator
+     * @param \Zend\Config\Config  $config  VuFind configuration
      */
-    public function __construct(\VuFind\Auth\Manager $account, ILSConnection $ils)
-    {
+    public function __construct(\VuFind\Auth\Manager $account, ILSConnection $ils,
+        \VuFind\Crypt\HMAC $hmac, \Zend\Config\Config $config
+    ) {
         $this->account = $account;
-        $this->config = ConfigReader::getConfig();
+        $this->hmac = $hmac;
+        $this->config = $config;
 
         if (isset($this->config->Record->hide_holdings)) {
             foreach ($this->config->Record->hide_holdings as $current) {
@@ -136,7 +169,7 @@ class Holds
             // needed for hold data.
             $patron = $this->account->storedCatalogLogin();
             $result = $this->catalog->getHolding($id, $patron);
-            $mode = ILSConnection::getHoldsMode();
+            $mode = $this->catalog->getHoldsMode();
 
             if ($mode == "disabled") {
                  $holdings = $this->standardHoldings($result);
@@ -315,7 +348,7 @@ class Holds
     protected function getHoldDetails($holdDetails, $HMACKeys)
     {
         // Generate HMAC
-        $HMACkey = HMAC::generate($HMACKeys, $holdDetails);
+        $HMACkey = $this->hmac->generate($HMACKeys, $holdDetails);
 
         // Add Params
         foreach ($holdDetails as $key => $param) {
@@ -325,7 +358,7 @@ class Holds
             }
         }
 
-        //Add HMAC
+        // Add HMAC
         $queryString[] = "hashKey=" . urlencode($HMACkey);
         $queryString = implode('&', $queryString);
 
diff --git a/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php b/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
index cdaf97d05ee09e2e5a2c6f336b3b9f60f8ce7046..f24aa34d75b9b8432c9e2cdf55cacae4bd771bd1 100644
--- a/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
+++ b/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
@@ -27,8 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\ILS\Logic;
-use VuFind\Config\Reader as ConfigReader, VuFind\Crypt\HMAC,
-    VuFind\ILS\Connection as ILSConnection;
+use VuFind\ILS\Connection as ILSConnection;
 
 /**
  * Title Hold Logic Class
@@ -42,9 +41,39 @@ use VuFind\Config\Reader as ConfigReader, VuFind\Crypt\HMAC,
  */
 class TitleHolds
 {
+    /**
+     * Auth manager object
+     *
+     * @var \VuFind\Auth\Manager
+     */
     protected $account;
+
+    /**
+     * Catalog connection object
+     *
+     * @var ILSConnection
+     */
     protected $catalog;
+
+    /**
+     * HMAC generator
+     *
+     * @var \VuFind\Crypt\HMAC
+     */
+    protected $hmac;
+
+    /**
+     * VuFind configuration
+     *
+     * @var \Zend\Config\Config
+     */
     protected $config;
+
+    /**
+     * Holding locations to hide from display
+     *
+     * @var array
+     */
     protected $hideHoldings = array();
 
     /**
@@ -52,11 +81,15 @@ class TitleHolds
      *
      * @param \VuFind\Auth\Manager $account Auth manager object
      * @param ILSConnection        $ils     A catalog connection
+     * @param \VuFind\Crypt\HMAC   $hmac    HMAC generator
+     * @param \Zend\Config\Config  $config  VuFind configuration
      */
-    public function __construct(\VuFind\Auth\Manager $account, ILSConnection $ils)
-    {
+    public function __construct(\VuFind\Auth\Manager $account, ILSConnection $ils,
+        \VuFind\Crypt\HMAC $hmac, \Zend\Config\Config $config
+    ) {
         $this->account = $account;
-        $this->config = ConfigReader::getConfig();
+        $this->hmac = $hmac;
+        $this->config = $config;
 
         if (isset($this->config->Record->hide_holdings)) {
             foreach ($this->config->Record->hide_holdings as $current) {
@@ -78,7 +111,7 @@ class TitleHolds
     {
         // Get Holdings Data
         if ($this->catalog) {
-            $mode = ILSConnection::getTitleHoldsMode();
+            $mode = $this->catalog->getTitleHoldsMode();
             if ($mode == "disabled") {
                  return false;
             } else if ($mode == "driver") {
@@ -236,7 +269,7 @@ class TitleHolds
     protected function getHoldDetails($data, $HMACKeys)
     {
         // Generate HMAC
-        $HMACkey = HMAC::generate($HMACKeys, $data);
+        $HMACkey = $this->hmac->generate($HMACKeys, $data);
 
         // Add Params
         foreach ($data as $key => $param) {
@@ -246,7 +279,7 @@ class TitleHolds
             }
         }
 
-        //Add HMAC
+        // Add HMAC
         $queryString[] = "hashKey=" . urlencode($HMACkey);
         $queryString = implode('&', $queryString);
 
diff --git a/module/VuFind/src/VuFind/OAI/Server.php b/module/VuFind/src/VuFind/OAI/Server.php
index ad4cb3b0284e5a06e377018edce643685a9e0dd4..a3feb3583d14bd912d821465b644941e31d05abb 100644
--- a/module/VuFind/src/VuFind/OAI/Server.php
+++ b/module/VuFind/src/VuFind/OAI/Server.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:developer_manual Wiki
  */
 namespace VuFind\OAI;
-use SimpleXMLElement, VuFind\Config\Reader as ConfigReader,
+use SimpleXMLElement,
     VuFind\Exception\RecordMissing as RecordMissingException, VuFind\SimpleXML;
 
 /**
@@ -42,48 +42,123 @@ use SimpleXMLElement, VuFind\Config\Reader as ConfigReader,
  */
 class Server
 {
-    protected $baseURL;                         // Repository base URL
-    protected $params;                          // Incoming request parameters
-    protected $searchClassId = 'Solr';          // Search object class to use
-    protected $core = 'biblio';                 // What Solr core are we serving up?
-    protected $iso8601 = 'Y-m-d\TH:i:s\Z';      // ISO-8601 date format
-    protected $pageSize = 100;                  // Records per page in lists
-    protected $setField = null;                 // Solr field for set membership
-
-    // Supported metadata formats:
+    /**
+     * Repository base URL
+     *
+     * @var string
+     */
+    protected $baseURL;
+
+    /**
+     * Incoming request parameters
+     *
+     * @var array
+     */
+    protected $params;
+
+    /**
+     * Search object class to use
+     *
+     * @var string
+     */
+    protected $searchClassId = 'Solr';
+
+    /**
+     * What Solr core are we serving up?
+     *
+     * @var string
+     */
+    protected $core = 'biblio';
+
+    /**
+     * ISO-8601 date format
+     *
+     * @var string
+     */
+    protected $iso8601 = 'Y-m-d\TH:i:s\Z';
+
+    /**
+     * Records per page in lists
+     *
+     * @var int
+     */
+    protected $pageSize = 100;
+
+    /**
+     * Solr field for set membership
+     *
+     * @var string
+     */
+    protected $setField = null;
+
+    /**
+     * Supported metadata formats
+     *
+     * @var array
+     */
     protected $metadataFormats = array();
 
-    // Namespace used for ID prefixing (if any):
+    /**
+     * Namespace used for ID prefixing (if any)
+     *
+     * @var string
+     */
     protected $idNamespace = null;
 
-    // Values used in "Identify" response:
+    /**
+     * Repository name used in "Identify" response
+     *
+     * @var string
+     */
     protected $repositoryName = 'VuFind';
+
+    /**
+     * Earliest datestamp used in "Identify" response
+     *
+     * @var string
+     */
     protected $earliestDatestamp = '2000-01-01T00:00:00Z';
+
+    /**
+     * Admin email used in "Identify" response
+     *
+     * @var string
+     */
     protected $adminEmail;
 
-    // Search manager:
+    /**
+     * Search manager
+     *
+     * @var \VuFind\Search\Manager
+     */
     protected $searchManager;
 
-    // Table manager:
+    /**
+     * Table manager
+     *
+     * @var \VuFind\Db\Table\PluginManager
+     */
     protected $tableManager;
 
     /**
      * Constructor
      *
      * @param \VuFind\Search\Manager $sm      Search manager for retrieving records
+     * @param \Zend\Config\Config    $config  VuFind configuration
      * @param string                 $baseURL The base URL for the OAI server
      * @param array                  $params  The incoming OAI-PMH parameters
      * (i.e. $_GET)
      */
-    public function __construct(\VuFind\Search\Manager $sm, $baseURL, $params)
-    {
+    public function __construct(\VuFind\Search\Manager $sm,
+        \Zend\Config\Config $config, $baseURL, $params
+    ) {
         $this->searchManager = $sm;
         $this->tableManager = $sm->getServiceLocator()
             ->get('VuFind\DbTablePluginManager');
         $this->baseURL = $baseURL;
         $this->params = isset($params) && is_array($params) ? $params : array();
         $this->initializeMetadataFormats(); // Load details on supported formats
-        $this->initializeSettings();        // Load config.ini settings
+        $this->initializeSettings($config); // Load config.ini settings
     }
 
     /**
@@ -327,12 +402,12 @@ class Server
      * constructor and is only a separate method to allow easy override by child
      * classes).
      *
+     * @param \Zend\Config\Config $config VuFind configuration
+     *
      * @return void
      */
-    protected function initializeSettings()
+    protected function initializeSettings(\Zend\Config\Config $config)
     {
-        $config = ConfigReader::getConfig();
-
         // Override default repository name if configured:
         if (isset($config->OAI->repository_name)) {
             $this->repositoryName = $config->OAI->repository_name;
diff --git a/module/VuFind/src/VuFind/OAI/Server/Auth.php b/module/VuFind/src/VuFind/OAI/Server/Auth.php
index 761a9bec172301f6a989fbd3105e32390e3ae403..3cfec572068e6d5731e3d92ec9afa0b8d6b5a880 100644
--- a/module/VuFind/src/VuFind/OAI/Server/Auth.php
+++ b/module/VuFind/src/VuFind/OAI/Server/Auth.php
@@ -45,13 +45,15 @@ class Auth extends Base
      * Constructor
      *
      * @param \VuFind\Search\Manager $sm      Search manager for retrieving records
+     * @param \Zend\Config\Config    $config  VuFind configuration
      * @param string                 $baseURL The base URL for the OAI server
      * @param array                  $params  The incoming OAI-PMH parameters
      * (i.e. $_GET)
      */
-    public function __construct(\VuFind\Search\Manager $sm, $baseURL, $params)
-    {
-        parent::__construct($sm, $baseURL, $params);
+    public function __construct(\VuFind\Search\Manager $sm,
+        \Zend\Config\Config $config, $baseURL, $params
+    ) {
+        parent::__construct($sm, $config, $baseURL, $params);
         $this->core = 'authority';
         $this->searchClassId = 'SolrAuth';
     }
@@ -61,13 +63,15 @@ class Auth extends Base
      * constructor and is only a separate method to allow easy override by child
      * classes).
      *
+     * @param \Zend\Config\Config $config VuFind configuration
+     *
      * @return void
      */
-    protected function initializeSettings()
+    protected function initializeSettings(\Zend\Config\Config $config)
     {
         // Use some of the same settings as the regular OAI server, but override
         // others:
-        parent::initializeSettings();
+        parent::initializeSettings($config);
         $this->repositoryName = 'Authority Data Store';
         $this->setField = 'source';
     }
diff --git a/module/VuFind/src/VuFind/Recommend/AuthorInfo.php b/module/VuFind/src/VuFind/Recommend/AuthorInfo.php
index 0341c6dfe7f30ba97aaa1bb651050085950621cb..c1ec9e3a6ff1d1932ff5b4b88eb28cc59dd007d6 100644
--- a/module/VuFind/src/VuFind/Recommend/AuthorInfo.php
+++ b/module/VuFind/src/VuFind/Recommend/AuthorInfo.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:recommendation_modules Wiki
  */
 namespace VuFind\Recommend;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\I18n\Translator\TranslatorAwareInterface;
+use VuFind\I18n\Translator\TranslatorAwareInterface;
 
 /**
  * AuthorInfo Recommendations Module
diff --git a/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php b/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php
index beb0178100e884e4b826ad1f2e65f55818dd5827..77fc2e934babef02e9100006a9fff95a5783b4f4 100644
--- a/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php
+++ b/module/VuFind/src/VuFind/Recommend/EuropeanaResults.php
@@ -27,8 +27,7 @@
  * @link     http://vufind.org/wiki/vufind2:recommendation_modules Wiki
  */
 namespace VuFind\Recommend;
-use VuFind\Config\Reader as ConfigReader, Zend\Feed\Reader\Reader as FeedReader,
-    Zend\Log\LoggerInterface;
+use Zend\Feed\Reader\Reader as FeedReader, Zend\Log\LoggerInterface;
 
 /**
  * EuropeanaResults Recommendations Module
@@ -129,6 +128,16 @@ class EuropeanaResults implements RecommendInterface,
      */
     protected $httpService = null;
 
+    /**
+     * Constructor
+     *
+     * @param string $key API key
+     */
+    public function __construct($key)
+    {
+        $this->key = $key;
+    }
+
     /**
      * Set the HTTP service to be used for HTTP requests.
      *
@@ -192,10 +201,6 @@ class EuropeanaResults implements RecommendInterface,
         if (!empty($this->excludeProviders)) {
             $this->excludeProviders = explode(',', $this->excludeProviders);
         }
-
-        //get the key from config.ini
-        $config = ConfigReader::getConfig();
-        $this->key = $config->Content->europeanaAPI;
         $this->searchSite = "Europeana.eu";
     }
 
@@ -215,7 +220,7 @@ class EuropeanaResults implements RecommendInterface,
     {
         // build url
         $url = $targetUrl . "?" . $requestParam . "=" . $this->lookfor;
-        //add providers to ignore
+        // add providers to ignore
         foreach ($excludeProviders as $provider) {
             $provider = trim($provider);
             if (!empty($provider)) {
@@ -224,7 +229,7 @@ class EuropeanaResults implements RecommendInterface,
         }
         $url .= '&wskey=' . urlencode($this->key);
 
-        //return complete url
+        // return complete url
         return $url;
     }
 
diff --git a/module/VuFind/src/VuFind/Recommend/ExpandFacets.php b/module/VuFind/src/VuFind/Recommend/ExpandFacets.php
index b529e18d9a960124641293433a245c6f56671c33..2b232dd1b6f4781fd102bee9072fc13105cd7c00 100644
--- a/module/VuFind/src/VuFind/Recommend/ExpandFacets.php
+++ b/module/VuFind/src/VuFind/Recommend/ExpandFacets.php
@@ -26,7 +26,6 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Recommend;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Recommendation class to expand recommendation interfaces
@@ -39,10 +38,44 @@ use VuFind\Config\Reader as ConfigReader;
  */
 class ExpandFacets extends AbstractSearchManagerAwareModule
 {
+    /**
+     * Facets to display
+     *
+     * @var array
+     */
     protected $facets;
+
+    /**
+     * Settings from configuration
+     *
+     * @var string
+     */
     protected $settings;
+
+    /**
+     * Search results
+     *
+     * @var \VuFind\Search\Base\Results
+     */
     protected $searchObject;
 
+    /**
+     * Configuration loader
+     *
+     * @var \VuFind\Config\PluginManager
+     */
+    protected $configLoader;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Config\PluginManager $configLoader Configuration loader
+     */
+    public function __construct(\VuFind\Config\PluginManager $configLoader)
+    {
+        $this->configLoader = $configLoader;
+    }
+
     /**
      * setConfig
      *
@@ -56,7 +89,7 @@ class ExpandFacets extends AbstractSearchManagerAwareModule
     {
         // Save the basic parameters:
         $this->settings = $settings;
-        
+
         // Parse the additional settings:
         $settings = explode(':', $settings);
         $mainSection = empty($settings[0]) ? 'Results' : $settings[0];
@@ -64,7 +97,7 @@ class ExpandFacets extends AbstractSearchManagerAwareModule
         $iniName = isset($settings[2]) ? $settings[2] : 'facets';
 
         // Load the desired facet information...
-        $config = ConfigReader::getConfig($iniName);
+        $config = $this->configLoader->get($iniName);
 
         // All standard facets to display:
         $this->facets = isset($config->$mainSection) ?
diff --git a/module/VuFind/src/VuFind/Recommend/SideFacets.php b/module/VuFind/src/VuFind/Recommend/SideFacets.php
index 795921bf01067afa7d009b7aeb33b6ca17b800c3..1457e4d2a94d28c569e81c1f0186516af1f52010 100644
--- a/module/VuFind/src/VuFind/Recommend/SideFacets.php
+++ b/module/VuFind/src/VuFind/Recommend/SideFacets.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:recommendation_modules Wiki
  */
 namespace VuFind\Recommend;
-use VuFind\Config\Reader as ConfigReader, VuFind\Solr\Utils as SolrUtils;
+use VuFind\Solr\Utils as SolrUtils;
 
 /**
  * SideFacets Recommendations Module
@@ -41,11 +41,51 @@ use VuFind\Config\Reader as ConfigReader, VuFind\Solr\Utils as SolrUtils;
  */
 class SideFacets implements RecommendInterface
 {
+    /**
+     * Date facet configuration
+     *
+     * @var array
+     */
     protected $dateFacets = array();
+
+    /**
+     * Main facet configuration
+     *
+     * @var array
+     */
     protected $mainFacets = array();
+
+    /**
+     * Checkbox facet configuration
+     *
+     * @var array
+     */
     protected $checkboxFacets = array();
+
+    /**
+     * Search results
+     *
+     * @var \VuFind\Search\Base\Results
+     */
     protected $results;
 
+    /**
+     * Configuration loader
+     *
+     * @var \VuFind\Config\PluginManager
+     */
+    protected $configLoader;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Config\PluginManager $configLoader Configuration loader
+     */
+    public function __construct(\VuFind\Config\PluginManager $configLoader)
+    {
+        $this->configLoader = $configLoader;
+    }
+
     /**
      * setConfig
      *
@@ -64,7 +104,7 @@ class SideFacets implements RecommendInterface
         $iniName = isset($settings[2]) ? $settings[2] : 'facets';
 
         // Load the desired facet information...
-        $config = ConfigReader::getConfig($iniName);
+        $config = $this->configLoader->get($iniName);
 
         // All standard facets to display:
         $this->mainFacets = isset($config->$mainSection) ?
diff --git a/module/VuFind/src/VuFind/Recommend/TopFacets.php b/module/VuFind/src/VuFind/Recommend/TopFacets.php
index 1d934e3b8f5c2f243fb9ca4fd93e613af060762c..0bfaf19bfb27301f5003146b1f065b9d66e63dea 100644
--- a/module/VuFind/src/VuFind/Recommend/TopFacets.php
+++ b/module/VuFind/src/VuFind/Recommend/TopFacets.php
@@ -27,7 +27,6 @@
  * @link     http://vufind.org/wiki/vufind2:recommendation_modules Wiki
  */
 namespace VuFind\Recommend;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * SideFacets Recommendations Module
@@ -43,10 +42,44 @@ use VuFind\Config\Reader as ConfigReader;
  */
 class TopFacets implements RecommendInterface
 {
+    /**
+     * Facet configuration
+     *
+     * @var array
+     */
     protected $facets;
+
+    /**
+     * Basic configurations
+     *
+     * @var array
+     */
     protected $baseSettings;
+
+    /**
+     * Search results
+     *
+     * @var \VuFind\Search\Base\Results
+     */
     protected $results;
 
+    /**
+     * Configuration loader
+     *
+     * @var \VuFind\Config\PluginManager
+     */
+    protected $configLoader;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Config\PluginManager $configLoader Configuration loader
+     */
+    public function __construct(\VuFind\Config\PluginManager $configLoader)
+    {
+        $this->configLoader = $configLoader;
+    }
+
     /**
      * setConfig
      *
@@ -67,7 +100,7 @@ class TopFacets implements RecommendInterface
         $iniName = isset($settings[1]) ? $settings[1] : 'facets';
 
         // Load the desired facet information:
-        $config = ConfigReader::getConfig($iniName);
+        $config = $this->configLoader->get($iniName);
         $this->facets = isset($config->$mainSection)
             ? $config->$mainSection->toArray() : array();
 
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
index 57b2cbe084112312155ecc9d6949fecba9b9a6ca..e7807ffbb8fd65cdb808dab617c4b8799423ddbd 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
@@ -875,11 +875,9 @@ class SolrDefault extends AbstractBase
      * Get an array of information about record holdings, obtained in real-time
      * from the ILS.
      *
-     * @param \VuFind\Auth\Manager $account Auth manager object
-     *
      * @return array
      */
-    public function getRealTimeHoldings(\VuFind\Auth\Manager $account)
+    public function getRealTimeHoldings()
     {
         // Not supported by the Solr index -- implement in child classes.
         return array();
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php b/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php
index 4836bd097bbf997ac972f3e23dfbbe5e26df9231..053b114b5cb6c4234260883d4638e4addf6323ea 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php
@@ -26,11 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:record_drivers Wiki
  */
 namespace VuFind\RecordDriver;
-use VuFind\Exception\ILS as ILSException,
-    VuFind\ILS\Connection as ILSConnection,
-    VuFind\ILS\Logic\Holds as HoldLogic,
-    VuFind\ILS\Logic\TitleHolds as TitleHoldLogic,
-    VuFind\XSLT\Processor as XSLTProcessor;
+use VuFind\Exception\ILS as ILSException, VuFind\XSLT\Processor as XSLTProcessor;
 
 /**
  * Model for MARC records in Solr.
@@ -50,6 +46,27 @@ class SolrMarc extends SolrDefault
      */
     protected $marcRecord;
 
+    /**
+     * ILS connection
+     *
+     * @var \VuFind\ILS\Connection
+     */
+    protected $ils = null;
+
+    /**
+     * Hold logic
+     *
+     * @var \VuFind\ILS\Logic\Holds
+     */
+    protected $holdLogic;
+
+    /**
+     * Title hold logic
+     *
+     * @var \VuFind\ILS\Logic\TitleHolds
+     */
+    protected $titleHoldLogic;
+
     /**
      * Set raw data to initialize the object.
      *
@@ -915,28 +932,44 @@ class SolrMarc extends SolrDefault
     }
 
     /**
-     * Get the ILS connection.
+     * Attach an ILS connection and related logic to the driver
+     *
+     * @param \VuFind\ILS\Connection       $ils            ILS connection
+     * @param \VuFind\ILS\Logic\Holds      $holdLogic      Hold logic handler
+     * @param \VuFind\ILS\Logic\TitleHolds $titleHoldLogic Title hold logic handler
+     *
+     * @return void
+     */
+    public function attachILS(\VuFind\ILS\Connection $ils,
+        \VuFind\ILS\Logic\Holds $holdLogic,
+        \VuFind\ILS\Logic\TitleHolds $titleHoldLogic
+    ) {
+        $this->ils = $ils;
+        $this->holdLogic = $holdLogic;
+        $this->titleHoldLogic = $titleHoldLogic;
+    }
+
+    /**
+     * Do we have an attached ILS connection?
      *
-     * @return \VuFind\ILS\Connection
+     * @return bool
      */
-    protected function getILS()
+    protected function hasILS()
     {
-        return $this->getServiceLocator()->getServiceLocator()
-            ->get('VuFind\ILSConnection');
+        return null !== $this->ils;
     }
 
     /**
      * Get an array of information about record holdings, obtained in real-time
      * from the ILS.
      *
-     * @param \VuFind\Auth\Manager $account Auth manager object
-     *
      * @return array
      */
-    public function getRealTimeHoldings(\VuFind\Auth\Manager $account)
+    public function getRealTimeHoldings()
     {
-        $holdLogic = new HoldLogic($account, $this->getILS());
-        return $holdLogic->getHoldings($this->getUniqueID());
+        return $this->hasILS()
+            ? $this->holdLogic->getHoldings($this->getUniqueID())
+            : array();
     }
 
     /**
@@ -948,8 +981,11 @@ class SolrMarc extends SolrDefault
     public function getRealTimeHistory()
     {
         // Get Acquisitions Data
+        if (!$this->hasILS()) {
+            return array();
+        }
         try {
-            return $this->getILS()->getPurchaseHistory($this->getUniqueID());
+            return $this->ils->getPurchaseHistory($this->getUniqueID());
         } catch (ILSException $e) {
             return array();
         }
@@ -958,19 +994,16 @@ class SolrMarc extends SolrDefault
     /**
      * Get a link for placing a title level hold.
      *
-     * @param \VuFind\Auth\Manager $account Auth manager object
-     *
      * @return mixed A url if a hold is possible, boolean false if not
      */
-    public function getRealTimeTitleHold(\VuFind\Auth\Manager $account)
+    public function getRealTimeTitleHold()
     {
-        $biblioLevel = $this->getBibliographicLevel();
-        if ("monograph" == strtolower($biblioLevel)
-            || stristr("part", $biblioLevel)
-        ) {
-            if (ILSConnection::getTitleHoldsMode() != "disabled") {
-                $holdLogic = new TitleHoldLogic($account, $this->getILS());
-                return $holdLogic->getHold($this->getUniqueID());
+        if ($this->hasILS()) {
+            $biblioLevel = strtolower($this->getBibliographicLevel());
+            if ("monograph" == $biblioLevel || strstr("part", $biblioLevel)) {
+                if ($this->ils->getTitleHoldsMode() != "disabled") {
+                    return $this->titleHoldLogic->getHold($this->getUniqueID());
+                }
             }
         }
 
diff --git a/module/VuFind/src/VuFind/RecordDriver/WorldCat.php b/module/VuFind/src/VuFind/RecordDriver/WorldCat.php
index c172fff649d3c3df7c72a4d103b4ea6fa977c624..0510ec6a2addd1a42441b558985e64632dcd4671 100644
--- a/module/VuFind/src/VuFind/RecordDriver/WorldCat.php
+++ b/module/VuFind/src/VuFind/RecordDriver/WorldCat.php
@@ -81,11 +81,9 @@ class WorldCat extends SolrMarc
      * Get an array of information about record holdings, obtained in real-time
      * from the ILS.
      *
-     * @param \VuFind\Auth\Manager $account Auth manager object
-     *
      * @return array
      */
-    public function getRealTimeHoldings(\VuFind\Auth\Manager $account)
+    public function getRealTimeHoldings()
     {
         // Not supported here:
         return array();
diff --git a/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php b/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php
index 6ce6fdb5c80468eaf6a000d19221fa23ff5de45d..493fee2784d70e79a65e96a8f04d2f96b8b487c1 100644
--- a/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php
+++ b/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php
@@ -48,10 +48,13 @@ class CollectionHierarchyTree extends HierarchyTree
     /**
      * Constructor
      *
+     * @param \Zend\Config\Config   $config Configuration
      * @param \VuFind\Record\Loader $loader Record loader
      */
-    public function __construct(\VuFind\Record\Loader $loader)
-    {
+    public function __construct(\Zend\Config\Config $config,
+        \VuFind\Record\Loader $loader
+    ) {
+        parent::__construct($config);
         $this->loader = $loader;
     }
 
diff --git a/module/VuFind/src/VuFind/RecordTab/Excerpt.php b/module/VuFind/src/VuFind/RecordTab/Excerpt.php
index 9532efdcd558f1512908bdd826198daa062d51b5..32c8c7445d40f8e74f253d725ce68ff78dcdbc57 100644
--- a/module/VuFind/src/VuFind/RecordTab/Excerpt.php
+++ b/module/VuFind/src/VuFind/RecordTab/Excerpt.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:record_tabs Wiki
  */
 namespace VuFind\RecordTab;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Excerpt tab
@@ -39,6 +38,23 @@ use VuFind\Config\Reader as ConfigReader;
  */
 class Excerpt extends AbstractBase
 {
+    /**
+     * Is this module enabled in the configuration?
+     *
+     * @var bool
+     */
+    protected $enabled;
+
+    /**
+     * Constructor
+     *
+     * @param bool $enabled Is this module enabled in the configuration?
+     */
+    public function __construct($enabled = true)
+    {
+        $this->enabled = $enabled;
+    }
+
     /**
      * Get the on-screen description for this tab.
      *
@@ -56,8 +72,7 @@ class Excerpt extends AbstractBase
      */
     public function isActive()
     {
-        $config = ConfigReader::getConfig();
-        if (!isset($config->Content->excerpts)) {
+        if (!$this->enabled) {
             return false;
         }
         $isbns = $this->getRecordDriver()->tryMethod('getISBNs');
diff --git a/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php b/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php
index dff411f10e7079ef59710ac44303ca63b7d9fda9..00ad966e9989064965496d169b3f67e902db155f 100644
--- a/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php
+++ b/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:record_tabs Wiki
  */
 namespace VuFind\RecordTab;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * HierarchyTree tab
@@ -53,6 +52,16 @@ class HierarchyTree extends AbstractBase
      */
     protected $config = null;
 
+    /**
+     * Constructor
+     *
+     * @param \Zend\Config\Config $config Configuration
+     */
+    public function __construct(\Zend\Config\Config $config)
+    {
+        $this->config = $config;
+    }
+
     /**
      * Get the VuFind configuration.
      *
@@ -60,9 +69,6 @@ class HierarchyTree extends AbstractBase
      */
     protected function getConfig()
     {
-        if (null === $this->config) {
-            $this->config = ConfigReader::getConfig();
-        }
         return $this->config;
     }
 
diff --git a/module/VuFind/src/VuFind/RecordTab/Map.php b/module/VuFind/src/VuFind/RecordTab/Map.php
index b3a72940252402c745063539164218becdb7a03a..0f0937f313bf8e0fb7493170ca0e0abb9a297fbe 100644
--- a/module/VuFind/src/VuFind/RecordTab/Map.php
+++ b/module/VuFind/src/VuFind/RecordTab/Map.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:record_tabs Wiki
  */
 namespace VuFind\RecordTab;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Map tab
@@ -47,6 +46,23 @@ class Map extends AbstractBase
      */
     protected $translator = null;
 
+    /**
+     * Is this module enabled in the configuration?
+     *
+     * @var bool
+     */
+    protected $enabled;
+
+    /**
+     * Constructor
+     *
+     * @param bool $enabled Is this module enabled in the configuration?
+     */
+    public function __construct($enabled = true)
+    {
+        $this->enabled = $enabled;
+    }
+
     /**
      * Get the on-screen description for this tab.
      *
@@ -121,8 +137,7 @@ class Map extends AbstractBase
      */
     public function isActive()
     {
-        $config = ConfigReader::getConfig();
-        if (!isset($config->Content->recordMap)) {
+        if (!$this->enabled) {
             return false;
         }
         $longLat = $this->getRecordDriver()->tryMethod('getLongLat');
diff --git a/module/VuFind/src/VuFind/RecordTab/Reviews.php b/module/VuFind/src/VuFind/RecordTab/Reviews.php
index 3b00d37c3d3947a4f365a001dd807747d5c2416e..b86c8247ce96db5f67f66e11955b85771499096a 100644
--- a/module/VuFind/src/VuFind/RecordTab/Reviews.php
+++ b/module/VuFind/src/VuFind/RecordTab/Reviews.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org/wiki/vufind2:record_tabs Wiki
  */
 namespace VuFind\RecordTab;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Reviews tab
@@ -39,6 +38,23 @@ use VuFind\Config\Reader as ConfigReader;
  */
 class Reviews extends AbstractBase
 {
+    /**
+     * Is this module enabled in the configuration?
+     *
+     * @var bool
+     */
+    protected $enabled;
+
+    /**
+     * Constructor
+     *
+     * @param bool $enabled Is this module enabled in the configuration?
+     */
+    public function __construct($enabled = true)
+    {
+        $this->enabled = $enabled;
+    }
+
     /**
      * Get the on-screen description for this tab.
      *
@@ -56,8 +72,7 @@ class Reviews extends AbstractBase
      */
     public function isActive()
     {
-        $config = ConfigReader::getConfig();
-        if (!isset($config->Content->reviews)) {
+        if (!$this->enabled) {
             return false;
         }
         $isbns = $this->getRecordDriver()->tryMethod('getISBNs');
diff --git a/module/VuFind/src/VuFind/Search/Base/Options.php b/module/VuFind/src/VuFind/Search/Base/Options.php
index 5c501f8ff78717070681c9f516644a82f7af8139..d7e933dd9258c0f918ae2941d2d1904215768d18 100644
--- a/module/VuFind/src/VuFind/Search/Base/Options.php
+++ b/module/VuFind/src/VuFind/Search/Base/Options.php
@@ -126,6 +126,16 @@ abstract class Options implements ServiceLocatorAwareInterface
         $this->limitOptions = array($this->defaultLimit);
     }
 
+    /**
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
+     *
+     * @return void
+     */
+    public function init()
+    {
+    }
+
     /**
      * Get string listing special advanced facet types.
      *
diff --git a/module/VuFind/src/VuFind/Search/Base/Params.php b/module/VuFind/src/VuFind/Search/Base/Params.php
index 1305d40d4eb045bfeab0c70b2ab3123221576f21..a3887561c35fb1a1d5272f41108214ce60a6e987 100644
--- a/module/VuFind/src/VuFind/Search/Base/Params.php
+++ b/module/VuFind/src/VuFind/Search/Base/Params.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\Base;
-use VuFind\Config\Reader as ConfigReader,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
+use Zend\ServiceManager\ServiceLocatorAwareInterface,
     Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
@@ -87,6 +86,16 @@ class Params implements ServiceLocatorAwareInterface
         }
     }
 
+    /**
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
+     *
+     * @return void
+     */
+    public function init()
+    {
+    }
+
     /**
      * Get the search options object.
      *
@@ -727,8 +736,8 @@ class Params implements ServiceLocatorAwareInterface
 
         // Load the necessary settings to determine the appropriate recommendations
         // module:
-        $searchSettings
-            = ConfigReader::getConfig($this->getOptions()->getSearchIni());
+        $searchSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->getOptions()->getSearchIni());
 
         // If we have a search type set, save it so we can try to load a
         // type-specific recommendations module:
@@ -1293,7 +1302,7 @@ class Params implements ServiceLocatorAwareInterface
         if (isset($this->searchTerms[0]['group'])) {
             foreach ($this->searchTerms as $group) {
                 foreach ($group['group'] as $search) {
-                    if (preg_match("/\b$needle\b/", $search['lookfor'])) {
+                    if (preg_match("/\b$needle\b/u", $search['lookfor'])) {
                         return true;
                     }
                 }
@@ -1301,7 +1310,7 @@ class Params implements ServiceLocatorAwareInterface
         } else {
             // Basic search
             foreach ($this->searchTerms as $haystack) {
-                if (preg_match("/\b$needle\b/", $haystack['lookfor'])) {
+                if (preg_match("/\b$needle\b/u", $haystack['lookfor'])) {
                     return true;
                 }
             }
diff --git a/module/VuFind/src/VuFind/Search/Manager.php b/module/VuFind/src/VuFind/Search/Manager.php
index 7fa4554d9bc16c0eec0f0cb60795e5c7650aa3e1..ca4b670bf9e007988c07e5eabd4857b34d6abc33 100644
--- a/module/VuFind/src/VuFind/Search/Manager.php
+++ b/module/VuFind/src/VuFind/Search/Manager.php
@@ -164,6 +164,7 @@ class Manager implements ServiceLocatorAwareInterface
                 throw new \Exception('Invalid options object.');
             }
             $this->injectDependencies($this->optionsStore[$this->classId]);
+            $this->optionsStore[$this->classId]->init();
         }
         return $this->optionsStore[$this->classId];
     }
@@ -184,6 +185,7 @@ class Manager implements ServiceLocatorAwareInterface
             throw new \Exception('Invalid params object.');
         }
         $this->injectDependencies($params);
+        $params->init();
         return $params;
     }
 
diff --git a/module/VuFind/src/VuFind/Search/Solr/Options.php b/module/VuFind/src/VuFind/Search/Solr/Options.php
index 4b2fab1393cd3af428c752dc6cfb334925920a38..ed2b51499566d7b80a8abd3186560cbad2aa6479 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Options.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Options.php
@@ -26,8 +26,6 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\Solr;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Search\Base\Options as BaseOptions;
 
 /**
  * Solr Search Options
@@ -38,7 +36,7 @@ use VuFind\Config\Reader as ConfigReader,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://www.vufind.org  Main Page
  */
-class Options extends BaseOptions
+class Options extends \VuFind\Search\Base\Options
 {
     /**
      * Spelling limit
@@ -83,15 +81,17 @@ class Options extends BaseOptions
     protected $solrShardsFieldsToStrip = array();
 
     /**
-     * Constructor
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
      *
      * @return void
      */
-    public function __construct()
+    public function init()
     {
-        parent::__construct();
+        parent::init();
 
-        $searchSettings = ConfigReader::getConfig($this->searchIni);
+        $searchSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->searchIni);
         if (isset($searchSettings->General->default_limit)) {
             $this->defaultLimit = $searchSettings->General->default_limit;
         }
@@ -156,7 +156,8 @@ class Options extends BaseOptions
         }
 
         // Load facet preferences
-        $facetSettings = ConfigReader::getConfig($this->facetsIni);
+        $facetSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->facetsIni);
         if (isset($facetSettings->Advanced_Settings->translated_facets)
             && count($facetSettings->Advanced_Settings->translated_facets) > 0
         ) {
@@ -170,7 +171,7 @@ class Options extends BaseOptions
         }
 
         // Load Spelling preferences
-        $config = ConfigReader::getConfig();
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
         if (isset($config->Spelling->enabled)) {
             $this->spellcheck = $config->Spelling->enabled;
         }
diff --git a/module/VuFind/src/VuFind/Search/Solr/Params.php b/module/VuFind/src/VuFind/Search/Solr/Params.php
index addb0b1d6298784996363ba23f1de1aedeb72832..45697f0b486b9ebf0c750dc20ad4f1d51779da66 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Params.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Params.php
@@ -26,7 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\Solr;
-use VuFind\Config\Reader as ConfigReader, VuFind\Search\Base\Params as BaseParams;
+
 use VuFindSearch\Query\Query;
 use VuFind\Search\Legacy\QueryAdapter;
 
@@ -39,7 +39,7 @@ use VuFind\Search\Legacy\QueryAdapter;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://www.vufind.org  Main Page
  */
-class Params extends BaseParams
+class Params extends \VuFind\Search\Base\Params
 {
     /**
      * Facet result limit
@@ -64,17 +64,17 @@ class Params extends BaseParams
     protected $overrideQuery = false;
 
     /**
-     * Constructor
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
      *
-     * @param \VuFind\Search\Base\Options $options Options to use (null to load
-     * defaults)
+     * @return void
      */
-    public function __construct($options = null)
+    public function init()
     {
-        parent::__construct($options);
+        parent::init();
 
         // Use basic facet limit by default, if set:
-        $config = ConfigReader::getConfig('facets');
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('facets');
         if (isset($config->Results_Settings->facet_limit)
             && is_numeric($config->Results_Settings->facet_limit)
         ) {
@@ -301,7 +301,7 @@ class Params extends BaseParams
      */
     protected function initFacetList($facetList, $facetSettings)
     {
-        $config = ConfigReader::getConfig('facets');
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('facets');
         if (!isset($config->$facetList)) {
             return false;
         }
@@ -346,7 +346,7 @@ class Params extends BaseParams
      */
     public function initBasicFacets()
     {
-        $config = ConfigReader::getConfig('facets');
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('facets');
         if (isset($config->ResultsTop)) {
             foreach ($config->ResultsTop as $key => $value) {
                 $this->addFacet($key, $value);
@@ -488,7 +488,7 @@ class Params extends BaseParams
      */
     public function getQueryIDLimit()
     {
-        $config = ConfigReader::getConfig();
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
         return isset($config->Index->maxBooleanClauses)
             ? $config->Index->maxBooleanClauses : 1024;
     }
diff --git a/module/VuFind/src/VuFind/Search/Solr/Results.php b/module/VuFind/src/VuFind/Search/Solr/Results.php
index 08fa65cf9c4803913b6ea1fb06b95b28c729088b..71077380b5121777473322fb6f9ec2d9898a30b9 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Results.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Results.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\Solr;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Connection\Manager as ConnectionManager,
+use VuFind\Connection\Manager as ConnectionManager,
     VuFind\Exception\RecordMissing as RecordMissingException,
     VuFind\Search\Base\Results as BaseResults;
 
@@ -386,7 +385,7 @@ class Results extends BaseResults
     protected function doSpellingReplace($term, $targetTerm, $inToken, $details,
         $returnArray
     ) {
-        $config = ConfigReader::getConfig();
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
 
         $returnArray[$targetTerm]['freq'] = $details['freq'];
         foreach ($details['suggestions'] as $word => $freq) {
diff --git a/module/VuFind/src/VuFind/Search/SolrAuthor/Params.php b/module/VuFind/src/VuFind/Search/SolrAuthor/Params.php
index fb5f9f4af16333636458ae5ec228757456ae9044..f84e5806f997b1cf79e77be1854b3a2c2648d455 100644
--- a/module/VuFind/src/VuFind/Search/SolrAuthor/Params.php
+++ b/module/VuFind/src/VuFind/Search/SolrAuthor/Params.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Search\SolrAuthor;
-use VuFind\Config\Reader as ConfigReader, VuFind\Search\Solr\Params as SolrParams;
+use VuFind\Search\Solr\Params as SolrParams;
 
 /**
  * Author Search Options
@@ -89,7 +89,8 @@ class Params extends SolrParams
     {
         // Load the necessary settings to determine the appropriate recommendations
         // module:
-        $ss = ConfigReader::getConfig($this->getOptions()->getSearchIni());
+        $ss = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->getOptions()->getSearchIni());
 
         // Load the AuthorModuleRecommendations configuration if available, use
         // standard defaults otherwise:
diff --git a/module/VuFind/src/VuFind/Search/SolrCollection/Options.php b/module/VuFind/src/VuFind/Search/SolrCollection/Options.php
index e53233ee6829163b0cbbeea0fef6b8694ba7a301..c0cd39b2e4267beffef1990995dd56ec3e3288b6 100644
--- a/module/VuFind/src/VuFind/Search/SolrCollection/Options.php
+++ b/module/VuFind/src/VuFind/Search/SolrCollection/Options.php
@@ -26,7 +26,6 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Search\SolrCollection;
-use VuFind\Config\Reader as ConfigReader;
 
 /**
  * Solr Collection Search Options
@@ -40,16 +39,18 @@ use VuFind\Config\Reader as ConfigReader;
 class Options extends \VuFind\Search\Solr\Options
 {
     /**
-     * Constructor
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
      *
      * @return void
      */
-    public function __construct()
+    public function init()
     {
-        parent::__construct();
+        parent::init();
 
         // Load sort preferences (or defaults if none in .ini file):
-        $searchSettings = ConfigReader::getConfig('Collection');
+        $searchSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get('Collection');
         if (isset($searchSettings->Sort)) {
             $this->sortOptions = array();
             foreach ($searchSettings->Sort as $key => $value) {
diff --git a/module/VuFind/src/VuFind/Search/SolrCollection/Params.php b/module/VuFind/src/VuFind/Search/SolrCollection/Params.php
index 0082f105532e3088a5722344e01481bbce1bc0d8..f62490651388194e56e6afccc747ad712657e223 100644
--- a/module/VuFind/src/VuFind/Search/SolrCollection/Params.php
+++ b/module/VuFind/src/VuFind/Search/SolrCollection/Params.php
@@ -119,7 +119,8 @@ class Params extends \VuFind\Search\Solr\Params
     protected function getRecommendationSettings()
     {
         // Collection recommendations
-        $searchSettings = \VuFind\Config\Reader::getConfig('Collection');
+        $searchSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get('Collection');
         return isset($searchSettings->Recommend)
             ? $searchSettings->Recommend->toArray()
             : array('side' => array('CollectionSideFacets:Facets::Collection:true'));
diff --git a/module/VuFind/src/VuFind/Search/Summon/Options.php b/module/VuFind/src/VuFind/Search/Summon/Options.php
index 201c8c9c6b96d8b135888dfaadedecad9273cf3a..83d39b387213f57272e0c396dbad6b2194dfbd1b 100644
--- a/module/VuFind/src/VuFind/Search/Summon/Options.php
+++ b/module/VuFind/src/VuFind/Search/Summon/Options.php
@@ -26,8 +26,6 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\Summon;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Search\Base\Options as BaseOptions;
 
 /**
  * Summon Search Options
@@ -38,10 +36,12 @@ use VuFind\Config\Reader as ConfigReader,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://www.vufind.org  Main Page
  */
-class Options extends BaseOptions
+class Options extends \VuFind\Search\Base\Options
 {
     /**
      * Maximum number of results
+     *
+     * @var int
      */
     protected $resultLimit = 400;
 
@@ -53,10 +53,21 @@ class Options extends BaseOptions
     public function __construct()
     {
         $this->searchIni = $this->facetsIni = 'Summon';
-        parent::__construct();
+    }
+
+    /**
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
+     *
+     * @return void
+     */
+    public function init()
+    {
+        parent::init();
 
         // Load facet preferences:
-        $facetSettings = ConfigReader::getConfig($this->facetsIni);
+        $facetSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->facetsIni);
         if (isset($facetSettings->Advanced_Settings->translated_facets)
             && count($facetSettings->Advanced_Facet_Settings->translated_facets) > 0
         ) {
@@ -71,7 +82,8 @@ class Options extends BaseOptions
         }
 
         // Load the search configuration file:
-        $searchSettings = ConfigReader::getConfig($this->searchIni);
+        $searchSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->searchIni);
 
         // Set up highlighting preference
         if (isset($searchSettings->General->highlighting)) {
diff --git a/module/VuFind/src/VuFind/Search/Summon/Results.php b/module/VuFind/src/VuFind/Search/Summon/Results.php
index 2a5222724f145b13de2112ac301636a6aff0e28f..e00221b5d71c76a81eaa093e5aa5c68761c14a28 100644
--- a/module/VuFind/src/VuFind/Search/Summon/Results.php
+++ b/module/VuFind/src/VuFind/Search/Summon/Results.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\Summon;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Connection\Summon as SummonConnection,
+use VuFind\Connection\Summon as SummonConnection,
     VuFind\Connection\Summon\Query as SummonQuery,
     VuFind\Exception\RecordMissing as RecordMissingException,
     VuFind\Search\Base\Results as BaseResults;
@@ -57,11 +56,14 @@ class Results extends BaseResults
     {
         static $conn = false;
         if (!$conn) {
-            $config = ConfigReader::getConfig();
+            $configReader = $this->getServiceLocator()->get('VuFind\Config');
+            $config = $configReader->get('config');
             $id = isset($config->Summon->apiId) ? $config->Summon->apiId : null;
             $key = isset($config->Summon->apiKey) ? $config->Summon->apiKey : null;
             $client = $this->getServiceLocator()->get('VuFind\Http')->createClient();
-            $conn = new SummonConnection($id, $key, array(), $client);
+            $conn = new SummonConnection(
+                $configReader->get('Summon'), $id, $key, array(), $client
+            );
             \VuFind\ServiceManager\Initializer::initInstance(
                 $conn, $this->getServiceLocator()
             );
@@ -91,7 +93,8 @@ class Results extends BaseResults
                 'pageNumber' => $this->getParams()->getPage(),
                 'pageSize' => $this->getParams()->getLimit(),
                 'didYouMean' => $this->getOptions()->spellcheckEnabled()
-            )
+            ),
+            $this->getServiceLocator()->get('VuFind\Config')->get('Summon')
         );
         if ($this->getOptions()->highlightEnabled()) {
             $query->setHighlight(true);
diff --git a/module/VuFind/src/VuFind/Search/WorldCat/Options.php b/module/VuFind/src/VuFind/Search/WorldCat/Options.php
index 0f5947c1d3ddd2af6786e7a68ba35e636fbdefe1..ee7246b9c5288210ede84f80148cba994d2b19f3 100644
--- a/module/VuFind/src/VuFind/Search/WorldCat/Options.php
+++ b/module/VuFind/src/VuFind/Search/WorldCat/Options.php
@@ -26,8 +26,6 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\WorldCat;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Search\Base\Options as BaseOptions;
 
 /**
  * WorldCat Search Options
@@ -38,7 +36,7 @@ use VuFind\Config\Reader as ConfigReader,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://www.vufind.org  Main Page
  */
-class Options extends BaseOptions
+class Options extends \VuFind\Search\Base\Options
 {
     /**
      * Constructor
@@ -48,10 +46,21 @@ class Options extends BaseOptions
     public function __construct()
     {
         $this->searchIni = $this->facetsIni = 'WorldCat';
-        parent::__construct();
+    }
+
+    /**
+     * Perform initialization that cannot occur in constructor due to need for
+     * injected dependencies.
+     *
+     * @return void
+     */
+    public function init()
+    {
+        parent::init();
 
         // Load the configuration file:
-        $searchSettings = ConfigReader::getConfig($this->searchIni);
+        $searchSettings = $this->getServiceLocator()->get('VuFind\Config')
+            ->get($this->searchIni);
 
         // Search handler setup:
         $this->defaultHandler = 'srw.kw';
diff --git a/module/VuFind/src/VuFind/Search/WorldCat/Results.php b/module/VuFind/src/VuFind/Search/WorldCat/Results.php
index 1de96d6a9435fa5e9e95bc64761d53804b4261db..f8af4815e0bcbd5ca02360e87aac6aaf23721f44 100644
--- a/module/VuFind/src/VuFind/Search/WorldCat/Results.php
+++ b/module/VuFind/src/VuFind/Search/WorldCat/Results.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind\Search\WorldCat;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Exception\RecordMissing as RecordMissingException,
+use VuFind\Exception\RecordMissing as RecordMissingException,
     VuFind\Search\Base\Results as BaseResults;
 
 /**
@@ -65,7 +64,7 @@ class Results extends BaseResults
     protected function performSearch()
     {
         // Collect the search parameters:
-        $config = ConfigReader::getConfig();
+        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
         $wc = $this->getWorldCatConnection();
         $overrideQuery = $this->getParams()->getOverrideQuery();
         $query = empty($overrideQuery)
diff --git a/module/VuFind/src/VuFind/Session/File.php b/module/VuFind/src/VuFind/Session/File.php
index eaccf012e53078a342d550691a011abbc2548208..4d10d3b651a390f781eb53b3acf5631a4eb8a313 100644
--- a/module/VuFind/src/VuFind/Session/File.php
+++ b/module/VuFind/src/VuFind/Session/File.php
@@ -140,7 +140,10 @@ class File extends AbstractBase
 
         // Perform file-specific cleanup:
         $sess_file = $this->getPath() . '/sess_' . $sess_id;
-        return(unlink($sess_file));
+        if (file_exists($sess_file)) {
+            return(unlink($sess_file));
+        }
+        return true;
     }
 
     /**
@@ -160,4 +163,4 @@ class File extends AbstractBase
         }
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/module/VuFind/src/VuFind/Sitemap.php b/module/VuFind/src/VuFind/Sitemap.php
index c3b507f782c11fcccb30e354ef57cf95faba297f..b6e5b967b833903dc5aff1188c0715a8c86b11dd 100644
--- a/module/VuFind/src/VuFind/Sitemap.php
+++ b/module/VuFind/src/VuFind/Sitemap.php
@@ -26,8 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFind;
-use VuFind\Config\Reader as ConfigReader,
-    VuFind\Connection\Manager as ConnectionManager;
+use VuFind\Connection\Manager as ConnectionManager;
 
 /**
  * Class for generating sitemaps
@@ -40,25 +39,74 @@ use VuFind\Config\Reader as ConfigReader,
  */
 class Sitemap
 {
+    /**
+     * Base URL for site
+     *
+     * @var string
+     */
     protected $baseUrl;
+
+    /**
+     * Base URL for record
+     *
+     * @var string
+     */
     protected $resultUrl;
+
+    /**
+     * Sitemap configuration (sitemap.ini)
+     *
+     * @var \Zend\Config\Config
+     */
     protected $config;
+
+    /**
+     * Frequency of URL updates (always, daily, weekly, monthly, yearly, never)
+     *
+     * @var string
+     */
     protected $frequency;
+
+    /**
+     * URL entries per sitemap
+     *
+     * @var int
+     */
     protected $countPerPage;
+
+    /**
+     * Base path to sitemap files, including base filename
+     *
+     * @var string
+     */
     protected $fileStart;
+
+    /**
+     * Filename of sitemap index
+     *
+     * @var string
+     */
     protected $indexFile = false;
+
+    /**
+     * Warnings thrown during sitemap generation
+     *
+     * @var array
+     */
     protected $warnings = array();
 
     /**
      * Constructor
+     *
+     * @param string              $baseUrl VuFind base URL
+     * @param \Zend\Config\Config $config  Sitemap configuration settings
      */
-    public function __construct()
+    public function __construct($baseUrl, \Zend\Config\Config $config)
     {
         // Read Config file
-        $config = ConfigReader::getConfig();
-        $this->baseUrl = $config->Site->url;
+        $this->baseUrl = $baseUrl;
         $this->resultUrl = $this->baseUrl . '/Record/';
-        $this->config = ConfigReader::getConfig('sitemap');
+        $this->config = $config;
         $this->frequency = $this->config->Sitemap->frequency;
         $this->countPerPage = $this->config->Sitemap->countPerPage;
         $this->fileStart = $this->config->Sitemap->fileLocation . "/" .
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/AbstractSyndetics.php b/module/VuFind/src/VuFind/View/Helper/Root/AbstractSyndetics.php
index 6f7be7f91bf8f01ee5b2ca187ae30f4abd762775..0d1711aed8e3b59a324f877d34dfb2fa9a9f5a28 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/AbstractSyndetics.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/AbstractSyndetics.php
@@ -63,10 +63,12 @@ abstract class AbstractSyndetics extends AbstractHelper
 
     /**
      * Constructor
+     *
+     * @param \Zend\Config\Config $config VuFind configuration
      */
-    public function __construct()
+    public function __construct(\Zend\Config\Config $config)
     {
-        $this->config = \VuFind\Config\Reader::getConfig();
+        $this->config = $config;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/XSLT/Import/VuFind.php b/module/VuFind/src/VuFind/XSLT/Import/VuFind.php
index 648c210a5460c2221e24da4d90604a6660d665a3..ac6803e46b33c2af61304103a7c6d5373c1ebc45 100644
--- a/module/VuFind/src/VuFind/XSLT/Import/VuFind.php
+++ b/module/VuFind/src/VuFind/XSLT/Import/VuFind.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/importing_records Wiki
  */
 namespace VuFind\XSLT\Import;
-use DOMDocument, VuFind\Config\Reader as ConfigReader;
+use DOMDocument, VuFind\Config\Locator as ConfigLocator;
 
 /**
  * XSLT support class -- all methods of this class must be public and static;
@@ -41,6 +41,11 @@ use DOMDocument, VuFind\Config\Reader as ConfigReader;
  */
 class VuFind
 {
+    /**
+     * Service locator
+     *
+     * @var ServiceLocatorInterface
+     */
     protected static $serviceLocator;
 
     /**
@@ -66,6 +71,18 @@ class VuFind
             ->get('ChangeTracker');
     }
 
+    /**
+     * Get a configuration file.
+     *
+     * @param string $config Configuration name
+     *
+     * @return \Zend\Config\Config
+     */
+    public static function getConfig($config = 'config')
+    {
+        return static::$serviceLocator->get('VuFind\Config')->get($config);
+    }
+
     /**
      * Get the date/time of the first time this record was indexed.
      *
@@ -128,7 +145,7 @@ class VuFind
      */
     public static function getParser()
     {
-        $settings = ConfigReader::getConfig('fulltext');
+        $settings = static::getConfig('fulltext');
 
         // Is user preference explicitly set?
         if (isset($settings->General->parser)) {
@@ -158,12 +175,12 @@ class VuFind
      */
     public static function harvestWithParser($url)
     {
-        $parser = self::getParser();
+        $parser = static::getParser();
         switch (strtolower($parser)) {
         case 'aperture':
-            return self::harvestWithAperture($url);
+            return static::harvestWithAperture($url);
         case 'tika':
-            return self::harvestWithTika($url);
+            return static::harvestWithTika($url);
         default:
             // Ignore unrecognized parser option:
             return '';
@@ -183,7 +200,7 @@ class VuFind
         $method = "webcrawler"
     ) {
         // get the path to our sh/bat from the config
-        $settings = ConfigReader::getConfig('fulltext');
+        $settings = static::getConfig('fulltext');
         if (!isset($settings->Aperture->webcrawler)) {
             return '';
         }
@@ -214,7 +231,7 @@ class VuFind
         $xmlFile = tempnam('/tmp', 'apt');
 
         // Determine the base Aperture command (or fail if it is not configured):
-        $aptCmd = self::getApertureCommand($url, $xmlFile, $method);
+        $aptCmd = static::getApertureCommand($url, $xmlFile, $method);
         if (empty($aptCmd)) {
             return '';
         }
@@ -251,7 +268,7 @@ class VuFind
      */
     public static function getTikaCommand($input, $output, $arg)
     {
-        $settings = ConfigReader::getConfig('fulltext');
+        $settings = static::getConfig('fulltext');
         if (!isset($settings->Tika->path)) {
             return '';
         }
@@ -285,7 +302,7 @@ class VuFind
         $outputFile = tempnam('/tmp', 'tika');
 
         // Determine the base Tika command and execute
-        $tikaCommand = self::getTikaCommand($url, $outputFile, $arg);
+        $tikaCommand = static::getTikaCommand($url, $outputFile, $arg);
         proc_close(proc_open($tikaCommand[0], $tikaCommand[1], $tikaCommand[2]));
 
         // If we failed to process the file, give up now:
@@ -315,7 +332,7 @@ class VuFind
         // style of properties map, so we are parsing this manually.
         $map = array();
         $mapFile
-            = ConfigReader::getConfigPath($filename, 'import/translation_maps');
+            = ConfigLocator::getConfigPath($filename, 'import/translation_maps');
         foreach (file($mapFile) as $line) {
             $parts = explode('=', $line, 2);
             if (isset($parts[1])) {
@@ -405,7 +422,7 @@ class VuFind
             }
         }
 
-        return self::xmlAsText($in);
+        return static::xmlAsText($in);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/XSLT/Importer.php b/module/VuFind/src/VuFind/XSLT/Importer.php
index 1549c4d6fa80a23009d989a9c38ce90bc313def5..1e73d8f40455fec51624ac5947c8f1518e024812 100644
--- a/module/VuFind/src/VuFind/XSLT/Importer.php
+++ b/module/VuFind/src/VuFind/XSLT/Importer.php
@@ -26,7 +26,7 @@
  * @link     http://vufind.org/wiki/ Wiki
  */
 namespace VuFind\XSLT;
-use DOMDocument, VuFind\Config\Reader as ConfigReader,
+use DOMDocument, VuFind\Config\Locator as ConfigLocator,
     VuFind\Connection\Manager as ConnectionManager,
     XSLTProcessor, Zend\Console\Console,
     Zend\ServiceManager\ServiceLocatorAwareInterface,
@@ -88,7 +88,7 @@ class Importer implements ServiceLocatorAwareInterface
     protected function generateXML($xmlFile, $properties)
     {
         // Load properties file:
-        $properties = ConfigReader::getConfigPath($properties, 'import');
+        $properties = ConfigLocator::getConfigPath($properties, 'import');
         if (!file_exists($properties)) {
             throw new \Exception("Cannot load properties file: {$properties}.");
         }
@@ -100,7 +100,7 @@ class Importer implements ServiceLocatorAwareInterface
                 "Properties file ({$properties}) is missing General/xslt setting."
             );
         }
-        $xslFile = ConfigReader::getConfigPath(
+        $xslFile = ConfigLocator::getConfigPath(
             $options['General']['xslt'], 'import/xsl'
         );
 
diff --git a/module/VuFind/src/VuFindTest/Unit/DbTestCase.php b/module/VuFind/src/VuFindTest/Unit/DbTestCase.php
index b3a9a35769bbede9b21ce1f2136945e7752bc54d..960babca78b32eaf11a1cce73ca57db18d9f6111 100644
--- a/module/VuFind/src/VuFindTest/Unit/DbTestCase.php
+++ b/module/VuFind/src/VuFindTest/Unit/DbTestCase.php
@@ -52,9 +52,10 @@ abstract class DbTestCase extends TestCase
 
         // Add database service:
         if (!$sm->has('VuFind\DbTablePluginManager')) {
-            $sm->setService(
-                'VuFind\DbAdapter', \VuFind\Db\AdapterFactory::getAdapter()
+            $dbFactory = new \VuFind\Db\AdapterFactory(
+                $sm->get('VuFind\Config')->get('config')
             );
+            $sm->setService('VuFind\DbAdapter', $dbFactory->getAdapter());
             $factory = new \VuFind\Db\Table\PluginManager(
                 new \Zend\ServiceManager\Config(
                     array(
diff --git a/module/VuFind/src/VuFindTest/Unit/TestCase.php b/module/VuFind/src/VuFindTest/Unit/TestCase.php
index c7bc70dd657c547cfe3e656337761d4100ea68f5..04a6e1a99234f937acca537f5f8e191d29d62b37 100644
--- a/module/VuFind/src/VuFindTest/Unit/TestCase.php
+++ b/module/VuFind/src/VuFindTest/Unit/TestCase.php
@@ -136,6 +136,12 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
             $this->serviceManager->setService(
                 'VuFind\Http', new \VuFindHttp\HttpService()
             );
+            $cfg = new \Zend\ServiceManager\Config(
+                array('abstract_factories' => array('VuFind\Config\PluginFactory'))
+            );
+            $this->serviceManager->setService(
+                'VuFind\Config', new \VuFind\Config\PluginManager($cfg)
+            );
             \VuFind\Connection\Manager::setServiceLocator($this->serviceManager);
         }
         return $this->serviceManager;
@@ -153,16 +159,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
             $authManager = new \VuFind\Auth\PluginManager(
                 new \Zend\ServiceManager\Config(
                     array(
-                        'abstract_factories' =>
-                            array('VuFind\Auth\PluginFactory'),
-                        'factories' => array(
-                            'ils' => 
-                                function ($sm) {
-                                    return new \VuFind\Auth\ILS(
-                                        new \VuFind\ILS\Connection()
-                                    );
-                                },
-                        ),
+                        'abstract_factories' => array('VuFind\Auth\PluginFactory'),
                     )
                 )
             );
diff --git a/module/VuFind/tests/unit-tests/src/Auth/ILSTest.php b/module/VuFind/tests/unit-tests/src/Auth/ILSTest.php
index 4d9cd4da1a0ee4343c67317bf2eda4858735a843..53745533b7e063ce0a93dc2a69f25d4dde2fb219 100644
--- a/module/VuFind/tests/unit-tests/src/Auth/ILSTest.php
+++ b/module/VuFind/tests/unit-tests/src/Auth/ILSTest.php
@@ -48,8 +48,21 @@ class ILSTest extends \VuFindTest\Unit\DbTestCase
     public function __construct()
     {
         $this->driver = $this->getMock('VuFind\ILS\Driver\Sample');
-        $this->auth = $this->getAuthManager()->get('ILS');
-        $this->auth->getCatalog()->setDriver($this->driver);;
+        $driverManager = new \VuFind\ILS\Driver\PluginManager();
+        $driverManager->setService('Sample', $this->driver);
+        $mockConfigReader = $this->getMock('VuFind\Config\PluginManager');
+        $mockConfigReader->expects($this->any())->method('get')
+            ->will($this->returnValue(new \Zend\Config\Config(array())));
+        $this->auth = new \VuFind\Auth\ILS(
+            new \VuFind\ILS\Connection(
+                new \Zend\Config\Config(array('driver' => 'Sample')),
+                $driverManager, $mockConfigReader
+            )
+        );
+        $this->auth->setDbTableManager(
+            $this->getServiceManager()->get('VuFind\DbTablePluginManager')
+        );
+        $this->auth->getCatalog()->setDriver($this->driver);
     }
 
     /**
diff --git a/module/VuFind/tests/unit-tests/src/Config/ReaderTest.php b/module/VuFind/tests/unit-tests/src/Config/PluginFactoryTest.php
similarity index 80%
rename from module/VuFind/tests/unit-tests/src/Config/ReaderTest.php
rename to module/VuFind/tests/unit-tests/src/Config/PluginFactoryTest.php
index 9e078669e211bedbb2f8f45f078e05330419a71a..36817e66d618ffeb800b55a939cbd7f00fdb8434 100644
--- a/module/VuFind/tests/unit-tests/src/Config/ReaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/Config/PluginFactoryTest.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Config Reader Test Class
+ * Config Factory Test Class
  *
  * PHP version 5
  *
@@ -26,10 +26,10 @@
  * @link     http://vufind.org/wiki/vufind2:unit_tests Wiki
  */
 namespace VuFindTest\Config;
-use VuFind\Config\Reader;
+use VuFind\Config\Locator;
 
 /**
- * Config Reader Test Class
+ * Config Factory Test Class
  *
  * @category VuFind2
  * @package  Tests
@@ -38,7 +38,7 @@ use VuFind\Config\Reader;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/vufind2:unit_tests Wiki
  */
-class ReaderTest extends \VuFindTest\Unit\TestCase
+class PluginFactoryTest extends \VuFindTest\Unit\TestCase
 {
     /**
      * Flag -- did writing config files fail?
@@ -54,6 +54,13 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
      */
     protected static $filesToDelete = array();
 
+    /**
+     * Plugin factory instance.
+     *
+     * @var \VuFind\Config\PluginFactory
+     */
+    protected $factory;
+
     /**
      * Standard setup method.
      *
@@ -62,14 +69,14 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
     public static function setUpBeforeClass()
     {
         // Create test files:
-        $parentPath = Reader::getLocalConfigPath('unit-test-parent.ini', null, true);
+        $parentPath = Locator::getLocalConfigPath('unit-test-parent.ini', null, true);
         $parent = "[Section1]\n"
             . "a=1\nb=2\nc=3\n"
             . "[Section2]\n"
             . "d=4\ne=5\nf=6\n"
             . "[Section3]\n"
             . "g=7\nh=8\ni=9\n";
-        $childPath = Reader::getLocalConfigPath('unit-test-child.ini', null, true);
+        $childPath = Locator::getLocalConfigPath('unit-test-child.ini', null, true);
         $child = "[Section1]\n"
             . "j=10\nk=11\nl=12\n"
             . "[Section2]\n"
@@ -91,6 +98,29 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
         self::$filesToDelete = array($parentPath, $childPath);
     }
 
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        $this->factory = new \VuFind\Config\PluginFactory();
+    }
+
+    /**
+     * Wrapper around factory
+     *
+     * @param string $name Configuration to load
+     *
+     * @return \Zend\Config\Config
+     */
+    protected function getConfig($name)
+    {
+        return $this->factory->createServiceWithName(
+            $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'),
+            $name, $name
+        );
+    }
+
     /**
      * Test basic config.ini loading.
      *
@@ -100,7 +130,7 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
     {
         // This should retrieve config.ini, which should have "Library Catalog"
         // set as the default system title.
-        $config = Reader::getConfig();
+        $config = $this->getConfig('config');
         $this->assertEquals('Library Catalog', $config->Site->title);
     }
 
@@ -112,7 +142,7 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
     public function testCustomRead()
     {
         // This should retrieve sms.ini, which should include a Carriers array.
-        $config = Reader::getConfig('sms');
+        $config = $this->getConfig('sms');
         $this->assertTrue(isset($config->Carriers) && count($config->Carriers) > 0);
     }
 
@@ -128,7 +158,7 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
         }
 
         // Make sure load succeeds:
-        $config = Reader::getConfig('unit-test-child');
+        $config = $this->getConfig('unit-test-child');
         $this->assertTrue(is_object($config));
 
         // Make sure Section 1 was overridden; values from parent should not be
@@ -155,7 +185,7 @@ class ReaderTest extends \VuFindTest\Unit\TestCase
         if (self::$writeFailed) {
             $this->markTestSkipped('Could not write test configurations.');
         }
-        $config = Reader::getConfig('unit-test-parent');
+        $config = $this->getConfig('unit-test-parent');
         $this->setExpectedException('Zend\Config\Exception\RuntimeException');
         $config->Section1->z = 'bad';
     }
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php b/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php
index 726ae73cdd7888e6614cd84ecf6a9bf66e3e7cdb..dac8c25c1ccae6c1d46c7e2b568d35aef28516cd 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php
@@ -26,8 +26,7 @@
  * @link     http://vufind.org/wiki/vufind2:building_a_controller Wiki
  */
 namespace VuFindConsole\Controller;
-use VuFind\Config\Reader as ConfigReader, VuFind\Harvester\NAF, VuFind\Harvester\OAI,
-    Zend\Console\Console;
+use VuFind\Harvester\NAF, VuFind\Harvester\OAI, Zend\Console\Console;
 
 /**
  * This controller handles various command-line tools
@@ -77,7 +76,7 @@ class HarvestController extends AbstractBase
         $this->checkLocalSetting();
 
         // Read Config files
-        $configFile = ConfigReader::getConfigPath('oai.ini', 'harvest');
+        $configFile = \VuFind\Config\Locator::getConfigPath('oai.ini', 'harvest');
         $oaiSettings = @parse_ini_file($configFile, true);
         if (empty($oaiSettings)) {
             Console::writeLine("Please add OAI-PMH settings to oai.ini.");
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
index 83db78b6a18b5f9587aeac41c07ea02a6ceb160f..0a16b88a7dadcf6f268094485c7cf85352881c21 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
@@ -204,7 +204,10 @@ class UtilController extends AbstractBase
     public function sitemapAction()
     {
         // Build sitemap and display appropriate warnings if needed:
-        $generator = new Sitemap();
+        $configLoader = $this->getServiceLocator()->get('VuFind\Config');
+        $generator = new Sitemap(
+            $configLoader->get('config')->Site->url, $configLoader->get('sitemap')
+        );
         $generator->generate();
         foreach ($generator->getWarnings() as $warning) {
             Console::writeLine("$warning");
diff --git a/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php b/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php
index d7ada3d7c934e3a26637ad140f956e98a40923b2..6ec573a152af68368f4bbc63dbadb034034d4674 100644
--- a/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php
+++ b/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php
@@ -151,7 +151,7 @@ class DevtoolsController extends \VuFind\Controller\AbstractBase
      */
     public function getLangName($lang)
     {
-        $config = \VuFind\Config\Reader::getConfig();
+        $config = $this->getConfig();
         if (isset($config->Languages->$lang)) {
             return $config->Languages->$lang;
         }
diff --git a/themes/blueprint/templates/RecordTab/holdingsils.phtml b/themes/blueprint/templates/RecordTab/holdingsils.phtml
index 8eeec476b1f05b34e938e4820c54fc19ab2f5311..79e862bd3f57c3689618fc41dac1e331e84cd5d6 100644
--- a/themes/blueprint/templates/RecordTab/holdingsils.phtml
+++ b/themes/blueprint/templates/RecordTab/holdingsils.phtml
@@ -2,7 +2,7 @@
     // Set up convenience variables:
     $account = $this->auth()->getManager();
     $user = $account->isLoggedIn();
-    $holdings = $this->driver->getRealTimeHoldings($account);
+    $holdings = $this->driver->getRealTimeHoldings();
     $openUrl = $this->driver->openURLActive('holdings') ? $this->driver->getOpenURL() : false;
     $offlineMode = $this->ils()->getOfflineMode();
     // Account for replace_other_urls setting
@@ -20,7 +20,7 @@
     <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
   </div>
 <? endif; ?>
-<? if ((\VuFind\ILS\Connection::getHoldsMode() == 'driver' && !empty($holdings)) || \VuFind\ILS\Connection::getTitleHoldsMode() == 'driver'): ?>
+<? if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings)) || $this->ils()->getTitleHoldsMode() == 'driver'): ?>
   <? if ($account->loginEnabled() && $offlineMode != 'ils-offline'): ?>
     <? if (!$user): ?>
       <div class="info">
@@ -33,7 +33,7 @@
     <? endif; ?>
   <? endif; ?>
 <? endif; ?>
-<? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold', array($account)); if (!empty($holdingTitleHold)): ?>
+<? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold'); if (!empty($holdingTitleHold)): ?>
     <a class="holdPlace" href="<?=$this->recordLink()->getHoldUrl($holdingTitleHold)?>"><?=$this->transEsc('title_hold_place')?></a>
 <? endif; ?>
 <? if (!empty($urls) || $openUrl): ?>
diff --git a/themes/blueprint/templates/error/index.phtml b/themes/blueprint/templates/error/index.phtml
index a61370916b7164bbb4e72240217d2b44cb2f7af5..346120b6cc4c16ea4fa7471d1454f2516b1df7c7 100644
--- a/themes/blueprint/templates/error/index.phtml
+++ b/themes/blueprint/templates/error/index.phtml
@@ -8,7 +8,7 @@
   <p>
     <?=$this->transEsc('Please contact the Library Reference Department for assistance')?>
     <br/>
-    <? $supportEmail = $this->escapeHtml(\VuFind\Config\Reader::getConfig()->Site->email); ?>
+    <? $supportEmail = $this->escapeHtml($this->systememail()); ?>
     <a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a>
   </p>
 </div>
diff --git a/themes/jquerymobile/templates/RecordTab/holdingsils.phtml b/themes/jquerymobile/templates/RecordTab/holdingsils.phtml
index c80ed848e83bb4d0e283aac45caedcb92b19f764..66f3848768af9603bd6219b10b2fd145f26e7187 100644
--- a/themes/jquerymobile/templates/RecordTab/holdingsils.phtml
+++ b/themes/jquerymobile/templates/RecordTab/holdingsils.phtml
@@ -2,7 +2,7 @@
     // Set up convenience variables:
     $account = $this->auth()->getManager();
     $user = $account->isLoggedIn();
-    $holdings = $this->driver->getRealTimeHoldings($account);
+    $holdings = $this->driver->getRealTimeHoldings();
     $offlineMode = $this->ils()->getOfflineMode();
 
     // Set page title.
@@ -17,7 +17,7 @@
     <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
   </div>
 <? endif; ?>
-<? if ((\VuFind\ILS\Connection::getHoldsMode() == 'driver' && !empty($holdings)) || \VuFind\ILS\Connection::getTitleHoldsMode() == 'driver'): ?>
+<? if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings)) || $this->ils()->getTitleHoldsMode() == 'driver'): ?>
   <? if ($account->loginEnabled() && $offlineMode != 'ils-offline'): ?>
     <? if (!$user): ?>
       <div class="info">
@@ -30,7 +30,7 @@
     <? endif; ?>
   <? endif; ?>
 <? endif; ?>
-<? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold', array($account)); if (!empty($holdingTitleHold)): ?>
+<? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold'); if (!empty($holdingTitleHold)): ?>
     <a rel="external" class="holdPlace" href="<?=$this->recordLink()->getHoldUrl($holdingTitleHold, false)?>"><?=$this->transEsc('title_hold_place')?></a>
 <? endif; ?>
 <? foreach ($holdings as $location => $holding): ?>
diff --git a/themes/root/templates/Email/record-sms.phtml b/themes/root/templates/Email/record-sms.phtml
index 5bf63173fa150f959e6b4405bb234e3be002c20d..411c4ce214d00450b72f1e33a97d0602543b132d 100644
--- a/themes/root/templates/Email/record-sms.phtml
+++ b/themes/root/templates/Email/record-sms.phtml
@@ -7,7 +7,7 @@
     // since text messages can be short, and we want the most important stuff
     // at the top!
     if ($this->driver->supportsAjaxStatus()) {
-        $holdings = $this->driver->getRealTimeHoldings($this->auth()->getManager());
+        $holdings = $this->driver->getRealTimeHoldings();
 
         // Figure out which call number/location to display.  We'll try to find
         // a location with an available item that has a call number.  Failing that,
diff --git a/themes/root/theme.config.php b/themes/root/theme.config.php
index 0934d858f03de05af34af572ed82af190fb0f180..30803512ce468a1358f5d28c0135bb7f2b451d79 100644
--- a/themes/root/theme.config.php
+++ b/themes/root/theme.config.php
@@ -14,6 +14,11 @@ return array(
                     $sm->getServiceLocator()->get('VuFind\AuthManager')
                 );
             },
+            'authornotes' => function ($sm) {
+                return new \VuFind\View\Helper\Root\AuthorNotes(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
             'cart' => function ($sm) {
                 return new \VuFind\View\Helper\Root\Cart(
                     $sm->getServiceLocator()->get('VuFind\Cart')
@@ -34,6 +39,11 @@ return array(
                     $sm->getServiceLocator()->get('VuFind\Translator')
                 );
             },
+            'excerpt' => function ($sm) {
+                return new \VuFind\View\Helper\Root\Excerpt(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
             'export' => function ($sm) {
                 return new \VuFind\View\Helper\Root\Export(
                     $sm->getServiceLocator()->get('VuFind\Export')
@@ -71,6 +81,11 @@ return array(
                     $sm->getServiceLocator()->get('VuFind\RecordRouter')
                 );
             },
+            'reviews' => function ($sm) {
+                return new \VuFind\View\Helper\Root\Reviews(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
             'searchoptions' => function ($sm) {
                 return new VuFind\View\Helper\Root\SearchOptions(
                     $sm->getServiceLocator()->get('SearchManager')
@@ -88,14 +103,17 @@ return array(
                     isset($config->Site->email) ? $config->Site->email : ''
                 );
             },
+            'videoclips' => function ($sm) {
+                return new \VuFind\View\Helper\Root\VideoClips(
+                    $sm->getServiceLocator()->get('VuFind\Config')->get('config')
+                );
+            },
         ),
         'invokables' => array(
             'addellipsis' => 'VuFind\View\Helper\Root\AddEllipsis',
-            'authornotes' => 'VuFind\View\Helper\Root\AuthorNotes',
             'browse' => 'VuFind\View\Helper\Root\Browse',
             'context' => 'VuFind\View\Helper\Root\Context',
             'currentpath' => 'VuFind\View\Helper\Root\CurrentPath',
-            'excerpt' => 'VuFind\View\Helper\Root\Excerpt',
             'getlastsearchlink' => 'VuFind\View\Helper\Root\GetLastSearchLink',
             'highlight' => 'VuFind\View\Helper\Root\Highlight',
             'jqueryvalidation' => 'VuFind\View\Helper\Root\JqueryValidation',
@@ -104,7 +122,6 @@ return array(
             'related' => 'VuFind\View\Helper\Root\Related',
             'renderarray' => 'VuFind\View\Helper\Root\RenderArray',
             'resultfeed' => 'VuFind\View\Helper\Root\ResultFeed',
-            'reviews' => 'VuFind\View\Helper\Root\Reviews',
             'safemoneyformat' => 'VuFind\View\Helper\Root\SafeMoneyFormat',
             'sortfacetlist' => 'VuFind\View\Helper\Root\SortFacetList',
             'summon' => 'VuFind\View\Helper\Root\Summon',
@@ -112,7 +129,6 @@ return array(
             'translate' => 'VuFind\View\Helper\Root\Translate',
             'truncate' => 'VuFind\View\Helper\Root\Truncate',
             'userlist' => 'VuFind\View\Helper\Root\UserList',
-            'videoclips' => 'VuFind\View\Helper\Root\VideoClips',
         )
     ),
 );