From 6a211344ac41e0d85e9e5dfe15adea8926486b52 Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Wed, 27 Jun 2012 13:59:57 -0400
Subject: [PATCH] Implemented YAML loading; began some basic ConfigReader unit
 tests.

---
 module/VuFind/src/VuFind/Cache/Manager.php | 179 +++++++++++++++++++++
 module/VuFind/src/VuFind/Config/Reader.php |  25 +--
 module/VuFind/tests/Code/ISBNTest.php      |   2 +-
 module/VuFind/tests/Config/ReaderTest.php  |  83 ++++++++++
 4 files changed, 277 insertions(+), 12 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/Cache/Manager.php
 create mode 100644 module/VuFind/tests/Config/ReaderTest.php

diff --git a/module/VuFind/src/VuFind/Cache/Manager.php b/module/VuFind/src/VuFind/Cache/Manager.php
new file mode 100644
index 00000000000..091dfc36e0a
--- /dev/null
+++ b/module/VuFind/src/VuFind/Cache/Manager.php
@@ -0,0 +1,179 @@
+<?php
+/**
+ * VuFind Cache Manager
+ *
+ * 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  Support_Classes
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Cache;
+use VuFind\Config\Reader as ConfigReader,
+    Zend\Cache\StorageFactory, Zend\Registry;
+
+/**
+ * VuFind Cache Manager
+ *
+ * Creates file and APC caches
+ *
+ * @category VuFind2
+ * @package  Support_Classes
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class Manager
+{
+    protected $directoryCreationError = false;
+    protected $cacheSettings = array();
+    protected $caches = array();
+
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        // If we have a parent constructor, call it (none exists at the time of
+        // this writing, but this is just in case Zend Framework changes later).
+        if (is_callable($this, 'parent::__construct')) {
+            parent::__construct();
+        }
+
+        // Get base cache directory.
+        $cacheBase = $this->getCacheDir();
+
+        // Set up basic object cache:
+        $this->createFileCache('object', $cacheBase . 'objects');
+
+        // Set up language cache:
+        $this->createFileCache('language', $cacheBase . 'languages');
+
+        // Set up search specs cache based on config settings:
+        $config = ConfigReader::getConfig('searches');
+        $cacheSetting = isset($config->Cache->type) ? $config->Cache->type : false;
+        switch ($cacheSetting) {
+        case 'APC':
+            $this->createAPCCache('searchspecs');
+            break;
+        case 'File':
+            $this->createFileCache(
+                'searchspecs', $cacheBase . 'searchspecs'
+            );
+            break;
+        }
+    }
+
+    /**
+     * Retrieve the specified cache object.
+     *
+     * @param string $key Key identifying the requested cache.
+     *
+     * @return object
+     */
+    public function getCache($key)
+    {
+        if (!isset($this->caches[$key])) {
+            if (!isset($this->cacheSettings[$key])) {
+                throw new Exception('Requested unknown cache: ' . $key);
+            }
+            $this->caches[$key] = StorageFactory::factory(
+                $this->cacheSettings[$key]
+            );
+        }
+        return $this->caches[$key];
+    }
+
+    /**
+     * Get the path to the directory containing VuFind's cache data.
+     *
+     * @return string
+     */
+    public function getCacheDir()
+    {
+        if (strlen(LOCAL_OVERRIDE_DIR) > 0) {
+            return LOCAL_OVERRIDE_DIR . '/cache/';
+        }
+        return realpath(APPLICATION_PATH . '/../cache') . '/';
+    }
+
+    /**
+     * Check if there have been problems creating directories.
+     *
+     * @return bool
+     */
+    public function hasDirectoryCreationError()
+    {
+        return $this->directoryCreationError;
+    }
+
+    /**
+     * Add a file cache to the manager and ensure that necessary directory exists.
+     *
+     * @param string $cacheName    Name of new cache to create
+     * @param string $dirName      Directory to use for storage
+     *
+     * @return void
+     */
+    protected function createFileCache($cacheName, $dirName)
+    {
+        if (!is_dir($dirName)) {
+            if (!@mkdir($dirName)) {
+                $this->directoryCreationError = true;
+            }
+        }
+        $this->cacheSettings[$cacheName] = array(
+            'adapter' => array(
+                'name' => 'filesystem',
+                'options' => array('cache_dir' => $dirName)
+            ),
+            'plugins' => array('serializer')
+        );
+    }
+
+    /**
+     * Add an APC cache to the manager.
+     *
+     * @param string $cacheName    Name of new cache to create
+     *
+     * @return void
+     */
+    protected function createAPCCache($cacheName, $frontOptions)
+    {
+        $this->cacheSettings[$cacheName] = array(
+            'adapter' => 'APC',
+            'plugins' => array('serializer')
+        );
+    }
+
+    /**
+     * Get the current instance of the class.
+     *
+     * @return Manager
+     */
+    public static function getInstance()
+    {
+        $registry = Registry::getInstance();
+        if (!$registry->isRegistered('VF_Cache_Manager')) {
+            $registry->set('VF_Cache_Manager', new Manager());
+        }
+        return $registry->get('VF_Cache_Manager');
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Config/Reader.php b/module/VuFind/src/VuFind/Config/Reader.php
index 11536449d49..fb29f22baca 100644
--- a/module/VuFind/src/VuFind/Config/Reader.php
+++ b/module/VuFind/src/VuFind/Config/Reader.php
@@ -26,7 +26,9 @@
  * @link     http://vufind.org   Main Site
  */
 namespace VuFind\Config;
-use Zend\Config\Config,
+use Horde_Yaml as Yaml,
+    VuFind\Cache\Manager as CacheManager,
+    Zend\Config\Config,
     Zend\Config\Reader\Ini as IniReader;
 
 /**
@@ -144,14 +146,16 @@ class Reader
      * 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)
+    public static function loadConfigFile($filename, $path = 'config/vufind')
     {
         $configs = array();
 
-        $fullpath = self::getConfigPath($filename);
+        $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:
@@ -201,12 +205,11 @@ class Reader
      * @return array
      */
     public static function getSearchSpecs($filename)
-    {/*
+    {
         // Load data if it is not already in the object's static cache:
         if (!isset(self::$searchSpecs[$filename])) {
             // Connect to searchspecs cache:
-            $manager = new VF_Cache_Manager();
-            $cache = $manager->getCache('searchspecs');
+            $cache = CacheManager::getInstance()->getCache('searchspecs');
 
             // Determine full configuration file path:
             $fullpath = self::getBaseConfigPath($filename);
@@ -220,22 +223,22 @@ class Reader
             $key = md5($key);
 
             // Generate data if not found in cache:
-            if (!$cache || !($results = $cache->load($key))) {
-                $results = Horde_Yaml::load(file_get_contents($fullpath));
+            if (!$cache || !($results = $cache->getItem($key))) {
+                $results = Yaml::load(file_get_contents($fullpath));
                 if (!empty($local)) {
-                    $localResults = Horde_Yaml::load(file_get_contents($local));
+                    $localResults = Yaml::load(file_get_contents($local));
                     foreach ($localResults as $key => $value) {
                         $results[$key] = $value;
                     }
                 }
                 if ($cache) {
-                    $cache->save($results, $key);
+                    $cache->setItem($results, $key);
                 }
             }
             self::$searchSpecs[$filename] = $results;
         }
 
-        return self::$searchSpecs[$filename];*/
+        return self::$searchSpecs[$filename];
     }
 
     /**
diff --git a/module/VuFind/tests/Code/ISBNTest.php b/module/VuFind/tests/Code/ISBNTest.php
index bd49969fdf2..022734aca7a 100644
--- a/module/VuFind/tests/Code/ISBNTest.php
+++ b/module/VuFind/tests/Code/ISBNTest.php
@@ -25,7 +25,7 @@
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org/wiki/unit_tests Wiki
  */
-namespace VuFind\Tests;
+namespace VuFind\Tests\Code;
 use VuFind\Code\ISBN;
 
 /**
diff --git a/module/VuFind/tests/Config/ReaderTest.php b/module/VuFind/tests/Config/ReaderTest.php
new file mode 100644
index 00000000000..4b21767b32e
--- /dev/null
+++ b/module/VuFind/tests/Config/ReaderTest.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Config Reader Test Class
+ *
+ * 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  Tests
+ * @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/unit_tests Wiki
+ */
+namespace VuFind\Tests\Config;
+use VuFind\Config\Reader;
+
+/**
+ * Config Reader Test Class
+ *
+ * @category VuFind2
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/unit_tests Wiki
+ */
+class ReaderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Test basic config.ini loading.
+     *
+     * @return void
+     */
+    public function testBasicRead()
+    {
+        // This should retrieve config.ini, which should have "Library Catalog"
+        // set as the default system title.
+        $config = Reader::getConfig();
+        $this->assertEquals('Library Catalog', $config->Site->title);
+    }
+
+    /**
+     * Test loading of a custom .ini file.
+     *
+     * @return void
+     */
+    public function testCustomRead()
+    {
+        // This should retrieve sms.ini, which should include a Carriers array.
+        $config = Reader::getConfig('sms');
+        $this->assertTrue(isset($config->Carriers) && count($config->Carriers) > 0);
+    }
+
+    /**
+     * Test loading of a YAML file.
+     *
+     * @return void
+     */
+    public function testSearchSpecsRead()
+    {
+        // The searchspecs.yaml file should define author dismax fields (among many
+        // other things).
+        $specs = Reader::getSearchSpecs('searchspecs.yaml');
+        $this->assertTrue(
+            isset($specs['Author']['DismaxFields'])
+            && !empty($specs['Author']['DismaxFields'])
+        );
+    }
+}
\ No newline at end of file
-- 
GitLab