From 4bac766e3869edbf917e792d1a3b71346ade21a9 Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Wed, 27 Jun 2012 10:24:47 -0400 Subject: [PATCH] Began setting up unit testing infrastructure; ported over ISBN code as a first test case. --- module/VuFind/src/VuFind/Code/ISBN.php | 205 +++++++++++++++++++++++++ module/VuFind/tests/Code/ISBNTest.php | 123 +++++++++++++++ tests/bootstrap.php | 38 +++++ tests/phpunit.xml | 13 ++ 4 files changed, 379 insertions(+) create mode 100644 module/VuFind/src/VuFind/Code/ISBN.php create mode 100644 module/VuFind/tests/Code/ISBNTest.php create mode 100644 tests/bootstrap.php create mode 100644 tests/phpunit.xml diff --git a/module/VuFind/src/VuFind/Code/ISBN.php b/module/VuFind/src/VuFind/Code/ISBN.php new file mode 100644 index 00000000000..fda87d0dcab --- /dev/null +++ b/module/VuFind/src/VuFind/Code/ISBN.php @@ -0,0 +1,205 @@ +<?php +/** + * ISBN validation and conversion functionality + * + * PHP version 5 + * + * Copyright (c) Demian Katz 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 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\Code; + +/** + * ISBN Class + * + * This class provides ISBN validation and conversion functionality. + * + * @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 ISBN +{ + protected $raw; + protected $valid = null; + + /** + * Constructor + * + * @param string $raw Raw ISBN string to convert/validate. + */ + public function __construct($raw) + { + // Strip out irrelevant characters: + $this->raw = self::normalizeISBN($raw); + } + + /** + * Get the ISBN in ISBN-10 format: + * + * @return mixed ISBN, or false if invalid/incompatible. + */ + public function get10() + { + // Is it valid? + if ($this->isValid()) { + // Is it already an ISBN-10? If so, return as-is. + if (strlen($this->raw) == 10) { + return $this->raw; + } else if (strlen($this->raw) == 13 + && substr($this->raw, 0, 3) == '978' + ) { + // Is it a Bookland EAN? If so, we can convert to ISBN-10. + $start = substr($this->raw, 3, 9); + return $start . self::getISBN10CheckDigit($start); + } + } + + // If we made it this far, conversion was not possible: + return false; + } + + /** + * Get the ISBN in ISBN-13 format: + * + * @return mixed ISBN, or false if invalid/incompatible. + */ + public function get13() + { + // Is it valid? + if ($this->isValid()) { + // Is it already an ISBN-13? If so, return as-is. + if (strlen($this->raw) == 13) { + return $this->raw; + } else if (strlen($this->raw) == 10) { + // Is it an ISBN-10? If so, convert to Bookland EAN: + $start = '978' . substr($this->raw, 0, 9); + return $start . self::getISBN13CheckDigit($start); + } + } + + // If we made it this far, conversion was not possible: + return false; + } + + /** + * Is the current ISBN valid in some format? (May be 10 or 13 digit). + * + * @return boolean + */ + public function isValid() + { + // If we haven't already checked validity, do so now and store the result: + if (is_null($this->valid)) { + if (self::isValidISBN10($this->raw) + || self::isValidISBN13($this->raw) + ) { + $this->valid = true; + } else { + $this->valid = false; + } + } + return $this->valid; + } + + /** + * Strip extraneous characters and whitespace from an ISBN. + * + * @param string $raw ISBN to clean up. + * + * @return string Normalized ISBN. + */ + public static function normalizeISBN($raw) + { + return preg_replace('/[^0-9X]/', '', strtoupper($raw)); + } + + /** + * Given the first 9 digits of an ISBN-10, generate the check digit. + * + * @param string $isbn The first 9 digits of an ISBN-10. + * + * @return string The check digit. + */ + public static function getISBN10CheckDigit($isbn) + { + $sum = 0; + for ($x = 0; $x < strlen($isbn); $x++) { + $sum += intval(substr($isbn, $x, 1)) * (1 + $x); + } + $checkdigit = $sum % 11; + return $checkdigit == 10 ? 'X' : $checkdigit; + } + + /** + * Is the provided ISBN-10 valid? + * + * @param string $isbn The ISBN-10 to test. + * + * @return boolean + */ + public static function isValidISBN10($isbn) + { + $isbn = self::normalizeISBN($isbn); + if (strlen($isbn) != 10) { + return false; + } + return (substr($isbn, 9) == self::getISBN10CheckDigit(substr($isbn, 0, 9))); + } + + /** + * Given the first 12 digits of an ISBN-13, generate the check digit. + * + * @param string $isbn The first 12 digits of an ISBN-13. + * + * @return string The check digit. + */ + public static function getISBN13CheckDigit($isbn) + { + $sum = 0; + $weight = 1; + for ($x = 0; $x < strlen($isbn); $x++) { + $sum += intval(substr($isbn, $x, 1)) * $weight; + $weight = $weight == 1 ? 3 : 1; + } + $retval = 10 - ($sum % 10); + return $retval == 10 ? 0 : $retval; + } + + /** + * Is the provided ISBN-13 valid? + * + * @param string $isbn The ISBN-13 to test. + * + * @return boolean + */ + public static function isValidISBN13($isbn) + { + $isbn = self::normalizeISBN($isbn); + if (strlen($isbn) != 13) { + return false; + } + return + (substr($isbn, 12) == self::getISBN13CheckDigit(substr($isbn, 0, 12))); + } +} diff --git a/module/VuFind/tests/Code/ISBNTest.php b/module/VuFind/tests/Code/ISBNTest.php new file mode 100644 index 00000000000..bd49969fdf2 --- /dev/null +++ b/module/VuFind/tests/Code/ISBNTest.php @@ -0,0 +1,123 @@ +<?php +/** + * ISBN 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; +use VuFind\Code\ISBN; + +/** + * ISBN 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 ISBNTest extends \PHPUnit_Framework_TestCase +{ + /** + * Test Valid ISBN-10. + * + * @return void + */ + public function testValidISBN10() + { + $isbn = new ISBN('0123456789'); + $this->assertEquals($isbn->get10(), '0123456789'); + $this->assertEquals($isbn->get13(), '9780123456786'); + $this->assertTrue($isbn->isValid()); + } + + /** + * Test Valid ISBN-13. + * + * @return void + */ + public function testValidISBN13() + { + $isbn = new ISBN('9780123456786'); + $this->assertEquals($isbn->get10(), '0123456789'); + $this->assertEquals($isbn->get13(), '9780123456786'); + $this->assertTrue($isbn->isValid()); + } + + /** + * Test Valid ISBN-10 with dashes. + * + * @return void + */ + public function testValidISBN10WithDashes() + { + $isbn = new ISBN('0-12-345678-9'); + $this->assertEquals($isbn->get10(), '0123456789'); + $this->assertEquals($isbn->get13(), '9780123456786'); + $this->assertTrue($isbn->isValid()); + } + + /** + * Test Valid ISBN-13 with dashes. + * + * @return void + */ + public function testValidISBN13WithDashes() + { + // Valid ISBN-13 with dashes: + $isbn = new ISBN('978-0-12-345678-6'); + $this->assertEquals($isbn->get10(), '0123456789'); + $this->assertEquals($isbn->get13(), '9780123456786'); + $this->assertTrue($isbn->isValid()); + } + + /** + * Test Valid ISBN-13 that is not part of the Bookland EAN. + * + * @return void + */ + public function testValidISBN13OutsideOfBooklandEAN() + { + // Valid ISBN-13 outside of Bookland EAN: + $isbn = new ISBN('9790123456785'); + $this->assertEquals($isbn->get10(), false); + $this->assertEquals($isbn->get13(), '9790123456785'); + $this->assertTrue($isbn->isValid()); + } + + /** + * Test Invalid ISBN-10. + * + * @return void + */ + public function testInvalidISBN10() + { + // Invalid ISBN-10: + $isbn = new ISBN('2314346323'); + $this->assertEquals($isbn->get10(), false); + $this->assertEquals($isbn->get13(), false); + $this->assertFalse($isbn->isValid()); + } +} \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000000..d7c7afba72d --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,38 @@ +<?php +use Zend\Loader\AutoloaderFactory; +use Zend\ServiceManager\ServiceManager; +use Zend\Mvc\Service\ServiceManagerConfiguration; + +// Set flag that we're in test mode +define('VUFIND_PHPUNIT_RUNNING', 1); + +// Define path to application directory +defined('APPLICATION_PATH') + || define('APPLICATION_PATH', dirname(__DIR__)); + +// Define application environment +defined('APPLICATION_ENV') + || define('APPLICATION_ENV', (getenv('VUFIND_ENV') ? getenv('VUFIND_ENV') : 'testing')); + +// Define path to local override directory +defined('LOCAL_OVERRIDE_DIR') + || define('LOCAL_OVERRIDE_DIR', (getenv('VUFIND_LOCAL_DIR') ? getenv('VUFIND_LOCAL_DIR') : '')); + +chdir(APPLICATION_PATH); + +// Composer autoloading +if (file_exists('vendor/autoload.php')) { + $loader = include 'vendor/autoload.php'; +} + +if (!class_exists('Zend\Loader\AutoloaderFactory')) { + throw new RuntimeException('Unable to load ZF2.'); +} + +// Get application stack configuration +$configuration = include 'config/application.config.php'; + +// Setup service manager +$serviceManager = new ServiceManager(new ServiceManagerConfiguration($configuration['service_manager'])); +$serviceManager->setService('ApplicationConfiguration', $configuration); +$serviceManager->get('ModuleManager')->loadModules(); \ No newline at end of file diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 00000000000..78b63f11402 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,13 @@ +<phpunit bootstrap="./bootstrap.php" backupGlobals="false"> + <testsuites> + <testsuite name="VuFind"> + <directory>../module/VuFind/tests</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist addUncoveredFilesFromWhitelist="true"> + <directory suffix=".php">../module/VuFind/src</directory> + </whitelist> + </filter> +</phpunit> -- GitLab