Add validation for barcode types (#111, #246)

Fallback to code128 if invalid EAN8 or EAN13 is detected
This commit is contained in:
jekkos
2015-12-13 15:45:45 +01:00
parent 2f14a0f868
commit 9f5782e0ba
4 changed files with 112 additions and 102 deletions

View File

@@ -70,9 +70,24 @@ class Barcode_lib
try
{
$barcode = $this->get_barcode_instance($barcode_config['barcode_type']);
$is_valid = $barcode->validate($item['item_number']);
// if barcdoe validation does not succeed, then fallback to the default, which should not require specific formatting
if (!$is_valid)
{
$barcode = $this->get_barcode_instance();
}
$barcode_content = $barcode_config['barcode_content'] !== "id" && isset($item['item_number']) ? $item['item_number'] : $item['item_id'];
$barcode->setData($barcode_content);
if( $barcode_config['barcode_content'] !== "id" && isset($item['item_number']))
{
$barcode->setData($item['item_number']);
}
else
{
$barcode->setData($item['item_id']);
}
$barcode->setQuality($barcode_config['barcode_quality']);
$barcode->setDimensions($barcode_config['barcode_width'], $barcode_config['barcode_height']);
@@ -113,24 +128,34 @@ class Barcode_lib
}
}
public function get_barcode($item, $barcode_config)
public function get_new_barcode($item, $barcode_config)
{
try
{
$barcode = $this->get_barcode_instance($barcode_config['barcode_type']);
$barcode_content = $barcode_config['barcode_content'] !== "id" && isset($item['item_number']) ? $item['item_number'] : $item['item_id'];
$barcode->setData($barcode_content);
$code = $barcode->getData();
// in case no new code is generated like in Code39 and Code128 return an empty string because we don't want to override it with a pure item_id
if( $code == $item['item_id'] )
// generate a barcode only if one is not already available and we use the item_id as seed.
// This to avoid generating Barcodes out of existing Barcodes
if( $barcode_config['barcode_content'] !== "id" && isset($item['item_number']) )
{
$code = null;
$barcode->setData($item['item_number'], false);
return null;
}
else
{
$barcode->setData($item['item_id'], true);
$code = $barcode->getData();
// in case no new code is generated like in Code39 and Code128 return an empty string because we don't want to override it with a pure item_id
if( $code == $item['item_id'] )
{
$code = null;
}
return $code;
}
return $code;
}
catch(Exception $e)
{

View File

@@ -74,7 +74,16 @@ abstract class BarcodeBase
{
return $this->data;
}
/**
* Validate the given barcode.
* @param $barcode The barcode to validate
* @return bool true if it complies with the barcode formatting
*/
public function validate($barcode)
{
return TRUE;
}
/*
* (Abstract) Draw the image
*

View File

@@ -116,42 +116,54 @@ class Ean13 extends BarcodeBase
'9' => array('A','B','B','A','B','A')
);
/*
* Generate EAN13 code out of a provided number
* Code taken from http://stackoverflow.com/questions/19890144/generate-valid-ean13-in-php (unknown copyright / license claims)
*
* @param number is the internal code you want to have EANed. The prefix, zero-padding and checksum are added by the function.
* @return string with complete EAN13 code
*/
private function generateEAN($number)
{
$this->data = '200' . str_pad($number, 9, '0');
$weightflag = true;
$sum = 0;
// Weight for a digit in the checksum is 3, 1, 3.. starting from the last digit.
// loop backwards to make the loop length-agnostic. The same basic functionality
// will work for codes of different lengths.
for ($i = strlen($this->data) - 1; $i >= 0; $i--)
{
$sum += (int)$this->data[$i] * ($weightflag?3:1);
$weightflag = !$weightflag;
}
$this->data .= (10 - ($sum % 10)) % 10;
return $this->data;
}
/*
* Set the data
*
* @param mixed data - (int or string) Data to be encoded
* @return instance of \emberlabs\Barcode\BarcodeInterface
* @return throws \OverflowException
*/
public function setData($data)
{
$this->data = $this->generateEAN($data);
$this->data = $data;
}
public function validate($barcode)
{
// check to see if barcode is 13 digits long
if (!preg_match("/^[0-9]{13}$/", $barcode)) {
return false;
}
$digits = $barcode;
// 1. Add the values of the digits in the
// even-numbered positions: 2, 4, 6, etc.
$even_sum = $digits[1] + $digits[3] + $digits[5] +
$digits[7] + $digits[9] + $digits[11];
// 2. Multiply this result by 3.
$even_sum_three = $even_sum * 3;
// 3. Add the values of the digits in the
// odd-numbered positions: 1, 3, 5, etc.
$odd_sum = $digits[0] + $digits[2] + $digits[4] +
$digits[6] + $digits[8] + $digits[10];
// 4. Sum the results of steps 2 and 3.
$total_sum = $even_sum_three + $odd_sum;
// 5. The check character is the smallest number which,
// when added to the result in step 4, produces a multiple of 10.
$next_ten = (ceil($total_sum / 10)) * 10;
$check_digit = $next_ten - $total_sum;
// if the check digit and the last digit of the
// barcode are OK return true;
if ($check_digit == $digits[12]) {
return true;
}
return false;
}
/*

View File

@@ -89,69 +89,34 @@ class Ean8 extends BarcodeBase
)
);
/*
* Calculate EAN8 or EAN13 automatically
* set $len = 8 for EAN8, $len = 13 for EAN13
*
* @param number is the internal code you want to have EANed. The prefix, zero-padding and checksum are added by the function.
* @return string with complete EAN code
*/
private function generateEAN($number, $len = 8)
public function validate($barcode)
{
$this->data = null;
if($number > -1)
$ean = str_replace(array("-","/"," ","\t","\n"), "", $barcode); // make a clean ean
$len = strlen($ean);
if( !is_numeric($ean) )
{
$data_len = $len - 1;
$this->data = $number;
//Padding
$this->data = str_pad($this->data, $data_len, '0', STR_PAD_LEFT);
$this->data_len = strlen($this->data);
// calculate check digit
$sum_a = 0;
for ($i = 1; $i < $data_len; $i += 2)
{
$sum_a += $this->data{$i};
}
if ($len > 12)
{
$sum_a *= 3;
}
$sum_b = 0;
for ($i = 0; $i < $data_len; $i += 2)
{
$sum_b += ($this->data{$i});
}
if ($len < 13)
{
$sum_b *= 3;
}
$r = ($sum_a + $sum_b) % 10;
if($r > 0)
{
$r = (10 - $r);
}
if ($this->data_len == $data_len)
{
// add check digit
$this->data .= $r;
}
elseif ($r !== intval($this->data{$data_len}))
{
// wrong checkdigit
$this->data = null;
}
return false;
}
return $this->data;
$weights = array(3,1,3,1,3,1,3); // weights
$chk = $ean{7}; // 8. digit
$i = 0;
$sum = 0;
// sum or weight * digit
foreach($weights as $num) {
$sum += $num * $ean{$i};
$i++;
}
if( (($sum + $chk) % 10) == 0 )
{
return true;
}
return false;
}
/*
@@ -159,11 +124,10 @@ class Ean8 extends BarcodeBase
*
* @param mixed data - (int or string) Data to be encoded
* @return instance of \emberlabs\Barcode\BarcodeInterface
* @return throws \OverflowException
*/
public function setData($data)
{
$this->data = $this->generateEAN($data);
$this->data = $data;
}
/*