167 lines
5.5 KiB
PHP
167 lines
5.5 KiB
PHP
<?php
|
|
/**
|
|
*--------------------------------------------------------------------
|
|
*
|
|
* Sub-Class - ISBN-10 and ISBN-13
|
|
*
|
|
* You can provide an ISBN with 10 digits with or without the checksum.
|
|
* You can provide an ISBN with 13 digits with or without the checksum.
|
|
* Calculate the ISBN based on the EAN-13 encoding.
|
|
*
|
|
* The checksum is always displayed.
|
|
*
|
|
*--------------------------------------------------------------------
|
|
* @author Akhtar Khan <er.akhtarkhan@gmail.com>
|
|
* @link http://www.codeitnow.in
|
|
* @package https://github.com/codeitnowin/barcode-generator
|
|
*/
|
|
namespace CodeItNow\BarcodeBundle\Generator;
|
|
|
|
use CodeItNow\BarcodeBundle\Generator\CINParseException;
|
|
use CodeItNow\BarcodeBundle\Generator\CINArgumentException;
|
|
use CodeItNow\BarcodeBundle\Generator\CINean13;
|
|
|
|
class CINisbn extends CINean13 {
|
|
const GS1_AUTO = 0;
|
|
const GS1_PREFIX978 = 1;
|
|
const GS1_PREFIX979 = 2;
|
|
|
|
private $gs1;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param int $gs1
|
|
*/
|
|
public function __construct($gs1 = self::GS1_AUTO) {
|
|
parent::__construct();
|
|
$this->setGS1($gs1);
|
|
}
|
|
|
|
/**
|
|
* Adds the default label.
|
|
*/
|
|
protected function addDefaultLabel() {
|
|
if ($this->isDefaultEanLabelEnabled()) {
|
|
$isbn = $this->createISBNText();
|
|
$font = $this->font;
|
|
|
|
$topLabel = new CINLabel($isbn, $font, CINLabel::POSITION_TOP, CINLabel::ALIGN_CENTER);
|
|
|
|
$this->addLabel($topLabel);
|
|
}
|
|
|
|
parent::addDefaultLabel();
|
|
}
|
|
|
|
/**
|
|
* Sets the first numbers of the barcode.
|
|
* - GS1_AUTO: Adds 978 before the code
|
|
* - GS1_PREFIX978: Adds 978 before the code
|
|
* - GS1_PREFIX979: Adds 979 before the code
|
|
*
|
|
* @param int $gs1
|
|
*/
|
|
public function setGS1($gs1) {
|
|
$gs1 = (int)$gs1;
|
|
if ($gs1 !== self::GS1_AUTO && $gs1 !== self::GS1_PREFIX978 && $gs1 !== self::GS1_PREFIX979) {
|
|
throw new CINArgumentException('The GS1 argument must be CINisbn::GS1_AUTO, CINisbn::GS1_PREFIX978, or CINisbn::GS1_PREFIX979', 'gs1');
|
|
}
|
|
|
|
$this->gs1 = $gs1;
|
|
}
|
|
|
|
/**
|
|
* Check chars allowed.
|
|
*/
|
|
protected function checkCharsAllowed() {
|
|
$c = strlen($this->text);
|
|
|
|
// Special case, if we have 10 digits, the last one can be X
|
|
if ($c === 10) {
|
|
if (array_search($this->text[9], $this->keys) === false && $this->text[9] !== 'X') {
|
|
throw new CINParseException('isbn', 'The character \'' . $this->text[9] . '\' is not allowed.');
|
|
}
|
|
|
|
// Drop the last char
|
|
$this->text = substr($this->text, 0, 9);
|
|
}
|
|
|
|
return parent::checkCharsAllowed();
|
|
}
|
|
|
|
/**
|
|
* Check correct length.
|
|
*/
|
|
protected function checkCorrectLength() {
|
|
$c = strlen($this->text);
|
|
|
|
// If we have 13 chars just flush the last one
|
|
if ($c === 13) {
|
|
$this->text = substr($this->text, 0, 12);
|
|
} elseif ($c === 9 || $c === 10) {
|
|
if ($c === 10) {
|
|
// Before dropping it, we check if it's legal
|
|
if (array_search($this->text[9], $this->keys) === false && $this->text[9] !== 'X') {
|
|
throw new CINParseException('isbn', 'The character \'' . $this->text[9] . '\' is not allowed.');
|
|
}
|
|
|
|
$this->text = substr($this->text, 0, 9);
|
|
}
|
|
|
|
if ($this->gs1 === self::GS1_AUTO || $this->gs1 === self::GS1_PREFIX978) {
|
|
$this->text = '978' . $this->text;
|
|
} elseif ($this->gs1 === self::GS1_PREFIX979) {
|
|
$this->text = '979' . $this->text;
|
|
}
|
|
} elseif ($c !== 12) {
|
|
throw new CINParseException('isbn', 'The code parsed must be 9, 10, 12, or 13 digits long.');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates the ISBN text.
|
|
*
|
|
* @return string
|
|
*/
|
|
private function createISBNText() {
|
|
$isbn = '';
|
|
if (!empty($this->text)) {
|
|
// We try to create the ISBN Text... the hyphen really depends the ISBN agency.
|
|
// We just put one before the checksum and one after the GS1 if present.
|
|
$c = strlen($this->text);
|
|
if ($c === 12 || $c === 13) {
|
|
// If we have 13 characters now, just transform it temporarily to find the checksum...
|
|
// Further in the code we take care of that anyway.
|
|
$lastCharacter = '';
|
|
if ($c === 13) {
|
|
$lastCharacter = $this->text[12];
|
|
$this->text = substr($this->text, 0, 12);
|
|
}
|
|
|
|
$checksum = $this->processChecksum();
|
|
$isbn = 'ISBN ' . substr($this->text, 0, 3) . '-' . substr($this->text, 3, 9) . '-' . $checksum;
|
|
|
|
// Put the last character back
|
|
if ($c === 13) {
|
|
$this->text .= $lastCharacter;
|
|
}
|
|
} elseif ($c === 9 || $c === 10) {
|
|
$checksum = 0;
|
|
for ($i = 10; $i >= 2; $i--) {
|
|
$checksum += $this->text[10 - $i] * $i;
|
|
}
|
|
|
|
$checksum = 11 - $checksum % 11;
|
|
if ($checksum === 10) {
|
|
$checksum = 'X'; // Changing type
|
|
}
|
|
|
|
$isbn = 'ISBN ' . substr($this->text, 0, 9) . '-' . $checksum;
|
|
}
|
|
}
|
|
|
|
return $isbn;
|
|
}
|
|
}
|
|
?>
|