diff --git a/vendor/File/MARC.php b/vendor/File/MARC.php new file mode 100644 index 0000000000000000000000000000000000000000..43de35bb4ed7e5b40db24b8c1420ba07382bbf04 --- /dev/null +++ b/vendor/File/MARC.php @@ -0,0 +1,385 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2010 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: MARC.php 308144 2011-02-08 20:28:20Z dbs $ + * @link http://pear.php.net/package/File_MARC + * @example read.php Retrieve specific fields and subfields from a record + * @example subfields.php Create new subfields and add them in specific order + * @example marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension + */ + +require_once 'PEAR/Exception.php'; +require_once 'Structures/LinkedList/Double.php'; +require_once 'File/MARCBASE.php'; +require_once 'File/MARC/Record.php'; +require_once 'File/MARC/Field.php'; +require_once 'File/MARC/Control_Field.php'; +require_once 'File/MARC/Data_Field.php'; +require_once 'File/MARC/Subfield.php'; +require_once 'File/MARC/Exception.php'; +require_once 'File/MARC/List.php'; + +// {{{ class File_MARC +/** + * The main File_MARC class enables you to return File_MARC_Record + * objects from a stream or string. + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC extends File_MARCBASE +{ + + // {{{ constants + + /** + * MARC records retrieved from a file + */ + const SOURCE_FILE = 1; + + /** + * MARC records retrieved from a binary string + */ + const SOURCE_STRING = 2; + + /** + * Hexadecimal value for Subfield indicator + */ + const SUBFIELD_INDICATOR = "\x1F"; + + /** + * Hexadecimal value for End of Field + */ + const END_OF_FIELD = "\x1E"; + + /** + * Hexadecimal value for End of Record + */ + const END_OF_RECORD = "\x1D"; + + /** + * Length of the Directory + */ + const DIRECTORY_ENTRY_LEN = 12; + + /** + * Length of the Leader + */ + const LEADER_LEN = 24; + + /** + * Maximum record length + */ + const MAX_RECORD_LENGTH = 99999; + // }}} + + // {{{ properties + /** + * Source containing raw records + * + * @var resource + */ + protected $source; + + /** + * Source type (SOURCE_FILE or SOURCE_STRING) + * + * @var int + */ + protected $type; + + /** + * XMLWriter for writing collections + * + * @var XMLWriter + */ + protected $xmlwriter; + // }}} + + // {{{ Constructor: function __construct() + /** + * Read in MARC records + * + * This function reads in MARC record files or strings that + * contain one or more MARC records. + * + * <code> + * <?php + * // Retrieve MARC records from a file + * $journals = new File_MARC('journals.mrc', SOURCE_FILE); + * + * // Retrieve MARC records from a string (e.g. Z39 query results) + * $monographs = new File_MARC($raw_marc, SOURCE_STRING); + * ?> + * </code> + * + * @param string $source Name of the file, or a raw MARC string + * @param int $type Source of the input, either SOURCE_FILE or SOURCE_STRING + */ + function __construct($source, $type = self::SOURCE_FILE) + { + + parent::__construct($source, $type); + + switch ($type) { + + case self::SOURCE_FILE: + $this->type = self::SOURCE_FILE; + $this->source = fopen($source, 'rb'); + if (!$this->source) { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE); + } + break; + + case self::SOURCE_STRING: + $this->type = self::SOURCE_STRING; + $this->source = explode(File_MARC::END_OF_RECORD, $source); + break; + + default: + throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE); + } + } + // }}} + + // {{{ nextRaw() + /** + * Return the next raw MARC record + * + * Returns the next raw MARC record, unless all records already have + * been read. + * + * @return string Either a raw record or false + */ + function nextRaw() + { + if ($this->type == self::SOURCE_FILE) { + $record = stream_get_line($this->source, File_MARC::MAX_RECORD_LENGTH, File_MARC::END_OF_RECORD); + + // Remove illegal stuff that sometimes occurs between records + $record = preg_replace('/^[\\x0a\\x0d\\x00]+/', "", $record); + + } elseif ($this->type == self::SOURCE_STRING) { + $record = array_shift($this->source); + } + + // Exit if we are at the end of the file + if (!$record) { + return false; + } + + // Append the end of record we lost during stream_get_line() or explode() + $record .= File_MARC::END_OF_RECORD; + return $record; + } + // }}} + + // {{{ next() + /** + * Return next {@link File_MARC_Record} object + * + * Decodes the next raw MARC record and returns the {@link File_MARC_Record} + * object. + * <code> + * <?php + * // Retrieve a set of MARC records from a file + * $journals = new File_MARC('journals.mrc', SOURCE_FILE); + * + * // Iterate through the retrieved records + * while ($record = $journals->next()) { + * print $record; + * print "\n"; + * } + * + * ?> + * </code> + * + * @return File_MARC_Record next record, or false if there are + * no more records + */ + function next() + { + $raw = $this->nextRaw(); + if ($raw) { + return $this->_decode($raw); + } else { + return false; + } + } + // }}} + + // {{{ _decode() + /** + * Decode a given raw MARC record + * + * Port of Andy Lesters MARC::File::USMARC->decode() Perl function into PHP. + * + * @param string $text Raw MARC record + * + * @return File_MARC_Record Decoded File_MARC_Record object + */ + private function _decode($text) + { + $marc = new File_MARC_Record($this); + + // fallback on the actual byte length + $record_length = strlen($text); + + $matches = array(); + if (preg_match("/^(\d{5})/", $text, $matches)) { + // Store record length + $record_length = $matches[1]; + if ($record_length != strlen($text)) { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INCORRECT_LENGTH], array("record_length" => $record_length, "actual" => strlen($text)))); + // Real beats declared byte length + $record_length = strlen($text); + } + } else { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NONNUMERIC_LENGTH], array("record_length" => substr($text, 0, 5)))); + } + + if (substr($text, -1, 1) != File_MARC::END_OF_RECORD) + throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TERMINATOR], File_MARC_Exception::ERROR_INVALID_TERMINATOR); + + // Store leader + $marc->setLeader(substr($text, 0, File_MARC::LEADER_LEN)); + + // bytes 12 - 16 of leader give offset to the body of the record + $data_start = 0 + substr($text, 12, 5); + + // immediately after the leader comes the directory (no separator) + $dir = substr($text, File_MARC::LEADER_LEN, $data_start - File_MARC::LEADER_LEN - 1); // -1 to allow for \x1e at end of directory + + // character after the directory must be \x1e + if (substr($text, $data_start-1, 1) != File_MARC::END_OF_FIELD) { + $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NO_DIRECTORY]); + } + + // All directory entries 12 bytes long, so length % 12 must be 0 + if (strlen($dir) % File_MARC::DIRECTORY_ENTRY_LEN != 0) { + $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_LENGTH]); + } + + // go through all the fields + $nfields = strlen($dir) / File_MARC::DIRECTORY_ENTRY_LEN; + for ($n=0; $n<$nfields; $n++) { + // As pack returns to key 1, leave place 0 in list empty + list(, $tag) = unpack("A3", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN)); + list(, $len) = unpack("A3/A4", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN)); + list(, $offset) = unpack("A3/A4/A5", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN)); + + // Check directory validity + if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG], array("tag" => $tag))); + } + if (!preg_match("/^\d{4}$/", $len)) { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG_LENGTH], array("tag" => $tag, "len" => $len))); + } + if (!preg_match("/^\d{5}$/", $offset)) { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_OFFSET], array("tag" => $tag, "offset" => $offset))); + } + if ($offset + $len > $record_length) { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY], array("tag" => $tag))); + } + + $tag_data = substr($text, $data_start + $offset, $len); + + if (substr($tag_data, -1, 1) == File_MARC::END_OF_FIELD) { + /* get rid of the end-of-tag character */ + $tag_data = substr($tag_data, 0, -1); + $len--; + } else { + $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_FIELD_EOF], array("tag" => $tag))); + } + + if (preg_match("/^\d+$/", $tag) and ($tag < 10)) { + $marc->appendField(new File_MARC_Control_Field($tag, $tag_data)); + } else { + $subfields = explode(File_MARC::SUBFIELD_INDICATOR, $tag_data); + $indicators = array_shift($subfields); + + if (strlen($indicators) != 2) { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATORS], array("tag" => $tag, "indicators" => $indicators)); + $marc->addWarning($errorMessage); + // Do the best with the indicators we've got + if (strlen($indicators) == 1) { + $ind1 = $indicators; + $ind2 = " "; + } else { + list($ind1,$ind2) = array(" ", " "); + } + } else { + $ind1 = substr($indicators, 0, 1); + $ind2 = substr($indicators, 1, 1); + } + + // Split the subfield data into subfield name and data pairs + $subfield_data = array(); + foreach ($subfields as $subfield) { + if (strlen($subfield) > 0) { + $subfield_data[] = new File_MARC_Subfield(substr($subfield, 0, 1), substr($subfield, 1)); + } else { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag)); + $marc->addWarning($errorMessage); + } + } + + if (!isset($subfield_data)) { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag)); + $marc->addWarning($errorMessage); + } + + + // If the data is invalid, let's just ignore the one field + try { + $new_field = new File_MARC_Data_Field($tag, $subfield_data, $ind1, $ind2); + $marc->appendField($new_field); + } catch (Exception $e) { + $marc->addWarning($e->getMessage()); + } + } + } + + return $marc; + } + // }}} + +} +// }}} + diff --git a/vendor/File/MARC/Control_Field.php b/vendor/File/MARC/Control_Field.php new file mode 100644 index 0000000000000000000000000000000000000000..bd29f94804cf52ff96d9f191de221c7e8261ff8a --- /dev/null +++ b/vendor/File/MARC/Control_Field.php @@ -0,0 +1,177 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Control_Field.php 301737 2010-07-31 04:14:44Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Control_Field extends File_MARC_Field +/** + * The File_MARC_Control_Field class represents a single control field + * in a MARC record. + * + * A MARC control field consists of a tag name and control data. + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Control_Field extends File_MARC_Field +{ + + // {{{ Properties + /** + * Value of field, if field is a Control field + * @var string + */ + protected $data; + // }}} + + // {{{ Constructor: function __construct() + /** + * Field init function + * + * Create a new {@link File_MARC_Control_Field} object from passed arguments + * + * @param string $tag tag + * @param string $data control field data + * @param string $ind1 placeholder for class strictness + * @param string $ind2 placeholder for class strictness + */ + function __construct($tag, $data, $ind1 = null, $ind2 = null) + { + $this->data = $data; + parent::__construct($tag); + + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Destroys the control field + */ + function __destruct() + { + $this->data = null; + parent::__destruct(); + } + // }}} + + // {{{ Explicit destructor: function delete() + /** + * Destroys the control field + * + * @return true + */ + function delete() + { + $this->__destruct(); + } + // }}} + + // {{{ getData() + /** + * Get control field data + * + * @return string returns data in control field + */ + function getData() + { + return (string)$this->data; + } + // }}} + + // {{{ isEmpty() + /** + * Is empty + * + * Checks if the field contains data + * + * @return bool Returns true if the field is empty, otherwise false + */ + function isEmpty() + { + return ($this->data) ? false : true; + } + // }}} + + // {{{ setData() + /** + * Set control field data + * + * @param string $data data for the control field + * + * @return bool returns the new data in the control field + */ + function setData($data) + { + $this->data = $data; + return $this->getData(); + } + // }}} + + // {{{ __toString() + /** + * Return as a formatted string + * + * Return the control field as a formatted string for pretty printing + * + * @return string Formatted output of control Field + */ + function __toString() + { + return sprintf("%3s %s", $this->tag, $this->data); + } + // }}} + + // {{{ toRaw() + /** + * Return as raw MARC + * + * Return the control field formatted in Raw MARC for saving into MARC files + * + * @return string Raw MARC + */ + function toRaw() + { + return (string)$this->data.File_MARC::END_OF_FIELD; + } + // }}} + +} +// }}} + diff --git a/vendor/File/MARC/Data_Field.php b/vendor/File/MARC/Data_Field.php new file mode 100644 index 0000000000000000000000000000000000000000..691e243c28273e9cfde0bb64001bcffb4eac1aad --- /dev/null +++ b/vendor/File/MARC/Data_Field.php @@ -0,0 +1,481 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Data_Field.php 301737 2010-07-31 04:14:44Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Data_Field extends File_MARC_Field +/** + * The File_MARC_Data_Field class represents a single field in a MARC record. + * + * A MARC data field consists of a tag name, two indicators which may be null, + * and zero or more subfields represented by {@link File_MARC_Subfield} objects. + * Subfields are held within a linked list structure. + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Data_Field extends File_MARC_Field +{ + + // {{{ properties + /** + * Value of the first indicator + * @var string + */ + protected $ind1; + + /** + * Value of the second indicator + * @var string + */ + protected $ind2; + + /** + * Linked list of subfields + * @var File_MARC_List + */ + protected $subfields; + + // }}} + + // {{{ Constructor: function __construct() + /** + * {@link File_MARC_Data_Field} constructor + * + * Create a new {@link File_MARC_Data_Field} object. The only required + * parameter is a tag. This enables programs to build up new fields + * programmatically. + * + * <code> + * // Example: Create a new data field + * + * // We can optionally create an array of subfields first + * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.'); + * + * // Create the new 100 field complete with a _a subfield and an indicator + * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null); + * </code> + * + * @param string $tag tag + * @param array $subfields array of {@link File_MARC_Subfield} objects + * @param string $ind1 first indicator + * @param string $ind2 second indicator + */ + function __construct($tag, array $subfields = null, $ind1 = null, $ind2 = null) + { + $this->subfields = new File_MARC_List(); + + parent::__construct($tag); + + $this->ind1 = $this->_validateIndicator($ind1); + $this->ind2 = $this->_validateIndicator($ind2); + + // we'll let users add subfields after if they so desire + if ($subfields) { + $this->addSubfields($subfields); + } + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Destroys the data field + */ + function __destruct() + { + $this->subfields = null; + $this->ind1 = null; + $this->ind2 = null; + parent::__destruct(); + } + // }}} + + // {{{ Explicit destructor: function delete() + /** + * Destroys the data field + * + * @return true + */ + function delete() + { + $this->__destruct(); + } + // }}} + + // {{{ protected function _validateIndicator() + /** + * Validates an indicator field + * + * Validates the value passed in for an indicator. This routine ensures + * that an indicator is a single character. If the indicator value is null, + * then this method returns a single character. + * + * If the indicator value contains more than a single character, this + * throws an exception. + * + * @param string $indicator Value of the indicator to be validated + * + * @return string Returns the indicator, or space if the indicator was null + */ + private function _validateIndicator($indicator) + { + if ($indicator == null) { + $indicator = ' '; + } elseif (strlen($indicator) > 1) { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR], array("tag" => $this->getTag(), "indicator" => $indicator)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR); + } + return $indicator; + } + // }}} + + // {{{ appendSubfield() + /** + * Appends subfield to subfield list + * + * Adds a File_MARC_Subfield object to the end of the existing list + * of subfields. + * + * @param File_MARC_Subfield $new_subfield The subfield to add + * + * @return File_MARC_Subfield the new File_MARC_Subfield object + */ + function appendSubfield(File_MARC_Subfield $new_subfield) + { + /* Append as the last field in the record */ + $this->subfields->appendNode($new_subfield); + return $new_subfield; + } + // }}} + + // {{{ prependSubfield() + /** + * Prepends subfield to subfield liss + * + * Adds a File_MARC_Subfield object to the start of the existing list + * of subfields. + * + * @param File_MARC_Subfield $new_subfield The subfield to add + * + * @return File_MARC_Subfield the new File_MARC_Subfield object + */ + function prependSubfield(File_MARC_Subfield $new_subfield) + { + $this->subfields->prependNode($new_subfield); + return $new_subfield; + } + // }}} + + // {{{ insertSubfield() + /** + * Inserts a field in the MARC record relative to an existing field + * + * Inserts a {@link File_MARC_Subfield} object before or after an existing + * subfield. + * + * @param File_MARC_Subfield $new_field The subfield to add + * @param File_MARC_Subfield $existing_field The target subfield + * @param bool $before Insert the subfield before the existing subfield if true; after the existing subfield if false + * + * @return File_MARC_Subfield The new subfield + */ + function insertSubfield(File_MARC_Subfield $new_field, File_MARC_Subfield $existing_field, $before = false) + { + switch ($before) { + /* Insert before the specified subfield in the record */ + case true: + $this->subfields->insertNode($new_field, $existing_field, true); + break; + + /* Insert after the specified subfield in the record */ + case false: + $this->subfields->insertNode($new_field, $existing_field); + break; + + default: + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INSERTSUBFIELD_MODE], array("mode" => $mode)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INSERTSUBFIELD_MODE); + return false; + } + return $new_field; + } + // }}} + + // {{{ addSubfields() + /** + * Adds an array of subfields to a {@link File_MARC_Data_Field} object + * + * Appends subfields to existing subfields in the order in which + * they appear in the array. For finer grained control of the subfield + * order, use {@link appendSubfield()}, {@link prependSubfield()}, + * or {@link insertSubfield()} to add each subfield individually. + * + * @param array $subfields array of {@link File_MARC_Subfield} objects + * + * @return int returns the number of subfields that were added + */ + function addSubfields(array $subfields) + { + /* + * Just in case someone passes in a single File_MARC_Subfield + * instead of an array + */ + if ($subfields instanceof File_MARC_Subfield) { + $this->appendSubfield($subfields); + return 1; + } + + // Add subfields + $cnt = 0; + foreach ($subfields as $subfield) { + $this->appendSubfield($subfield); + $cnt++; + } + + return $cnt; + } + // }}} + + // {{{ deleteSubfield() + /** + * Delete a subfield from the field. + * + * @param File_MARC_Subfield $subfield The subfield to delete + * + * @return bool Success or failure + */ + function deleteSubfield(File_MARC_Subfield $subfield) + { + if ($this->subfields->deleteNode($subfield)) { + return true; + } + return false; + } + // }}} + + // {{{ getIndicator() + /** + * Get the value of an indicator + * + * @param int $ind number of the indicator (1 or 2) + * + * @return string returns indicator value if it exists, otherwise false + */ + function getIndicator($ind) + { + if ($ind == 1) { + return (string)$this->ind1; + } elseif ($ind == 2) { + return (string)$this->ind2; + } else { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $indicator)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST); + } + return false; + } + // }}} + + // {{{ setIndicator() + /** + * Set the value of an indicator + * + * @param int $ind number of the indicator (1 or 2) + * @param string $value value of the indicator + * + * @return string returns indicator value if it exists, otherwise false + */ + function setIndicator($ind, $value) + { + switch ($ind) { + + case 1: + $this->ind1 = $this->_validateIndicator($value); + break; + + case 2: + $this->ind2 = $this->_validateIndicator($value); + break; + + default: + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $ind)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST); + return false; + } + + return $this->getIndicator($ind); + } + // }}} + + // {{{ getSubfield() + /** + * Returns the first subfield that matches a requested code. + * + * @param string $code subfield code for which the + * {@link File_MARC_Subfield} is retrieved + * + * @return File_MARC_Subfield returns the first subfield that matches + * $code, or false if no codes match $code + */ + function getSubfield($code = null) + { + // iterate merrily through the subfields looking for the requested code + foreach ($this->subfields as $sf) { + if ($sf->getCode() == $code) { + return $sf; + } + } + + // No matches were found + return false; + } + // }}} + + // {{{ getSubfields() + /** + * Returns an array of subfields that match a requested code, + * or a {@link File_MARC_List} that contains all of the subfields + * if the requested code is null. + * + * @param string $code subfield code for which the + * {@link File_MARC_Subfield} is retrieved + * + * @return File_MARC_List|array returns a linked list of all subfields + * if $code is null, an array of {@link File_MARC_Subfield} objects if + * one or more subfields match, or false if no codes match $code + */ + function getSubfields($code = null) + { + $results = array(); + + // return all subfields if no specific subfields were requested + if ($code === null) { + $results = $this->subfields; + return $results; + } + + // iterate merrily through the subfields looking for the requested code + foreach ($this->subfields as $sf) { + if ($sf->getCode() == $code) { + $results[] = $sf; + } + } + return $results; + } + // }}} + + // {{{ isEmpty() + /** + * Checks if the field is empty. + * + * Checks if the field is empty. If the field has at least one subfield + * with data, it is not empty. + * + * @return bool Returns true if the field is empty, otherwise false + */ + function isEmpty() + { + // If $this->subfields is null, we must have deleted it + if (!$this->subfields) { + return true; + } + + // Iterate through the subfields looking for some data + foreach ($this->subfields as $subfield) { + // Check if subfield has data + if (!$subfield->isEmpty()) { + return false; + } + } + // It is empty + return true; + } + // }}} + + /** + * ========== OUTPUT METHODS ========== + */ + + // {{{ __toString() + /** + * Return Field formatted + * + * Return Field as a formatted string. + * + * @return string Formatted output of Field + */ + function __toString() + { + // Variables + $lines = array(); + // Process tag and indicators + $pre = sprintf("%3s %1s%1s", $this->tag, $this->ind1, $this->ind2); + + // Process subfields + foreach ($this->subfields as $subfield) { + $lines[] = sprintf("%6s _%1s%s", $pre, $subfield->getCode(), $subfield->getData()); + $pre = ""; + } + + return join("\n", $lines); + } + // }}} + + // {{{ toRaw() + /** + * Return Field in Raw MARC + * + * Return the Field formatted in Raw MARC for saving into MARC files + * + * @return string Raw MARC + */ + function toRaw() + { + $subfields = array(); + foreach ($this->subfields as $subfield) { + if (!$subfield->isEmpty()) { + $subfields[] = $subfield->toRaw(); + } + } + return (string)$this->ind1.$this->ind2.implode("", $subfields).File_MARC::END_OF_FIELD; + } + // }}} +} +// }}} + diff --git a/vendor/File/MARC/Exception.php b/vendor/File/MARC/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..48f521c2c30fc2bbf7ebca240fe2dc39203f4c0b --- /dev/null +++ b/vendor/File/MARC/Exception.php @@ -0,0 +1,214 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Exception.php 268035 2008-10-30 17:01:14Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Exception extends PEAR_Exception +/** + * The File_MARC_Exception class enables error-handling + * for the File_MARC package. + * + * @category File_Formats + * @package File_MARC + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Exception extends PEAR_Exception +{ + // {{{ Error codes + /** + * File could not be opened + */ + const ERROR_INVALID_FILE = -1; + + /** + * User passed an unknown SOURCE_ constant + */ + const ERROR_INVALID_SOURCE = -2; + + /** + * MARC record ended with an invalid terminator + */ + const ERROR_INVALID_TERMINATOR = -3; + + /** + * No directory was found for the MARC record + */ + const ERROR_NO_DIRECTORY = -4; + + /** + * An entry in the MARC directory was not 12 bytes + */ + const ERROR_INVALID_DIRECTORY_LENGTH = -5; + + /** + * An entry in the MARC directory specified an invalid tag + */ + const ERROR_INVALID_DIRECTORY_TAG = -6; + + /** + * An entry in the MARC directory specified an invalid tag length + */ + const ERROR_INVALID_DIRECTORY_TAG_LENGTH = -7; + + /** + * An entry in the MARC directory specified an invalid field offset + */ + const ERROR_INVALID_DIRECTORY_OFFSET = -8; + + /** + * An entry in the MARC directory runs past the end of the record + */ + const ERROR_INVALID_DIRECTORY = -9; + + /** + * A field does not end with the expected end-of-field character + */ + const ERROR_FIELD_EOF = -10; + + /** + * A field has invalid indicators + */ + const ERROR_INVALID_INDICATORS = -11; + + /** + * A subfield is defined, but has no data + */ + const ERROR_EMPTY_SUBFIELD = -12; + + /** + * An indicator other than 1 or 2 was requested + */ + const ERROR_INVALID_INDICATOR_REQUEST = -13; + + /** + * An invalid mode for adding a field was specified + */ + const ERROR_INSERTFIELD_MODE = -14; + + /** + * An invalid object was passed instead of a File_MARC_Field object + */ + const ERROR_INVALID_FIELD = -15; + + /** + * An invalid object was passed instead of a File_MARC_Subfield object + */ + const ERROR_INVALID_SUBFIELD = -16; + + /** + * An invalid mode for adding a subfield was specified + */ + const ERROR_INSERTSUBFIELD_MODE = -17; + + /** + * The length in the MARC leader does not match the actual record length + */ + const ERROR_INCORRECT_LENGTH = -18; + + /** + * The length field in the leader was less than five characters long + */ + const ERROR_MISSING_LENGTH = -19; + + /** + * A five-digit length could not be found in the MARC leader + */ + const ERROR_NONNUMERIC_LENGTH = -20; + + /** + * Tag does not adhere to MARC standards + */ + const ERROR_INVALID_TAG = -21; + + /** + * A field has invalid indicators + */ + const ERROR_INVALID_INDICATOR = -22; + // }}} + + // {{{ error messages + public static $messages = array( + self::ERROR_EMPTY_SUBFIELD => 'No subfield data found in tag "%tag%"', + self::ERROR_FIELD_EOF => 'Field for tag "%tag%" does not end with an end of field character', + self::ERROR_INCORRECT_LENGTH => 'Invalid record length: Leader says "%record_length%" bytes; actual record length is "%actual%"', + self::ERROR_INSERTFIELD_MODE => 'insertField() mode "%mode%" was not recognized', + self::ERROR_INSERTSUBFIELD_MODE => 'insertSubfield() mode "%mode%" was not recognized', + self::ERROR_INVALID_DIRECTORY => 'Directory entry for tag "%tag%" runs past the end of the record', + self::ERROR_INVALID_DIRECTORY_LENGTH => 'Invalid directory length', + self::ERROR_INVALID_DIRECTORY_OFFSET => 'Invalid offset "%offset%" for tag "%tag%" in directory', + self::ERROR_INVALID_DIRECTORY_TAG => 'Invalid tag "%tag%" in directory', + self::ERROR_INVALID_DIRECTORY_TAG_LENGTH => 'Invalid length "%len%" in directory for tag "%tag%"', + self::ERROR_INVALID_FIELD => 'Specified field must be a File_MARC_Data_Field or File_MARC_Control_Field object, but was "%field%"', + self::ERROR_INVALID_FILE => 'Invalid input file "%filename%"', + self::ERROR_INVALID_INDICATOR_REQUEST => 'Attempt to access indicator "%indicator%" failed; 1 and 2 are the only valid indicators', + self::ERROR_INVALID_INDICATORS => 'Invalid indicators "%indicators%" forced to blanks for tag "%tag%"', + self::ERROR_INVALID_SOURCE => "Invalid source for MARC records", + self::ERROR_INVALID_SUBFIELD => 'Specified field must be a File_MARC_Subfield object, but was "%class%"', + self::ERROR_INVALID_TAG => 'Tag "%tag%" is not a valid tag.', + self::ERROR_INVALID_TERMINATOR => 'Invalid record terminator', + self::ERROR_MISSING_LENGTH => "Couldn't find record length", + self::ERROR_NO_DIRECTORY => 'No directory found', + self::ERROR_NONNUMERIC_LENGTH => 'Record length "%record_length%" is not numeric', + self::ERROR_INVALID_INDICATOR => 'Illegal indicator "%indicator%" in field "%tag%" forced to blank', + ); + // }}} + + // {{{ formatError() + /** + * Replaces placeholder tokens in an error message with actual values. + * + * This method enables you to internationalize the messages for the + * File_MARC class by simply replacing the File_MARC_Exception::$messages + * array with translated values for the messages. + * + * @param string $message Error message containing placeholders + * @param array $errorValues Actual values to substitute for placeholders + * + * @return string Formatted message + */ + public static function formatError($message, $errorValues) + { + foreach ($errorValues as $token => $value) { + $message = preg_replace("/\%$token\%/", $value, $message); + } + return $message; + } + // }}} +} +// }}} + diff --git a/vendor/File/MARC/Field.php b/vendor/File/MARC/Field.php new file mode 100644 index 0000000000000000000000000000000000000000..85883b2448618ab346fb35c14ada4d1e5af72bdd --- /dev/null +++ b/vendor/File/MARC/Field.php @@ -0,0 +1,241 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Field.php 301737 2010-07-31 04:14:44Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Field extends Structures_LinkedList_DoubleNode +/** + * The File_MARC_Field class is expected to be extended to reflect the + * requirements of control and data fields. + * + * Every MARC field contains a tag name. + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Field extends Structures_LinkedList_DoubleNode +{ + + // {{{ properties + /** + * The tag name of the Field + * @var string + */ + protected $tag; + // }}} + + // {{{ Constructor: function __construct() + /** + * File_MARC_Field constructor + * + * Create a new {@link File_MARC_Field} object from passed arguments. We + * define placeholders for the arguments required by child classes. + * + * @param string $tag tag + * @param string $subfields placeholder for subfields or control data + * @param string $ind1 placeholder for first indicator + * @param string $ind2 placeholder for second indicator + */ + function __construct($tag, $subfields = null, $ind1 = null, $ind2 = null) + { + $this->tag = $tag; + + // Check if valid tag + if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TAG], array("tag" => $tag)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_TAG); + } + + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Destroys the data field + */ + function __destruct() + { + $this->tag = null; + parent::__destruct(); + } + // }}} + + // {{{ getTag() + /** + * Returns the tag for this {@link File_MARC_Field} object + * + * @return string returns the tag number of the field + */ + function getTag() + { + return (string)$this->tag; + } + // }}} + + // {{{ setTag() + /** + * Sets the tag for this {@link File_MARC_Field} object + * + * @param string $tag new value for the tag + * + * @return string returns the tag number of the field + */ + function setTag($tag) + { + $this->tag = $tag; + return $this->getTag(); + } + // }}} + + // {{{ isEmpty() + /** + * Is empty + * + * Checks if the field is empty. + * + * @return bool Returns true if the field is empty, otherwise false + */ + function isEmpty() + { + if ($this->getTag()) { + return false; + } + // It is empty + return true; + } + // }}} + + // {{{ isControlField() + /** + * Is control field + * + * Checks if the field is a control field. + * + * @return bool Returns true if the field is a control field, otherwise false + */ + function isControlField() + { + if (get_class($this) == 'File_MARC_Control_Field') { + return true; + } + return false; + } + // }}} + + // {{{ isDataField() + /** + * Is data field + * + * Checks if the field is a data field. + * + * @return bool Returns true if the field is a data field, otherwise false + */ + function isDataField() + { + if (get_class($this) == 'File_MARC_Data_Field') { + return true; + } + return false; + } + // }}} + + + /** + * ========== OUTPUT METHODS ========== + */ + + // {{{ __toString() + /** + * Return Field formatted + * + * Return Field as a formatted string. + * + * @return string Formatted output of Field + */ + function __toString() + { + return (string)$this->getTag(); + } + // }}} + + // {{{ toRaw() + /** + * Return field in raw MARC format (stub) + * + * Return the field formatted in raw MARC for saving into MARC files. This + * stub method is extended by the child classes. + * + * @return bool Raw MARC + */ + function toRaw() + { + return false; + } + // }}} + + // {{{ formatField() + /** + * Pretty print a MARC_Field object without tags, indicators, etc. + * + * @param array $exclude Subfields to exclude from formatted output + * + * @return string Returns the formatted field data + */ + + function formatField($exclude = array('2')) + { + if ($this->isControlField()) { + return $this->getData(); + } else { + $out = ''; + foreach ($this->getSubfields() as $subfield) { + if (substr($this->getTag(), 0, 1) == '6' and (in_array($subfield->getCode(), array('v','x','y','z')))) { + $out .= ' -- ' . $subfield->getData(); + } elseif (!in_array($subfield->getCode(), $exclude)) { + $out .= ' ' . $subfield->getData(); + } + } + return trim($out); + } + } + // }}} +} +// }}} + diff --git a/vendor/File/MARC/Lint.php b/vendor/File/MARC/Lint.php new file mode 100644 index 0000000000000000000000000000000000000000..67705570b41ee9f14bce63ef1c559b2e59a4a96a --- /dev/null +++ b/vendor/File/MARC/Lint.php @@ -0,0 +1,3750 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Lint for MARC records + * + * This module is adapted from the MARC::Lint CPAN module for Perl, maintained by + * Bryan Baldus <eijabb@cpan.org> and available at http://search.cpan.org/~eijabb/ + * + * Current MARC::Lint version used as basis for this module: 1.44 + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Demian Katz <demian.katz@villanova.edu> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ +require_once 'File/MARC/Lint/CodeData.php'; +require_once 'Validate/ISPN.php'; + +// {{{ class File_MARC_Lint +/** + * Class for testing validity of MARC records against MARC21 standard. + * + * @category File_Formats + * @package File_MARC + * @author Demian Katz <demian.katz@villanova.edu> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Lint +{ + + // {{{ properties + /** + * Rules used for testing records + * @var array + */ + protected $rules; + + /** + * A File_MARC_Lint_CodeData object for validating codes + * @var File_MARC_Lint_CodeData + */ + protected $data; + + /** + * Warnings generated during analysis + * @var array + */ + protected $warnings = array(); + + // }}} + + // {{{ Constructor: function __construct() + /** + * Start function + * + * Set up rules for testing MARC records. + * + * @return true + */ + public function __construct() + { + $this->parseRules(); + $this->data = new File_MARC_Lint_CodeData(); + } + // }}} + + // {{{ getWarnings() + /** + * Check the provided MARC record and return an array of warning messages. + * + * @param File_MARC_Record $marc Record to check + * + * @return array + */ + public function checkRecord($marc) + { + // Reset warnings: + $this->warnings = array(); + + // Fail if we didn't get a valid object: + if (!is_a($marc, 'File_MARC_Record')) { + $this->warn('Must pass a File_MARC_Record object to checkRecord'); + } else { + $this->checkDuplicate1xx($marc); + $this->checkMissing245($marc); + $this->standardFieldChecks($marc); + } + + return $this->warnings; + } + // }}} + + // {{{ warn() + /** + * Add a warning. + * + * @param string $warning Warning to add + * + * @return void + */ + protected function warn($warning) + { + $this->warnings[] = $warning; + } + // }}} + + // {{{ checkDuplicate1xx() + /** + * Check for multiple 1xx fields. + * + * @param File_MARC_Record $marc Record to check + * + * @return void + */ + protected function checkDuplicate1xx($marc) + { + $result = $marc->getFields('1[0-9][0-9]', true); + $count = count($result); + if ($count > 1) { + $this->warn( + "1XX: Only one 1XX tag is allowed, but I found $count of them." + ); + } + } + // }}} + + // {{{ checkMissing245() + /** + * Check for missing 245 field. + * + * @param File_MARC_Record $marc Record to check + * + * @return void + */ + protected function checkMissing245($marc) + { + $result = $marc->getFields('245'); + if (count($result) == 0) { + $this->warn('245: No 245 tag.'); + } + } + // }}} + + // {{{ standardFieldChecks() + /** + * Check all fields against the standard rules encoded in the class. + * + * @param File_MARC_Record $marc Record to check + * + * @return void + */ + protected function standardFieldChecks($marc) + { + $fieldsSeen = array(); + foreach ($marc->getFields() as $current) { + $tagNo = $current->getTag(); + // if 880 field, inherit rules from tagno in subfield _6 + if ($tagNo == 880) { + if ($sub6 = $current->getSubfield(6)) { + $tagNo = substr($sub6->getData(), 0, 3); + $tagrules = isset($this->rules[$tagNo]) + ? $this->rules[$tagNo] : null; + // 880 is repeatable, but its linked field may not be + if (isset($tagrules['repeatable']) + && $tagrules['repeatable'] == 'NR' + && isset($fieldsSeen['880.'.$tagNo]) + ) { + $this->warn("$tagNo: Field is not repeatable."); + } + $fieldsSeen['880.'.$tagNo] = isset($fieldsSeen['880.'.$tagNo]) + ? $fieldsSeen['880.'.$tagNo] + 1 : 1; + } else { + $this->warn("880: No subfield 6."); + $tagRules = null; + } + } else { + // Default case -- not an 880 field: + $tagrules = isset($this->rules[$tagNo]) + ? $this->rules[$tagNo] : null; + if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR' + && isset($fieldsSeen[$tagNo]) + ) { + $this->warn("$tagNo: Field is not repeatable."); + } + $fieldsSeen[$tagNo] = isset($fieldsSeen[$tagNo]) + ? $fieldsSeen[$tagNo] + 1 : 1; + } + + // Treat data fields differently from control fields: + if (intval(ltrim($tagNo, '0')) >= 10) { + if (!empty($tagrules)) { + $this->checkIndicators($tagNo, $current, $tagrules); + $this->checkSubfields($tagNo, $current, $tagrules); + } + } else { + // Control field: + if (strstr($current->toRaw(), chr(hexdec('1F')))) { + $this->warn( + "$tagNo: Subfields are not allowed in fields lower than 010" + ); + } + } + + // Check to see if a checkxxx() function exists, and call it on the + // field if it does + $method = 'check' . $tagNo; + if (method_exists($this, $method)) { + $this->$method($current); + } + } + } + // }}} + + // {{{ checkIndicators() + /** + * Check the indicators for the provided field. + * + * @param string $tagNo Tag number being checked + * @param File_MARC_Field $field Field to check + * @param array $rules Rules to use for checking + * + * @return void + */ + protected function checkIndicators($tagNo, $field, $rules) + { + for ($i = 1; $i <= 2; $i++) { + $ind = $field->getIndicator($i); + if ($ind === false || $ind == ' ') { + $ind = 'b'; + } + if (!strstr($rules['ind' . $i]['values'], $ind)) { + // Make indicator blank value human-readable for message: + if ($ind == 'b') { + $ind = 'blank'; + } + $this->warn( + "$tagNo: Indicator $i must be " + . $rules['ind' . $i]['hr_values'] + . " but it's \"$ind\"" + ); + } + } + } + // }}} + + // {{{ checkSubfields() + /** + * Check the subfields for the provided field. + * + * @param string $tagNo Tag number being checked + * @param File_MARC_Field $field Field to check + * @param array $rules Rules to use for checking + * + * @return void + */ + protected function checkSubfields($tagNo, $field, $rules) + { + $subSeen = array(); + + foreach ($field->getSubfields() as $current) { + $code = $current->getCode(); + $data = $current->getData(); + + $subrules = isset($rules['sub' . $code]) + ? $rules['sub' . $code] : null; + + if (empty($subrules)) { + $this->warn("$tagNo: Subfield _$code is not allowed."); + } elseif ($subrules['repeatable'] == 'NR' && isset($subSeen[$code])) { + $this->warn("$tagNo: Subfield _$code is not repeatable."); + } + + if (preg_match('/\r|\t|\n/', $data)) { + $this->warn( + "$tagNo: Subfield _$code has an invalid control character" + ); + } + + $subSeen[$code] = isset($subSeen[$code]) ? $subSeen[$code]++ : 1; + } + } + // }}} + + // {{{ check020() + /** + * Looks at 020$a and reports errors if the check digit is wrong. + * Looks at 020$z and validates number if hyphens are present. + * + * @param File_MARC_Field $field Field to check + * + * @return void + */ + protected function check020($field) + { + foreach ($field->getSubfields() as $current) { + $data = $current->getData(); + // remove any hyphens + $isbn = str_replace('-', '', $data); + // remove nondigits + $isbn = preg_replace('/^\D*(\d{9,12}[X\d])\b.*$/', '$1', $isbn); + + if ($current->getCode() == 'a') { + if ((substr($data, 0, strlen($isbn)) != $isbn)) { + $this->warn("020: Subfield a may have invalid characters."); + } + + // report error if no space precedes a qualifier in subfield a + if (preg_match('/\(/', $data) && !preg_match('/[X0-9] \(/', $data)) { + $this->warn( + "020: Subfield a qualifier must be preceded by space, $data." + ); + } + + // report error if unable to find 10-13 digit string of digits in + // subfield 'a' + if (!preg_match('/(?:^\d{10}$)|(?:^\d{13}$)|(?:^\d{9}X$)/', $isbn)) { + $this->warn( + "020: Subfield a has the wrong number of digits, $data." + ); + } else { + if (strlen($isbn) == 10) { + if (!Validate_ISPN::isbn10($isbn)) { + $this->warn("020: Subfield a has bad checksum, $data."); + } + } else if (strlen($isbn) == 13) { + if (!Validate_ISPN::isbn13($isbn)) { + $this->warn( + "020: Subfield a has bad checksum (13 digit), $data." + ); + } + } + } + } else if ($current->getCode() == 'z') { + // look for valid isbn in 020$z + if (preg_match('/^ISBN/', $data) + || preg_match('/^\d*\-\d+/', $data) + ) { + // ################################################## + // ## Turned on for now--Comment to unimplement #### + // ################################################## + if ((strlen($isbn) == 10) + && (Validate_ISPN::isbn10($isbn) == 1) + ) { + $this->warn("020: Subfield z is numerically valid."); + } + } + } + } + } + // }}} + + // {{{ check041() + /** + * Warns if subfields are not evenly divisible by 3 unless second indicator is 7 + * (future implementation would ensure that each subfield is exactly 3 characters + * unless ind2 is 7--since subfields are now repeatable. This is not implemented + * here due to the large number of records needing to be corrected.). Validates + * against the MARC Code List for Languages (<http://www.loc.gov/marc/>). + * + * @param File_MARC_Field $field Field to check + * + * @return void + */ + protected function check041($field) + { + // warn if length of each subfield is not divisible by 3 unless ind2 is 7 + if ($field->getIndicator(2) != '7') { + foreach ($field->getSubfields() as $sub) { + $code = $sub->getCode(); + $data = $sub->getData(); + if (strlen($data) % 3 != 0) { + $this->warn( + "041: Subfield _$code must be evenly divisible by 3 or " + . "exactly three characters if ind2 is not 7, ($data)." + ); + } else { + for ($i = 0; $i < strlen($data); $i += 3) { + $chk = substr($data, $i, 3); + if (!in_array($chk, $this->data->languageCodes)) { + $obs = $this->data->obsoleteLanguageCodes; + if (in_array($chk, $obs)) { + $this->warn( + "041: Subfield _$code, $data, may be obsolete." + ); + } else { + $this->warn( + "041: Subfield _$code, $data ($chk)," + . " is not valid." + ); + } + } + } + } + } + } + } + // }}} + + // {{{ check043() + /** + * Warns if each subfield a is not exactly 7 characters. Validates each code + * against the MARC code list for Geographic Areas (<http://www.loc.gov/marc/>). + * + * @param File_MARC_Field $field Field to check + * + * @return void + */ + protected function check043($field) + { + foreach ($field->getSubfields('a') as $suba) { + // warn if length of subfield a is not exactly 7 + $data = $suba->getData(); + if (strlen($data) != 7) { + $this->warn("043: Subfield _a must be exactly 7 characters, $data"); + } else if (!in_array($data, $this->data->geogAreaCodes)) { + if (in_array($data, $this->data->obsoleteGeogAreaCodes)) { + $this->warn("043: Subfield _a, $data, may be obsolete."); + } else { + $this->warn("043: Subfield _a, $data, is not valid."); + } + } + } + } + // }}} + + // {{{ check245() + /** + * -Makes sure $a exists (and is first subfield). + * -Warns if last character of field is not a period + * --Follows LCRI 1.0C, Nov. 2003 rather than MARC21 rule + * -Verifies that $c is preceded by / (space-/) + * -Verifies that initials in $c are not spaced + * -Verifies that $b is preceded by :;= (space-colon, space-semicolon, + * space-equals) + * -Verifies that $h is not preceded by space unless it is dash-space + * -Verifies that data of $h is enclosed in square brackets + * -Verifies that $n is preceded by . (period) + * --As part of that, looks for no-space period, or dash-space-period + * (for replaced elipses) + * -Verifies that $p is preceded by , (no-space-comma) when following $n and + * . (period) when following other subfields. + * -Performs rudimentary article check of 245 2nd indicator vs. 1st word of + * 245$a (for manual verification). + * + * Article checking is done by internal checkArticle method, which should work + * for 130, 240, 245, 440, 630, 730, and 830. + * + * @param File_MARC_Field $field Field to check + * + * @return void + */ + protected function check245($field) + { + if (count($field->getSubfields('a')) == 0) { + $this->warn("245: Must have a subfield _a."); + } + + // Convert subfields to array and set flags indicating which subfields are + // present while we're at it. + $tmp = $field->getSubfields(); + $hasSubfields = $subfields = array(); + foreach ($tmp as $current) { + $subfields[] = $current; + $hasSubfields[$current->getCode()] = true; + } + + // 245 must end in period (may want to make this less restrictive by allowing + // trailing spaces) + // do 2 checks--for final punctuation (MARC21 rule), and for period + // (LCRI 1.0C, Nov. 2003) + $lastChar = substr($subfields[count($subfields)-1]->getData(), -1); + if (!in_array($lastChar, array('.', '?', '!'))) { + $this->warn("245: Must end with . (period)."); + } else if ($lastChar != '.') { + $this->warn( + "245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov." + . " 2003, requires period." + ); + } + + // Check for first subfield + // subfield a should be first subfield (or 2nd if subfield '6' is present) + if (isset($hasSubfields['6'])) { + // make sure there are at least 2 subfields + if (count($subfields) < 2) { + $this->warn("245: May have too few subfields."); + } else { + $first = $subfields[0]->getCode(); + $second = $subfields[1]->getCode(); + if ($first != '6') { + $this->warn("245: First subfield must be _6, but it is $first"); + } + if ($second != 'a') { + $this->warn( + "245: First subfield after subfield _6 must be _a, but it " + . "is _$second" + ); + } + } + } else { + // 1st subfield must be 'a' + $first = $subfields[0]->getCode(); + if ($first != 'a') { + $this->warn("245: First subfield must be _a, but it is _$first"); + } + } + // End check for first subfield + + // subfield c, if present, must be preceded by / + // also look for space between initials + if (isset($hasSubfields['c'])) { + foreach ($subfields as $i => $current) { + // 245 subfield c must be preceded by / (space-/) + if ($current->getCode() == 'c') { + if ($i > 0 + && !preg_match('/\s\/$/', $subfields[$i-1]->getData()) + ) { + $this->warn("245: Subfield _c must be preceded by /"); + } + // 245 subfield c initials should not have space + if (preg_match('/\b\w\. \b\w\./', $current->getData())) { + $this->warn( + "245: Subfield _c initials should not have a space." + ); + } + break; + } + } + } + + // each subfield b, if present, should be preceded by :;= (colon, semicolon, + // or equals sign) + if (isset($hasSubfields['b'])) { + // 245 subfield b should be preceded by space-:;= (colon, semicolon, or + // equals sign) + foreach ($subfields as $i => $current) { + if ($current->getCode() == 'b' && $i > 0 + && !preg_match('/ [:;=]$/', $subfields[$i-1]->getData()) + ) { + $this->warn( + "245: Subfield _b should be preceded by space-colon, " + . "space-semicolon, or space-equals sign." + ); + } + } + } + + // each subfield h, if present, should be preceded by non-space + if (isset($hasSubfields['h'])) { + // 245 subfield h should not be preceded by space + foreach ($subfields as $i => $current) { + // report error if subfield 'h' is preceded by space (unless + // dash-space) + if ($current->getCode() == 'h') { + $prev = $subfields[$i-1]->getData(); + if ($i > 0 && !preg_match('/(\S$)|(\-\- $)/', $prev)) { + $this->warn( + "245: Subfield _h should not be preceded by space." + ); + } + // report error if subfield 'h' does not start with open square + // bracket with a matching close bracket; could have check + // against list of valid values here + $data = $current->getData(); + if (!preg_match('/^\[\w*\s*\w*\]/', $data)) { + $this->warn( + "245: Subfield _h must have matching square brackets," + . " $data." + ); + } + } + } + } + + // each subfield n, if present, must be preceded by . (period) + if (isset($hasSubfields['n'])) { + // 245 subfield n must be preceded by . (period) + foreach ($subfields as $i => $current) { + // report error if subfield 'n' is not preceded by non-space-period + // or dash-space-period + if ($current->getCode() == 'n' && $i > 0) { + $prev = $subfields[$i-1]->getData(); + if (!preg_match('/(\S\.$)|(\-\- \.$)/', $prev)) { + $this->warn( + "245: Subfield _n must be preceded by . (period)." + ); + } + } + } + } + + // each subfield p, if present, must be preceded by a , (no-space-comma) + // if it follows subfield n, or by . (no-space-period or + // dash-space-period) following other subfields + if (isset($hasSubfields['p'])) { + // 245 subfield p must be preceded by . (period) or , (comma) + foreach ($subfields as $i => $current) { + if ($current->getCode() == 'p' && $i > 0) { + $prev = $subfields[$i-1]; + // case for subfield 'n' being field before this one (allows + // dash-space-comma) + if ($prev->getCode() == 'n' + && !preg_match('/(\S,$)|(\-\- ,$)/', $prev->getData()) + ) { + $this->warn( + "245: Subfield _p must be preceded by , (comma) " + . "when it follows subfield _n." + ); + } else if ($prev->getCode() != 'n' + && !preg_match('/(\S\.$)|(\-\- \.$)/', $prev->getData()) + ) { + $this->warn( + "245: Subfield _p must be preceded by . (period)" + . " when it follows a subfield other than _n." + ); + } + } + } + } + + // check for invalid 2nd indicator + $this->checkArticle($field); + } + // }}} + + // {{{ checkArticle() + /** + * Check of articles is based on code from Ian Hamilton. This version is more + * limited in that it focuses on English, Spanish, French, Italian and German + * articles. Certain possible articles have been removed if they are valid + * English non-articles. This version also disregards 008_language/041 codes + * and just uses the list of articles to provide warnings/suggestions. + * + * source for articles = <http://www.loc.gov/marc/bibliographic/bdapp-e.html> + * + * Should work with fields 130, 240, 245, 440, 630, 730, and 830. Reports error + * if another field is passed in. + * + * @param File_MARC_Field $field Field to check + * + * @return void + */ + protected function checkArticle($field) + { + // add articles here as needed + // Some omitted due to similarity with valid words (e.g. the German 'die'). + static $article = array( + 'a' => 'eng glg hun por', + 'an' => 'eng', + 'das' => 'ger', + 'dem' => 'ger', + 'der' => 'ger', + 'ein' => 'ger', + 'eine' => 'ger', + 'einem' => 'ger', + 'einen' => 'ger', + 'einer' => 'ger', + 'eines' => 'ger', + 'el' => 'spa', + 'en' => 'cat dan nor swe', + 'gl' => 'ita', + 'gli' => 'ita', + 'il' => 'ita mlt', + 'l' => 'cat fre ita mlt', + 'la' => 'cat fre ita spa', + 'las' => 'spa', + 'le' => 'fre ita', + 'les' => 'cat fre', + 'lo' => 'ita spa', + 'los' => 'spa', + 'os' => 'por', + 'the' => 'eng', + 'um' => 'por', + 'uma' => 'por', + 'un' => 'cat spa fre ita', + 'una' => 'cat spa ita', + 'une' => 'fre', + 'uno' => 'ita', + ); + + // add exceptions here as needed + // may want to make keys lowercase + static $exceptions = array( + 'A & E', + 'A-', + 'A+', + 'A is ', + 'A isn\'t ', + 'A l\'', + 'A la ', + 'A posteriori', + 'A priori', + 'A to ', + 'El Nino', + 'El Salvador', + 'L-', + 'La Salle', + 'Las Vegas', + 'Lo mein', + 'Los Alamos', + 'Los Angeles', + ); + + // get tagno to determine which indicator to check and for reporting + $tagNo = $field->getTag(); + // retrieve tagno from subfield 6 if 880 field + if ($tagNo == '880' && ($sub6 = $field->getSubfield('6'))) { + $tagNo = substr($sub6->getData(), 0, 3); + } + + // $ind holds nonfiling character indicator value + $ind = ''; + // $first_or_second holds which indicator is for nonfiling char value + $first_or_second = ''; + if (in_array($tagNo, array(130, 630, 730))) { + $ind = $field->getIndicator(1); + $first_or_second = '1st'; + } else if (in_array($tagNo, array(240, 245, 440, 830))) { + $ind = $field->getIndicator(2); + $first_or_second = '2nd'; + } else { + $this->warn( + 'Internal error: ' . $tagNo + . " is not a valid field for article checking\n" + ); + return; + } + + if (!is_numeric($ind)) { + $this->warn($tagNo . ": Non-filing indicator is non-numeric"); + return; + } + + // get subfield 'a' of the title field + $titleField = $field->getSubfield('a'); + $title = $titleField ? $titleField->getData() : ''; + + $char1_notalphanum = 0; + // check for apostrophe, quote, bracket, or parenthesis, before first word + // remove if found and add to non-word counter + while (preg_match('/^["\'\[\(*]/', $title)) { + $char1_notalphanum++; + $title = preg_replace('/^["\'\[\(*]/', '', $title); + } + // split title into first word + rest on space, parens, bracket, apostrophe, + // quote, or hyphen + preg_match('/^([^ \(\)\[\]\'"\-]+)([ \(\)\[\]\'"\-])?(.*)/i', $title, $hits); + $firstword = isset($hits[1]) ? $hits[1] : ''; + $separator = isset($hits[2]) ? $hits[2] : ''; + $etc = isset($hits[3]) ? $hits[3] : ''; + + // get length of first word plus the number of chars removed above plus one + // for the separator + $nonfilingchars = strlen($firstword) + $char1_notalphanum + 1; + + // check to see if first word is an exception + $isan_exception = false; + foreach ($exceptions as $current) { + if (substr($title, 0, strlen($current)) == $current) { + $isan_exception = true; + break; + } + } + + // lowercase chars of $firstword for comparison with article list + $firstword = strtolower($firstword); + + // see if first word is in the list of articles and not an exception + $isan_article = !$isan_exception && isset($article[$firstword]); + + // if article then $nonfilingchars should match $ind + if ($isan_article) { + // account for quotes, apostrophes, parens, or brackets before 2nd word + if (strlen($separator) && preg_match('/^[ \(\)\[\]\'"\-]+/', $etc)) { + while (preg_match('/^[ "\'\[\]\(\)*]/', $etc)) { + $nonfilingchars++; + $etc = preg_replace('/^[ "\'\[\]\(\)*]/', '', $etc); + } + } + if ($nonfilingchars != $ind) { + $this->warn( + $tagNo . ": First word, $firstword, may be an article, check " + . "$first_or_second indicator ($ind)." + ); + } + } else { + // not an article so warn if $ind is not 0 + if ($ind != '0') { + $this->warn( + $tagNo . ": First word, $firstword, does not appear to be an " + . "article, check $first_or_second indicator ($ind)." + ); + } + } + } + // }}} + + // {{{ parseRules() + /** + * Support method for constructor to load MARC rules. + * + * @return void + */ + protected function parseRules() + { + // Break apart the rule data on line breaks: + $lines = explode("\n", $this->getRawRules()); + + // Each group of data is split by a blank line -- process one group + // at a time: + $currentGroup = array(); + foreach ($lines as $currentLine) { + if (empty($currentLine) && !empty($currentGroup)) { + $this->processRuleGroup($currentGroup); + $currentGroup = array(); + } else { + $currentGroup[] = preg_replace("/\s+/", " ", $currentLine); + } + } + + // Still have unprocessed data after the loop? Handle it now: + if (!empty($currentGroup)) { + $this->processRuleGroup($currentGroup); + } + } + // }}} + + // {{{ processRuleGroup() + /** + * Support method for parseRules() -- process one group of lines representing + * a single tag. + * + * @param array $rules Rule lines to process + * + * @return void + */ + protected function processRuleGroup($rules) + { + // The first line is guaranteed to exist and gives us some basic info: + list($tag, $repeatable, $description) = explode(' ', $rules[0]); + $this->rules[$tag] = array( + 'repeatable' => $repeatable, + 'desc' => $description + ); + + // We may or may not have additional details: + for ($i = 1; $i < count($rules); $i++) { + list($key, $value, $lineDesc) = explode(' ', $rules[$i]); + if (substr($key, 0, 3) == 'ind') { + // Expand ranges: + $value = str_replace('0-9', '0123456789', $value); + $this->rules[$tag][$key] = array( + 'values' => $value, + 'hr_values' => $this->getHumanReadableIndicatorValues($value), + 'desc'=> $lineDesc + ); + } else { + if (strlen($key) <= 1) { + $this->rules[$tag]['sub' . $key] = array( + 'repeatable' => $value, + 'desc' => $lineDesc + ); + } elseif (strstr($key, '-')) { + list($startKey, $endKey) = explode('-', $key); + for ($key = $startKey; $key <= $endKey; $key++) { + $this->rules[$tag]['sub' . $key] = array( + 'repeatable' => $value, + 'desc' => $lineDesc + ); + } + } + } + } + } + // }}} + + // {{{ getHumanReadableIndicatorValues() + /** + * Turn a set of indicator rules into a human-readable list. + * + * @param string $rules Indicator rules + * + * @return string + */ + protected function getHumanReadableIndicatorValues($rules) + { + // No processing needed for blank rule: + if ($rules == 'blank') { + return $rules; + } + + // Create string: + $string = ''; + $length = strlen($rules); + for ($i = 0; $i < $length; $i++) { + $current = substr($rules, $i, 1); + if ($current == 'b') { + $current = 'blank'; + } + $string .= $current; + if ($length - $i == 2) { + $string .= ' or '; + } else if ($length - $i > 2) { + $string .= ', '; + } + } + + return $string; + } + // }}} + + // {{{ getRawRules() + /** + * Support method for parseRules() -- get the raw rules from MARC::Lint. + * + * @return string + */ + protected function getRawRules() + { + // When updating rules, don't forget to escape the dollar signs in the text! + // It would be simpler to change from HEREDOC to NOWDOC syntax, but that + // would raise the requirements to PHP 5.3. + // @codingStandardsIgnoreStart + return <<<RULES +001 NR CONTROL NUMBER +ind1 blank Undefined +ind2 blank Undefined + NR Undefined + +002 NR LOCALLY DEFINED (UNOFFICIAL) +ind1 blank Undefined +ind2 blank Undefined + NR Undefined + +003 NR CONTROL NUMBER IDENTIFIER +ind1 blank Undefined +ind2 blank Undefined + NR Undefined + +005 NR DATE AND TIME OF LATEST TRANSACTION +ind1 blank Undefined +ind2 blank Undefined + NR Undefined + +006 R FIXED-LENGTH DATA ELEMENTS--ADDITIONAL MATERIAL CHARACTERISTICS--GENERAL INFORMATION +ind1 blank Undefined +ind2 blank Undefined + R Undefined + +007 R PHYSICAL DESCRIPTION FIXED FIELD--GENERAL INFORMATION +ind1 blank Undefined +ind2 blank Undefined + R Undefined + +008 NR FIXED-LENGTH DATA ELEMENTS--GENERAL INFORMATION +ind1 blank Undefined +ind2 blank Undefined + NR Undefined + +010 NR LIBRARY OF CONGRESS CONTROL NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR LC control number +b R NUCMC control number +z R Canceled/invalid LC control number +8 R Field link and sequence number + +013 R PATENT CONTROL INFORMATION +ind1 blank Undefined +ind2 blank Undefined +a NR Number +b NR Country +c NR Type of number +d R Date +e R Status +f R Party to document +6 NR Linkage +8 R Field link and sequence number + +015 R NATIONAL BIBLIOGRAPHY NUMBER +ind1 blank Undefined +ind2 blank Undefined +a R National bibliography number +z R Canceled/Invalid national bibliography number +2 NR Source +6 NR Linkage +8 R Field link and sequence number + +016 R NATIONAL BIBLIOGRAPHIC AGENCY CONTROL NUMBER +ind1 b7 National bibliographic agency +ind2 blank Undefined +a NR Record control number +z R Canceled or invalid record control number +2 NR Source +8 R Field link and sequence number + +017 R COPYRIGHT OR LEGAL DEPOSIT NUMBER +ind1 blank Undefined +ind2 b8 Undefined +a R Copyright or legal deposit number +b NR Assigning agency +d NR Date +i NR Display text +z R Canceled/invalid copyright or legal deposit number +2 NR Source +6 NR Linkage +8 R Field link and sequence number + +018 NR COPYRIGHT ARTICLE-FEE CODE +ind1 blank Undefined +ind2 blank Undefined +a NR Copyright article-fee code +6 NR Linkage +8 R Field link and sequence number + +020 R INTERNATIONAL STANDARD BOOK NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR International Standard Book Number +c NR Terms of availability +z R Canceled/invalid ISBN +6 NR Linkage +8 R Field link and sequence number + +022 R INTERNATIONAL STANDARD SERIAL NUMBER +ind1 b01 Level of international interest +ind2 blank Undefined +a NR International Standard Serial Number +l NR ISSN-L +m R Canceled ISSN-L +y R Incorrect ISSN +z R Canceled ISSN +2 NR Source +6 NR Linkage +8 R Field link and sequence number + +024 R OTHER STANDARD IDENTIFIER +ind1 0123478 Type of standard number or code +ind2 b01 Difference indicator +a NR Standard number or code +c NR Terms of availability +d NR Additional codes following the standard number or code +z R Canceled/invalid standard number or code +2 NR Source of number or code +6 NR Linkage +8 R Field link and sequence number + +025 R OVERSEAS ACQUISITION NUMBER +ind1 blank Undefined +ind2 blank Undefined +a R Overseas acquisition number +8 R Field link and sequence number + +026 R FINGERPRINT IDENTIFIER +ind1 blank Undefined +ind2 blank Undefined +a R First and second groups of characters +b R Third and fourth groups of characters +c NR Date +d R Number of volume or part +e NR Unparsed fingerprint +2 NR Source +5 R Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +027 R STANDARD TECHNICAL REPORT NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR Standard technical report number +z R Canceled/invalid number +6 NR Linkage +8 R Field link and sequence number + +028 R PUBLISHER NUMBER +ind1 012345 Type of publisher number +ind2 0123 Note/added entry controller +a NR Publisher number +b NR Source +6 NR Linkage +8 R Field link and sequence number + +030 R CODEN DESIGNATION +ind1 blank Undefined +ind2 blank Undefined +a NR CODEN +z R Canceled/invalid CODEN +6 NR Linkage +8 R Field link and sequence number + +031 R MUSICAL INCIPITS INFORMATION +ind1 blank Undefined +ind2 blank Undefined +a NR Number of work +b NR Number of movement +c NR Number of excerpt +d R Caption or heading +e NR Role +g NR Clef +m NR Voice/instrument +n NR Key signature +o NR Time signature +p NR Musical notation +q R General note +r NR Key or mode +s R Coded validity note +t R Text incipit +u R Uniform Resource Identifier +y R Link text +z R Public note +2 NR System code +6 NR Linkage +8 R Field link and sequence number + +032 R POSTAL REGISTRATION NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR Postal registration number +b NR Source (agency assigning number) +6 NR Linkage +8 R Field link and sequence number + +033 R DATE/TIME AND PLACE OF AN EVENT +ind1 b012 Type of date in subfield \$a +ind2 b012 Type of event +a R Formatted date/time +b R Geographic classification area code +c R Geographic classification subarea code +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +034 R CODED CARTOGRAPHIC MATHEMATICAL DATA +ind1 013 Type of scale +ind2 b01 Type of ring +a NR Category of scale +b R Constant ratio linear horizontal scale +c R Constant ratio linear vertical scale +d NR Coordinates--westernmost longitude +e NR Coordinates--easternmost longitude +f NR Coordinates--northernmost latitude +g NR Coordinates--southernmost latitude +h R Angular scale +j NR Declination--northern limit +k NR Declination--southern limit +m NR Right ascension--eastern limit +n NR Right ascension--western limit +p NR Equinox +r NR Distance from earth +s R G-ring latitude +t R G-ring longitude +x NR Beginning date +y NR Ending date +z NR Name of extraterrestrial body +2 NR Source +6 NR Linkage +8 R Field link and sequence number + +035 R SYSTEM CONTROL NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR System control number +z R Canceled/invalid control number +6 NR Linkage +8 R Field link and sequence number + +036 NR ORIGINAL STUDY NUMBER FOR COMPUTER DATA FILES +ind1 blank Undefined +ind2 blank Undefined +a NR Original study number +b NR Source (agency assigning number) +6 NR Linkage +8 R Field link and sequence number + +037 R SOURCE OF ACQUISITION +ind1 blank Undefined +ind2 blank Undefined +a NR Stock number +b NR Source of stock number/acquisition +c R Terms of availability +f R Form of issue +g R Additional format characteristics +n R Note +6 NR Linkage +8 R Field link and sequence number + +038 NR RECORD CONTENT LICENSOR +ind1 blank Undefined +ind2 blank Undefined +a NR Record content licensor +6 NR Linkage +8 R Field link and sequence number + +040 NR CATALOGING SOURCE +ind1 blank Undefined +ind2 blank Undefined +a NR Original cataloging agency +b NR Language of cataloging +c NR Transcribing agency +d R Modifying agency +e NR Description conventions +6 NR Linkage +8 R Field link and sequence number + +041 R LANGUAGE CODE +ind1 b01 Translation indication +ind2 b7 Source of code +a R Language code of text/sound track or separate title +b R Language code of summary or abstract +d R Language code of sung or spoken text +e R Language code of librettos +f R Language code of table of contents +g R Language code of accompanying material other than librettos +h R Language code of original and/or intermediate translations of text +j R Language code of subtitles or captions +2 NR Source of code +6 NR Linkage +8 R Field link and sequence number + +042 NR AUTHENTICATION CODE +ind1 blank Undefined +ind2 blank Undefined +a R Authentication code + +043 NR GEOGRAPHIC AREA CODE +ind1 blank Undefined +ind2 blank Undefined +a R Geographic area code +b R Local GAC code +c R ISO code +2 R Source of local code +6 NR Linkage +8 R Field link and sequence number + +044 NR COUNTRY OF PUBLISHING/PRODUCING ENTITY CODE +ind1 blank Undefined +ind2 blank Undefined +a R MARC country code +b R Local subentity code +c R ISO country code +2 R Source of local subentity code +6 NR Linkage +8 R Field link and sequence number + +045 NR TIME PERIOD OF CONTENT +ind1 b012 Type of time period in subfield \$b or \$c +ind2 blank Undefined +a R Time period code +b R Formatted 9999 B.C. through C.E. time period +c R Formatted pre-9999 B.C. time period +6 NR Linkage +8 R Field link and sequence number + +046 R SPECIAL CODED DATES +ind1 blank Undefined +ind2 blank Undefined +a NR Type of date code +b NR Date 1 (B.C. date) +c NR Date 1 (C.E. date) +d NR Date 2 (B.C. date) +e NR Date 2 (C.E. date) +j NR Date resource modified +k NR Beginning or single date created +l NR Ending date created +m NR Beginning of date valid +n NR End of date valid +2 NR Source of date +6 NR Linkage +8 R Field link and sequence number + +047 R FORM OF MUSICAL COMPOSITION CODE +ind1 blank Undefined +ind2 b7 Source of code +a R Form of musical composition code +2 NR Source of code +8 R Field link and sequence number + +048 R NUMBER OF MUSICAL INSTRUMENTS OR VOICES CODE +ind1 blank Undefined +ind2 b7 Source specified in subfield \$2 +a R Performer or ensemble +b R Soloist +2 NR Source of code +8 R Field link and sequence number + +050 R LIBRARY OF CONGRESS CALL NUMBER +ind1 b01 Existence in LC collection +ind2 04 Source of call number +a R Classification number +b NR Item number +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +051 R LIBRARY OF CONGRESS COPY, ISSUE, OFFPRINT STATEMENT +ind1 blank Undefined +ind2 blank Undefined +a NR Classification number +b NR Item number +c NR Copy information +8 R Field link and sequence number + +052 R GEOGRAPHIC CLASSIFICATION +ind1 b17 Code source +ind2 blank Undefined +a NR Geographic classification area code +b R Geographic classification subarea code +d R Populated place name +2 NR Code source +6 NR Linkage +8 R Field link and sequence number + +055 R CLASSIFICATION NUMBERS ASSIGNED IN CANADA +ind1 b01 Existence in LAC collection +ind2 0123456789 Type, completeness, source of class/call number +a NR Classification number +b NR Item number +2 NR Source of call/class number +8 R Field link and sequence number + +060 R NATIONAL LIBRARY OF MEDICINE CALL NUMBER +ind1 b01 Existence in NLM collection +ind2 04 Source of call number +a R Classification number +b NR Item number +8 R Field link and sequence number + +061 R NATIONAL LIBRARY OF MEDICINE COPY STATEMENT +ind1 blank Undefined +ind2 blank Undefined +a R Classification number +b NR Item number +c NR Copy information +8 R Field link and sequence number + +066 NR CHARACTER SETS PRESENT +ind1 blank Undefined +ind2 blank Undefined +a NR Primary G0 character set +b NR Primary G1 character set +c R Alternate G0 or G1 character set + +070 R NATIONAL AGRICULTURAL LIBRARY CALL NUMBER +ind1 01 Existence in NAL collection +ind2 blank Undefined +a R Classification number +b NR Item number +8 R Field link and sequence number + +071 R NATIONAL AGRICULTURAL LIBRARY COPY STATEMENT +ind1 blank Undefined +ind2 blank Undefined +a R Classification number +b NR Item number +c NR Copy information +8 R Field link and sequence number + +072 R SUBJECT CATEGORY CODE +ind1 blank Undefined +ind2 07 Source specified in subfield \$2 +a NR Subject category code +x R Subject category code subdivision +2 NR Source +6 NR Linkage +8 R Field link and sequence number + +074 R GPO ITEM NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR GPO item number +z R Canceled/invalid GPO item number +8 R Field link and sequence number + +080 R UNIVERSAL DECIMAL CLASSIFICATION NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR Universal Decimal Classification number +b NR Item number +x R Common auxiliary subdivision +2 NR Edition identifier +6 NR Linkage +8 R Field link and sequence number + +082 R DEWEY DECIMAL CLASSIFICATION NUMBER +ind1 01 Type of edition +ind2 b04 Source of classification number +a R Classification number +b NR Item number +m NR Standard or optional designation +q NR Assigning agency +2 NR Edition number +6 NR Linkage +8 R Field link and sequence number + +083 R ADDITIONAL DEWEY DECIMAL CLASSIFICATION NUMBER +ind1 01 Type of edition +ind2 blank Undefined +a R Classification number +c R Classification number--Ending number of span +m NR Standard or optional designation +q NR Assigning agency +y R Table sequence number for internal subarrangement or add table +z R Table identification +2 NR Edition number +6 NR Linkage +8 R Field link and sequence number + +084 R OTHER CLASSIFICATION NUMBER +ind1 blank Undefined +ind2 blank Undefined +a R Classification number +b NR Item number +2 NR Source of number +6 NR Linkage +8 R Field link and sequence number + +085 R SYNTHESIZED CLASSIFICATION NUMBER COMPONENTS +ind1 blank Undefined +ind2 blank Undefined +a R Number where instructions are found-single number or beginning number of span +b R Base number +c R Classification number-ending number of span +f R Facet designator +r R Root number +s R Digits added from classification number in schedule or external table +t R Digits added from internal subarrangement or add table +u R Number being analyzed +v R Number in internal subarrangement or add table where instructions are found +w R Table identification-Internal subarrangement or add table +y R Table sequence number for internal subarrangement or add table +z R Table identification +6 NR Linkage +8 R Field link and sequence number + +086 R GOVERNMENT DOCUMENT CLASSIFICATION NUMBER +ind1 b01 Number source +ind2 blank Undefined +a NR Classification number +z R Canceled/invalid classification number +2 NR Number source +6 NR Linkage +8 R Field link and sequence number + +088 R REPORT NUMBER +ind1 blank Undefined +ind2 blank Undefined +a NR Report number +z R Canceled/invalid report number +6 NR Linkage +8 R Field link and sequence number + +100 NR MAIN ENTRY--PERSONAL NAME +ind1 013 Type of personal name entry element +ind2 blank Undefined +a NR Personal name +b NR Numeration +c R Titles and other words associated with a name +d NR Dates associated with a name +e R Relator term +f NR Date of a work +g NR Miscellaneous information +j R Attribution qualifier +k R Form subheading +l NR Language of a work +n R Number of part/section of a work +p R Name of part/section of a work +q NR Fuller form of name +t NR Title of a work +u NR Affiliation +0 R Authority record control number +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +110 NR MAIN ENTRY--CORPORATE NAME +ind1 012 Type of corporate name entry element +ind2 blank Undefined +a NR Corporate name or jurisdiction name as entry element +b R Subordinate unit +c NR Location of meeting +d R Date of meeting or treaty signing +e R Relator term +f NR Date of a work +g NR Miscellaneous information +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +t NR Title of a work +u NR Affiliation +0 R Authority record control number +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +111 NR MAIN ENTRY--MEETING NAME +ind1 012 Type of meeting name entry element +ind2 blank Undefined +a NR Meeting name or jurisdiction name as entry element +c NR Location of meeting +d NR Date of meeting +e R Subordinate unit +f NR Date of a work +g NR Miscellaneous information +j R Relator term +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +q NR Name of meeting following jurisdiction name entry element +t NR Title of a work +u NR Affiliation +0 R Authority record control number +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +130 NR MAIN ENTRY--UNIFORM TITLE +ind1 0-9 Nonfiling characters +ind2 blank Undefined +a NR Uniform title +d R Date of treaty signing +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +0 R Authority record control number +6 NR Linkage +8 R Field link and sequence number + +210 R ABBREVIATED TITLE +ind1 01 Title added entry +ind2 b0 Type +a NR Abbreviated title +b NR Qualifying information +2 R Source +6 NR Linkage +8 R Field link and sequence number + +222 R KEY TITLE +ind1 blank Specifies whether variant title and/or added entry is required +ind2 0-9 Nonfiling characters +a NR Key title +b NR Qualifying information +6 NR Linkage +8 R Field link and sequence number + +240 NR UNIFORM TITLE +ind1 01 Uniform title printed or displayed +ind2 0-9 Nonfiling characters +a NR Uniform title +d R Date of treaty signing +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +0 R Authority record control number +6 NR Linkage +8 R Field link and sequence number + +242 R TRANSLATION OF TITLE BY CATALOGING AGENCY +ind1 01 Title added entry +ind2 0-9 Nonfiling characters +a NR Title +b NR Remainder of title +c NR Statement of responsibility, etc. +h NR Medium +n R Number of part/section of a work +p R Name of part/section of a work +y NR Language code of translated title +6 NR Linkage +8 R Field link and sequence number + +243 NR COLLECTIVE UNIFORM TITLE +ind1 01 Uniform title printed or displayed +ind2 0-9 Nonfiling characters +a NR Uniform title +d R Date of treaty signing +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +6 NR Linkage +8 R Field link and sequence number + +245 NR TITLE STATEMENT +ind1 01 Title added entry +ind2 0-9 Nonfiling characters +a NR Title +b NR Remainder of title +c NR Statement of responsibility, etc. +f NR Inclusive dates +g NR Bulk dates +h NR Medium +k R Form +n R Number of part/section of a work +p R Name of part/section of a work +s NR Version +6 NR Linkage +8 R Field link and sequence number + +246 R VARYING FORM OF TITLE +ind1 0123 Note/added entry controller +ind2 b012345678 Type of title +a NR Title proper/short title +b NR Remainder of title +f NR Date or sequential designation +g NR Miscellaneous information +h NR Medium +i NR Display text +n R Number of part/section of a work +p R Name of part/section of a work +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +247 R FORMER TITLE +ind1 01 Title added entry +ind2 01 Note controller +a NR Title +b NR Remainder of title +f NR Date or sequential designation +g NR Miscellaneous information +h NR Medium +n R Number of part/section of a work +p R Name of part/section of a work +x NR International Standard Serial Number +6 NR Linkage +8 R Field link and sequence number + +250 NR EDITION STATEMENT +ind1 blank Undefined +ind2 blank Undefined +a NR Edition statement +b NR Remainder of edition statement +6 NR Linkage +8 R Field link and sequence number + +254 NR MUSICAL PRESENTATION STATEMENT +ind1 blank Undefined +ind2 blank Undefined +a NR Musical presentation statement +6 NR Linkage +8 R Field link and sequence number + +255 R CARTOGRAPHIC MATHEMATICAL DATA +ind1 blank Undefined +ind2 blank Undefined +a NR Statement of scale +b NR Statement of projection +c NR Statement of coordinates +d NR Statement of zone +e NR Statement of equinox +f NR Outer G-ring coordinate pairs +g NR Exclusion G-ring coordinate pairs +6 NR Linkage +8 R Field link and sequence number + +256 NR COMPUTER FILE CHARACTERISTICS +ind1 blank Undefined +ind2 blank Undefined +a NR Computer file characteristics +6 NR Linkage +8 R Field link and sequence number + +257 NR COUNTRY OF PRODUCING ENTITY FOR ARCHIVAL FILMS +ind1 blank Undefined +ind2 blank Undefined +a NR Country of producing entity +6 NR Linkage +8 R Field link and sequence number + +258 R PHILATELIC ISSUE DATE +ind1 blank Undefined +ind2 blank Undefined +a NR Issuing jurisdiction +b NR Denomination +6 NR Linkage +8 R Field link and sequence number + +260 R PUBLICATION, DISTRIBUTION, ETC. (IMPRINT) +ind1 b23 Sequence of publishing statements +ind2 blank Undefined +a R Place of publication, distribution, etc. +b R Name of publisher, distributor, etc. +c R Date of publication, distribution, etc. +d NR Plate or publisher's number for music (Pre-AACR 2) +e R Place of manufacture +f R Manufacturer +g R Date of manufacture +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +261 NR IMPRINT STATEMENT FOR FILMS (Pre-AACR 1 Revised) +ind1 blank Undefined +ind2 blank Undefined +a R Producing company +b R Releasing company (primary distributor) +d R Date of production, release, etc. +e R Contractual producer +f R Place of production, release, etc. +6 NR Linkage +8 R Field link and sequence number + +262 NR IMPRINT STATEMENT FOR SOUND RECORDINGS (Pre-AACR 2) +ind1 blank Undefined +ind2 blank Undefined +a NR Place of production, release, etc. +b NR Publisher or trade name +c NR Date of production, release, etc. +k NR Serial identification +l NR Matrix and/or take number +6 NR Linkage +8 R Field link and sequence number + +263 NR PROJECTED PUBLICATION DATE +ind1 blank Undefined +ind2 blank Undefined +a NR Projected publication date +6 NR Linkage +8 R Field link and sequence number + +270 R ADDRESS +ind1 b12 Level +ind2 b07 Type of address +a R Address +b NR City +c NR State or province +d NR Country +e NR Postal code +f NR Terms preceding attention name +g NR Attention name +h NR Attention position +i NR Type of address +j R Specialized telephone number +k R Telephone number +l R Fax number +m R Electronic mail address +n R TDD or TTY number +p R Contact person +q R Title of contact person +r R Hours +z R Public note +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +300 R PHYSICAL DESCRIPTION +ind1 blank Undefined +ind2 blank Undefined +a R Extent +b NR Other physical details +c R Dimensions +e NR Accompanying material +f R Type of unit +g R Size of unit +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +306 NR PLAYING TIME +ind1 blank Undefined +ind2 blank Undefined +a R Playing time +6 NR Linkage +8 R Field link and sequence number + +307 R HOURS, ETC. +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Hours +b NR Additional information +6 NR Linkage +8 R Field link and sequence number + +310 NR CURRENT PUBLICATION FREQUENCY +ind1 blank Undefined +ind2 blank Undefined +a NR Current publication frequency +b NR Date of current publication frequency +6 NR Linkage +8 R Field link and sequence number + +321 R FORMER PUBLICATION FREQUENCY +ind1 blank Undefined +ind2 blank Undefined +a NR Former publication frequency +b NR Dates of former publication frequency +6 NR Linkage +8 R Field link and sequence number + +340 R PHYSICAL MEDIUM +ind1 blank Undefined +ind2 blank Undefined +a R Material base and configuration +b R Dimensions +c R Materials applied to surface +d R Information recording technique +e R Support +f R Production rate/ratio +h R Location within medium +i R Technical specifications of medium +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +342 R GEOSPATIAL REFERENCE DATA +ind1 01 Geospatial reference dimension +ind2 012345678 Geospatial reference method +a NR Name +b NR Coordinate or distance units +c NR Latitude resolution +d NR Longitude resolution +e R Standard parallel or oblique line latitude +f R Oblique line longitude +g NR Longitude of central meridian or projection center +h NR Latitude of projection origin or projection center +i NR False easting +j NR False northing +k NR Scale factor +l NR Height of perspective point above surface +m NR Azimuthal angle +o NR Landsat number and path number +p NR Zone identifier +q NR Ellipsoid name +r NR Semi-major axis +s NR Denominator of flattening ratio +t NR Vertical resolution +u NR Vertical encoding method +v NR Local planar, local, or other projection or grid description +w NR Local planar or local georeference information +2 NR Reference method used +6 NR Linkage +8 R Field link and sequence number + +343 R PLANAR COORDINATE DATA +ind1 blank Undefined +ind2 blank Undefined +a NR Planar coordinate encoding method +b NR Planar distance units +c NR Abscissa resolution +d NR Ordinate resolution +e NR Distance resolution +f NR Bearing resolution +g NR Bearing units +h NR Bearing reference direction +i NR Bearing reference meridian +6 NR Linkage +8 R Field link and sequence number + +351 R ORGANIZATION AND ARRANGEMENT OF MATERIALS +ind1 blank Undefined +ind2 blank Undefined +a R Organization +b R Arrangement +c NR Hierarchical level +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +352 R DIGITAL GRAPHIC REPRESENTATION +ind1 blank Undefined +ind2 blank Undefined +a NR Direct reference method +b R Object type +c R Object count +d NR Row count +e NR Column count +f NR Vertical count +g NR VPF topology level +i NR Indirect reference description +q R Format of the digital image +6 NR Linkage +8 R Field link and sequence number + +355 R SECURITY CLASSIFICATION CONTROL +ind1 0123458 Controlled element +ind2 blank Undefined +a NR Security classification +b R Handling instructions +c R External dissemination information +d NR Downgrading or declassification event +e NR Classification system +f NR Country of origin code +g NR Downgrading date +h NR Declassification date +j R Authorization +6 NR Linkage +8 R Field link and sequence number + +357 NR ORIGINATOR DISSEMINATION CONTROL +ind1 blank Undefined +ind2 blank Undefined +a NR Originator control term +b R Originating agency +c R Authorized recipients of material +g R Other restrictions +6 NR Linkage +8 R Field link and sequence number + +362 R DATES OF PUBLICATION AND/OR SEQUENTIAL DESIGNATION +ind1 01 Format of date +ind2 blank Undefined +a NR Dates of publication and/or sequential designation +z NR Source of information +6 NR Linkage +8 R Field link and sequence number + +363 R NORMALIZED DATE AND SEQUENTIAL DESIGNATION +ind1 b01 Start/End designator +ind2 b01 State of issuanceUndefined +a NR First level of enumeration +b NR Second level of enumeration +c NR Third level of enumeration +d NR Fourth level of enumeration +e NR Fifth level of enumeration +f NR Sixth level of enumeration +g NR Alternative numbering scheme, first level of enumeration +h NR Alternative numbering scheme, second level of enumeration +i NR First level of chronology +j NR Second level of chronology +k NR Third level of chronology +l NR Fourth level of chronology +m NR Alternative numbering scheme, chronology +u NR First level textual designation +v NR First level of chronology, issuance +x R Nonpublic note +z R Public note +6 NR Linkage +8 NR Field link and sequence number + +365 R TRADE PRICE +ind1 blank Undefined +ind2 blank Undefined +a NR Price type code +b NR Price amount +c NR Currency code +d NR Unit of pricing +e NR Price note +f NR Price effective from +g NR Price effective until +h NR Tax rate 1 +i NR Tax rate 2 +j NR ISO country code +k NR MARC country code +m NR Identification of pricing entity +2 NR Source of price type code +6 NR Linkage +8 R Field link and sequence number + +366 R TRADE AVAILABILITY INFORMATION +ind1 blank Undefined +ind2 blank Undefined +a NR Publishers' compressed title identification +b NR Detailed date of publication +c NR Availability status code +d NR Expected next availability date +e NR Note +f NR Publishers' discount category +g NR Date made out of print +j NR ISO country code +k NR MARC country code +m NR Identification of agency +2 NR Source of availability status code +6 NR Linkage +8 R Field link and sequence number + +400 R SERIES STATEMENT/ADDED ENTRY--PERSONAL NAME +ind1 013 Type of personal name entry element +ind2 01 Pronoun represents main entry +a NR Personal name +b NR Numeration +c R Titles and other words associated with a name +d NR Dates associated with a name +e R Relator term +f NR Date of a work +g NR Miscellaneous information +k R Form subheading +l NR Language of a work +n R Number of part/section of a work +p R Name of part/section of a work +t NR Title of a work +u NR Affiliation +v NR Volume number/sequential designation +x NR International Standard Serial Number +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +410 R SERIES STATEMENT/ADDED ENTRY--CORPORATE NAME +ind1 012 Type of corporate name entry element +ind2 01 Pronoun represents main entry +a NR Corporate name or jurisdiction name as entry element +b R Subordinate unit +c NR Location of meeting +d R Date of meeting or treaty signing +e R Relator term +f NR Date of a work +g NR Miscellaneous information +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +t NR Title of a work +u NR Affiliation +v NR Volume number/sequential designation +x NR International Standard Serial Number +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +411 R SERIES STATEMENT/ADDED ENTRY--MEETING NAME +ind1 012 Type of meeting name entry element +ind2 01 Pronoun represents main entry +a NR Meeting name or jurisdiction name as entry element +c NR Location of meeting +d NR Date of meeting +e R Subordinate unit +f NR Date of a work +g NR Miscellaneous information +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +q NR Name of meeting following jurisdiction name entry element +t NR Title of a work +u NR Affiliation +v NR Volume number/sequential designation +x NR International Standard Serial Number +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +440 R SERIES STATEMENT/ADDED ENTRY--TITLE [OBSOLETE] +ind1 blank Undefined +ind2 0-9 Nonfiling characters +a NR Title +n R Number of part/section of a work +p R Name of part/section of a work +v NR Volume number/sequential designation +x NR International Standard Serial Number +w R Bibliographic record control number +0 R Authority record control number +6 NR Linkage +8 R Field link and sequence number + +490 R SERIES STATEMENT +ind1 01 Specifies whether series is traced +ind2 blank Undefined +a R Series statement +l NR Library of Congress call number +v R Volume number/sequential designation +x NR International Standard Serial Number +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +500 R GENERAL NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR General note +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +501 R WITH NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR With note +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +502 R DISSERTATION NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Dissertation note +b NR Degree type +c NR Name of granting institution +d NR Year of degree granted +g R Miscellaneous information +o R Dissertation identifier +6 NR Linkage +8 R Field link and sequence number + +504 R BIBLIOGRAPHY, ETC. NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Bibliography, etc. note +b NR Number of references +6 NR Linkage +8 R Field link and sequence number + +505 R FORMATTED CONTENTS NOTE +ind1 0128 Display constant controller +ind2 b0 Level of content designation +a NR Formatted contents note +g R Miscellaneous information +r R Statement of responsibility +t R Title +u R Uniform Resource Identifier +6 NR Linkage +8 R Field link and sequence number + +506 R RESTRICTIONS ON ACCESS NOTE +ind1 b01 Restriction +ind2 blank Undefined +a NR Terms governing access +b R Jurisdiction +c R Physical access provisions +d R Authorized users +e R Authorization +f R Standard terminology for access restiction +u R Uniform Resource Identifier +2 NR Source of term +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +507 NR SCALE NOTE FOR GRAPHIC MATERIAL +ind1 blank Undefined +ind2 blank Undefined +a NR Representative fraction of scale note +b NR Remainder of scale note +6 NR Linkage +8 R Field link and sequence number + +508 R CREATION/PRODUCTION CREDITS NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Creation/production credits note +6 NR Linkage +8 R Field link and sequence number + +510 R CITATION/REFERENCES NOTE +ind1 01234 Coverage/location in source +ind2 blank Undefined +a NR Name of source +b NR Coverage of source +c NR Location within source +x NR International Standard Serial Number +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +511 R PARTICIPANT OR PERFORMER NOTE +ind1 01 Display constant controller +ind2 blank Undefined +a NR Participant or performer note +6 NR Linkage +8 R Field link and sequence number + +513 R TYPE OF REPORT AND PERIOD COVERED NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Type of report +b NR Period covered +6 NR Linkage +8 R Field link and sequence number + +514 NR DATA QUALITY NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Attribute accuracy report +b R Attribute accuracy value +c R Attribute accuracy explanation +d NR Logical consistency report +e NR Completeness report +f NR Horizontal position accuracy report +g R Horizontal position accuracy value +h R Horizontal position accuracy explanation +i NR Vertical positional accuracy report +j R Vertical positional accuracy value +k R Vertical positional accuracy explanation +m NR Cloud cover +u R Uniform Resource Identifier +z R Display note +6 NR Linkage +8 R Field link and sequence number + +515 R NUMBERING PECULIARITIES NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Numbering peculiarities note +6 NR Linkage +8 R Field link and sequence number + +516 R TYPE OF COMPUTER FILE OR DATA NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Type of computer file or data note +6 NR Linkage +8 R Field link and sequence number + +518 R DATE/TIME AND PLACE OF AN EVENT NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Date/time and place of an event note +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +520 R SUMMARY, ETC. +ind1 b012348 Display constant controller +ind2 blank Undefined +a NR Summary, etc. note +b NR Expansion of summary note +c NR Assigning agency +u R Uniform Resource Identifier +2 NR Source +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +521 R TARGET AUDIENCE NOTE +ind1 b012348 Display constant controller +ind2 blank Undefined +a R Target audience note +b NR Source +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +522 R GEOGRAPHIC COVERAGE NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Geographic coverage note +6 NR Linkage +8 R Field link and sequence number + +524 R PREFERRED CITATION OF DESCRIBED MATERIALS NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Preferred citation of described materials note +2 NR Source of schema used +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +525 R SUPPLEMENT NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Supplement note +6 NR Linkage +8 R Field link and sequence number + +526 R STUDY PROGRAM INFORMATION NOTE +ind1 08 Display constant controller +ind2 blank Undefined +a NR Program name +b NR Interest level +c NR Reading level +d NR Title point value +i NR Display text +x R Nonpublic note +z R Public note +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +530 R ADDITIONAL PHYSICAL FORM AVAILABLE NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Additional physical form available note +b NR Availability source +c NR Availability conditions +d NR Order number +u R Uniform Resource Identifier +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +533 R REPRODUCTION NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Type of reproduction +b R Place of reproduction +c R Agency responsible for reproduction +d NR Date of reproduction +e NR Physical description of reproduction +f R Series statement of reproduction +m R Dates and/or sequential designation of issues reproduced +n R Note about reproduction +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +7 NR Fixed-length data elements of reproduction +8 R Field link and sequence number + +534 R ORIGINAL VERSION NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Main entry of original +b NR Edition statement of original +c NR Publication, distribution, etc. of original +e NR Physical description, etc. of original +f R Series statement of original +k R Key title of original +l NR Location of original +m NR Material specific details +n R Note about original +o R Other resource identifier +p NR Introductory phrase +t NR Title statement of original +x R International Standard Serial Number +z R International Standard Book Number +6 NR Linkage +8 R Field link and sequence number + +535 R LOCATION OF ORIGINALS/DUPLICATES NOTE +ind1 12 Additional information about custodian +ind2 blank Undefined +a NR Custodian +b R Postal address +c R Country +d R Telecommunications address +g NR Repository location code +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +536 R FUNDING INFORMATION NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Text of note +b R Contract number +c R Grant number +d R Undifferentiated number +e R Program element number +f R Project number +g R Task number +h R Work unit number +6 NR Linkage +8 R Field link and sequence number + +538 R SYSTEM DETAILS NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR System details note +i NR Display text +u R Uniform Resource Identifier +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +540 R TERMS GOVERNING USE AND REPRODUCTION NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Terms governing use and reproduction +b NR Jurisdiction +c NR Authorization +d NR Authorized users +u R Uniform Resource Identifier +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +541 R IMMEDIATE SOURCE OF ACQUISITION NOTE +ind1 b01 Undefined +ind2 blank Undefined +a NR Source of acquisition +b NR Address +c NR Method of acquisition +d NR Date of acquisition +e NR Accession number +f NR Owner +h NR Purchase price +n R Extent +o R Type of unit +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +542 R INFORMATION RELATING TO COPYRIGHT STATUS +ind1 b01 Relationship +ind2 blank Undefined +a NR Personal creator +b NR Personal creator death date +c NR Corporate creator +d R Copyright holder +e R Copyright holder contact information +f R Copyright statement +g NR Copyright date +h R Copyright renewal date +i NR Publication date +j NR Creation date +k R Publisher +l NR Copyright status +m NR Publication status +n R Note +o NR Research date +q NR Assigning agency +r NR Jurisdiction of copyright assessment +s NR Source of information +u R Uniform Resource Identifier +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +544 R LOCATION OF OTHER ARCHIVAL MATERIALS NOTE +ind1 b01 Relationship +ind2 blank Undefined +a R Custodian +b R Address +c R Country +d R Title +e R Provenance +n R Note +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +545 R BIOGRAPHICAL OR HISTORICAL DATA +ind1 b01 Type of data +ind2 blank Undefined +a NR Biographical or historical note +b NR Expansion +u R Uniform Resource Identifier +6 NR Linkage +8 R Field link and sequence number + +546 R LANGUAGE NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Language note +b R Information code or alphabet +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +547 R FORMER TITLE COMPLEXITY NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Former title complexity note +6 NR Linkage +8 R Field link and sequence number + +550 R ISSUING BODY NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Issuing body note +6 NR Linkage +8 R Field link and sequence number + +552 R ENTITY AND ATTRIBUTE INFORMATION NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Entity type label +b NR Entity type definition and source +c NR Attribute label +d NR Attribute definition and source +e R Enumerated domain value +f R Enumerated domain value definition and source +g NR Range domain minimum and maximum +h NR Codeset name and source +i NR Unrepresentable domain +j NR Attribute units of measurement and resolution +k NR Beginning date and ending date of attribute values +l NR Attribute value accuracy +m NR Attribute value accuracy explanation +n NR Attribute measurement frequency +o R Entity and attribute overview +p R Entity and attribute detail citation +u R Uniform Resource Identifier +z R Display note +6 NR Linkage +8 R Field link and sequence number + +555 R CUMULATIVE INDEX/FINDING AIDS NOTE +ind1 b08 Display constant controller +ind2 blank Undefined +a NR Cumulative index/finding aids note +b R Availability source +c NR Degree of control +d NR Bibliographic reference +u R Uniform Resource Identifier +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +556 R INFORMATION ABOUT DOCUMENTATION NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Information about documentation note +z R International Standard Book Number +6 NR Linkage +8 R Field link and sequence number + +561 R OWNERSHIP AND CUSTODIAL HISTORY +ind1 b01 Undefined +ind2 blank Undefined +a NR History +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +562 R COPY AND VERSION IDENTIFICATION NOTE +ind1 blank Undefined +ind2 blank Undefined +a R Identifying markings +b R Copy identification +c R Version identification +d R Presentation format +e R Number of copies +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +563 R BINDING INFORMATION +ind1 blank Undefined +ind2 blank Undefined +a NR Binding note +u R Uniform Resource Identifier +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +565 R CASE FILE CHARACTERISTICS NOTE +ind1 b08 Display constant controller +ind2 blank Undefined +a NR Number of cases/variables +b R Name of variable +c R Unit of analysis +d R Universe of data +e R Filing scheme or code +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +567 R METHODOLOGY NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Methodology note +6 NR Linkage +8 R Field link and sequence number + +580 R LINKING ENTRY COMPLEXITY NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Linking entry complexity note +6 NR Linkage +8 R Field link and sequence number + +581 R PUBLICATIONS ABOUT DESCRIBED MATERIALS NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Publications about described materials note +z R International Standard Book Number +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +583 R ACTION NOTE +ind1 b01 Undefined +ind2 blank Undefined +a NR Action +b R Action identification +c R Time/date of action +d R Action interval +e R Contingency for action +f R Authorization +h R Jurisdiction +i R Method of action +j R Site of action +k R Action agent +l R Status +n R Extent +o R Type of unit +u R Uniform Resource Identifier +x R Nonpublic note +z R Public note +2 NR Source of term +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +584 R ACCUMULATION AND FREQUENCY OF USE NOTE +ind1 blank Undefined +ind2 blank Undefined +a R Accumulation +b R Frequency of use +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +585 R EXHIBITIONS NOTE +ind1 blank Undefined +ind2 blank Undefined +a NR Exhibitions note +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +586 R AWARDS NOTE +ind1 b8 Display constant controller +ind2 blank Undefined +a NR Awards note +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +600 R SUBJECT ADDED ENTRY--PERSONAL NAME +ind1 013 Type of personal name entry element +ind2 01234567 Thesaurus +a NR Personal name +b NR Numeration +c R Titles and other words associated with a name +d NR Dates associated with a name +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +j R Attribution qualifier +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +q NR Fuller form of name +r NR Key for music +s NR Version +t NR Title of a work +u NR Affiliation +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +610 R SUBJECT ADDED ENTRY--CORPORATE NAME +ind1 012 Type of corporate name entry element +ind2 01234567 Thesaurus +a NR Corporate name or jurisdiction name as entry element +b R Subordinate unit +c NR Location of meeting +d R Date of meeting or treaty signing +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section/meeting +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +u NR Affiliation +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +611 R SUBJECT ADDED ENTRY--MEETING NAME +ind1 012 Type of meeting name entry element +ind2 01234567 Thesaurus +a NR Meeting name or jurisdiction name as entry element +c NR Location of meeting +d NR Date of meeting +e R Subordinate unit +f NR Date of a work +g NR Miscellaneous information +h NR Medium +j R Relator term +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +q NR Name of meeting following jurisdiction name entry element +s NR Version +t NR Title of a work +u NR Affiliation +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +630 R SUBJECT ADDED ENTRY--UNIFORM TITLE +ind1 0-9 Nonfiling characters +ind2 01234567 Thesaurus +a NR Uniform title +d R Date of treaty signing +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +648 R SUBJECT ADDED ENTRY--CHRONOLOGICAL TERM +ind1 blank Undefined +ind2 01234567 Thesaurus +a NR Chronological term +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +650 R SUBJECT ADDED ENTRY--TOPICAL TERM +ind1 b012 Level of subject +ind2 01234567 Thesaurus +a NR Topical term or geographic name as entry element +b NR Topical term following geographic name as entry element +c NR Location of event +d NR Active dates +e NR Relator term +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +651 R SUBJECT ADDED ENTRY--GEOGRAPHIC NAME +ind1 blank Undefined +ind2 01234567 Thesaurus +a NR Geographic name +e R Relator term +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +653 R INDEX TERM--UNCONTROLLED +ind1 b012 Level of index term +ind2 b0123456 Type of term or name +a R Uncontrolled term +6 NR Linkage +8 R Field link and sequence number + +654 R SUBJECT ADDED ENTRY--FACETED TOPICAL TERMS +ind1 b012 Level of subject +ind2 blank Undefined +a R Focus term +b R Non-focus term +c R Facet/hierarchy designation +e R Relator term +v R Form subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +655 R INDEX TERM--GENRE/FORM +ind1 b0 Type of heading +ind2 01234567 Thesaurus +a NR Genre/form data or focus term +b R Non-focus term +c R Facet/hierarchy designation +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of term +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +656 R INDEX TERM--OCCUPATION +ind1 blank Undefined +ind2 7 Source of term +a NR Occupation +k NR Form +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of term +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +657 R INDEX TERM--FUNCTION +ind1 blank Undefined +ind2 7 Source of term +a NR Function +v R Form subdivision +x R General subdivision +y R Chronological subdivision +z R Geographic subdivision +0 R Authority record control number +2 NR Source of term +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +658 R INDEX TERM--CURRICULUM OBJECTIVE +ind1 blank Undefined +ind2 blank Undefined +a NR Main curriculum objective +b R Subordinate curriculum objective +c NR Curriculum code +d NR Correlation factor +2 NR Source of term or code +6 NR Linkage +8 R Field link and sequence number + +662 R SUBJECT ADDED ENTRY--HIERARCHICAL PLACE NAME +ind1 blank Undefined +ind2 blank Undefined +a R Country or larger entity +b NR First-order political jurisdiction +c R Intermediate political jurisdiction +d NR City +e R Relator term +f R City subsection +g R Other nonjurisdictional geographic region and feature +h R Extraterrestrial area +0 R Authority record control number +2 NR Source of heading or term +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +700 R ADDED ENTRY--PERSONAL NAME +ind1 013 Type of personal name entry element +ind2 b2 Type of added entry +a NR Personal name +b NR Numeration +c R Titles and other words associated with a name +d NR Dates associated with a name +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +j R Attribution qualifier +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +q NR Fuller form of name +r NR Key for music +s NR Version +t NR Title of a work +u NR Affiliation +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +4 R Relator code +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +710 R ADDED ENTRY--CORPORATE NAME +ind1 012 Type of corporate name entry element +ind2 b2 Type of added entry +a NR Corporate name or jurisdiction name as entry element +b R Subordinate unit +c NR Location of meeting +d R Date of meeting or treaty signing +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section/meeting +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +u NR Affiliation +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +4 R Relator code +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +711 R ADDED ENTRY--MEETING NAME +ind1 012 Type of meeting name entry element +ind2 b2 Type of added entry +a NR Meeting name or jurisdiction name as entry element +c NR Location of meeting +d NR Date of meeting +e R Subordinate unit +f NR Date of a work +g NR Miscellaneous information +h NR Medium +j R Relator term +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +q NR Name of meeting following jurisdiction name entry element +s NR Version +t NR Title of a work +u NR Affiliation +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +4 R Relator code +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +720 R ADDED ENTRY--UNCONTROLLED NAME +ind1 b12 Type of name +ind2 blank Undefined +a NR Name +e R Relator term +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +730 R ADDED ENTRY--UNIFORM TITLE +ind1 0-9 Nonfiling characters +ind2 b2 Type of added entry +a NR Uniform title +d R Date of treaty signing +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +740 R ADDED ENTRY--UNCONTROLLED RELATED/ANALYTICAL TITLE +ind1 0-9 Nonfiling characters +ind2 b2 Type of added entry +a NR Uncontrolled related/analytical title +h NR Medium +n R Number of part/section of a work +p R Name of part/section of a work +5 NR Institution to which field applies +6 NR Linkage +8 R Field link and sequence number + +751 R ADDED ENTRY--GEOGRAPHIC NAME +ind1 blank Undefined +ind2 blank Undefined +a NR Geographic name +e R Relator term +0 R Authority record control number +2 NR Source of heading or term +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +752 R ADDED ENTRY--HIERARCHICAL PLACE NAME +ind1 blank Undefined +ind2 blank Undefined +a NR Country or larger entity +b NR First-order political jurisdiction +c NR Intermediate political jurisdiction +d NR City +f R City subsection +g R Other nonjurisdictional geographic region and feature +h R Extraterrestrial area +0 R Authority record control number +2 NR Source of heading or term +6 NR Linkage +8 R Field link and sequence number + +753 R SYSTEM DETAILS ACCESS TO COMPUTER FILES +ind1 blank Undefined +ind2 blank Undefined +a NR Make and model of machine +b NR Programming language +c NR Operating system +6 NR Linkage +8 R Field link and sequence number + +754 R ADDED ENTRY--TAXONOMIC IDENTIFICATION +ind1 blank Undefined +ind2 blank Undefined +a R Taxonomic name +c R Taxonomic category +d R Common or alternative name +x R Non-public note +z R Public note +0 R Authority record control number +2 NR Source of taxonomic identification +6 NR Linkage +8 R Field link and sequence number + +760 R MAIN SERIES ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +m NR Material-specific details +n R Note +o R Other item identifier +s NR Uniform title +t NR Title +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +762 R SUBSERIES ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +m NR Material-specific details +n R Note +o R Other item identifier +s NR Uniform title +t NR Title +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +765 R ORIGINAL LANGUAGE ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +767 R TRANSLATION ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +770 R SUPPLEMENT/SPECIAL ISSUE ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +772 R SUPPLEMENT PARENT ENTRY +ind1 01 Note controller +ind2 b08 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Stan dard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +773 R HOST ITEM ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +p NR Abbreviated title +q NR Enumeration and first page +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +3 NR Materials specified +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +774 R CONSTITUENT UNIT ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +775 R OTHER EDITION ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +e NR Language code +f NR Country code +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +776 R ADDITIONAL PHYSICAL FORM ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +777 R ISSUED WITH ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +s NR Uniform title +t NR Title +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +780 R PRECEDING ENTRY +ind1 01 Note controller +ind2 01234567 Type of relationship +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +785 R SUCCEEDING ENTRY +ind1 01 Note controller +ind2 012345678 Type of relationship +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standa rd Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +786 R DATA SOURCE ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +j NR Period of content +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +p NR Abbreviated title +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +v NR Source Contribution +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +787 R NONSPECIFIC RELATIONSHIP ENTRY +ind1 01 Note controller +ind2 b8 Display constant controller +a NR Main entry heading +b NR Edition +c NR Qualifying information +d NR Place, publisher, and date of publication +g R Relationship information +h NR Physical description +i NR Display text +k R Series data for related item +m NR Material-specific details +n R Note +o R Other item identifier +r R Report number +s NR Uniform title +t NR Title +u NR Standard Technical Report Number +w R Record control number +x NR International Standard Serial Number +y NR CODEN designation +z R International Standard Book Number +6 NR Linkage +7 NR Control subfield +8 R Field link and sequence number + +800 R SERIES ADDED ENTRY--PERSONAL NAME +ind1 013 Type of personal name entry element +ind2 blank Undefined +a NR Personal name +b NR Numeration +c R Titles and other words associated with a name +d NR Dates associated with a name +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +j R Attribution qualifier +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +q NR Fuller form of name +r NR Key for music +s NR Version +t NR Title of a work +u NR Affiliation +v NR Volume/sequential designation +w R Bibliographic record control number +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +810 R SERIES ADDED ENTRY--CORPORATE NAME +ind1 012 Type of corporate name entry element +ind2 blank Undefined +a NR Corporate name or jurisdiction name as entry element +b R Subordinate unit +c NR Location of meeting +d R Date of meeting or treaty signing +e R Relator term +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section/meeting +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +u NR Affiliation +v NR Volume/sequential designation +w R Bibliographic record control number +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +811 R SERIES ADDED ENTRY--MEETING NAME +ind1 012 Type of meeting name entry element +ind2 blank Undefined +a NR Meeting name or jurisdiction name as entry element +c NR Location of meeting +d NR Date of meeting +e R Subordinate unit +f NR Date of a work +g NR Miscellaneous information +h NR Medium +j R Relator term +k R Form subheading +l NR Language of a work +n R Number of part/section/meeting +p R Name of part/section of a work +q NR Name of meeting following jurisdiction name entry element +s NR Version +t NR Title of a work +u NR Affiliation +v NR Volume/sequential designation +w R Bibliographic record control number +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +4 R Relator code +6 NR Linkage +8 R Field link and sequence number + +830 R SERIES ADDED ENTRY--UNIFORM TITLE +ind1 blank Undefined +ind2 0-9 Nonfiling characters +a NR Uniform title +d R Date of treaty signing +f NR Date of a work +g NR Miscellaneous information +h NR Medium +k R Form subheading +l NR Language of a work +m R Medium of performance for music +n R Number of part/section of a work +o NR Arranged statement for music +p R Name of part/section of a work +r NR Key for music +s NR Version +t NR Title of a work +v NR Volume/sequential designation +w R Bibliographic record control number +x NR International Standard Serial Number +0 R Authority record control number +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +841 NR HOLDINGS CODED DATA VALUES + +842 NR TEXTUAL PHYSICAL FORM DESIGNATOR + +843 R REPRODUCTION NOTE + +844 NR NAME OF UNIT + +845 R TERMS GOVERNING USE AND REPRODUCTION NOTE + +850 R HOLDING INSTITUTION +ind1 blank Undefined +ind2 blank Undefined +a R Holding institution +8 R Field link and sequence number + +852 R LOCATION +ind1 b012345678 Shelving scheme +ind2 b012 Shelving order +a NR Location +b R Sublocation or collection +c R Shelving location +d R Former shelving location +e R Address +f R Coded location qualifier +g R Non-coded location qualifier +h NR Classification part +i R Item part +j NR Shelving control number +k R Call number prefix +l NR Shelving form of title +m R Call number suffix +n NR Country code +p NR Piece designation +q NR Piece physical condition +s R Copyright article-fee code +t NR Copy number +u R Uniform Resource Identifier +x R Nonpublic note +z R Public note +2 NR Source of classification or shelving scheme +3 NR Materials specified +6 NR Linkage +8 NR Sequence number + +853 R CAPTIONS AND PATTERN--BASIC BIBLIOGRAPHIC UNIT + +854 R CAPTIONS AND PATTERN--SUPPLEMENTARY MATERIAL + +855 R CAPTIONS AND PATTERN--INDEXES + +856 R ELECTRONIC LOCATION AND ACCESS +ind1 b012347 Access method +ind2 b0128 Relationship +a R Host name +b R Access number +c R Compression information +d R Path +f R Electronic name +h NR Processor of request +i R Instruction +j NR Bits per second +k NR Password +l NR Logon +m R Contact for access assistance +n NR Name of location of host +o NR Operating system +p NR Port +q NR Electronic format type +r NR Settings +s R File size +t R Terminal emulation +u R Uniform Resource Identifier +v R Hours access method available +w R Record control number +x R Nonpublic note +y R Link text +z R Public note +2 NR Access method +3 NR Materials specified +6 NR Linkage +8 R Field link and sequence number + +863 R ENUMERATION AND CHRONOLOGY--BASIC BIBLIOGRAPHIC UNIT + +864 R ENUMERATION AND CHRONOLOGY--SUPPLEMENTARY MATERIAL + +865 R ENUMERATION AND CHRONOLOGY--INDEXES + +866 R TEXTUAL HOLDINGS--BASIC BIBLIOGRAPHIC UNIT + +867 R TEXTUAL HOLDINGS--SUPPLEMENTARY MATERIAL + +868 R TEXTUAL HOLDINGS--INDEXES + +876 R ITEM INFORMATION--BASIC BIBLIOGRAPHIC UNIT + +877 R ITEM INFORMATION--SUPPLEMENTARY MATERIAL + +878 R ITEM INFORMATION--INDEXES + +880 R ALTERNATE GRAPHIC REPRESENTATION +ind1 Same as associated field +ind2 Same as associated field +6 NR Linkage + +882 NR REPLACEMENT RECORD INFORMATION +ind1 blank Undefined +ind2 blank Undefined +a R Replacement title +i R Explanatory text +w R Replacement bibliographic record control number +6 NR Linkage +8 R Field link and sequence number + +886 R FOREIGN MARC INFORMATION FIELD +ind1 012 Type of field +ind2 blank Undefined +a NR Tag of the foreign MARC field +b NR Content of the foreign MARC field +c-z NR Foreign MARC subfield +0-1 NR Foreign MARC subfield +2 NR Source of data +4 NR Source of data +3-9 NR Source of data + +887 R NON-MARC INFORMATION FIELD +ind1 blank Undefined +ind2 blank Undefined +a NR Content of non-MARC field +2 NR Source of data +RULES; + // @codingStandardsIgnoreEnd + } + // }}} +} +// }}} + diff --git a/vendor/File/MARC/Lint/CodeData.php b/vendor/File/MARC/Lint/CodeData.php new file mode 100644 index 0000000000000000000000000000000000000000..cae0c129e9944e2b03edb18d4782c6d9e92098ed --- /dev/null +++ b/vendor/File/MARC/Lint/CodeData.php @@ -0,0 +1,166 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Code Data to support Lint for MARC records + * + * This module is adapted from the MARC::Lint::CodeData CPAN module for Perl, + * maintained by Bryan Baldus <eijabb@cpan.org> and available for download at + * http://search.cpan.org/~eijabb/ + * + * Current MARC::Lint::CodeData version used as basis for this module: 1.28 + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Demian Katz <demian.katz@villanova.edu> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Lint +/** + * Contains codes from the MARC code lists for Geographic Areas, Languages, and + * Countries. + * + * Code data is used for validating fields 008, 040, 041, and 043. + * + * Also, sources for subfield 2 in 600-651 and 655. + * + * Note: According to the official MARC documentation, Sears is not a valid 655 + * term. The code data below treats it as valid, in anticipation of a change in + * the official documentation. + * + * @category File_Formats + * @package File_MARC + * @author Demian Katz <demian.katz@villanova.edu> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Lint_CodeData +{ + + // {{{ properties + /** + * Valid Geographic Area Codes + * @var array + */ + public $geogAreaCodes; + + /** + * Obsolete Geographic Area Codes + * @var array + */ + public $obsoleteGeogAreaCodes; + + /** + * Valid Language Codes + * @var array + */ + public $languageCodes; + + /** + * Obsolete Language Codes + * @var array + */ + public $obsoleteLanguageCodes; + + /** + * Valid Country Codes + * @var array + */ + public $countryCodes; + + /** + * Obsolete Country Codes + * @var array + */ + public $obsoleteCountryCodes; + + /** + * Valid sources for fields 600-651 + * @var array + */ + public $sources600_651; + + /** + * Obsolete sources for fields 600-651 + * @var array + */ + public $obsoleteSources600_651; + + /** + * Valid sources for field 655 + * @var array + */ + public $sources655; + + /** + * Obsolete sources for field 655 + * @var array + */ + public $obsoleteSources655; + + // }}} + + // {{{ Constructor: function __construct() + /** + * Start function + * + * Initialize code arrays. + * + * @return true + */ + public function __construct() + { + // @codingStandardsIgnoreStart + // fill the valid Geographic Area Codes array + $this->geogAreaCodes = explode("\t", "a-af--- f------ fc----- fe----- fq----- ff----- fh----- fs----- fb----- fw----- n-us-al n-us-ak e-aa--- n-cn-ab f-ae--- ea----- sa----- poas--- aa----- sn----- e-an--- f-ao--- nwxa--- a-cc-an t------ nwaq--- nwla--- n-usa-- ma----- ar----- au----- r------ s-ag--- n-us-az n-us-ar a-ai--- nwaw--- lsai--- u-ac--- a------ ac----- as----- l------ fa----- u------ u-at--- u-at-ac e-au--- a-aj--- lnaz--- nwbf--- a-ba--- ed----- eb----- a-bg--- nwbb--- a-cc-pe e-bw--- e-be--- ncbh--- el----- ab----- f-dm--- lnbm--- a-bt--- mb----- a-ccp-- s-bo--- nwbn--- a-bn--- e-bn--- f-bs--- lsbv--- s-bl--- n-cn-bc i-bi--- nwvb--- a-bx--- e-bu--- f-uv--- a-br--- f-bd--- n-us-ca a-cb--- f-cm--- n-cn--- nccz--- lnca--- lncv--- cc----- poci--- ak----- e-urk-- e-urr-- nwcj--- f-cx--- nc----- e-urc-- f-cd--- s-cl--- a-cc--- a-cc-cq i-xa--- i-xb--- q------ s-ck--- n-us-co b------ i-cq--- f-cf--- f-cg--- fg----- n-us-ct pocw--- u-cs--- nccr--- e-ci--- nwcu--- nwco--- a-cy--- e-xr--- e-cs--- f-iv--- eo----- zd----- n-us-de e-dk--- dd----- d------ f-ft--- nwdq--- nwdr--- x------ n-usr-- ae----- an----- a-em--- poea--- xa----- s-ec--- f-ua--- nces--- e-uk-en f-eg--- f-ea--- e-er--- f-et--- me----- e------ ec----- ee----- en----- es----- ew----- lsfk--- lnfa--- pofj--- e-fi--- n-us-fl e-fr--- h------ s-fg--- pofp--- a-cc-fu f-go--- pogg--- f-gm--- a-cc-ka awgz--- n-us-ga a-gs--- e-gx--- e-ge--- e-gw--- f-gh--- e-gi--- e-uk--- e-uk-ui nl----- np----- fr----- e-gr--- n-gl--- nwgd--- nwgp--- pogu--- a-cc-kn a-cc-kc ncgt--- f-gv--- f-pg--- a-cc-kw s-gy--- a-cc-ha nwht--- n-us-hi i-hm--- a-cc-hp a-cc-he a-cc-ho ah----- nwhi--- ncho--- a-cc-hk a-cc-hh n-cnh-- a-cc-hu e-hu--- e-ic--- n-us-id n-us-il a-ii--- i------ n-us-in ai----- a-io--- a-cc-im m------ c------ n-us-ia a-ir--- a-iq--- e-ie--- a-is--- e-it--- nwjm--- lnjn--- a-ja--- a-cc-ku a-cc-ki a-cc-kr poji--- a-jo--- zju---- n-us-ks a-kz--- n-us-ky f-ke--- poki--- pokb--- a-kr--- a-kn--- a-ko--- a-cck-- a-ku--- a-kg--- a-ls--- cl----- e-lv--- a-le--- nwli--- f-lo--- a-cc-lp f-lb--- f-ly--- e-lh--- poln--- e-li--- n-us-la e-lu--- a-cc-mh e-xn--- f-mg--- lnma--- n-us-me f-mw--- am----- a-my--- i-xc--- f-ml--- e-mm--- n-cn-mb poxd--- n-cnm-- zma---- poxe--- nwmq--- n-us-md n-us-ma f-mu--- i-mf--- i-my--- mm----- ag----- pome--- zme---- n-mx--- nm----- n-us-mi pott--- pomi--- n-usl-- aw----- n-usc-- poxf--- n-us-mn n-us-ms n-usm-- n-us-mo n-uss-- e-mv--- e-mc--- a-mp--- n-us-mt nwmj--- zmo---- f-mr--- f-mz--- f-sx--- ponu--- n-us-nb a-np--- zne---- e-ne--- nwna--- n-us-nv n-cn-nk ponl--- n-usn-- a-nw--- n-us-nh n-us-nj n-us-nm u-at-ne n-us-ny u-nz--- n-cn-nf ncnq--- f-ng--- fi----- f-nr--- fl----- a-cc-nn poxh--- n------ ln----- n-us-nc n-us-nd pn----- n-use-- xb----- e-uk-ni u-at-no n-cn-nt e-no--- n-cn-ns n-cn-nu po----- n-us-oh n-uso-- n-us-ok a-mk--- n-cn-on n-us-or zo----- p------ a-pk--- popl--- ncpn--- a-pp--- aopf--- s-py--- n-us-pa ap----- s-pe--- a-ph--- popc--- zpl---- e-pl--- pops--- e-po--- n-cnp-- n-cn-pi nwpr--- ep----- a-qa--- a-cc-ts u-at-qn n-cn-qu mr----- er----- n-us-ri sp----- nr----- e-rm--- e-ru--- e-ur--- e-urf-- f-rw--- i-re--- nwsd--- fd----- nweu--- lsxj--- nwxi--- nwxk--- nwst--- n-xl--- nwxm--- pows--- posh--- e-sm--- f-sf--- n-cn-sn zsa---- a-su--- ev----- e-uk-st f-sg--- i-se--- a-cc-ss a-cc-sp a-cc-sm a-cc-sh e-urs-- e-ure-- e-urw-- a-cc-sz f-sl--- a-si--- e-xo--- e-xv--- i-xo--- zs----- pobp--- f-so--- f-sa--- s------ az----- ls----- u-at-sa n-us-sc ao----- n-us-sd lsxs--- ps----- xc----- n-usu-- n-ust-- e-urn-- e-sp--- f-sh--- aoxp--- a-ce--- f-sj--- fn----- fu----- zsu---- s-sr--- lnsb--- nwsv--- f-sq--- e-sw--- e-sz--- a-sy--- a-ch--- a-ta--- f-tz--- u-at-tm n-us-tn i-fs--- n-us-tx a-th--- af----- a-cc-tn a-cc-ti at----- f-tg--- potl--- poto--- nwtr--- lstd--- w------ f-ti--- a-tu--- a-tk--- nwtc--- potv--- f-ug--- e-un--- a-ts--- n-us--- nwuc--- poup--- e-uru-- zur---- s-uy--- n-us-ut a-uz--- ponn--- e-vc--- s-ve--- zve---- n-us-vt u-at-vi a-vt--- nwvi--- n-us-va e-urp-- fv----- powk--- e-uk-wl powf--- n-us-dc n-us-wa n-usp-- awba--- nw----- n-us-wv u-at-we xd----- f-ss--- nwwi--- n-us-wi n-us-wy a-ccs-- a-cc-su a-ccg-- a-ccy-- ay----- a-ye--- e-yu--- n-cn-yk a-cc-yu fz----- f-za--- a-cc-ch f-rh--- u-atc-- u-ate-- u-atn-- e-rb--- e-mo--- e-kv---"); + + // fill the obsolete Geographic Area Codes array + $this->obsoleteGeogAreaCodes = explode("\t", "t-ay--- e-ur-ai e-ur-aj nwbc--- e-ur-bw f-by--- pocp--- e-url-- cr----- v------ e-ur-er et----- e-ur-gs pogn--- nwga--- nwgs--- a-hk--- ei----- f-if--- awiy--- awiw--- awiu--- e-ur-kz e-ur-kg e-ur-lv e-ur-li a-mh--- cm----- e-ur-mv n-usw-- a-ok--- a-pt--- e-ur-ru pory--- nwsb--- posc--- a-sk--- posn--- e-uro-- e-ur-ta e-ur-tk e-ur-un e-ur-uz a-vn--- a-vs--- nwvr--- e-urv-- a-ys---"); + + // fill the valid Language Codes array + $this->languageCodes = explode("\t", " aar abk ace ach ada ady afa afh afr ain aka akk alb ale alg alt amh ang anp apa ara arc arg arm arn arp art arw asm ast ath aus ava ave awa aym aze bad bai bak bal bam ban baq bas bat bej bel bem ben ber bho bih bik bin bis bla bnt bos bra bre btk bua bug bul bur byn cad cai car cat cau ceb cel cha chb che chg chi chk chm chn cho chp chr chu chv chy cmc cop cor cos cpe cpf cpp cre crh crp csb cus cze dak dan dar day del den dgr din div doi dra dsb dua dum dut dyu dzo efi egy eka elx eng enm epo est ewe ewo fan fao fat fij fil fin fiu fon fre frm fro frr frs fry ful fur gaa gay gba gem geo ger gez gil gla gle glg glv gmh goh gon gor got grb grc gre grn gsw guj gwi hai hat hau haw heb her hil him hin hit hmn hmo hrv hsb hun hup iba ibo ice ido iii ijo iku ile ilo ina inc ind ine inh ipk ira iro ita jav jbo jpn jpr jrb kaa kab kac kal kam kan kar kas kau kaw kaz kbd kha khi khm kho kik kin kir kmb kok kom kon kor kos kpe krc krl kro kru kua kum kur kut lad lah lam lao lat lav lez lim lin lit lol loz ltz lua lub lug lui lun luo lus mac mad mag mah mai mak mal man mao map mar mas may mdf mdr men mga mic min mis mkh mlg mlt mnc mni mno moh mon mos mul mun mus mwl mwr myn myv nah nai nap nau nav nbl nde ndo nds nep new nia nic niu nno nob nog non nor nqo nso nub nwc nya nym nyn nyo nzi oci oji ori orm osa oss ota oto paa pag pal pam pan pap pau peo per phi phn pli pol pon por pra pro pus que raj rap rar roa roh rom rum run rup rus sad sag sah sai sal sam san sas sat scn sco sel sem sga sgn shn sid sin sio sit sla slo slv sma sme smi smj smn smo sms sna snd snk sog som son sot spa srd srn srp srr ssa ssw suk sun sus sux swa swe syc syr tah tai tam tat tel tem ter tet tgk tgl tha tib tig tir tiv tkl tlh tli tmh tog ton tpi tsi tsn tso tuk tum tup tur tut tvl twi tyv udm uga uig ukr umb und urd uzb vai ven vie vol vot wak wal war was wel wen wln wol xal xho yao yap yid yor ypk zap zbl zen zha znd zul zun zxx zza"); + + // fill the obsolete Language Codes array + $this->obsoleteLanguageCodes = explode("\t", "ajm esk esp eth far fri gag gua int iri cam kus mla max mol lan gal lap sao gae scc scr sho snh sso swz tag taj tar tru tsw"); + + // fill the valid Country Codes array + $this->countryCodes = explode("\t", "aca af alu aku aa abc ae as an ao am ay aq ag azu aru ai aw at au aj bf ba bg bb bw be bh dm bm bt bo bn bs bv bl bcc bi vb bx bu uv br bd cau cb cm xxc cv cj cx cd cl cc ch xa xb ck cou cq cf cg ctu cw cr ci cu cy xr iv deu dk dcu ft dq dr em ec ua es enk eg ea er et fk fa fj fi flu fr fg fp go gm gz gau gs gw gh gi gr gl gd gp gu gt gv pg gy ht hiu hm ho hu ic idu ilu ii inu io iau ir iq iy ie is it jm ja ji jo ksu kv kz kyu ke gb kn ko ku kg ls lv le lo lb ly lh li lau lu xn mg meu mw my xc ml mm mbc xe mq mdu mau mu mf ot mx miu fm xf mnu msu mou mv mc mp mtu mj mr mz sx nu nbu np ne na nvu nkc nl nhu nju nmu nyu nz nfc nq ng nr xh xx nx ncu ndu nik nw ntc no nsc nuc ohu oku mk onc oru pk pw pn pp pf py pau pe ph pc pl po pic pr qa qea quc riu rm ru rw re xj xd xk xl xm ws sm sf snc su stk sg rb mo se sl si xo xv bp so sa scu sdu xs sp sh xp ce sj sr sq sw sz sy ta tz tnu fs txu th tg tl tma to tr ti tu tk tc tv ug un ts xxk uik xxu uc up uy utu uz nn vp vc ve vtu vm vi vau vra wea wk wlk wf wau wj wvu ss wiu wyu xga xna xoa xra ye ykc za rh "); + + // fill the obsolete Country Codes array + $this->obsoleteCountryCodes = explode("\t", "ai air ac ajr bwr cn cz cp ln cs err gsr ge gn hk iw iu jn kzr kgr lvr lir mh mvr nm pt rur ry xi sk xxr sb sv tar tt tkr unr uk ui us uzr vn vs wb ys yu "); + + // the codes cash, lcsh, lcshac, mesh, nal, and rvm are covered by 2nd + // indicators in 600-655 + // they are only used when indicators are not available + $this->sources600_651 = explode("\t", "aass aat abne afset agrifors agrovoc agrovocf agrovocs aiatsisl aiatsisp aiatsiss aktp albt allars amg apaist asft asrcrfcd asrcseo asrctoa asth atla aucsh barn bella bet bgtchm bhammf bhashe bibalex biccbmc bicssc bidex bisacsh bisacmt bisacrt blmlsh bt cabt cash cct ccte cctf ceeus chirosh cht ciesiniv cilla conorsi csahssa csalsct csapa csh csht cstud czenas dacs dcs ddcrit dissao dit drama dtict ebfem eclas eet eflch eks embne ept ericd est eurovocen eurovocsl fast fgtpcm finmesh fire fmesh fnhl francis galestne gem georeft gst gtt hapi hkcan helecon henn hlasstg hoidokki huc iaat ica icpsr idas iescs iest ilot ilpt inist inspect ipat ipsp isis itglit itoamc itrt jhpb jhpk jlabsh kaa kao kaunokki kdm kitu kkts kssbar kta ktpt ktta kula kupu lacnaf larpcal lcsh lcshac lcstt lctgm lemac lemb liv lnmmbr local ltcsh lua maaq mar masa mech mesh mipfesd mmm mpirdes msh mtirdes musa muzeukc muzeukn muzeukv muzvukci nal nalnaf nasat ncjt ndllsh nicem nimacsc nlgaf nlgkk nlgsh nlmnaf nsbncf ntcpsc ntcsd ntissc nzggn nznb ogst onet opms pascal peri pha pkk pmbok pmcsg pmt poliscit popinte precis prvt psychit quiding qlsp qrma qrmak qtglit raam ram rasuqam renib reo rero rerovoc reveal rma rpe rswk rswkaf rugeo rurkp rvm sao sbiao scbi scgdst scisshl scot sears sfit sgc sgce shbe she sigle sipri sk skon slem smda snt socio sosa spines ssg swd swemesh taika taxhs tbit tesa test tgn tho thub tlka tlsh toit trt trtsa tsht ttka tucua ulan umitrist unbisn unbist unescot usaidt vmj waqaf watrest wgst wot wpicsh ysa"); + $this->obsoleteSources600_651 = explode("\t", "cash lcsh lcshac mesh nal reroa rvm"); + $this->sources655 = explode("\t", "aat afset aiatsisl aiatsisp aiatsiss aktp amg asrcrfcd asrcseo asrctoa asth aucsh barn bibalex biccbmc bgtchm bisacsh bisacmt bisacrt bt cash chirosh cct conorsi csht czenas dacs dcs dct eet eflch embne ept ericd estc eurovocen eurovocsl fast fbg finmesh fire galestne gem gmgpc gsafd gst gtlm hapi hkcan hoidokki ica ilot itglit itrt jhpb jhpk kkts lacnaf lcsh lcshac lcstt lctgm lemac local maaq mar marcgt mech mesh migfg mim msh muzeukc muzeukn muzeukv muzvukci nal nalnaf ngl nimafc nlgaf nlgkk nlgsh nlmnaf nmc nsbncf nzggn nznb onet opms pkk pmcsg pmt quiding qlsp qrmak qtglit raam radfg rbbin rbgenr rbpap rbpri rbprov rbpub rbtyp reo rerovoc reveal rma rswk rswkaf rugeo rvm sao scbi sears sgc sgce sgp sipri skon snt socio spines ssg swd swemesh tbit tesa tho thub toit tsht tucua ulan vmj waqaf"); + $this->obsoleteSources655 = explode("\t", "cash ftamc lcsh lcshac mesh nal reroa rvm"); + // @codingStandardsIgnoreEnd + } + // }}} +} +// }}} diff --git a/vendor/File/MARC/List.php b/vendor/File/MARC/List.php new file mode 100644 index 0000000000000000000000000000000000000000..878b62fea80c3bfce4ed034531d8f25578d170cc --- /dev/null +++ b/vendor/File/MARC/List.php @@ -0,0 +1,98 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: List.php 268035 2008-10-30 17:01:14Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_List extends Structures_LinkedList_Double +/** + * The File_MARC_List class extends the Structures_LinkedList_Double class + * to override the key() method in a meaningful way for foreach() iterators. + * + * For the list of {@link File_MARC_Field} objects in a {@link File_MARC_Record} + * object, the key() method returns the tag name of the field. + * + * For the list of {@link File_MARC_Subfield} objects in a {@link + * File_MARC_Data_Field} object, the key() method returns the code of + * the subfield. + * + * <code> + * // Iterate through the fields in a record with key=>value iteration + * foreach ($record->getFields() as $tag=>$value) { + * print "$tag: "; + * if ($value instanceof File_MARC_Control_Field) { + * print $value->getData(); + * } + * else { + * // Iterate through the subfields in this data field + * foreach ($value->getSubfields() as $code=>$subdata) { + * print "_$code"; + * } + * } + * print "\n"; + * } + * </code> + * + * @category File_Formats + * @package File_MARC + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_List extends Structures_LinkedList_Double +{ + // {{{ key() + /** + * Returns the tag for a {@link File_MARC_Field} object, or the code + * for a {@link File_MARC_Subfield} object. + * + * This method enables you to use a foreach iterator to retrieve + * the tag or code as the key for the iterator. + * + * @return string returns the tag or code + */ + function key() + { + if ($this->current() instanceof File_MARC_Field) { + return $this->current()->getTag(); + } elseif ($this->current() instanceof File_MARC_Subfield) { + return $this->current()->getCode(); + } + return false; + } + // }}} +} +// }}} + diff --git a/vendor/File/MARC/Record.php b/vendor/File/MARC/Record.php new file mode 100644 index 0000000000000000000000000000000000000000..43e91a08edde3cc77014ea745e4d88d4017355ae --- /dev/null +++ b/vendor/File/MARC/Record.php @@ -0,0 +1,691 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Record +/** + * Represents a single MARC record + * + * A MARC record contains a leader and zero or more fields held within a + * linked list structure. Fields are represented by {@link File_MARC_Data_Field} + * objects. + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Record +{ + + // {{{ properties + /** + * Contains a linked list of {@link File_MARC_Data_Field} objects for + * this record + * @var File_MARC_List + */ + protected $fields; + + /** + * Record leader + * @var string + */ + protected $leader; + + /** + * Non-fatal warnings generated during parsing + * @var array + */ + protected $warnings; + + /** + * XMLWriter for writing collections + * + * @var XMLWriter + */ + protected $marcxml; + + /** + * MARC instance for access to the XML header/footer methods + * We need this so that we can properly wrap a collection of MARC records. + * + * @var File_MARC + */ + protected $marc; + + // }}} + + // {{{ Constructor: function __construct() + /** + * Start function + * + * Set all variables to defaults to create new File_MARC_Record object + * + * @param File_MARC $marc MARC record from File_MARC or File_MARCXML + * + * @return true + */ + function __construct($marc = null) + { + $this->fields = new File_MARC_List(); + $this->setLeader(str_repeat(' ', 24)); + if (!$marc) { + $marc = new File_MARC(null, File_MARC::SOURCE_STRING); // oh the hack + } + $this->marc = $marc; + $this->marcxml = $marc->getXMLWriter(); + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Destroys the data field + */ + function __destruct() + { + $this->fields = null; + $this->warnings = null; + } + // }}} + + // {{{ getLeader() + /** + * Get MARC leader + * + * Returns the leader for the MARC record. No validation + * on the specified leader is performed. + * + * @return string returns the leader + */ + function getLeader() + { + return (string)$this->leader; + } + // }}} + + // {{{ setLeader() + /** + * Set MARC record leader + * + * Sets the leader for the MARC record. No validation + * on the specified leader is performed. + * + * @param string $leader Leader + * + * @return string returns the leader + */ + function setLeader($leader) + { + $this->leader = $leader; + return $this->leader; + } + // }}} + + // {{{ appendField() + /** + * Appends field to MARC record + * + * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field} + * object to the end of the existing list of fields. + * + * @param File_MARC_Field $new_field The field to add + * + * @return File_MARC_Field The field that was added + */ + function appendField(File_MARC_Field $new_field) + { + /* Append as the last field in the record */ + $this->fields->appendNode($new_field); + return $new_field; + } + // }}} + + // {{{ prependField() + /** + * Prepends field to MARC record + * + * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field} + * object to the start of to the existing list of fields. + * + * @param File_MARC_Field $new_field The field to add + * + * @return File_MARC_Field The field that was added + */ + function prependField(File_MARC_Field $new_field) + { + $this->fields->prependNode($new_field); + return $new_field; + } + // }}} + + // {{{ insertField() + /** + * Inserts a field in the MARC record relative to an existing field + * + * Inserts a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field} + * object before or after a specified existing field. + * + * <code> + * // Example: Insert a new field before the first 650 field + * + * // Create the new field + * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.'); + * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null); + * + * // Retrieve the target field for our insertion point + * $subject = $record->getFields('650'); + * + * // Insert the new field + * if (is_array($subject)) { + * $record->insertField($new_field, $subject[0], true); + * } + * elseif ($subject) { + * $record->insertField($new_field, $subject, true); + * } + * </code> + * + * @param File_MARC_Field $new_field The field to add + * @param File_MARC_Field $existing_field The target field + * @param bool $before Insert the new field before the existing field if true, after the existing field if false + * + * @return File_MARC_Field The field that was added + */ + function insertField(File_MARC_Field $new_field, File_MARC_Field $existing_field, $before = false) + { + switch ($before) { + /* Insert before the specified field in the record */ + case true: + $this->fields->insertNode($new_field, $existing_field, true); + break; + + /* Insert after the specified field in the record */ + case false: + $this->fields->insertNode($new_field, $existing_field); + break; + + default: + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INSERTFIELD_MODE], array("mode" => $before)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INSERTFIELD_MODE); + } + return $new_field; + } + // }}} + + // {{{ _buildDirectory() + /** + * Build record directory + * + * Generate the directory of the record according to the current contents + * of the record. + * + * @return array Array ($fields, $directory, $total, $base_address) + */ + private function _buildDirectory() + { + // Vars + $fields = array(); + $directory = array(); + $data_end = 0; + + foreach ($this->fields as $field) { + // No empty fields allowed + if (!$field->isEmpty()) { + // Get data in raw format + $str = $field->toRaw(); + $fields[] = $str; + + // Create directory entry + $len = strlen($str); + $direntry = sprintf("%03s%04d%05d", $field->getTag(), $len, $data_end); + $directory[] = $direntry; + $data_end += $len; + } + } + + /** + * Rules from MARC::Record::USMARC + */ + $base_address + = File_MARC::LEADER_LEN + // better be 24 + (count($directory) * File_MARC::DIRECTORY_ENTRY_LEN) + + // all the directory entries + 1; // end-of-field marker + + + $total + = $base_address + // stuff before first field + $data_end + // Length of the fields + 1; // End-of-record marker + + + return array($fields, $directory, $total, $base_address); + } + // }}} + + // {{{ setLeaderLengths() + /** + * Set MARC record leader lengths + * + * Set the Leader lengths of the record according to defaults specified in + * {@link http://www.loc.gov/marc/bibliographic/ecbdldrd.html} + * + * @param int $record_length Record length + * @param int $base_address Base address of data + * + * @return bool Success or failure + */ + function setLeaderLengths($record_length, $base_address) + { + if (!is_int($record_length)) { + return false; + } + if (!is_int($base_address)) { + return false; + } + + // Set record length + $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $record_length), 0, 5)); + $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $base_address), File_MARC::DIRECTORY_ENTRY_LEN, 5)); + $this->setLeader(substr_replace($this->getLeader(), '22', 10, 2)); + $this->setLeader(substr_replace($this->getLeader(), '4500', 20, 4)); + + if (strlen($this->getLeader()) > File_MARC::LEADER_LEN) { + // Avoid incoming leaders that are mangled to be overly long + $this->setLeader(substr($this->getLeader(), 0, File_MARC::LEADER_LEN)); + $this->addWarning("Input leader was too long; truncated to " . File_MARC::LEADER_LEN . " characters"); + } + return true; + } + // }}} + + // {{{ getField() + /** + * Return the first {@link File_MARC_Data_Field} or + * {@link File_MARC_Control_Field} object that matches the specified tag + * name. Returns false if no match is found. + * + * @param string $spec tag name + * @param bool $pcre if true, then match as a regular expression + * + * @return {@link File_MARC_Data_Field}|{@link File_MARC_Control_Field} first field that matches the requested tag name + */ + function getField($spec = null, $pcre = null) + { + foreach ($this->fields as $field) { + if (($pcre + && preg_match("/$spec/", $field->getTag())) + || (!$pcre + && $spec == $field->getTag()) + ) { + return $field; + } + } + return false; + } + // }}} + + // {{{ getFields() + /** + * Return an array or {@link File_MARC_List} containing all + * {@link File_MARC_Data_Field} or {@link File_MARC_Control_Field} objects + * that match the specified tag name. If the tag name is omitted all + * fields are returned. + * + * @param string $spec tag name + * @param bool $pcre if true, then match as a regular expression + * + * @return File_MARC_List|array {@link File_MARC_Data_Field} or + * {@link File_MARC_Control_Field} objects that match the requested tag name + */ + function getFields($spec = null, $pcre = null) + { + if (!$spec) { + return $this->fields; + } + + // Okay, we're actually looking for something specific + $matches = array(); + foreach ($this->fields as $field) { + if (($pcre && preg_match("/$spec/", $field->getTag())) + || (!$pcre && $spec == $field->getTag()) + ) { + $matches[] = $field; + } + } + return $matches; + } + // }}} + + // {{{ deleteFields() + /** + * Delete all occurrences of a field matching a tag name from the record. + * + * @param string $tag tag for the fields to be deleted + * @param bool $pcre if true, then match as a regular expression + * + * @return int number of fields that were deleted + */ + function deleteFields($tag, $pcre = null) + { + $cnt = 0; + foreach ($this->getFields() as $field) { + if (($pcre + && preg_match("/$tag/", $field->getTag())) + || (!$pcre + && $tag == $field->getTag()) + ) { + $field->delete(); + $cnt++; + } + } + return $cnt; + } + // }}} + + // {{{ addWarning() + /** + * Add a warning to the MARC record that something non-fatal occurred during + * parsing. + * + * @param string $warning warning message + * + * @return true + */ + public function addWarning($warning) + { + $this->warnings[] = $warning; + } + // }}} + + // {{{ getWarnings() + /** + * Return the array of warnings from the MARC record. + * + * @return array warning messages + */ + public function getWarnings() + { + return $this->warnings; + } + // }}} + + // {{{ output methods + /** + * ========== OUTPUT METHODS ========== + */ + + // {{{ toRaw() + /** + * Return the record in raw MARC format. + * + * If you have modified an existing MARC record or created a new MARC + * record, use this method to save the record for use in other programs + * that accept the MARC format -- for example, your integrated library + * system. + * + * <code> + * // Example: Modify a record and save the output to a file + * $record->deleteFields('650'); + * + * // Now that the record has no subject fields, save it to disk + * fopen($file, '/home/dan/no_subject.mrc', 'w'); + * fwrite($file, $record->toRaw()); + * fclose($file); + * </code> + * + * @return string Raw MARC data + */ + function toRaw() + { + list($fields, $directory, $record_length, $base_address) = $this->_buildDirectory(); + $this->setLeaderLengths($record_length, $base_address); + + /** + * Glue together all parts + */ + return $this->getLeader().implode("", $directory).File_MARC::END_OF_FIELD.implode("", $fields).File_MARC::END_OF_RECORD; + } + // }}} + + // {{{ __toString() + /** + * Return the MARC record in a pretty printed string + * + * This method produces an easy-to-read textual display of a MARC record. + * + * The structure is roughly: + * <tag> <ind1> <ind2> _<code><data> + * _<code><data> + * + * @return string Formatted representation of MARC record + */ + function __toString() + { + // Begin output + $formatted = "LDR " . $this->getLeader() . "\n"; + foreach ($this->fields as $field) { + if (!$field->isEmpty()) { + $formatted .= $field->__toString() . "\n"; + } + } + return $formatted; + } + // }}} + + // {{{ toJSON() + /** + * Return the MARC record in JSON format + * + * This method produces a JSON representation of a MARC record. The input + * encoding must be UTF8, otherwise the returned values will be corrupted. + * + * @return string representation of MARC record in JSON format + * + * @todo Fix encoding input / output issues (PHP 6.0 required?) + */ + function toJSON() + { + $json = new StdClass(); + $json->leader = utf8_encode($this->getLeader()); + + /* Start fields */ + $fields = array(); + foreach ($this->fields as $field) { + if (!$field->isEmpty()) { + switch(get_class($field)) { + case "File_MARC_Control_Field": + $fields[] = array(utf8_encode($field->getTag()) => utf8_encode($field->getData())); + break; + + case "File_MARC_Data_Field": + $subs = array(); + foreach ($field->getSubfields() as $sf) { + $subs[] = array(utf8_encode($sf->getCode()) => utf8_encode($sf->getData())); + } + $contents = new StdClass(); + $contents->ind1 = utf8_encode($field->getIndicator(1)); + $contents->ind2 = utf8_encode($field->getIndicator(2)); + $contents->subfields = $subs; + $fields[] = array(utf8_encode($field->getTag()) => $contents); + break; + } + } + } + /* End fields and record */ + + $json->fields = $fields; + return json_encode($json); + } + + // }}} + + // {{{ toJSONHash() + /** + * Return the MARC record in Bill Dueber's MARC-HASH JSON format + * + * This method produces a JSON representation of a MARC record as defined + * at http://robotlibrarian.billdueber.com/new-interest-in-marc-hash-json/ + * The input * encoding must be UTF8, otherwise the returned values will + * be corrupted. + * + * @return string representation of MARC record in JSON format + * + * @todo Fix encoding input / output issues (PHP 6.0 required?) + */ + function toJSONHash() + { + $json = new StdClass(); + $json->type = "marc-hash"; + $json->version = array(1, 0); + $json->leader = utf8_encode($this->getLeader()); + + /* Start fields */ + $fields = array(); + foreach ($this->fields as $field) { + if (!$field->isEmpty()) { + switch(get_class($field)) { + case "File_MARC_Control_Field": + $fields[] = array(utf8_encode($field->getTag()), utf8_encode($field->getData())); + break; + + case "File_MARC_Data_Field": + $subs = array(); + foreach ($field->getSubfields() as $sf) { + $subs[] = array(utf8_encode($sf->getCode()), utf8_encode($sf->getData())); + } + $contents = array( + utf8_encode($field->getTag()), + utf8_encode($field->getIndicator(1)), + utf8_encode($field->getIndicator(2)), + $subs + ); + $fields[] = $contents; + break; + } + } + } + /* End fields and record */ + + $json->fields = $fields; + return json_encode($json); + } + + // }}} + + + // {{{ toXML() + /** + * Return the MARC record in MARCXML format + * + * This method produces an XML representation of a MARC record that + * attempts to adhere to the MARCXML standard documented at + * http://www.loc.gov/standards/marcxml/ + * + * @param string $encoding output encoding for the MARCXML record + * @param bool $indent pretty-print the MARCXML record + * @param bool $single wrap the <record> element in a <collection> element + * + * @return string representation of MARC record in MARCXML format + * + * @todo Fix encoding input / output issues (PHP 6.0 required?) + */ + function toXML($encoding = "UTF-8", $indent = true, $single = true) + { + $this->marcxml->setIndent($indent); + if ($single) { + $this->marc->toXMLHeader(); + } + $this->marcxml->startElement("record"); + + // MARCXML schema has some strict requirements + // We'll set reasonable defaults to avoid invalid MARCXML + $xmlLeader = $this->getLeader(); + + // Record status + if ($xmlLeader[5] == " ") { + // Default to "n" (new record) + $xmlLeader[5] = "n"; + } + + // Type of record + if ($xmlLeader[6] == " ") { + // Default to "a" (language material) + $xmlLeader[6] = "a"; + } + + $this->marcxml->writeElement("leader", $xmlLeader); + + foreach ($this->fields as $field) { + if (!$field->isEmpty()) { + switch(get_class($field)) { + case "File_MARC_Control_Field": + $this->marcxml->startElement("controlfield"); + $this->marcxml->writeAttribute("tag", $field->getTag()); + $this->marcxml->text($field->getData()); + $this->marcxml->endElement(); // end control field + break; + + case "File_MARC_Data_Field": + $this->marcxml->startElement("datafield"); + $this->marcxml->writeAttribute("tag", $field->getTag()); + $this->marcxml->writeAttribute("ind1", $field->getIndicator(1)); + $this->marcxml->writeAttribute("ind2", $field->getIndicator(2)); + foreach ($field->getSubfields() as $subfield) { + $this->marcxml->startElement("subfield"); + $this->marcxml->writeAttribute("code", $subfield->getCode()); + $this->marcxml->text($subfield->getData()); + $this->marcxml->endElement(); // end subfield + } + $this->marcxml->endElement(); // end data field + break; + } + } + } + + $this->marcxml->endElement(); // end record + if ($single) { + return $this->marc->toXMLFooter(); + } + } + + // }}} + +} +// }}} + diff --git a/vendor/File/MARC/Subfield.php b/vendor/File/MARC/Subfield.php new file mode 100644 index 0000000000000000000000000000000000000000..9654a20f8cf127c80f648a0c3c445dd695a42564 --- /dev/null +++ b/vendor/File/MARC/Subfield.php @@ -0,0 +1,217 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2003-2008 Oy Realnode Ab, Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Subfield.php 301737 2010-07-31 04:14:44Z dbs $ + * @link http://pear.php.net/package/File_MARC + */ + +// {{{ class File_MARC_Subfield extends Structures_LinkedList_DoubleNode +/** + * The File_MARC_Subfield class represents a single subfield in a MARC + * record field. + * + * Represents a subfield within a MARC field and implements all management + * functions related to a single subfield. This class also implements + * the possibility of duplicate subfields within a single field, for example + * 650 _z Test1 _z Test2. + * + * @category File_Formats + * @package File_MARC + * @author Christoffer Landtman <landtman@realnode.com> + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARC_Subfield extends Structures_LinkedList_DoubleNode +{ + // {{{ properties + /** + * Subfield code, e.g. _a, _b + * @var string + */ + protected $code; + + /** + * Data contained by the subfield + * @var string + */ + protected $data; + // }}} + + // {{{ Constructor: function __construct() + /** + * File_MARC_Subfield constructor + * + * Create a new subfield to represent the code and data + * + * @param string $code Subfield code + * @param string $data Subfield data + */ + function __construct($code, $data) + { + $this->code = $code; + $this->data = $data; + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Destroys the subfield + */ + function __destruct() + { + $this->code = null; + $this->data = null; + parent::__destruct(); + } + // }}} + + // {{{ Explicit destructor: function delete() + /** + * Destroys the subfield + * + * @return true + */ + function delete() + { + $this->__destruct(); + } + // }}} + + // {{{ getCode() + /** + * Return code of the subfield + * + * @return string Tag name + */ + function getCode() + { + return (string)$this->code; + } + // }}} + + // {{{ getData() + /** + * Return data of the subfield + * + * @return string data + */ + function getData() + { + return (string)$this->data; + } + // }}} + + // {{{ __toString() + /** + * Return string representation of subfield + * + * @return string String representation + */ + public function __toString() + { + $pretty = '[' . $this->getCode() . ']: ' . $this->getData(); + return $pretty; + } + // }}} + + // {{{ toRaw() + /** + * Return the USMARC representation of the subfield + * + * @return string USMARC representation + */ + function toRaw() + { + $result = File_MARC::SUBFIELD_INDICATOR.$this->code.$this->data; + return (string)$result; + } + // }}} + + // {{{ setCode() + /** + * Sets code of the subfield + * + * @param string $code new code for the subfield + * + * @return string code + */ + function setCode($code) + { + if ($code) { + // could check more stringently; m/[a-Z]/ or the likes + $this->code = $code; + } else { + // code must be _something_; raise error + return false; + } + return true; + } + // }}} + + // {{{ setData() + /** + * Sets data of the subfield + * + * @param string $data new data for the subfield + * + * @return string data + */ + function setData($data) + { + $this->data = $data; + return true; + } + // }}} + + // {{{ isEmpty() + /** + * Checks whether the subfield is empty or not + * + * @return bool True or false + */ + function isEmpty() + { + // There is data + if ($this->data) { + return false; + } + + // There is no data + return true; + } + // }}} +} +// }}} + diff --git a/vendor/File/MARCBASE.php b/vendor/File/MARCBASE.php new file mode 100644 index 0000000000000000000000000000000000000000..ea4e4bae85ca4567e95d71c55445fa1a6a44d217 --- /dev/null +++ b/vendor/File/MARCBASE.php @@ -0,0 +1,144 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2007-2010 Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: MARCXML.php 301727 2010-07-30 17:30:51Z dbs $ + * @link http://pear.php.net/package/File_MARC + * @example read.php Retrieve specific fields and subfields from a record + * @example subfields.php Create new subfields and add them in specific order + * @example marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension + */ + +// {{{ class File_MARCBASE +/** + * The main File_MARCBASE class provides common methods for File_MARC and + * File_MARCXML - primarily for generating MARCXML output. + * + * @category File_Formats + * @package File_MARC + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARCBASE +{ + + /** + * XMLWriter for writing collections + * + * @var XMLWriter + */ + protected $xmlwriter; + // }}} + + // {{{ Constructor: function __construct() + /** + * Read in MARCXML records + * + * This function reads in files or strings that + * contain one or more MARCXML records. + * + * <code> + * <?php + * // Retrieve MARC records from a file + * $journals = new File_MARC('journals.mrc', SOURCE_FILE); + * + * // Retrieve MARC records from a string (e.g. Z39 query results) + * $monographs = new File_MARC($raw_marc, SOURCE_STRING); + * ?> + * </code> + * + * @param string $source Name of the file, or a raw MARC string + * @param int $type Source of the input, either SOURCE_FILE or SOURCE_STRING + */ + function __construct($source, $type) + { + $this->xmlwriter = new XMLWriter(); + $this->xmlwriter->openMemory(); + $this->xmlwriter->startDocument('1.0', 'UTF-8'); + } + // }}} + + // {{{ toXMLHeader() + /** + * Initializes the MARCXML output of a record or collection of records + * + * This method produces an XML representation of a MARC record that + * attempts to adhere to the MARCXML standard documented at + * http://www.loc.gov/standards/marcxml/ + * + * @return bool true if successful + */ + function toXMLHeader() + { + $this->xmlwriter->startElement("collection"); + $this->xmlwriter->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim"); + return true; + } + // }}} + + // {{{ getXMLWriter() + /** + * Returns the XMLWriter object + * + * This method produces an XML representation of a MARC record that + * attempts to adhere to the MARCXML standard documented at + * http://www.loc.gov/standards/marcxml/ + * + * @return XMLWriter XMLWriter instance + */ + function getXMLWriter() + { + return $this->xmlwriter; + } + // }}} + + // {{{ toXMLFooter() + /** + * Returns the MARCXML collection footer + * + * This method produces an XML representation of a MARC record that + * attempts to adhere to the MARCXML standard documented at + * http://www.loc.gov/standards/marcxml/ + * + * @return string representation of MARC record in MARCXML format + */ + function toXMLFooter() + { + $this->xmlwriter->endElement(); // end collection + $this->xmlwriter->endDocument(); + return $this->xmlwriter->outputMemory(); + } + // }}} + +} +// }}} diff --git a/vendor/File/MARCXML.php b/vendor/File/MARCXML.php new file mode 100644 index 0000000000000000000000000000000000000000..991c72a8a92e8a341d498a13a77a54e0e61a3690 --- /dev/null +++ b/vendor/File/MARCXML.php @@ -0,0 +1,243 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */ + +/** + * Parser for MARC records + * + * This package is based on the PHP MARC package, originally called "php-marc", + * that is part of the Emilda Project (http://www.emilda.org). Christoffer + * Landtman generously agreed to make the "php-marc" code available under the + * GNU LGPL so it could be used as the basis of this PEAR package. + * + * PHP version 5 + * + * LICENSE: This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category File_Formats + * @package File_MARC + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2007-2010 Dan Scott + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: MARCXML.php 302267 2010-08-15 13:42:59Z dbs $ + * @link http://pear.php.net/package/File_MARC + * @example read.php Retrieve specific fields and subfields from a record + * @example subfields.php Create new subfields and add them in specific order + * @example marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension + */ + +require_once 'PEAR/Exception.php'; +require_once 'Structures/LinkedList/Double.php'; +require_once 'File/MARCBASE.php'; +require_once 'File/MARC.php'; +require_once 'File/MARC/Record.php'; +require_once 'File/MARC/Field.php'; +require_once 'File/MARC/Control_Field.php'; +require_once 'File/MARC/Data_Field.php'; +require_once 'File/MARC/Subfield.php'; +require_once 'File/MARC/Exception.php'; +require_once 'File/MARC/List.php'; + +// {{{ class File_MARCXML +/** + * The main File_MARCXML class enables you to return File_MARC_Record + * objects from an XML stream or string. + * + * @category File_Formats + * @package File_MARC + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @link http://pear.php.net/package/File_MARC + */ +class File_MARCXML extends File_MARCBASE +{ + + // {{{ constants + + /** + * MARC records retrieved from a file + */ + const SOURCE_FILE = 1; + + /** + * MARC records retrieved from a binary string + */ + const SOURCE_STRING = 2; + // }}} + + // {{{ properties + /** + * Source containing raw records + * + * @var resource + */ + protected $source; + + /** + * Source type (SOURCE_FILE or SOURCE_STRING) + * + * @var int + */ + protected $type; + + /** + * Counter for MARCXML records in a collection + * + * @var int + */ + protected $counter; + + /** + * XMLWriter for writing collections + * + * @var XMLWriter + */ + protected $xmlwriter; + // }}} + + // {{{ Constructor: function __construct() + /** + * Read in MARCXML records + * + * This function reads in files or strings that + * contain one or more MARCXML records. + * + * <code> + * <?php + * // Retrieve MARC records from a file + * $journals = new File_MARC('journals.mrc', SOURCE_FILE); + * + * // Retrieve MARC records from a string (e.g. Z39 query results) + * $monographs = new File_MARC($raw_marc, SOURCE_STRING); + * ?> + * </code> + * + * @param string $source Name of the file, or a raw MARC string + * @param int $type Source of the input, either SOURCE_FILE or SOURCE_STRING + */ + function __construct($source, $type = self::SOURCE_FILE) + { + parent::__construct($source, $type); + + $this->counter = 0; + + switch ($type) { + + case self::SOURCE_FILE: + $this->type = self::SOURCE_FILE; + $this->source = simplexml_load_file($source); + break; + + case self::SOURCE_STRING: + $this->type = self::SOURCE_STRING; + $this->source = simplexml_load_string($source); + break; + + default: + throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE); + } + + if (!$this->source) { + $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source)); + throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE); + } + } + // }}} + + // {{{ next() + /** + * Return next {@link File_MARC_Record} object + * + * Decodes the next MARCXML record and returns the {@link File_MARC_Record} + * object. + * <code> + * <?php + * // Retrieve a set of MARCXML records from a file + * $journals = new File_MARCXML('journals.xml', SOURCE_FILE); + * + * // Iterate through the retrieved records + * while ($record = $journals->next()) { + * print $record; + * print "\n"; + * } + * + * ?> + * </code> + * + * @return File_MARC_Record next record, or false if there are + * no more records + */ + function next() + { + if (isset($this->source->record[$this->counter])) { + $record = $this->source->record[$this->counter++]; + } elseif ($this->source->getName() == "record" && $this->counter == 0) { + $record = $this->source; + $this->counter++; + } else { + return false; + } + + if ($record) { + return $this->_decode($record); + } else { + return false; + } + } + // }}} + + // {{{ _decode() + /** + * Decode a given MARCXML record + * + * @param string $text MARCXML record element + * + * @return File_MARC_Record Decoded File_MARC_Record object + */ + private function _decode($text) + { + $marc = new File_MARC_Record($this); + + // Store leader + $marc->setLeader($text->leader); + + // go through all the control fields + foreach ($text->controlfield as $controlfield) { + $marc->appendField(new File_MARC_Control_Field((string)$controlfield['tag'], $controlfield)); + } + + // go through all the data fields + foreach ($text->datafield as $datafield) { + $subfield_data = array(); + foreach ($datafield->subfield as $subfield) { + $subfield_data[] = new File_MARC_Subfield((string)$subfield['code'], $subfield); + } + + // If the data is invalid, let's just ignore the one field + try { + $new_field = new File_MARC_Data_Field((string)$datafield['tag'], $subfield_data, $datafield['ind1'], $datafield['ind2']); + $marc->appendField($new_field); + } catch (Exception $e) { + $marc->addWarning($e->getMessage()); + } + } + + return $marc; + } + // }}} + +} +// }}} + diff --git a/vendor/Horde/Exception.php b/vendor/Horde/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..c0271ad4c1b8fe8e434871890f8d91a30ec7ad90 --- /dev/null +++ b/vendor/Horde/Exception.php @@ -0,0 +1,89 @@ +<?php +if (version_compare(PHP_VERSION, '5.3.0', '<')) { + /** + * Horde base exception class that supports prior exception for PHP < 5.3.0 + * + * Originates from + * http://framework.zend.com/wiki/display/ZFPROP/previous+Exception+on+Zend_Exception+-+Marc+Bennewitz + * + * Copyright 2008-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ + class Horde_Exception extends Exception + { + private $_previous = null; + + /** + * Error details that should not be part of the main exception message, + * e.g. any additional debugging information. + * + * @var string + */ + public $details; + + /** + * Construct the exception + * + * @param string $msg + * @param int $code + * @param Exception $previous + */ + public function __construct($msg = '', $code = 0, Exception $previous = null) + { + parent::__construct($msg, $code); + $this->_previous = $previous; + } + + /** + * Returns previous Exception + * + * @return Exception|null + */ + final public function getPrevious() + { + return $this->_previous; + } + + /** + * String representation of the exception + * + * @return string + */ + public function __toString() + { + if ($this->getPrevious()) { + return $this->getPrevious()->__toString() . "\n\nNext " . parent::__toString(); + } else { + return parent::__toString(); + } + } + + } +} else { + /** + * Horde base exception class. + * + * Copyright 2008-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ + class Horde_Exception extends Exception + { + /** + * Error details that should not be part of the main exception message, + * e.g. any additional debugging information. + * + * @var string + */ + public $details; + } +} diff --git a/vendor/Horde/Exception/LastError.php b/vendor/Horde/Exception/LastError.php new file mode 100644 index 0000000000000000000000000000000000000000..39b1546ffa9b9cae7a359fcb9426b5bd4187894a --- /dev/null +++ b/vendor/Horde/Exception/LastError.php @@ -0,0 +1,45 @@ +<?php +/** + * Horde exception class that accepts output of error_get_last() as $code and + * mask itself as that error. + * + * Copyright 2008-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ +class Horde_Exception_LastError extends Horde_Exception +{ + /** + * Exception constructor + * + * If $lasterror is passed the return value of error_get_last() (or a + * matching format), the exception will be rewritten to have its file and + * line parameters match that of the array, and any message in the array + * will be appended to $message. + * + * @param mixed $message The exception message, a PEAR_Error + * object, or an Exception object. + * @param mixed $code_or_lasterror Either a numeric error code, or + * an array from error_get_last(). + */ + public function __construct($message = null, $code_or_lasterror = null) + { + if (is_array($code_or_lasterror)) { + if ($message) { + $message .= $code_or_lasterror['message']; + } else { + $message = $code_or_lasterror['message']; + } + parent::__construct($message, $code_or_lasterror['type']); + $this->file = $code_or_lasterror['file']; + $this->line = $code_or_lasterror['line']; + } else { + parent::__construct($message, $code_or_lasterror); + } + } + +} diff --git a/vendor/Horde/Exception/NotFound.php b/vendor/Horde/Exception/NotFound.php new file mode 100644 index 0000000000000000000000000000000000000000..ff6b00588af843cbb7012f8c8cefde739637b6a7 --- /dev/null +++ b/vendor/Horde/Exception/NotFound.php @@ -0,0 +1,31 @@ +<?php +/** + * Exception thrown if an object wasn't found. + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ +class Horde_Exception_NotFound extends Horde_Exception +{ + /** + * Constructor. + * + * @see Horde_Exception::__construct() + * + * @param mixed $message The exception message, a PEAR_Error + * object, or an Exception object. + * @param integer $code A numeric error code. + */ + public function __construct($message = null, $code = null) + { + if (is_null($message)) { + $message = Horde_Exception_Translation::t("Not Found"); + } + parent::__construct($message, $code); + } +} \ No newline at end of file diff --git a/vendor/Horde/Exception/Pear.php b/vendor/Horde/Exception/Pear.php new file mode 100644 index 0000000000000000000000000000000000000000..0c6c121d8af08294bd4b75064925c476daeaa25a --- /dev/null +++ b/vendor/Horde/Exception/Pear.php @@ -0,0 +1,87 @@ +<?php +/** + * Horde exception class that converts PEAR errors to exceptions. + * + * Copyright 2008-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ +class Horde_Exception_Pear extends Horde_Exception +{ + /** + * The class name for generated exceptions. + * + * @var string + */ + static protected $_class = __CLASS__; + + /** + * The original PEAR error. + * + * @var PEAR_Error + */ + private $_error; + + /** + * Exception constructor. + * + * @param PEAR_Error $error The PEAR error. + */ + public function __construct(PEAR_Error $error) + { + parent::__construct( + $error->getMessage() . $this->_getPearTrace($error), + $error->getCode() + ); + if ($details = $error->getUserInfo()) { + $this->details = $details; + } + } + + /** + * Return a trace for the PEAR error. + * + * @param PEAR_Error $error The PEAR error. + * + * @return string The backtrace as a string. + */ + private function _getPearTrace(PEAR_Error $error) + { + $backtrace = $error->getBacktrace(); + if (!empty($backtrace)) { + $pear_error = "\n\n" . 'PEAR Error:' . "\n"; + foreach ($backtrace as $frame) { + $pear_error .= ' ' + . (isset($frame['class']) ? $frame['class'] : '') + . (isset($frame['type']) ? $frame['type'] : '') + . (isset($frame['function']) ? $frame['function'] : 'unkown') . ' ' + . (isset($frame['file']) ? $frame['file'] : 'unkown') . ':' + . (isset($frame['line']) ? $frame['line'] : 'unkown') . "\n"; + } + $pear_error .= "\n"; + return $pear_error; + } + return ''; + } + + /** + * Exception handling. + * + * @param mixed $result The result to be checked for a PEAR_Error. + * + * @return mixed Returns the original result if it was no PEAR_Error. + * + * @throws Horde_Exception_Pear In case the result was a PEAR_Error. + */ + static public function catchError($result) + { + if ($result instanceOf PEAR_Error) { + throw new self::$_class($result); + } + return $result; + } +} diff --git a/vendor/Horde/Exception/PermissionDenied.php b/vendor/Horde/Exception/PermissionDenied.php new file mode 100644 index 0000000000000000000000000000000000000000..943c7cc3f5bec6f5713b815920c09f2b77e85be8 --- /dev/null +++ b/vendor/Horde/Exception/PermissionDenied.php @@ -0,0 +1,31 @@ +<?php +/** + * Exception thrown if any access without sufficient permissions occured. + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ +class Horde_Exception_PermissionDenied extends Horde_Exception +{ + /** + * Constructor. + * + * @see Horde_Exception::__construct() + * + * @param mixed $message The exception message, a PEAR_Error + * object, or an Exception object. + * @param integer $code A numeric error code. + */ + public function __construct($message = null, $code = null) + { + if (is_null($message)) { + $message = Horde_Exception_Translation::t("Permission Denied"); + } + parent::__construct($message, $code); + } +} \ No newline at end of file diff --git a/vendor/Horde/Exception/Translation.php b/vendor/Horde/Exception/Translation.php new file mode 100644 index 0000000000000000000000000000000000000000..ca98f3a24ea35a57eb27813c60cda43a4308486c --- /dev/null +++ b/vendor/Horde/Exception/Translation.php @@ -0,0 +1,50 @@ +<?php +/** + * @package Exception + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +/** + * Horde_Exception_Translation is the translation wrapper class for Horde_Exception. + * + * @author Jan Schneider <jan@horde.org> + * @package Exception + */ +class Horde_Exception_Translation extends Horde_Translation +{ + /** + * Returns the translation of a message. + * + * @var string $message The string to translate. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + static public function t($message) + { + self::$_domain = 'Horde_Exception'; + self::$_directory = '/usr/share/php/data' == '@'.'data_dir'.'@' ? dirname(__FILE__) . '/../../../locale' : '/usr/share/php/data/Horde_Exception/locale'; + return parent::t($message); + } + + /** + * Returns the plural translation of a message. + * + * @param string $singular The singular version to translate. + * @param string $plural The plural version to translate. + * @param integer $number The number that determines singular vs. plural. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + static public function ngettext($singular, $plural, $number) + { + self::$_domain = 'Horde_Exception'; + self::$_directory = '/usr/share/php/data' == '@'.'data_dir'.'@' ? dirname(__FILE__) . '/../../../locale' : '/usr/share/php/data/Horde_Exception/locale'; + return parent::ngettext($singular, $plural, $number); + } +} diff --git a/vendor/Horde/Exception/Wrapped.php b/vendor/Horde/Exception/Wrapped.php new file mode 100644 index 0000000000000000000000000000000000000000..173498d714148d57a32d68b667e68d8e0be59c0d --- /dev/null +++ b/vendor/Horde/Exception/Wrapped.php @@ -0,0 +1,44 @@ +<?php +/** + * Horde exception class that can wrap and set its details from PEAR_Error, + * Exception, and other objects with similar interfaces. + * + * Copyright 2008-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Exception + */ +class Horde_Exception_Wrapped extends Horde_Exception +{ + /** + * Exception constructor. + * + * @param mixed $message The exception message, a PEAR_Error + * object, or an Exception object. + * @param int $code A numeric error code. + */ + public function __construct($message = null, $code = 0) + { + $previous = null; + if (is_object($message) && + method_exists($message, 'getMessage')) { + if (empty($code) && + method_exists($message, 'getCode')) { + $code = $message->getCode(); + } + if ($message instanceof Exception) { + $previous = $message; + } + if (method_exists($message, 'getUserinfo') && + $details = $message->getUserinfo()) { + $this->details = $details; + } + $message = $message->getMessage(); + } + + parent::__construct($message, $code, $previous); + } +} diff --git a/vendor/Horde/Translation.php b/vendor/Horde/Translation.php new file mode 100644 index 0000000000000000000000000000000000000000..9eda63472b53b2bf4cb134258c040b5a79910326 --- /dev/null +++ b/vendor/Horde/Translation.php @@ -0,0 +1,111 @@ +<?php +/** + * @package Translation + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +/** + * Horde_Translation is the base class for any translation wrapper classes in + * libraries that want to utilize the Horde_Translation library for + * translations. + * + * @author Jan Schneider <jan@horde.org> + * @package Translation + */ +abstract class Horde_Translation +{ + /** + * The translation domain, e.g. the library name, for the default gettext + * handler. + * + * @var string + */ + static protected $_domain; + + /** + * The relative path to the translations for the default gettext handler. + * + * This path is relative to the + * + * @var string + */ + static protected $_directory; + + /** + * The handlers providing the actual translations. + * + * @var array + */ + static protected $_handlers = array(); + + /** + * Loads a translation handler class pointing to the library's translations + * and assigns it to $_handler. + * + * @param string $handlerClass The name of a class implementing the + * Horde_Translation_Handler interface. + */ + static public function loadHandler($handlerClass) + { + if (!self::$_domain || !self::$_directory) { + throw new Horde_Translation_Exception('The domain and directory properties must be set by the class that extends Horde_Translation.'); + } + self::setHandler(self::$_domain, new $handlerClass(self::$_domain, self::$_directory)); + } + + /** + * Assigns a translation handler object to $_handlers. + * + * Type hinting isn't used on purpose. You should extend a custom + * translation handler passed here from the Horde_Translation interface, + * but technically it's sufficient if you provide the API of that + * interface. + * + * @param string $domain The translation domain. + * @param Horde_Translation_Handler $handler An object implementing the + * Horde_Translation_Handler + * interface. + */ + static public function setHandler($domain, $handler) + { + self::$_handlers[$domain] = $handler; + } + + /** + * Returns the translation of a message. + * + * @var string $message The string to translate. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + static public function t($message) + { + if (!isset(self::$_handlers[self::$_domain])) { + self::loadHandler('Horde_Translation_Handler_Gettext'); + } + return self::$_handlers[self::$_domain]->t($message); + } + + /** + * Returns the plural translation of a message. + * + * @param string $singular The singular version to translate. + * @param string $plural The plural version to translate. + * @param integer $number The number that determines singular vs. plural. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + static public function ngettext($singular, $plural, $number) + { + if (!isset(self::$_handlers[self::$_domain])) { + self::loadHandler('Horde_Translation_Handler_Gettext'); + } + return self::$_handlers[self::$_domain]->ngettext($singular, $plural, $number); + } +} diff --git a/vendor/Horde/Translation/Exception.php b/vendor/Horde/Translation/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..1e89cfaaf6a38511d8a6093e47794f760888fe98 --- /dev/null +++ b/vendor/Horde/Translation/Exception.php @@ -0,0 +1,15 @@ +<?php +/** + * Exception class for Horde_Translation. + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @author Jan Schneider <jan@horde.org> + * @package Translation + */ +class Horde_Translation_Exception extends Horde_Exception_Wrapped +{ +} diff --git a/vendor/Horde/Translation/Handler.php b/vendor/Horde/Translation/Handler.php new file mode 100644 index 0000000000000000000000000000000000000000..3f87df6497acf9e83bb3235e2fc910622a47734a --- /dev/null +++ b/vendor/Horde/Translation/Handler.php @@ -0,0 +1,41 @@ +<?php +/** + * @package Translation + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +/** + * The Horde_Translation_Handler interface defines the interface for any + * classes providing translations. + * + * @author Jan Schneider <jan@horde.org> + * @package Translation + */ +interface Horde_Translation_Handler +{ + /** + * Returns the translation of a message. + * + * @var string $message The string to translate. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + public function t($message); + + /** + * Returns the plural translation of a message. + * + * @param string $singular The singular version to translate. + * @param string $plural The plural version to translate. + * @param integer $number The number that determines singular vs. plural. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + public function ngettext($singular, $plural, $number); +} diff --git a/vendor/Horde/Translation/Handler/Gettext.php b/vendor/Horde/Translation/Handler/Gettext.php new file mode 100644 index 0000000000000000000000000000000000000000..73dc181698921d0584ce5eb6b3bfafb838df523d --- /dev/null +++ b/vendor/Horde/Translation/Handler/Gettext.php @@ -0,0 +1,82 @@ +<?php +/** + * @package Translation + * + * Copyright 2010-2011 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +/** + * The Horde_Translation_Handler_Gettext provides translations through the + * gettext extension, but fails gracefully if gettext is not installed. + * + * @author Jan Schneider <jan@horde.org> + * @package Translation + */ +class Horde_Translation_Handler_Gettext implements Horde_Translation_Handler +{ + /** + * The translation domain, e.g. package name. + * + * @var string + */ + protected $_domain; + + /** + * Whether the gettext extension is installed. + * + * @var boolean + */ + protected $_gettext; + + /** + * Constructor. + * + * @param string $domain The translation domain, e.g. package name. + * @param string $path The path to the gettext catalog. + */ + public function __construct($domain, $path) + { + if (!is_dir($path)) { + throw new InvalidArgumentException("$path is not a directory"); + } + $this->_gettext = function_exists('_'); + if (!$this->_gettext) { + return; + } + $this->_domain = $domain; + bindtextdomain($this->_domain, $path); + } + + /** + * Returns the translation of a message. + * + * @param string $message The string to translate. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + public function t($message) + { + return $this->_gettext ? dgettext($this->_domain, $message) : $message; + } + + /** + * Returns the plural translation of a message. + * + * @param string $singular The singular version to translate. + * @param string $plural The plural version to translate. + * @param integer $number The number that determines singular vs. plural. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + public function ngettext($singular, $plural, $number) + { + return $this->_gettext + ? dngettext($this->_domain, $singular, $plural, $number) + : ($number > 1 ? $plural : $singular); + } +} diff --git a/vendor/Horde/Yaml.php b/vendor/Horde/Yaml.php new file mode 100644 index 0000000000000000000000000000000000000000..7a740221c915f00b1c514f215c779049ea040ccd --- /dev/null +++ b/vendor/Horde/Yaml.php @@ -0,0 +1,158 @@ +<?php +/** + * Horde YAML package + * + * This package is heavily inspired by the Spyc PHP YAML + * implementation (http://spyc.sourceforge.net/), and portions are + * copyright 2005-2006 Chris Wanstrath. + * + * @author Chris Wanstrath <chris@ozmm.org> + * @author Chuck Hagenbuch <chuck@horde.org> + * @author Mike Naberezny <mike@maintainable.com> + * @license http://opensource.org/licenses/bsd-license.php BSD + * @category Horde + * @package Yaml + */ + +/** + * Horde YAML parser. + * + * This class can be used to read a YAML file and convert its contents + * into a PHP array. The native PHP parser supports a limited + * subsection of the YAML spec, but if the syck extension is present, + * that will be used for parsing. + * + * @category Horde + * @package Yaml + */ +class Horde_Yaml +{ + /** + * Callback used for alternate YAML loader, typically exported + * by a faster PHP extension. This function's first argument + * must accept a string with YAML content. + * + * @var callback + */ + public static $loadfunc = 'syck_load'; + + /** + * Callback used for alternate YAML dumper, typically exported + * by a faster PHP extension. This function's first argument + * must accept a mixed variable to be dumped. + * + * @var callback + */ + public static $dumpfunc = 'syck_dump'; + + /** + * Whitelist of classes that can be instantiated automatically + * when loading YAML docs that include serialized PHP objects. + * + * @var array + */ + public static $allowedClasses = array('ArrayObject'); + + /** + * Load a string containing YAML and parse it into a PHP array. + * Returns an empty array on failure. + * + * @param string $yaml String containing YAML + * @return array PHP array representation of YAML content + */ + public static function load($yaml) + { + if (!is_string($yaml) || !strlen($yaml)) { + $msg = 'YAML to parse must be a string and cannot be empty.'; + throw new InvalidArgumentException($msg); + } + + if (is_callable(self::$loadfunc)) { + return call_user_func(self::$loadfunc, $yaml); + return is_array($array) ? $array : array(); + } + + if (strpos($yaml, "\r") !== false) { + $yaml = str_replace(array("\r\n", "\r"), array("\n", "\n"), $yaml); + } + $lines = explode("\n", $yaml); + $loader = new Horde_Yaml_Loader; + + while (list(,$line) = each($lines)) { + $loader->parse($line); + } + + return $loader->toArray(); + } + + /** + * Load a file containing YAML and parse it into a PHP array. + * + * If the file cannot be opened, an exception is thrown. If the + * file is read but parsing fails, an empty array is returned. + * + * @param string $filename Filename to load + * @return array PHP array representation of YAML content + * @throws IllegalArgumentException If $filename is invalid + * @throws Horde_Yaml_Exception If the file cannot be opened. + */ + public static function loadFile($filename) + { + if (!is_string($filename) || !strlen($filename)) { + $msg = 'Filename must be a string and cannot be empty'; + throw new InvalidArgumentException($msg); + } + + $stream = @fopen($filename, 'rb'); + if (!$stream) { + throw new Horde_Yaml_Exception('Failed to open file: ', error_get_last()); + } + + return self::loadStream($stream); + } + + /** + * Load YAML from a PHP stream resource. + * + * @param resource $stream PHP stream resource + * @return array PHP array representation of YAML content + */ + public static function loadStream($stream) + { + if (! is_resource($stream) || get_resource_type($stream) != 'stream') { + throw new InvalidArgumentException('Stream must be a stream resource'); + } + + if (is_callable(self::$loadfunc)) { + return call_user_func(self::$loadfunc, stream_get_contents($stream)); + } + + $loader = new Horde_Yaml_Loader; + while (!feof($stream)) { + $loader->parse(stream_get_line($stream, 100000, "\n")); + } + + return $loader->toArray(); + } + + /** + * Dump a PHP array to YAML. + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. + * + * @param array|Traversable $array PHP array or traversable object + * @param integer $options Options to pass to dumper + * @return string YAML representation of $value + */ + public static function dump($value, $options = array()) + { + if (is_callable(self::$dumpfunc)) { + return call_user_func(self::$dumpfunc, $value); + } + + $dumper = new Horde_Yaml_Dumper(); + return $dumper->dump($value, $options); + } + +} diff --git a/vendor/Horde/Yaml/Dumper.php b/vendor/Horde/Yaml/Dumper.php new file mode 100644 index 0000000000000000000000000000000000000000..2e9ea4efa97d0205e153d6241887054ac8cd5800 --- /dev/null +++ b/vendor/Horde/Yaml/Dumper.php @@ -0,0 +1,216 @@ +<?php +/** + * Horde YAML package + * + * This package is heavily inspired by the Spyc PHP YAML + * implementation (http://spyc.sourceforge.net/), and portions are + * copyright 2005-2006 Chris Wanstrath. + * + * @author Chris Wanstrath <chris@ozmm.org> + * @author Chuck Hagenbuch <chuck@horde.org> + * @author Mike Naberezny <mike@maintainable.com> + * @license http://opensource.org/licenses/bsd-license.php BSD + * @category Horde + * @package Yaml + */ + +/** + * Dump PHP data structures to YAML. + * + * @category Horde + * @package Yaml + */ +class Horde_Yaml_Dumper +{ + protected $_options = array(); + + /** + * Dump PHP array to YAML + * + * The dump method, when supplied with an array, will do its best + * to convert the array into valid YAML. + * + * Options: + * `indent`: + * number of spaces to indent children (default 2) + * `wordwrap`: + * wordwrap column number (default 40) + * + * @param array|Traversable $array PHP array or traversable object + * @param integer $options Options for dumping + * @return string YAML representation of $value + */ + public function dump($value, $options = array()) + { + // validate & merge default options + if (!is_array($options)) { + throw new InvalidArgumentException('Options must be an array'); + } + + $defaults = array('indent' => 2, + 'wordwrap' => 40); + $this->_options = array_merge($defaults, $options); + + if (! is_int($this->_options['indent'])) { + throw new InvalidArgumentException('Indent must be an integer'); + } + + if (! is_int($this->_options['wordwrap'])) { + throw new InvalidArgumentException('Wordwrap column must be an integer'); + } + + // new YAML document + $dump = "---\n"; + + // iterate through array and yamlize it + foreach ($value as $key => $value) { + $dump .= $this->_yamlize($key, $value, 0); + } + return $dump; + } + + /** + * Attempts to convert a key / value array item to YAML + * + * @param string $key The name of the key + * @param string|array $value The value of the item + * @param integer $indent The indent of the current node + * @return string + */ + protected function _yamlize($key, $value, $indent) + { + if ($value instanceof Serializable) { + // Dump serializable objects as !php/object::classname serialize_data + $data = '!php/object::' . get_class($value) . ' ' . $value->serialize(); + $string = $this->_dumpNode($key, $data, $indent); + } elseif (is_array($value) || $value instanceof Traversable) { + // It has children. Make it the right kind of item. + $string = $this->_dumpNode($key, null, $indent); + + // Add the indent. + $indent += $this->_options['indent']; + + // Yamlize the array. + $string .= $this->_yamlizeArray($value, $indent); + } elseif (!is_array($value)) { + // No children. + $string = $this->_dumpNode($key, $value, $indent); + } + + return $string; + } + + /** + * Attempts to convert an array to YAML + * + * @param array $array The array you want to convert + * @param integer $indent The indent of the current level + * @return string + */ + protected function _yamlizeArray($array, $indent) + { + if (!is_array($array)) { + return false; + } + + $string = ''; + foreach ($array as $key => $value) { + $string .= $this->_yamlize($key, $value, $indent); + } + return $string; + } + + /** + * Returns YAML from a key and a value + * + * @param string $key The name of the key + * @param string $value The value of the item + * @param integer $indent The indent of the current node + * @return string + */ + protected function _dumpNode($key, $value, $indent) + { + $literal = false; + // Do some folding here, for blocks. + if (strpos($value, "\n") !== false + || strpos($value, ': ') !== false + || strpos($value, '- ') !== false) { + $value = $this->_doLiteralBlock($value, $indent); + $literal = true; + } else { + $value = $this->_fold($value, $indent); + } + + if (is_bool($value)) { + $value = ($value) ? 'true' : 'false'; + } elseif (is_float($value)) { + if (is_nan($value)) { + $value = '.NAN'; + } elseif ($value === INF) { + $value = '.INF'; + } elseif ($value === -INF) { + $value = '-.INF'; + } + } + + $spaces = str_repeat(' ', $indent); + + // Quote strings if necessary, and not folded + if (!$literal && strpos($value, "\n") === false && strchr($value, '#')) { + $value = "'{$value}'"; + } + + if (is_int($key)) { + // It's a sequence. + $string = $spaces . '- ' . $value . "\n"; + } else { + // It's mapped. + $string = $spaces . $key . ': ' . $value . "\n"; + } + + return $string; + } + + /** + * Creates a literal block for dumping + * + * @param string $value + * @param integer $indent The value of the indent. + * @return string + */ + protected function _doLiteralBlock($value, $indent) + { + $exploded = explode("\n", $value); + $newValue = '|'; + $indent += $this->_options['indent']; + $spaces = str_repeat(' ', $indent); + foreach ($exploded as $line) { + $newValue .= "\n" . $spaces . trim($line); + } + return $newValue; + } + + /** + * Folds a string of text, if necessary + * + * @param $value The string you wish to fold + * @return string + */ + protected function _fold($value, $indent) + { + // Don't do anything if wordwrap is set to 0 + if (! $this->_options['wordwrap']) { + return $value; + } + + if (strlen($value) > $this->_options['wordwrap']) { + $indent += $this->_options['indent']; + $indent = str_repeat(' ', $indent); + $wrapped = wordwrap($value, $this->_options['wordwrap'], "\n$indent"); + $value = ">\n" . $indent . $wrapped; + } + + return $value; + } + +} diff --git a/vendor/Horde/Yaml/Exception.php b/vendor/Horde/Yaml/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..40ba711fce9241acfd85c3273e479c81e9cecf82 --- /dev/null +++ b/vendor/Horde/Yaml/Exception.php @@ -0,0 +1,25 @@ +<?php +/** + * Horde YAML package + * + * This package is heavily inspired by the Spyc PHP YAML + * implementation (http://spyc.sourceforge.net/), and portions are + * copyright 2005-2006 Chris Wanstrath. + * + * @author Chris Wanstrath <chris@ozmm.org> + * @author Chuck Hagenbuch <chuck@horde.org> + * @author Mike Naberezny <mike@maintainable.com> + * @license http://opensource.org/licenses/bsd-license.php BSD + * @category Horde + * @package Yaml + */ + +/** + * Exception class for exceptions thrown by Horde_Yaml + * + * @category Horde + * @package Yaml + */ +class Horde_Yaml_Exception extends Horde_Exception_LastError +{ +} diff --git a/vendor/Horde/Yaml/Loader.php b/vendor/Horde/Yaml/Loader.php new file mode 100644 index 0000000000000000000000000000000000000000..08160f64789c84db41adc13f5e13fa28a41a345e --- /dev/null +++ b/vendor/Horde/Yaml/Loader.php @@ -0,0 +1,751 @@ +<?php +/** + * Horde YAML package + * + * This package is heavily inspired by the Spyc PHP YAML + * implementation (http://spyc.sourceforge.net/), and portions are + * copyright 2005-2006 Chris Wanstrath. + * + * @author Chris Wanstrath <chris@ozmm.org> + * @author Chuck Hagenbuch <chuck@horde.org> + * @author Mike Naberezny <mike@maintainable.com> + * @license http://opensource.org/licenses/bsd-license.php BSD + * @category Horde + * @package Yaml + */ + +/** + * Parse YAML strings into PHP data structures + * + * @category Horde + * @package Yaml + */ +class Horde_Yaml_Loader +{ + /** + * List of nodes with references + * @var array + */ + protected $_haveRefs = array(); + + /** + * All nodes + * @var array + */ + protected $_allNodes = array(); + + /** + * Array of node parents + * @var array + */ + protected $_allParent = array(); + + /** + * Last indent level + * @var integer + */ + protected $_lastIndent = 0; + + /** + * Last node id + * @var integer + */ + protected $_lastNode = null; + + /** + * Is the parser inside a block? + * @var boolean + */ + protected $_inBlock = false; + + /** + * @var boolean + */ + protected $_isInline = false; + + /** + * Next node id to use + * @var integer + */ + protected $_nodeId = 1; + + /** + * Last line number parsed. + * @var integer + */ + protected $_lineNumber = 0; + + /** + * Create a new YAML parser. + */ + public function __construct() + { + $base = new Horde_Yaml_Node($this->_nodeId++); + $base->indent = 0; + $this->_lastNode = $base->id; + } + + /** + * Return the PHP built from all YAML parsed so far. + * + * @return array PHP version of parsed YAML + */ + public function toArray() + { + // Here we travel through node-space and pick out references + // (& and *). + $this->_linkReferences(); + + // Build the PHP array out of node-space. + return $this->_buildArray(); + } + + /** + * Parse a line of a YAML file. + * + * @param string $line The line of YAML to parse. + * @return Horde_Yaml_Node YAML Node + */ + public function parse($line) + { + // Keep track of how many lines we've parsed for friendlier + // error messages. + ++$this->_lineNumber; + + $trimmed = trim($line); + + // If the line starts with a tab (instead of a space), throw a fit. + if (preg_match('/^ *(\t) *[^\t ]/', $line)) { + $msg = "Line {$this->_lineNumber} indent contains a tab. " + . 'YAML only allows spaces for indentation.'; + throw new Horde_Yaml_Exception($msg); + } + + if (!$this->_inBlock && empty($trimmed)) { + return; + } elseif ($this->_inBlock && empty($trimmed)) { + $last =& $this->_allNodes[$this->_lastNode]; + $last->data[key($last->data)] .= "\n"; + } elseif ($trimmed[0] != '#' && substr($trimmed, 0, 3) != '---') { + // Create a new node and get its indent + $node = new Horde_Yaml_Node($this->_nodeId++); + $node->indent = $this->_getIndent($line); + + // Check where the node lies in the hierarchy + if ($this->_lastIndent == $node->indent) { + // If we're in a block, add the text to the parent's data + if ($this->_inBlock) { + $parent =& $this->_allNodes[$this->_lastNode]; + $parent->data[key($parent->data)] .= trim($line) . $this->_blockEnd; + } else { + // The current node's parent is the same as the previous node's + if (isset($this->_allNodes[$this->_lastNode])) { + $node->parent = $this->_allNodes[$this->_lastNode]->parent; + } + } + } elseif ($this->_lastIndent < $node->indent) { + if ($this->_inBlock) { + $parent =& $this->_allNodes[$this->_lastNode]; + $parent->data[key($parent->data)] .= trim($line) . $this->_blockEnd; + } elseif (!$this->_inBlock) { + // The current node's parent is the previous node + $node->parent = $this->_lastNode; + + // If the value of the last node's data was > or | + // we need to start blocking i.e. taking in all + // lines as a text value until we drop our indent. + $parent =& $this->_allNodes[$node->parent]; + $this->_allNodes[$node->parent]->children = true; + if (is_array($parent->data)) { + if (isset($parent->data[key($parent->data)])) { + $chk = $parent->data[key($parent->data)]; + if ($chk === '>') { + $this->_inBlock = true; + $this->_blockEnd = ''; + $parent->data[key($parent->data)] = + str_replace('>', '', $parent->data[key($parent->data)]); + $parent->data[key($parent->data)] .= trim($line) . ' '; + $this->_allNodes[$node->parent]->children = false; + $this->_lastIndent = $node->indent; + } elseif ($chk === '|') { + $this->_inBlock = true; + $this->_blockEnd = "\n"; + $parent->data[key($parent->data)] = + str_replace('|', '', $parent->data[key($parent->data)]); + $parent->data[key($parent->data)] .= trim($line) . "\n"; + $this->_allNodes[$node->parent]->children = false; + $this->_lastIndent = $node->indent; + } + } + } + } + } elseif ($this->_lastIndent > $node->indent) { + // Any block we had going is dead now + if ($this->_inBlock) { + $this->_inBlock = false; + if ($this->_blockEnd == "\n") { + $last =& $this->_allNodes[$this->_lastNode]; + $last->data[key($last->data)] = + trim($last->data[key($last->data)]); + } + } + + // We don't know the parent of the node so we have to + // find it + foreach ($this->_indentSort[$node->indent] as $n) { + if ($n->indent == $node->indent) { + $node->parent = $n->parent; + } + } + } + + if (!$this->_inBlock) { + // Set these properties with information from our + // current node + $this->_lastIndent = $node->indent; + + // Set the last node + $this->_lastNode = $node->id; + + // Parse the YAML line and return its data + $node->data = $this->_parseLine($line); + + // Add the node to the master list + $this->_allNodes[$node->id] = $node; + + // Add a reference to the parent list + $this->_allParent[intval($node->parent)][] = $node->id; + + // Add a reference to the node in an indent array + $this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id]; + + // Add a reference to the node in a References array + // if this node has a YAML reference in it. + $is_array = is_array($node->data); + $key = key($node->data); + $isset = isset($node->data[$key]); + if ($isset) { + $nodeval = $node->data[$key]; + } + if (($is_array && $isset && !is_array($nodeval) && !is_object($nodeval)) + && (strlen($nodeval) && ($nodeval[0] == '&' || $nodeval[0] == '*') && $nodeval[1] != ' ')) { + $this->_haveRefs[] =& $this->_allNodes[$node->id]; + } elseif ($is_array && $isset && is_array($nodeval)) { + // Incomplete reference making code. Needs to be + // cleaned up. + foreach ($node->data[$key] as $d) { + if (!is_array($d) && strlen($d) && (($d[0] == '&' || $d[0] == '*') && $d[1] != ' ')) { + $this->_haveRefs[] =& $this->_allNodes[$node->id]; + } + } + } + } + } + } + + /** + * Finds and returns the indentation of a YAML line + * + * @param string $line A line from the YAML file + * @return int Indentation level + */ + protected function _getIndent($line) + { + if (preg_match('/^\s+/', $line, $match)) { + return strlen($match[0]); + } else { + return 0; + } + } + + /** + * Parses YAML code and returns an array for a node + * + * @param string $line A line from the YAML file + * @return array + */ + protected function _parseLine($line) + { + $array = array(); + + $line = trim($line); + if (preg_match('/^-(.*):$/', $line)) { + // It's a mapped sequence + $key = trim(substr(substr($line, 1), 0, -1)); + $array[$key] = ''; + } elseif ($line[0] == '-' && substr($line, 0, 3) != '---') { + // It's a list item but not a new stream + if (strlen($line) > 1) { + // Set the type of the value. Int, string, etc + $array[] = $this->_toType(trim(substr($line, 1))); + } else { + $array[] = array(); + } + } elseif (preg_match('/^(.+):/', $line, $key)) { + // It's a key/value pair most likely + // If the key is in double quotes pull it out + if (preg_match('/^(["\'](.*)["\'](\s)*:)/', $line, $matches)) { + $value = trim(str_replace($matches[1], '', $line)); + $key = $matches[2]; + } else { + // Do some guesswork as to the key and the value + $explode = explode(':', $line); + $key = trim(array_shift($explode)); + $value = trim(implode(':', $explode)); + } + + // Set the type of the value. Int, string, etc + $value = $this->_toType($value); + if (empty($key)) { + $array[] = $value; + } else { + $array[$key] = $value; + } + } + + return $array; + } + + /** + * Finds the type of the passed value, returns the value as the new type. + * + * @param string $value + * @return mixed + */ + protected function _toType($value) + { + // Check for PHP specials + self::_unserialize($value); + if (!is_scalar($value)) { + return $value; + } + + // Used in a lot of cases. + $lower_value = strtolower($value); + + if (preg_match('/^("(.*)"|\'(.*)\')/', $value, $matches)) { + $value = (string)str_replace(array('\'\'', '\\\''), "'", end($matches)); + $value = str_replace('\\"', '"', $value); + } elseif (preg_match('/^\\[(\s*)\\]$/', $value)) { + // empty inline mapping + $value = array(); + } elseif (preg_match('/^\\[(.+)\\]$/', $value, $matches)) { + // Inline Sequence + + // Take out strings sequences and mappings + $explode = $this->_inlineEscape($matches[1]); + + // Propogate value array + $value = array(); + foreach ($explode as $v) { + $value[] = $this->_toType($v); + } + } elseif (preg_match('/^\\{(\s*)\\}$/', $value)) { + // empty inline mapping + $value = array(); + } elseif (strpos($value, ': ') !== false && !preg_match('/^{(.+)/', $value)) { + // inline mapping + $array = explode(': ', $value); + $key = trim($array[0]); + array_shift($array); + $value = trim(implode(': ', $array)); + $value = $this->_toType($value); + $value = array($key => $value); + } elseif (preg_match("/{(.+)}$/", $value, $matches)) { + // Inline Mapping + + // Take out strings sequences and mappings + $explode = $this->_inlineEscape($matches[1]); + + // Propogate value array + $array = array(); + foreach ($explode as $v) { + $array = $array + $this->_toType($v); + } + $value = $array; + } elseif ($lower_value == 'null' || $value == '' || $value == '~') { + $value = null; + } elseif ($lower_value == '.nan') { + $value = NAN; + } elseif ($lower_value == '.inf') { + $value = INF; + } elseif ($lower_value == '-.inf') { + $value = -INF; + } elseif (ctype_digit($value)) { + $value = (int)$value; + } elseif (in_array($lower_value, + array('true', 'on', '+', 'yes', 'y'))) { + $value = true; + } elseif (in_array($lower_value, + array('false', 'off', '-', 'no', 'n'))) { + $value = false; + } elseif (is_numeric($value)) { + $value = (float)$value; + } else { + // Just a normal string, right? + if (($pos = strpos($value, '#')) !== false) { + $value = substr($value, 0, $pos); + } + $value = trim($value); + } + + return $value; + } + + /** + * Handle PHP serialized data. + * + * @param string &$data Data to check for serialized PHP types. + */ + protected function _unserialize(&$data) + { + if (substr($data, 0, 5) != '!php/') { + return; + } + + $first_space = strpos($data, ' '); + $type = substr($data, 5, $first_space - 5); + $class = null; + if (strpos($type, '::') !== false) { + list($type, $class) = explode('::', $type); + + if (!in_array($class, Horde_Yaml::$allowedClasses)) { + throw new Horde_Yaml_Exception("$class is not in the list of allowed classes"); + } + } + + switch ($type) { + case 'object': + if (!class_exists($class)) { + throw new Horde_Yaml_Exception("$class is not defined"); + } + + $reflector = new ReflectionClass($class); + if (!$reflector->implementsInterface('Serializable')) { + throw new Horde_Yaml_Exception("$class does not implement Serializable"); + } + + $class_data = substr($data, $first_space + 1); + $serialized = 'C:' . strlen($class) . ':"' . $class . '":' . strlen($class_data) . ':{' . $class_data . '}'; + $data = unserialize($serialized); + break; + + case 'array': + case 'hash': + $array_data = substr($data, $first_space + 1); + $array_data = Horde_Yaml::load('a: ' . $array_data); + + if (is_null($class)) { + $data = $array_data['a']; + } else { + if (!class_exists($class)) { + throw new Horde_Yaml_Exception("$class is not defined"); + } + + $array = new $class; + if (!$array instanceof ArrayAccess) { + throw new Horde_Yaml_Exception("$class does not implement ArrayAccess"); + } + + foreach ($array_data['a'] as $key => $val) { + $array[$key] = $val; + } + + $data = $array; + } + break; + } + } + + /** + * Used in inlines to check for more inlines or quoted strings + * + * @todo There should be a cleaner way to do this. While + * pure sequences seem to be nesting just fine, + * pure mappings and mappings with sequences inside + * can't go very deep. This needs to be fixed. + * + * @param string $inline Inline data + * @return array + */ + protected function _inlineEscape($inline) + { + $saved_strings = array(); + + // Check for strings + $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; + if (preg_match_all($regex, $inline, $strings)) { + $saved_strings = $strings[0]; + $inline = preg_replace($regex, 'YAMLString', $inline); + } + + // Check for sequences + if (preg_match_all('/\[(.+)\]/U', $inline, $seqs)) { + $inline = preg_replace('/\[(.+)\]/U', 'YAMLSeq', $inline); + $seqs = $seqs[0]; + } + + // Check for mappings + if (preg_match_all('/{(.+)}/U', $inline, $maps)) { + $inline = preg_replace('/{(.+)}/U', 'YAMLMap', $inline); + $maps = $maps[0]; + } + + $explode = explode(', ', $inline); + + // Re-add the sequences + if (!empty($seqs)) { + $i = 0; + foreach ($explode as $key => $value) { + if (strpos($value, 'YAMLSeq') !== false) { + $explode[$key] = str_replace('YAMLSeq', $seqs[$i], $value); + ++$i; + } + } + } + + // Re-add the mappings + if (!empty($maps)) { + $i = 0; + foreach ($explode as $key => $value) { + if (strpos($value, 'YAMLMap') !== false) { + $explode[$key] = str_replace('YAMLMap', $maps[$i], $value); + ++$i; + } + } + } + + // Re-add the strings + if (!empty($saved_strings)) { + $i = 0; + foreach ($explode as $key => $value) { + while (strpos($value, 'YAMLString') !== false) { + $explode[$key] = preg_replace('/YAMLString/', $saved_strings[$i], $value, 1); + ++$i; + $value = $explode[$key]; + } + } + } + + return $explode; + } + + /** + * Builds the PHP array from all the YAML nodes we've gathered + * + * @return array + */ + protected function _buildArray() + { + $trunk = array(); + if (!isset($this->_indentSort[0])) { + return $trunk; + } + + foreach ($this->_indentSort[0] as $n) { + if (empty($n->parent)) { + $this->_nodeArrayizeData($n); + + // Check for references and copy the needed data to complete them. + $this->_makeReferences($n); + + // Merge our data with the big array we're building + $trunk = $this->_array_kmerge($trunk, $n->data); + } + } + + return $trunk; + } + + /** + * Traverses node-space and sets references (& and *) accordingly + * + * @return bool + */ + protected function _linkReferences() + { + if (is_array($this->_haveRefs)) { + foreach ($this->_haveRefs as $node) { + if (!empty($node->data)) { + $key = key($node->data); + // If it's an array, don't check. + if (is_array($node->data[$key])) { + foreach ($node->data[$key] as $k => $v) { + $this->_linkRef($node, $key, $k, $v); + } + } else { + $this->_linkRef($node, $key); + } + } + } + } + + return true; + } + + /** + * Helper for _linkReferences() + * + * @param Horde_Yaml_Node $n Node + * @param string $k Key + * @param mixed $v Value + * @return void + */ + function _linkRef(&$n, $key, $k = null, $v = null) + { + if (empty($k) && empty($v)) { + // Look for &refs + if (preg_match('/^&([^ ]+)/', $n->data[$key], $matches)) { + // Flag the node so we know it's a reference + $this->_allNodes[$n->id]->ref = substr($matches[0], 1); + $this->_allNodes[$n->id]->data[$key] = + substr($n->data[$key], strlen($matches[0]) + 1); + // Look for *refs + } elseif (preg_match('/^\*([^ ]+)/', $n->data[$key], $matches)) { + $ref = substr($matches[0], 1); + // Flag the node as having a reference + $this->_allNodes[$n->id]->refKey = $ref; + } + } elseif (!empty($k) && !empty($v)) { + if (preg_match('/^&([^ ]+)/', $v, $matches)) { + // Flag the node so we know it's a reference + $this->_allNodes[$n->id]->ref = substr($matches[0], 1); + $this->_allNodes[$n->id]->data[$key][$k] = + substr($v, strlen($matches[0]) + 1); + // Look for *refs + } elseif (preg_match('/^\*([^ ]+)/', $v, $matches)) { + $ref = substr($matches[0], 1); + // Flag the node as having a reference + $this->_allNodes[$n->id]->refKey = $ref; + } + } + } + + /** + * Finds the children of a node and aids in the building of the PHP array + * + * @param int $nid The id of the node whose children we're gathering + * @return array + */ + protected function _gatherChildren($nid) + { + $return = array(); + $node =& $this->_allNodes[$nid]; + if (is_array ($this->_allParent[$node->id])) { + foreach ($this->_allParent[$node->id] as $nodeZ) { + $z =& $this->_allNodes[$nodeZ]; + // We found a child + $this->_nodeArrayizeData($z); + + // Check for references + $this->_makeReferences($z); + + // Merge with the big array we're returning, the big + // array being all the data of the children of our + // parent node + $return = $this->_array_kmerge($return, $z->data); + } + } + return $return; + } + + /** + * Turns a node's data and its children's data into a PHP array + * + * @param array $node The node which you want to arrayize + * @return boolean + */ + protected function _nodeArrayizeData(&$node) + { + if ($node->children == true) { + if (is_array($node->data)) { + // This node has children, so we need to find them + $children = $this->_gatherChildren($node->id); + + // We've gathered all our children's data and are ready to use it + $key = key($node->data); + $key = empty($key) ? 0 : $key; + // If it's an array, add to it of course + if (isset($node->data[$key])) { + if (is_array($node->data[$key])) { + $node->data[$key] = $this->_array_kmerge($node->data[$key], $children); + } else { + $node->data[$key] = $children; + } + } else { + $node->data[$key] = $children; + } + } else { + // Same as above, find the children of this node + $children = $this->_gatherChildren($node->id); + $node->data = array(); + $node->data[] = $children; + } + } else { + // The node is a single string. See if we need to unserialize it. + if (is_array($node->data)) { + $key = key($node->data); + $key = empty($key) ? 0 : $key; + + if (!isset($node->data[$key]) || is_array($node->data[$key]) || is_object($node->data[$key])) { + return true; + } + + self::_unserialize($node->data[$key]); + } elseif (is_string($node->data)) { + self::_unserialize($node->data); + } + } + + // We edited $node by reference, so just return true + return true; + } + + /** + * Traverses node-space and copies references to / from this object. + * + * @param Horde_Yaml_Node $z A node whose references we wish to make real + * @return bool + */ + protected function _makeReferences(&$z) + { + // It is a reference + if (isset($z->ref)) { + $key = key($z->data); + // Copy the data to this object for easy retrieval later + $this->ref[$z->ref] =& $z->data[$key]; + // It has a reference + } elseif (isset($z->refKey)) { + if (isset($this->ref[$z->refKey])) { + $key = key($z->data); + // Copy the data from this object to make the node a real reference + $z->data[$key] =& $this->ref[$z->refKey]; + } + } + + return true; + } + + /** + * Merges two arrays, maintaining numeric keys. If two numeric + * keys clash, the second one will be appended to the resulting + * array. If string keys clash, the last one wins. + * + * @param array $arr1 + * @param array $arr2 + * @return array + */ + protected function _array_kmerge($arr1, $arr2) + { + while (list($key, $val) = each($arr2)) { + if (isset($arr1[$key]) && is_int($key)) { + $arr1[] = $val; + } else { + $arr1[$key] = $val; + } + } + + return $arr1; + } + +} diff --git a/vendor/Horde/Yaml/Node.php b/vendor/Horde/Yaml/Node.php new file mode 100644 index 0000000000000000000000000000000000000000..bc66839307b535781bdb659e2a57584f4b67c444 --- /dev/null +++ b/vendor/Horde/Yaml/Node.php @@ -0,0 +1,58 @@ +<?php +/** + * Horde YAML package + * + * This package is heavily inspired by the Spyc PHP YAML + * implementation (http://spyc.sourceforge.net/), and portions are + * copyright 2005-2006 Chris Wanstrath. + * + * @author Chris Wanstrath <chris@ozmm.org> + * @author Chuck Hagenbuch <chuck@horde.org> + * @author Mike Naberezny <mike@maintainable.com> + * @license http://opensource.org/licenses/bsd-license.php BSD + * @category Horde + * @package Yaml + */ + +/** + * A node, used for parsing YAML. + * + * @category Horde + * @package Yaml + */ +class Horde_Yaml_Node +{ + /** + * @var string + */ + public $parent; + + /** + */ + public $id; + + /** + * @var mixed + */ + public $data; + + /** + * @var integer + */ + public $indent; + + /** + * @var bool + */ + public $children = false; + + /** + * The constructor assigns the node a unique ID. + * @return void + */ + public function __construct($nodeId) + { + $this->id = $nodeId; + } + +} diff --git a/vendor/PEAR/Exception.php b/vendor/PEAR/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..112bdd0f5ac69d191f776f47de23e5e0caaae5ff --- /dev/null +++ b/vendor/PEAR/Exception.php @@ -0,0 +1,389 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ +/** + * PEAR_Exception + * + * PHP versions 4 and 5 + * + * @category pear + * @package PEAR + * @author Tomas V. V. Cox <cox@idecnet.com> + * @author Hans Lellelid <hans@velum.net> + * @author Bertrand Mansion <bmansion@mamasam.com> + * @author Greg Beaver <cellog@php.net> + * @copyright 1997-2009 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Exception.php 299813 2010-05-26 19:50:00Z dufuz $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.3.3 + */ + + +/** + * Base PEAR_Exception Class + * + * 1) Features: + * + * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) + * - Definable triggers, shot when exceptions occur + * - Pretty and informative error messages + * - Added more context info available (like class, method or cause) + * - cause can be a PEAR_Exception or an array of mixed + * PEAR_Exceptions/PEAR_ErrorStack warnings + * - callbacks for specific exception classes and their children + * + * 2) Ideas: + * + * - Maybe a way to define a 'template' for the output + * + * 3) Inherited properties from PHP Exception Class: + * + * protected $message + * protected $code + * protected $line + * protected $file + * private $trace + * + * 4) Inherited methods from PHP Exception Class: + * + * __clone + * __construct + * getMessage + * getCode + * getFile + * getLine + * getTraceSafe + * getTraceSafeAsString + * __toString + * + * 5) Usage example + * + * <code> + * require_once 'PEAR/Exception.php'; + * + * class Test { + * function foo() { + * throw new PEAR_Exception('Error Message', ERROR_CODE); + * } + * } + * + * function myLogger($pear_exception) { + * echo $pear_exception->getMessage(); + * } + * // each time a exception is thrown the 'myLogger' will be called + * // (its use is completely optional) + * PEAR_Exception::addObserver('myLogger'); + * $test = new Test; + * try { + * $test->foo(); + * } catch (PEAR_Exception $e) { + * print $e; + * } + * </code> + * + * @category pear + * @package PEAR + * @author Tomas V.V.Cox <cox@idecnet.com> + * @author Hans Lellelid <hans@velum.net> + * @author Bertrand Mansion <bmansion@mamasam.com> + * @author Greg Beaver <cellog@php.net> + * @copyright 1997-2009 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 1.9.3 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.3.3 + * + */ +class PEAR_Exception extends Exception +{ + const OBSERVER_PRINT = -2; + const OBSERVER_TRIGGER = -4; + const OBSERVER_DIE = -8; + protected $cause; + private static $_observers = array(); + private static $_uniqueid = 0; + private $_trace; + + /** + * Supported signatures: + * - PEAR_Exception(string $message); + * - PEAR_Exception(string $message, int $code); + * - PEAR_Exception(string $message, Exception $cause); + * - PEAR_Exception(string $message, Exception $cause, int $code); + * - PEAR_Exception(string $message, PEAR_Error $cause); + * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); + * - PEAR_Exception(string $message, array $causes); + * - PEAR_Exception(string $message, array $causes, int $code); + * @param string exception message + * @param int|Exception|PEAR_Error|array|null exception cause + * @param int|null exception code or null + */ + public function __construct($message, $p2 = null, $p3 = null) + { + if (is_int($p2)) { + $code = $p2; + $this->cause = null; + } elseif (is_object($p2) || is_array($p2)) { + // using is_object allows both Exception and PEAR_Error + if (is_object($p2) && !($p2 instanceof Exception)) { + if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { + throw new PEAR_Exception('exception cause must be Exception, ' . + 'array, or PEAR_Error'); + } + } + $code = $p3; + if (is_array($p2) && isset($p2['message'])) { + // fix potential problem of passing in a single warning + $p2 = array($p2); + } + $this->cause = $p2; + } else { + $code = null; + $this->cause = null; + } + parent::__construct($message, $code); + $this->signal(); + } + + /** + * @param mixed $callback - A valid php callback, see php func is_callable() + * - A PEAR_Exception::OBSERVER_* constant + * - An array(const PEAR_Exception::OBSERVER_*, + * mixed $options) + * @param string $label The name of the observer. Use this if you want + * to remove it later with removeObserver() + */ + public static function addObserver($callback, $label = 'default') + { + self::$_observers[$label] = $callback; + } + + public static function removeObserver($label = 'default') + { + unset(self::$_observers[$label]); + } + + /** + * @return int unique identifier for an observer + */ + public static function getUniqueId() + { + return self::$_uniqueid++; + } + + private function signal() + { + foreach (self::$_observers as $func) { + if (is_callable($func)) { + call_user_func($func, $this); + continue; + } + settype($func, 'array'); + switch ($func[0]) { + case self::OBSERVER_PRINT : + $f = (isset($func[1])) ? $func[1] : '%s'; + printf($f, $this->getMessage()); + break; + case self::OBSERVER_TRIGGER : + $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; + trigger_error($this->getMessage(), $f); + break; + case self::OBSERVER_DIE : + $f = (isset($func[1])) ? $func[1] : '%s'; + die(printf($f, $this->getMessage())); + break; + default: + trigger_error('invalid observer type', E_USER_WARNING); + } + } + } + + /** + * Return specific error information that can be used for more detailed + * error messages or translation. + * + * This method may be overridden in child exception classes in order + * to add functionality not present in PEAR_Exception and is a placeholder + * to define API + * + * The returned array must be an associative array of parameter => value like so: + * <pre> + * array('name' => $name, 'context' => array(...)) + * </pre> + * @return array + */ + public function getErrorData() + { + return array(); + } + + /** + * Returns the exception that caused this exception to be thrown + * @access public + * @return Exception|array The context of the exception + */ + public function getCause() + { + return $this->cause; + } + + /** + * Function must be public to call on caused exceptions + * @param array + */ + public function getCauseMessage(&$causes) + { + $trace = $this->getTraceSafe(); + $cause = array('class' => get_class($this), + 'message' => $this->message, + 'file' => 'unknown', + 'line' => 'unknown'); + if (isset($trace[0])) { + if (isset($trace[0]['file'])) { + $cause['file'] = $trace[0]['file']; + $cause['line'] = $trace[0]['line']; + } + } + $causes[] = $cause; + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } elseif ($this->cause instanceof Exception) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => $this->cause->getFile(), + 'line' => $this->cause->getLine()); + } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } elseif ($cause instanceof Exception) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => $cause->getFile(), + 'line' => $cause->getLine()); + } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($cause) && isset($cause['message'])) { + // PEAR_ErrorStack warning + $causes[] = array( + 'class' => $cause['package'], + 'message' => $cause['message'], + 'file' => isset($cause['context']['file']) ? + $cause['context']['file'] : + 'unknown', + 'line' => isset($cause['context']['line']) ? + $cause['context']['line'] : + 'unknown', + ); + } + } + } + } + + public function getTraceSafe() + { + if (!isset($this->_trace)) { + $this->_trace = $this->getTrace(); + if (empty($this->_trace)) { + $backtrace = debug_backtrace(); + $this->_trace = array($backtrace[count($backtrace)-1]); + } + } + return $this->_trace; + } + + public function getErrorClass() + { + $trace = $this->getTraceSafe(); + return $trace[0]['class']; + } + + public function getErrorMethod() + { + $trace = $this->getTraceSafe(); + return $trace[0]['function']; + } + + public function __toString() + { + if (isset($_SERVER['REQUEST_URI'])) { + return $this->toHtml(); + } + return $this->toText(); + } + + public function toHtml() + { + $trace = $this->getTraceSafe(); + $causes = array(); + $this->getCauseMessage($causes); + $html = '<table style="border: 1px" cellspacing="0">' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '<tr><td colspan="3" style="background: #ff9999">' + . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: ' + . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> ' + . 'on line <b>' . $cause['line'] . '</b>' + . "</td></tr>\n"; + } + $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n" + . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>' + . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>' + . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '<tr><td style="text-align: center;">' . $k . '</td>' + . '<td>'; + if (!empty($v['class'])) { + $html .= $v['class'] . $v['type']; + } + $html .= $v['function']; + $args = array(); + if (!empty($v['args'])) { + foreach ($v['args'] as $arg) { + if (is_null($arg)) $args[] = 'null'; + elseif (is_array($arg)) $args[] = 'Array'; + elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; + elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; + elseif (is_int($arg) || is_double($arg)) $args[] = $arg; + else { + $arg = (string)$arg; + $str = htmlspecialchars(substr($arg, 0, 16)); + if (strlen($arg) > 16) $str .= '…'; + $args[] = "'" . $str . "'"; + } + } + } + $html .= '(' . implode(', ',$args) . ')' + . '</td>' + . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown') + . ':' . (isset($v['line']) ? $v['line'] : 'unknown') + . '</td></tr>' . "\n"; + } + $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>' + . '<td>{main}</td>' + . '<td> </td></tr>' . "\n" + . '</table>'; + return $html; + } + + public function toText() + { + $causes = array(); + $this->getCauseMessage($causes); + $causeMsg = ''; + foreach ($causes as $i => $cause) { + $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' + . $cause['message'] . ' in ' . $cause['file'] + . ' on line ' . $cause['line'] . "\n"; + } + return $causeMsg . $this->getTraceAsString(); + } +} \ No newline at end of file diff --git a/vendor/SerialsSolutions/Summon/Base.php b/vendor/SerialsSolutions/Summon/Base.php new file mode 100644 index 0000000000000000000000000000000000000000..af230d8b745649db8d00155f6f78ff3080e1dfcc --- /dev/null +++ b/vendor/SerialsSolutions/Summon/Base.php @@ -0,0 +1,329 @@ +<?php +/** + * Summon Search API Interface (abstract base class) + * + * PHP version 5 + * + * Copyright (C) Serials Solutions 2011. + * + * 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 SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +require_once 'SerialsSolutions/Summon/Exception.php'; + +/** + * Summon REST API Interface (abstract base class) + * + * @category SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +abstract class SerialsSolutions_Summon_Base +{ + /** + * A boolean value determining whether to print debug information + * @var bool + */ + protected $debug = false; + + /** + * The URL of the Summon API server + * @var string + */ + protected $host = 'http://api.summon.serialssolutions.com'; + + /** + * The API version to use + * + * @var string + */ + protected $version = '2.0.0'; + + /** + * The secret Key used for authentication + * @var string + */ + protected $apiKey; + + /** + * The Client ID used for authentication + * @var string + */ + protected $apiId; + + /** + * The session for the current transaction + * @var string + */ + protected $sessionId = false; + + /** + * Is the end user authenticated or not? + * @var bool + */ + protected $authedUser = false; + + /** + * Constructor + * + * 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; legal keys: + * <ul> + * <li>authedUser - is the end-user authenticated?</li> + * <li>debug - boolean to control debug mode</li> + * <li>host - base URL of Summon API</li> + * <li>sessionId - Summon session ID to apply</li> + * <li>version - API version to use</li> + * </ul> + */ + public function __construct($apiId, $apiKey, $options = array()) + { + // Process incoming parameters: + $this->apiId = $apiId; + $this->apiKey = $apiKey; + $legalOptions = array('authedUser', 'debug', 'host', 'sessionId', 'version'); + foreach ($legalOptions as $option) { + if (isset($options[$option])) { + $this->$option = $options[$option]; + } + } + } + + /** + * Print a message if debug is enabled. + * + * @param string $msg Message to print + * + * @return void + */ + protected function debugPrint($msg) + { + if ($this->debug) { + echo "<pre>{$msg}</pre>\n"; + } + } + + /** + * Retrieves a document specified by the ID. + * + * @param string $id The document to retrieve from the Summon API + * + * @return string The requested resource + */ + public function getRecord($id) + { + $this->debugPrint("Get Record: $id"); + + // Query String Parameters + $options = array('s.q' => sprintf('ID:"%s"', $id)); + return $this->call($options); + } + + /** + * Execute a search. + * + * @param SerialsSolutions_Summon_Query $query Query object + * @param bool $returnErr On fatal error, should we fail + * outright (false) or treat it as an empty result set with an error key set + * (true)? + * + * @return array An array of query results + */ + public function query($query, $returnErr = false) + { + // Query String Parameters + $options = $query->getOptionsArray(); + $options['s.role'] = $this->authedUser ? 'authenticated' : 'none'; + + // Special case -- if user filtered down to newspapers AND excluded them, + // we can't possibly have any results: + if (isset($options['s.fvf']) && is_array($options['s.fvf']) + && in_array('ContentType,Newspaper Article,true', $options['s.fvf']) + && in_array('ContentType,Newspaper Article', $options['s.fvf']) + ) { + return array( + 'recordCount' => 0, + 'documents' => array() + ); + } + + $this->debugPrint('Query: ' . print_r($options, true)); + + try { + $result = $this->call($options); + } catch (SerialsSolutions_Summon_Exception $e) { + if ($returnErr) { + return array( + 'recordCount' => 0, + 'documents' => array(), + 'errors' => $e->getMessage() + ); + } else { + $this->handleFatalError($e); + } + } + + return $result; + } + + /** + * Submit REST Request + * + * @param array $params An array of parameters for the request + * @param string $service The API Service to call + * @param string $method The HTTP Method to use + * @param bool $raw Whether to return raw XML or processed + * + * @throws SerialsSolutions_Summon_Exception + * @return object The Summon API response (or a PEAR_Error object). + */ + protected function call($params = array(), $service = 'search', $method = 'GET', + $raw = false + ) { + $baseUrl = $this->host . '/' . $this->version . '/' . $service; + + // Build Query String + $query = array(); + foreach ($params as $function => $value) { + if (is_array($value)) { + foreach ($value as $additional) { + $additional = urlencode($additional); + $query[] = "$function=$additional"; + } + } else { + $value = urlencode($value); + $query[] = "$function=$value"; + } + } + asort($query); + $queryString = implode('&', $query); + + // Build Authorization Headers + $headers = array( + 'Accept' => 'application/json', + 'x-summon-date' => date('D, d M Y H:i:s T'), + 'Host' => 'api.summon.serialssolutions.com' + ); + $data = implode($headers, "\n") . "\n/$this->version/$service\n" . + urldecode($queryString) . "\n"; + $hmacHash = $this->hmacsha1($this->apiKey, $data); + $headers['Authorization'] = "Summon $this->apiId;$hmacHash"; + if ($this->sessionId) { + $headers['x-summon-session-id'] = $this->sessionId; + } + + // Send and process request + return $this->process( + $this->httpRequest($baseUrl, $method, $queryString, $headers) + ); + } + + /** + * Perform normalization and analysis of Summon return value. + * + * @param array $input The raw response from Summon + * + * @throws SerialsSolutions_Summon_Exception + * @return array The processed response from Summon + */ + protected function process($input) + { + // Unpack JSON Data + $result = json_decode($input, true); + + // Catch decoding errors -- turn a bad JSON input into an empty result set + // containing an appropriate error code. + if (!$result) { + $result = array( + 'recordCount' => 0, + 'documents' => array(), + 'errors' => array( + array( + 'code' => 'PHP-Internal', + 'message' => 'Cannot decode JSON response: ' . $input + ) + ) + ); + } + + // Detect errors + if (isset($result['errors']) && is_array($result['errors'])) { + foreach ($result['errors'] as $current) { + $errors[] = "{$current['code']}: {$current['message']}"; + } + $msg = 'Unable to process query<br />Summon returned: ' . + implode('<br />', $errors); + throw new SerialsSolutions_Summon_Exception($msg); + } + + return $result; + } + + /** + * Generate an HMAC hash + * + * @param string $key Hash key + * @param string $data Data to hash + * + * @return string Generated hash + */ + protected function hmacsha1($key, $data) + { + $blocksize=64; + $hashfunc='sha1'; + if (strlen($key)>$blocksize) { + $key=pack('H*', $hashfunc($key)); + } + $key=str_pad($key, $blocksize, chr(0x00)); + $ipad=str_repeat(chr(0x36), $blocksize); + $opad=str_repeat(chr(0x5c), $blocksize); + $hmac = pack( + 'H*', $hashfunc( + ($key^$opad).pack( + 'H*', $hashfunc( + ($key^$ipad).$data + ) + ) + ) + ); + return base64_encode($hmac); + } + + /** + * Perform an HTTP request. + * + * @param string $baseUrl Base URL for request + * @param string $method HTTP method for request + * @param string $queryString Query string to append to URL + * @param array $headers HTTP headers to send + * + * @throws SerialsSolutions_Summon_Exception + * @return string HTTP response body + */ + abstract protected function httpRequest($baseUrl, $method, $queryString, + $headers + ); +} diff --git a/vendor/SerialsSolutions/Summon/Exception.php b/vendor/SerialsSolutions/Summon/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..9a6224054c5a3fc751e207e2aee98dae67b6107f --- /dev/null +++ b/vendor/SerialsSolutions/Summon/Exception.php @@ -0,0 +1,42 @@ +<?php +/** + * Summon Search API Interface Exception + * + * PHP version 5 + * + * Copyright (C) Serials Solutions 2011. + * + * 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 SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ + +/** + * Summon Search API Interface Exception + * + * @category SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +class SerialsSolutions_Summon_Exception extends Exception +{ +} diff --git a/vendor/SerialsSolutions/Summon/PEAR.php b/vendor/SerialsSolutions/Summon/PEAR.php new file mode 100644 index 0000000000000000000000000000000000000000..21832a8ac09513021e5c821df382fc856d66b662 --- /dev/null +++ b/vendor/SerialsSolutions/Summon/PEAR.php @@ -0,0 +1,117 @@ +<?php +/** + * Summon Search API Interface (PEAR implementation) + * + * PHP version 5 + * + * Copyright (C) Serials Solutions 2011. + * + * 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 SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +require_once 'PEAR.php'; +require_once 'HTTP/Request.php'; +require_once 'SerialsSolutions/Summon/Base.php'; + +/** + * Summon Search API Interface (PEAR implementation) + * + * @category SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +class SerialsSolutions_Summon_PEAR extends SerialsSolutions_Summon_Base +{ + /** + * The HTTP_Request object used for API transactions + * @var object HTTP_Request + */ + protected $client; + + /** + * Constructor + * + * 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; legal keys: + * <ul> + * <li>authedUser - is the end-user authenticated?</li> + * <li>debug - boolean to control debug mode</li> + * <li>host - base URL of Summon API</li> + * <li>sessionId - Summon session ID to apply</li> + * <li>version - API version to use</li> + * </ul> + */ + public function __construct($apiId, $apiKey, $options = array()) + { + parent::__construct($apiId, $apiKey, $options); + $this->client = new HTTP_Request(null, array('useBrackets' => false)); + } + + /** + * Handle a fatal error. + * + * @param SerialsSolutions_Summon_Exception $e Exception to process. + * + * @return void + */ + public function handleFatalError($e) + { + PEAR::raiseError(new PEAR_Error($e->getMessage())); + } + + /** + * Perform an HTTP request. + * + * @param string $baseUrl Base URL for request + * @param string $method HTTP method for request + * @param string $queryString Query string to append to URL + * @param array $headers HTTP headers to send + * + * @throws SerialsSolutions_Summon_Exception + * @return string HTTP response body + */ + protected function httpRequest($baseUrl, $method, $queryString, $headers) + { + $this->debugPrint( + "{$method}: {$baseUrl}?{$queryString}" + ); + + // Set up request + $this->client->setURL($baseUrl); + $this->client->setMethod($method); + $this->client->addRawQueryString($queryString); + foreach ($headers as $key => $value) { + $this->client->addHeader($key, $value); + } + + // Send Request + $result = $this->client->sendRequest(); + if (PEAR::isError($result)) { + throw new SerialsSolutions_Summon_Exception($result->getMessage()); + } + return $this->client->getResponseBody(); + } +} diff --git a/vendor/SerialsSolutions/Summon/Query.php b/vendor/SerialsSolutions/Summon/Query.php new file mode 100644 index 0000000000000000000000000000000000000000..3b10a4914c4f3d622ce9d09c0f7a19407a20616d --- /dev/null +++ b/vendor/SerialsSolutions/Summon/Query.php @@ -0,0 +1,251 @@ +<?php +/** + * Summon Search API Interface (query model) + * + * PHP version 5 + * + * Copyright (C) Serials Solutions 2011. + * + * 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 SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ + +/** + * Summon REST API Interface (query model) + * + * @category SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +class SerialsSolutions_Summon_Query +{ + /** + * The query terms + * @var string + */ + protected $query; + + /** + * Whether to limit to the library's holdings or not + * @var bool + */ + protected $holdings = true; + + /** + * An array of facets to be requested + * @var array + */ + protected $facets = null; + + /** + * An array of filters to be applied + * @var array + */ + protected $filters = array(); + + /** + * An array of range filters to be applied + * @var array + */ + protected $rangeFilters = array(); + + /** + * Sort option + * @var string + */ + protected $sort = null; + + /** + * Results per page + * @var int + */ + protected $pageSize = 25; + + /** + * Page number to retrieve + * @var int + */ + protected $pageNumber = 1; + + /** + * Whether to enable spell checking + * @var bool + */ + protected $didYouMean = false; + + /** + * Whether to enable highlighting + * @var bool + */ + protected $highlight = false; + + /** + * Highlight start string + * @var string + */ + protected $highlightStart = ''; + + /** + * Highlight end string + * @var boolean + */ + protected $highlightEnd = ''; + + /** + * Constructor + * + * Sets up the Summon API Client + * + * @param string $query Search query + * @param array $options Other options to set (associative array) + */ + public function __construct($query = null, $options = array()) + { + $this->query = $query; + + foreach ($options as $key => $value) { + if (property_exists($this, $key)) { + $this->$key = $value; + } + } + + // Define default facets to request if necessary: + if (is_null($this->facets)) { + $this->facets = array( + 'IsScholarly,or,1,2', + 'Library,or,1,30', + 'ContentType,or,1,30', + 'SubjectTerms,or,1,30', + 'Language,or,1,30' + ); + } + } + + /** + * Turn the options within this object into an array of Summon parameters. + * + * @return array + */ + public function getOptionsArray() + { + $options = array( + 's.q' => $this->query, + 's.ps' => $this->pageSize, + 's.pn' => $this->pageNumber, + 's.ho' => $this->holdings ? 'true' : 'false', + 's.dym' => $this->didYouMean ? 'true' : 'false' + ); + if (!empty($this->facets)) { + $options['s.ff'] = $this->facets; + } + if (!empty($this->filters)) { + $options['s.fvf'] = $this->filters; + } + if (!empty($this->rangeFilters)) { + $options['s.rf'] = $this->rangeFilters; + } + if (!empty($this->sort)) { + $options['s.sort'] = $this->sort; + } + if ($this->highlight) { + $options['s.hl'] = 'true'; + $options['s.hs'] = $this->highlightStart; + $options['s.he'] = $this->highlightEnd; + } else { + $options['s.hl'] = 'false'; + $options['s.hs'] = $options['s.he'] = ''; + } + return $options; + } + + /** + * Add a filter + * + * @param string $f Filter to apply + * + * @return void + */ + public function addFilter($f) + { + $this->filters[] = $f; + } + + /** + * Add a range filter + * + * @param string $f Filter to apply + * + * @return void + */ + public function addRangeFilter($f) + { + $this->rangeFilters[] = $f; + } + + /** + * Magic method for getting/setting properties. + * + * @param string $method Method being called + * @param string $params Array of parameters + * + * @return mixed + */ + public function __call($method, $params) + { + if (strlen($method) > 4) { + $action = substr($method, 0, 3); + $property = strtolower(substr($method, 3, 1)) . substr($method, 4); + if ($action == 'get' && property_exists($this, $property)) { + return $this->$property; + } + if ($action == 'set' && property_exists($this, $property)) { + if (isset($params[0])) { + $this->$property = $params[0]; + return; + } + throw new ErrorException( + $method . ' missing required parameter', 0, E_ERROR + ); + } + } + throw new ErrorException( + 'Call to Undefined Method/Class Function', 0, E_ERROR + ); + } + + /** + * Escape a string for inclusion as part of a Summon parameter. + * + * @param string $input The string to escape. + * + * @return string The escaped string. + */ + public static function escapeParam($input) + { + // List of characters to escape taken from: + // http://api.summon.serialssolutions.com/help/api/search/parameters + return addcslashes($input, ",:\\()\${}"); + } +} + +?> diff --git a/vendor/SerialsSolutions/Summon/Zend.php b/vendor/SerialsSolutions/Summon/Zend.php new file mode 100644 index 0000000000000000000000000000000000000000..10cc5db9a940911243dd1a34ce635c5f9f3ecafd --- /dev/null +++ b/vendor/SerialsSolutions/Summon/Zend.php @@ -0,0 +1,124 @@ +<?php +/** + * Summon Search API Interface (Zend implementation) + * + * PHP version 5 + * + * Copyright (C) Serials Solutions 2011. + * + * 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 SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +require_once 'Zend/Http/Client.php'; +require_once 'SerialsSolutions/Summon/Base.php'; + +/** + * Summon Search API Interface (Zend implementation) + * + * @category SerialsSolutions + * @package Summon + * @author Andrew Nagy <andrew.nagy@serialssolutions.com> + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://api.summon.serialssolutions.com/help/api/ API Documentation + */ +class SerialsSolutions_Summon_Zend extends SerialsSolutions_Summon_Base +{ + /** + * The HTTP_Request object used for API transactions + * @var object HTTP_Request + */ + protected $client; + + /** + * Constructor + * + * 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; + * legal keys: + * <ul> + * <li>authedUser - is the end-user authenticated?</li> + * <li>debug - boolean to control debug mode</li> + * <li>host - base URL of Summon API</li> + * <li>sessionId - Summon session ID to apply</li> + * <li>version - API version to use</li> + * </ul> + * @param Zend_Http_Client $client HTTP client object (optional) + */ + public function __construct($apiId, $apiKey, $options = array(), $client = null) + { + parent::__construct($apiId, $apiKey, $options); + $this->client = is_object($client) ? $client : new Zend_Http_Client(); + } + + /** + * Handle a fatal error. + * + * @param SerialsSolutions_Summon_Exception $e Exception to process. + * + * @return void + */ + public function handleFatalError($e) + { + throw $e; + } + + /** + * Perform an HTTP request. + * + * @param string $baseUrl Base URL for request + * @param string $method HTTP method for request + * @param string $queryString Query string to append to URL + * @param array $headers HTTP headers to send + * + * @throws SerialsSolutions_Summon_Exception + * @return string HTTP response body + */ + protected function httpRequest($baseUrl, $method, $queryString, $headers) + { + $this->debugPrint( + "{$method}: {$baseUrl}?{$queryString}" + ); + + $this->client->resetParameters(); + if ($method == 'GET') { + $baseUrl .= '?' . $queryString; + } elseif ($method == 'POST') { + $this->client->setRawData( + $queryString, 'application/x-www-form-urlencoded' + ); + } + + foreach ($headers as $key => $value) { + $this->client->setHeaders($key, $value); + } + + // Send Request + $this->client->setUri($baseUrl); + $result = $this->client->request($method); + if ($result->isError()) { + throw new SerialsSolutions_Summon_Exception($result->getBody()); + } + return $result->getBody(); + } +} diff --git a/vendor/Structures/LinkedList/Double.php b/vendor/Structures/LinkedList/Double.php new file mode 100644 index 0000000000000000000000000000000000000000..75e696c0e1b5cd255857a756b03157502f2aa544 --- /dev/null +++ b/vendor/Structures/LinkedList/Double.php @@ -0,0 +1,375 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker textwidth=80: */ + +/** + * Linked list structure + * + * This package implements a doubly linked list structure. Each node + * (Structures_LinkedList_DoubleNode object) in the list + * (Structures_LinkedList_Double) knows the previous node and the next + * node in the list. Unlike an array, you can insert or delete nodes at + * arbitrary points in the list. + * + * If your application normally traverses the linked list in a forward-only + * direction, use the singly-linked list implemented by + * {@link Structures_LinkedList_Single}. If, however, your application + * needs to traverse the list backwards, or insert nodes into the list before + * other nodes in the list, use the double-linked list implemented by + * {@link Structures_LinkedList_Double} to give your application better + * performance at the cost of a slightly larger memory footprint. + * + * Structures_LinkedList_Double implements the Iterator interface so control + * structures like foreach($list as $node) and while($list->next()) work + * as expected. + * + * To use this package, derive a child class from + * Structures_LinkedList_DoubleNode and add data to the object. Then use the + * Structures_LinkedList_Double class to access the nodes. + * + * PHP version 5 + * + * LICENSE: Copyright 2006 Dan Scott + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @category Structures + * @package Structures_LinkedList_Double + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2006 Dan Scott + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 + * @version CVS: $Id: Double.php -1 $ + * @link http://pear.php.net/package/Structures_LinkedList + * @example double_link_example.php + * + * @todo Add some actual error conditions + **/ + +require_once 'PEAR/Exception.php'; +require_once 'Single.php'; + +// {{{ class Structures_LinkedList_Double +/** + * The Structures_LinkedList_Double class represents a linked list structure + * composed of {@link Structures_LinkedList_DoubleNode} objects. + * + * @category Structures + * @package Structures_LinkedList_Double + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 + * @link http://pear.php.net/package/Structures_LinkedList + */ +class Structures_LinkedList_Double extends Structures_LinkedList_Single implements Iterator +{ + // {{{ properties + /** + * Tail node of the linked list + * @var Structures_LinkedList_DoubleNode + */ + protected $tail_node; + // }}} + + // {{{ Constructor: function __construct() + /** + * Structures_LinkedList_Double constructor + * + * @param Structures_LinkedList_DoubleNode $root root node for the + * linked list + */ + function __construct(Structures_LinkedList_DoubleNode $root = null) + { + if ($root) { + $this->tail_node = $root; + } else { + $this->tail_node = null; + } + parent::__construct($root); + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Structures_LinkedList_Double destructor + * + * If we do not destroy all of the references in the linked list, + * we will quickly run out of memory for large / complex structures. + * + */ + function __destruct() + { + /* + * Starting with root node, set last node = root_node + * get next node + * if next node exists: + * delete last node's references to next node and previous node + * make the old next node the new last node + */ + if (!$last_node = $this->root_node) { + return; + } + while (($next_node = $last_node->next()) !== false) { + $last_node->setNext(null); + $last_node->setPrevious(null); + $last_node = $next_node; + } + $this->current = null; + $this->root_node = null; + $this->tail_node = null; + $last_node = null; + $next_node = null; + } + // }}} + + // {{{ function end() + /** + * Sets the pointer for the linked list to its last node + * + * @return Structures_LinkedList_DoubleNode last node in the linked list + */ + public function end() + { + if ($this->tail_node) { + $this->current = $this->tail_node; + } else { + $this->current = null; + } + return $this->current; + } + // }}} + + // {{{ function previous() + /** + * Sets the pointer for the linked list to the previous node and + * returns that node + * + * @return Structures_LinkedList_DoubleNode previous node in the linked list + */ + public function previous() + { + if (!$this->current()->previous()) { + return false; + } + $this->current = $this->current()->previous(); + return $this->current(); + } + // }}} + + // {{{ function insertNode() + /** + * Inserts a {@link Structures_LinkedList_DoubleNode} object into the linked + * list, based on a reference node that already exists in the list. + * + * @param Structures_LinkedList_DoubleNode $new_node New node to add to the list + * @param Structures_LinkedList_DoubleNode $existing_node Reference position node + * @param bool $before Insert new node before or after the existing node + * + * @return bool Success or failure + **/ + public function insertNode($new_node, $existing_node, $before = false) + { + if (!$this->root_node) { + $this->__construct($new_node); + } + + // Now add the node according to the requested mode + switch ($before) { + + case true: + $previous_node = $existing_node->previous(); + if ($previous_node) { + $previous_node->setNext($new_node); + $new_node->setPrevious($previous_node); + } else { + // The existing node must be root node; make new node root + $this->root_node = $new_node; + $new_node->setPrevious(); + } + $new_node->setNext($existing_node); + $existing_node->setPrevious($new_node); + + break; + + case false: + $new_node->setPrevious($existing_node); + $next_node = $existing_node->next(); + if ($next_node) { + $new_node->setNext($next_node); + $next_node->setPrevious($new_node); + } else { + // The existing node must have been the tail node + $this->tail_node = $new_node; + } + $existing_node->setNext($new_node); + + break; + + } + + return true; + } + // }}} + + // {{{ protected function getTailNode() + /** + * Returns the tail node of the linked list. + * + * This is a cheap operation for a doubly-linked list. + * + * @return bool Success or failure + **/ + protected function getTailNode() + { + return $this->tail_node; + } + // }}} + + // {{{ function deleteNode() + /** + * Deletes a {@link Structures_LinkedList_DoubleNode} from the list. + * + * @param Structures_LinkedList_DoubleNode $node Node to delete. + * + * @return null + */ + public function deleteNode($node) + { + /* If this is the root node, and there are more nodes in the list, + * make the next node the new root node before deleting this node. + */ + if ($node === $this->root_node) { + $this->root_node = $node->next(); + } + + /* If this is the tail node, and there are more nodes in the list, + * make the previous node the tail node before deleting this node + */ + if ($node === $this->tail_node) { + $this->tail_node = $node->previous(); + } + + /* If this is the current node, and there are other nodes in the list, + * try making the previous node the current node so that next() works + * as expected. + * + * If that fails, make the next node the current node. + * + * If that fails, null isn't such a bad place to be. + */ + if ($node === $this->current) { + if ($node->previous()) { + $this->current = $node->previous(); + } elseif ($node->next()) { + $this->current = $node->next(); + } else { + $this->current = null; + } + } + $node->__destruct(); + } + // }}} + +} +// }}} + +// {{{ class Structures_LinkedList_DoubleNode +/** + * The Structures_LinkedList_DoubleNode class represents a node in a + * {@link Structures_LinkedList_Double} linked list structure. + * + * @category Structures + * @package Structures_LinkedList_Double + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 + * @link http://pear.php.net/package/Structures_LinkedList + */ +class Structures_LinkedList_DoubleNode extends Structures_LinkedList_SingleNode +{ + // {{{ properties + /** + * Previous node in the linked list + * @var Structures_LinkedList_DoubleNode + */ + protected $previous; + // }}} + + // {{{ Constructor: function __construct() + /** + * Structures_LinkedList_DoubleNode constructor + */ + public function __construct() + { + $this->next = null; + $this->previous = null; + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Removes node from the list, adjusting the related nodes accordingly. + * + * This is a problem if the node is the root node for the list. + * At this point, however, we do not have access to the list itself. Hmm. + */ + public function __destruct() + { + $next = $this->next(); + $previous = $this->previous(); + if ($previous && $next) { + $previous->setNext($next); + $next->setPrevious($previous); + } elseif ($previous) { + $previous->setNext(); + } elseif ($next) { + $next->setPrevious(); + } + } + // }}} + + // {{{ function previous() + /** + * Return the previous node in the linked list + * + * @return Structures_LinkedList_DoubleNode previous node in the linked list + */ + public function previous() + { + if ($this->previous) { + return $this->previous; + } else { + return false; + } + } + // }}} + + // {{{ function setPrevious() + /** + * Sets the pointer for the previous node in the linked list + * to the specified node + * + * @param Structures_LinkedList_DoubleNode $node new previous node + * in the linked list + * + * @return Structures_LinkedList_DoubleNode new previous node in + * the linked list + */ + public function setPrevious($node = null) + { + $this->previous = $node; + return $this->previous; + } + // }}} + +} +// }}} + +?> diff --git a/vendor/Structures/LinkedList/Single.php b/vendor/Structures/LinkedList/Single.php new file mode 100644 index 0000000000000000000000000000000000000000..6f0d7078b5abf02c47692dbe4f56d60dce7e5f5a --- /dev/null +++ b/vendor/Structures/LinkedList/Single.php @@ -0,0 +1,535 @@ +<?php + +/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker textwidth=80: */ + +/** + * Linked list structure + * + * This package implements a singly linked list structure. Each node + * (Structures_LinkedList_SingleNode object) in the list + * (Structures_LinkedList_Single) knows the the next node in the list. + * Unlike an array, you can insert or delete nodes at arbitrary points + * in the list. + * + * If your application normally traverses the linked list in a forward-only + * direction, use the singly-linked list implemented by + * {@link Structures_LinkedList_Single}. If, however, your application + * needs to traverse the list backwards, or insert nodes into the list before + * other nodes in the list, use the double-linked list implemented by + * {@link Structures_LinkedList_Double} to give your application better + * performance at the cost of a slightly larger memory footprint. + * + * Structures_LinkedList_Single implements the Iterator interface so control + * structures like foreach($list as $node) and while($list->next()) work + * as expected. + * + * To use this package, derive a child class from + * Structures_LinkedList_SingleNode and add data to the object. Then use the + * Structures_LinkedList_Single class to access the nodes. + * + * PHP version 5 + * + * LICENSE: Copyright 2006 Dan Scott + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @category Structures + * @package Structures_LinkedList_Single + * @author Dan Scott <dscott@laurentian.ca> + * @copyright 2006 Dan Scott + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 + * @version CVS: $Id: Single.php -1 $ + * @link http://pear.php.net/package/Structures_LinkedList_Single + * @example single_link_example.php + * + * @todo Add some actual error conditions + **/ + +require_once 'PEAR/Exception.php'; + +// {{{ class Structures_LinkedList_Single +/** + * The Structures_LinkedList_Single class represents a linked list structure + * composed of {@link Structures_LinkedList_SingleNode} objects. + * + * @category Structures + * @package Structures_LinkedList_Single + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 + * @link http://pear.php.net/package/Structures_LinkedList_Single + */ +class Structures_LinkedList_Single implements Iterator +{ + // {{{ properties + /** + * Current node in the linked list + * @var Structures_LinkedList_SingleNode + */ + protected $current; + + /** + * Root node of the linked list + * @var Structures_LinkedList_SingleNode + */ + protected $root_node; + + /** + * The linked list contains no nodes + */ + const ERROR_EMPTY = -1; + + public static $messages = array( + self::ERROR_EMPTY => 'No nodes in this linked list' + ); + // }}} + + // {{{ Constructor: function __construct() + /** + * Structures_LinkedList_Single constructor + * + * @param Structures_LinkedList_SingleNode $root root node for the + * linked list + */ + function __construct(Structures_LinkedList_SingleNode $root = null) + { + if ($root) { + $this->root_node = $root; + $this->current = $root; + } else { + $this->root_node = null; + $this->current = null; + } + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Structures_LinkedList_Single destructor + * + * If we do not destroy all of the references in the linked list, + * we will quickly run out of memory for large / complex structures. + * + */ + function __destruct() + { + /* + * Starting with root node, set last node = root_node + * get next node + * if next node exists, delete last node reference to next node + */ + if (!$last_node = $this->root_node) { + return; + } + while (($next_node = $last_node->next()) !== false) { + $last_node->setNext(null); + $temp_node = $last_node; + $last_node = $next_node; + unset($temp_node); + } + $this->current = null; + $this->root_node = null; + $last_node = null; + $next_node = null; + } + // }}} + + // {{{ function current() + /** + * Returns the current node in the linked list + * + * @return Structures_LinkedList_SingleNode current node in the linked list + */ + public function current() + { + return $this->current; + } + // }}} + + // {{{ function rewind() + /** + * Sets the pointer for the linked list to the root node + * + * @return Structures_LinkedList_SingleNode root node in the linked list + */ + public function rewind() + { + if ($this->root_node) { + $this->current = $this->root_node; + } else { + $this->current = null; + } + return $this->current; + } + // }}} + + // {{{ function end() + /** + * Sets the pointer for the linked list to the root node + * + * @return Structures_LinkedList_SingleNode root node in the linked list + */ + public function end() + { + $this->current = $this->getTailNode(); + return $this->current; + } + // }}} + + // {{{ function key() + /** + * Stub for Iterator interface that simply returns the current node + * + * @return Structures_LinkedList_SingleNode current node in the linked list + */ + public function key() + { + return $this->current; + } + // }}} + + // {{{ function valid() + /** + * Stub for Iterator interface that simply returns the current node + * + * @return Structures_LinkedList_SingleNode current node in the linked list + */ + public function valid() + { + return $this->current(); + } + // }}} + + // {{{ function next() + /** + * Sets the pointer for the linked list to the next node and + * returns that node + * + * @return Structures_LinkedList_SingleNode next node in the linked list + */ + public function next() + { + if (!$this->current) { + return false; + } + $this->current = $this->current()->next(); + return $this->current; + } + // }}} + + // {{{ function previous() + /** + * Sets the pointer for the linked list to the previous node and + * returns that node + * + * @return Structures_LinkedList_SingleNode previous node in the linked list + */ + public function previous() + { + if (!$this->current) { + return false; + } + $this->current = $this->_getPreviousNode(); + return $this->current; + } + // }}} + + // {{{ protected function getTailNode() + /** + * Returns the tail node of the linked list. + * + * This is an expensive operation! + * + * @return bool Success or failure + **/ + protected function getTailNode() + { + $tail_node = $this->root_node; + while (($y = $tail_node->next()) !== false) { + $tail_node = $y; + } + return $tail_node; + } + // }}} + + // {{{ private function _getPreviousNode() + /** + * Returns the node prior to the current node in the linked list. + * + * This is an expensive operation for a singly linked list! + * + * @param Structures_LinkedList_SingleNode $node (Optional) Specific node + * for which we want to find the previous node + * + * @return Structures_LinkedList_SingleNode Previous node + **/ + private function _getPreviousNode($node = null) + { + if (!$node) { + $node = $this->current; + } + $prior_node = $this->root_node; + while (($y = $prior_node->next()) !== false) { + if ($y == $node) { + return $prior_node; + } + $prior_node = $y; + } + return null; + } + // }}} + + // {{{ function appendNode() + /** + * Adds a {@link Structures_LinkedList_SingleNode} object to the end of + * the linked list. + * + * @param Structures_LinkedList_SingleNode $new_node New node to append + * + * @return bool Success or failure + **/ + public function appendNode(Structures_LinkedList_SingleNode $new_node) + { + if (!$this->root_node) { + $this->__construct($new_node); + return true; + } + + // This is just a special case of insertNode() + $this->insertNode($new_node, $this->getTailNode()); + + return true; + } + // }}} + + // {{{ function insertNode() + /** + * Inserts a {@link Structures_LinkedList_SingleNode} object into the linked + * list, based on a reference node that already exists in the list. + * + * @param Structures_LinkedList_SingleNode $new_node New node to add to + * the list + * @param Structures_LinkedList_SingleNode $existing_node Reference + * position node + * @param bool $before Insert new node + * before or after the existing node + * + * @return bool Success or failure + **/ + public function insertNode($new_node, $existing_node, $before = false) + { + if (!$this->root_node) { + $this->__construct($new_node); + return true; + } + + // Now add the node according to the requested mode + switch ($before) { + + case true: + if ($existing_node === $this->root_node) { + $this->root_node = $new_node; + } + $previous_node = $this->_getPreviousNode($existing_node); + if ($previous_node) { + $previous_node->setNext($new_node); + } + $new_node->setNext($existing_node); + + break; + + case false: + $next_node = $existing_node->next(); + if ($next_node) { + $new_node->setNext($next_node); + } + $existing_node->setNext($new_node); + + break; + + } + + return true; + } + // }}} + + // {{{ function prependNode() + /** + * Adds a {@link Structures_LinkedList_SingleNode} object to the start + * of the linked list. + * + * @param Structures_LinkedList_SingleNode $new_node Node to prepend + * to the list + * + * @return bool Success or failure + **/ + public function prependNode(Structures_LinkedList_SingleNode $new_node) + { + if (!$this->root_node) { + $this->__construct($new_node); + return true; + } + + // This is just a special case of insertNode() + $this->insertNode($new_node, $this->root_node, true); + + return true; + } + // }}} + + // {{{ function deleteNode() + /** + * Deletes a {@link Structures_LinkedList_SingleNode} from the list. + * + * @param Structures_LinkedList_SingleNode $node Node to delete. + * + * @return null + */ + public function deleteNode($node) + { + /* If this is the root node, and there are more nodes in the list, + * make the next node the new root node before deleting this node. + */ + if ($node === $this->root_node) { + $this->root_node = $node->next(); + } + + /* If this is the current node, make the next node the current node. + * + * If that fails, null isn't such a bad place to be. + */ + if ($node === $this->current) { + if ($node->next()) { + $this->current = $node->next(); + } else { + $this->current = null; + } + } + $node->__destruct(); + } + // }}} + +} +// }}} + +// {{{ class Structures_LinkedList_SingleNode +/** + * The Structures_LinkedList_SingleNode class represents a node in a + * {@link Structures_LinkedList_Single} linked list structure. + * + * @category Structures + * @package Structures_LinkedList_Single + * @author Dan Scott <dscott@laurentian.ca> + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 + * @link http://pear.php.net/package/Structures_LinkedList_Single + */ +class Structures_LinkedList_SingleNode +{ + // {{{ properties + /** + * Next node in the linked list + * @var Structures_LinkedList_SingleNode + */ + protected $next; + // }}} + + // {{{ Constructor: function __construct() + /** + * Structures_LinkedList_SingleNode constructor + */ + public function __construct() + { + $this->next = null; + } + // }}} + + // {{{ Destructor: function __destruct() + /** + * Removes node from the list, adjusting the related nodes accordingly. + * + * This is a problem if the node is the root node for the list. + * At this point, however, we do not have access to the list itself. Hmm. + */ + public function __destruct() + { + } + // }}} + + // {{{ function next() + /** + * Return the next node in the linked list + * + * @return Structures_LinkedList_SingleNode next node in the linked list + */ + public function next() + { + if ($this->next) { + return $this->next; + } else { + return false; + } + } + // }}} + + // {{{ function previous() + /** + * Return the previous node in the linked list + * + * Stub method for Structures_LinkedList_DoubleNode to override. + * + * @return Structures_LinkedList_SingleNode previous node in the linked list + */ + public function previous() + { + return false; + } + // }}} + + // {{{ function setNext() + /** + * Sets the pointer for the next node in the linked list to the + * specified node + * + * @param Structures_LinkedList_SingleNode $node new next node in + * the linked list + * + * @return Structures_LinkedList_SingleNode new next node in the linked list + */ + public function setNext($node = null) + { + $this->next = $node; + return $this->next; + } + // }}} + + // {{{ function setPrevious() + /** + * Sets the pointer for the next node in the linked list to the + * specified node + * + * Stub method for Structures_LinkedList_DoubleNode to override. + * + * @param Structures_LinkedList_SingleNode $node new next node in + * the linked list + * + * @return Structures_LinkedList_SingleNode new next node in the linked list + */ + public function setPrevious($node = null) + { + return false; + } + // }}} +} + +// }}} + +?> diff --git a/vendor/Validate/ISPN.php b/vendor/Validate/ISPN.php new file mode 100644 index 0000000000000000000000000000000000000000..85eca16dff652ba69bab47c15648a680da206517 --- /dev/null +++ b/vendor/Validate/ISPN.php @@ -0,0 +1,371 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2005 Piotr Klaban, Damien Seguy, Helgi Þormar | +// | Þorbjörnsson, Pierre-Alain Joye | +// +----------------------------------------------------------------------+ +// | This source file is subject to the New BSD license, That is bundled | +// | with this package in the file LICENSE, and is available through | +// | the world-wide-web at | +// | http://www.opensource.org/licenses/bsd-license.php | +// | If you did not receive a copy of the new BSDlicense and are unable | +// | to obtain it through the world-wide-web, please send a note to | +// | pajoye@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Tomas V.V.Cox <cox@idecnet.com> | +// | Pierre-Alain Joye <pajoye@php.net> | +// +----------------------------------------------------------------------+ +// +/** + * Specific validation methods for International Standard Product Numbers (ISPN) + * + * @category Validate + * @package Validate_ISPN + * @author Piotr Klaban <makler@man.torun.pl> + * @author Damien Seguy <dams@nexen.net> + * @author Helgi Þormar Þorbjörnsson <dufuz@php.net> + * @copyright 1997-2005 Piotr Klaban, Damien Seguy, Helgi Þormar Þorbjörnsson, + * Pierre-Alain Joye + * @license http://www.opensource.org/licenses/bsd-license.php new BSD + * @version CVS: $Id: ISPN.php,v 1.13 2006/08/17 19:20:51 makler Exp $ + * @link http://pear.php.net/package/Validate_ISPN + */ + +/** + * Data validation class for International Standard Product Numbers (ISPN) + * + * This class provides methods to validate: + * - ISBN (International Standard Book Number) + * - ISSN (International Standard Serial Number) + * - ISMN (International Standard Music Number) + * - ISRC (International Standard Recording Code) + * - EAN/UCC-8 number + * - EAN/UCC-13 number + * - EAN/UCC-14 number + * - UCC-12 (U.P.C.) ID number + * - SSCC (Serial Shipping Container Code) + * + * @category Validate + * @package Validate_ISPN + * @author Piotr Klaban <makler@man.torun.pl> + * @author Damien Seguy <dams@nexen.net> + * @author Helgi Þormar Þorbjörnsson <dufuz@php.net> + * @copyright 1997-2005 Piotr Klaban, Damien Seguy, Helgi Þormar Þorbjörnsson, + * Pierre-Alain Joye + * @license http://www.opensource.org/licenses/bsd-license.php new BSD + * @version Release: @package_version@ + * @link http://pear.php.net/package/Validate_ISPN + */ +class Validate_ISPN +{ + function isbn($isbn) + { + if (preg_match("/[^0-9 IXSBN-]/", $isbn)) { + return false; + } + + $isbn = strtoupper($isbn); + $isbn = str_replace(array('ISBN', '-', ' ', "\t", "\n"), '', $isbn); + + if (strlen($isbn) == 13) { + return Validate_ISPN::isbn13($isbn); + } elseif (strlen($isbn) == 10) { + return Validate_ISPN::isbn10($isbn); + } else { + return false; + } + } + + /** + * Validate a ISBN 13 number + * The ISBN is a unique machine-readable identification number, + * which marks any book unmistakably. + * + * This function checks given number according + * + * Manual can be found at http://www.isbn-international.org + * + * @param string $isbn number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @author Helgi Þormar <dufuz@php.net> + * @author Piotr Klaban <makler@man.torun.pl> + */ + function isbn13($isbn) + { + if (preg_match("/[^0-9 ISBN-]/", $isbn)) { + return false; + } + + $isbn = strtoupper($isbn); + $isbn = str_replace(array('ISBN', '-', ' ', "\t", "\n"), '', $isbn); + if (!preg_match('/^[0-9]{13}$/', $isbn)) { + return false; + } + + return Validate_ISPN::ean13($isbn); + } + + /** + * Validate a ISBN 10 number + * The ISBN is a unique machine-readable identification number, + * which marks any book unmistakably. + * + * This function checks given number according + * + * Manual can be found at http://www.isbn-international.org + * + * @param string $isbn number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @author Damien Seguy <dams@nexen.net> + * @author Helgi Þormar <dufuz@php.net> + */ + function isbn10($isbn) + { + static $weights_isbn = array(10,9,8,7,6,5,4,3,2); + + if (preg_match("/[^0-9 IXSBN-]/", $isbn)) { + return false; + } + + $isbn = strtoupper($isbn); + $isbn = str_replace(array('ISBN', '-', ' ', "\t", "\n"), '', $isbn); + if (strlen($isbn) != 10) { + return false; + } + + if (!preg_match('/^[0-9]{9}[0-9X]$/', $isbn)) { + return false; + } + + // Requires base class Validate + require_once 'Validate.php'; + return Validate::_checkControlNumber($isbn, $weights_isbn, 11, 11); + } + + + /** + * Validate an ISSN (International Standard Serial Number) + * + * This function checks given ISSN number + * ISSN identifies periodical publications: + * http://www.issn.org + * + * @param string $issn number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @author Piotr Klaban <makler@man.torun.pl> + */ + function issn($issn) + { + static $weights_issn = array(8,7,6,5,4,3,2); + + $issn = strtoupper($issn); + $issn = str_replace(array('ISSN', '-', '/', ' ', "\t", "\n"), '', $issn); + $issn_num = str_replace('X', '0', $issn); + + // check if this is an 8-digit number + if (!is_numeric($issn_num) || strlen($issn) != 8) { + return false; + } + + // Requires base class Validate + require_once 'Validate.php'; + return Validate::_checkControlNumber($issn, $weights_issn, 11, 11); + } + + /** + * Validate a ISMN (International Standard Music Number) + * + * This function checks given ISMN number (ISO Standard 10957) + * ISMN identifies all printed music publications from all over the world + * whether available for sale, hire or gratis--whether a part, a score, + * or an element in a multi-media kit. + * + * Manual can be found at: + * http://www.ismn-international.org/ + * + * @param string $ismn ISMN number + * @return bool true if number is valid, otherwise false + * @access public + * @author Piotr Klaban <makler@man.torun.pl> + */ + function ismn($ismn) + { + static $weights_ismn = array(3,1,3,1,3,1,3,1,3); + + $ismn = strtoupper($ismn); + $ismn = str_replace(array('ISMN', '-', '/', ' ', "\t", "\n"), '', $ismn); + // First char has to be M (after ISMN has been stripped if present) + if ($ismn{0} != 'M') { + return false; + } + + // change M to 3 + $ismn{0} = 3; + + // check if this is a 10-digit number + if (!is_numeric($ismn) || strlen($ismn) != 10) { + return false; + } + + // Requires base class Validate + require_once 'Validate.php'; + return Validate::_checkControlNumber($ismn, $weights_ismn, 10, 10); + } + + /** + * Validate a ISRC (International Standard Recording Code) + * + * This function validates an International Standard Recording Code + * which is the international identification system for sound recordings + * and music videorecordings. + * + * @param string $isrc ISRC number + * @return bool true if number is valid, otherwise false + * @see http://www.ifpi.org/isrc/isrc_handbook.html + * @access public + * @author David Grant <david@grant.org.uk> + */ + function isrc($isrc) + { + $isrc = str_replace(array('ISRC', '-', ' '), '', strtoupper($isrc)); + if (!preg_match("/[A-Z]{2}[A-Z0-9]{3}[0-9]{7}/", $isrc)) { + return false; + } + + return true; + } + + /** + * Validate a EAN/UCC-8 number + * + * This function checks given EAN8 number + * used to identify trade items and special applications. + * http://www.ean-ucc.org/ + * http://www.uc-council.org/checkdig.htm + * + * @param string $ean number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @see Validate_ISPN::process() + * @author Piotr Klaban <makler@man.torun.pl> + */ + function ean8($ean) + { + static $weights_ean8 = array(3,1,3,1,3,1,3); + return Validate_ISPN::process($ean, 8, $weights_ean8, 10, 10); + } + + /** + * Validate a EAN/UCC-13 number + * + * This function checks given EAN/UCC-13 number used to identify + * trade items, locations, and special applications (e.g., coupons) + * http://www.ean-ucc.org/ + * http://www.uc-council.org/checkdig.htm + * + * @param string $ean number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @see Validate_ISPN::process() + * @author Piotr Klaban <makler@man.torun.pl> + */ + function ean13($ean) + { + static $weights_ean13 = array(1,3,1,3,1,3,1,3,1,3,1,3); + return Validate_ISPN::process($ean, 13, $weights_ean13, 10, 10); + } + + /** + * Validate a EAN/UCC-14 number + * + * This function checks given EAN/UCC-14 number + * used to identify trade items. + * http://www.ean-ucc.org/ + * http://www.uc-council.org/checkdig.htm + * + * @param string $ean number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @see Validate_ISPN::process() + * @author Piotr Klaban <makler@man.torun.pl> + */ + function ean14($ean) + { + static $weights_ean14 = array(3,1,3,1,3,1,3,1,3,1,3,1,3); + return Validate_ISPN::process($ean, 14, $weights_ean14, 10, 10); + } + + /** + * Validate a UCC-12 (U.P.C.) ID number + * + * This function checks given UCC-12 number used to identify + * trade items, locations, and special applications (e.g., * coupons) + * http://www.ean-ucc.org/ + * http://www.uc-council.org/checkdig.htm + * + * @param string $ucc number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @see Validate_ISPN::process() + * @author Piotr Klaban <makler@man.torun.pl> + */ + function ucc12($ucc) + { + static $weights_ucc12 = array(3,1,3,1,3,1,3,1,3,1,3); + return Validate_ISPN::process($ucc, 12, $weights_ucc12, 10, 10); + } + + /** + * Validate a SSCC (Serial Shipping Container Code) + * + * This function checks given SSCC number + * used to identify logistic units. + * http://www.ean-ucc.org/ + * http://www.uc-council.org/checkdig.htm + * + * @param string $sscc number (only numeric chars will be considered) + * @return bool true if number is valid, otherwise false + * @access public + * @see Validate_ISPN::process() + * @author Piotr Klaban <makler@man.torun.pl> + */ + function sscc($sscc) + { + static $weights_sscc = array(3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3); + return Validate_ISPN::process($sscc, 18, $weights_sscc, 10, 10); + } + + /** + * Does all the work for EAN8, EAN13, EAN14, UCC12 and SSCC + * and can be used for as base for similar kind of calculations + * + * @param int $data number (only numeric chars will be considered) + * @param int $lenght required length of number string + * @param int $modulo (optionsl) number + * @param int $subtract (optional) numbier + * @param array $weights holds the weight that will be used in calculations for the validation + * @return bool true if number is valid, otherwise false + * @access public + * @see Validate::_checkControlNumber() + */ + function process($data, $length, &$weights, $modulo = 10, $subtract = 0) + { + //$weights = array(3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3); + //$weights = array_slice($weights, 0, $length); + + $data = str_replace(array('-', '/', ' ', "\t", "\n"), '', $data); + + // check if this is a digit number and is the right length + if (!is_numeric($data) || strlen($data) != $length) { + return false; + } + + // Requires base class Validate + require_once 'Validate.php'; + return Validate::_checkControlNumber($data, $weights, $modulo, $subtract); + } +} +?> diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index 71800b6247d51952289c36157803ff51aaa0494b..425bed3f392ed9edf0544deb2ba1ae91c73e6e18 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -4,5 +4,11 @@ $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( + 'File' => $vendorDir, + 'Horde' => $vendorDir, + 'PEAR' => $vendorDir, + 'SerialsSolutions' => $vendorDir, + 'Structures' => $vendorDir, + 'Validate' => $vendorDir, 'Zend' => $vendorDir . '/ZF2/library/', );