identifiersAi = array( '00' => array($this->NUMERIC, 18, 18, true), '01' => array($this->NUMERIC, 14, 14, true), '02' => array($this->NUMERIC, 14, 14, true), '10' => array($this->ALPHA_NUMERIC, 1, 20, false), '11' => array($this->DATE_YYMMDD, 6, 6, false), '12' => array($this->DATE_YYMMDD, 6, 6, false), '13' => array($this->DATE_YYMMDD, 6, 6, false), '15' => array($this->DATE_YYMMDD, 6, 6, false), '17' => array($this->DATE_YYMMDD, 6, 6, false), '20' => array($this->NUMERIC, 2, 2, false), '21' => array($this->ALPHA_NUMERIC, 1, 20, false), '240' => array($this->ALPHA_NUMERIC, 1, 30, false), '241' => array($this->ALPHA_NUMERIC, 1, 30, false), '250' => array($this->ALPHA_NUMERIC, 1, 30, false), '251' => array($this->ALPHA_NUMERIC, 1, 30, false), '253' => array($this->NUMERIC, 14, 30, false), '30' => array($this->NUMERIC, 1, 8, false), '310y' => array($this->NUMERIC, 6, 6, false), '311y' => array($this->NUMERIC, 6, 6, false), '312y' => array($this->NUMERIC, 6, 6, false), '313y' => array($this->NUMERIC, 6, 6, false), '314y' => array($this->NUMERIC, 6, 6, false), '315y' => array($this->NUMERIC, 6, 6, false), '316y' => array($this->NUMERIC, 6, 6, false), '320y' => array($this->NUMERIC, 6, 6, false), '321y' => array($this->NUMERIC, 6, 6, false), '322y' => array($this->NUMERIC, 6, 6, false), '323y' => array($this->NUMERIC, 6, 6, false), '324y' => array($this->NUMERIC, 6, 6, false), '325y' => array($this->NUMERIC, 6, 6, false), '326y' => array($this->NUMERIC, 6, 6, false), '327y' => array($this->NUMERIC, 6, 6, false), '328y' => array($this->NUMERIC, 6, 6, false), '329y' => array($this->NUMERIC, 6, 6, false), '330y' => array($this->NUMERIC, 6, 6, false), '331y' => array($this->NUMERIC, 6, 6, false), '332y' => array($this->NUMERIC, 6, 6, false), '333y' => array($this->NUMERIC, 6, 6, false), '334y' => array($this->NUMERIC, 6, 6, false), '335y' => array($this->NUMERIC, 6, 6, false), '336y' => array($this->NUMERIC, 6, 6, false), '337y' => array($this->NUMERIC, 6, 6, false), '340y' => array($this->NUMERIC, 6, 6, false), '341y' => array($this->NUMERIC, 6, 6, false), '342y' => array($this->NUMERIC, 6, 6, false), '343y' => array($this->NUMERIC, 6, 6, false), '344y' => array($this->NUMERIC, 6, 6, false), '345y' => array($this->NUMERIC, 6, 6, false), '346y' => array($this->NUMERIC, 6, 6, false), '347y' => array($this->NUMERIC, 6, 6, false), '348y' => array($this->NUMERIC, 6, 6, false), '349y' => array($this->NUMERIC, 6, 6, false), '350y' => array($this->NUMERIC, 6, 6, false), '351y' => array($this->NUMERIC, 6, 6, false), '352y' => array($this->NUMERIC, 6, 6, false), '353y' => array($this->NUMERIC, 6, 6, false), '354y' => array($this->NUMERIC, 6, 6, false), '355y' => array($this->NUMERIC, 6, 6, false), '356y' => array($this->NUMERIC, 6, 6, false), '357y' => array($this->NUMERIC, 6, 6, false), '360y' => array($this->NUMERIC, 6, 6, false), '361y' => array($this->NUMERIC, 6, 6, false), '362y' => array($this->NUMERIC, 6, 6, false), '363y' => array($this->NUMERIC, 6, 6, false), '364y' => array($this->NUMERIC, 6, 6, false), '365y' => array($this->NUMERIC, 6, 6, false), '366y' => array($this->NUMERIC, 6, 6, false), '367y' => array($this->NUMERIC, 6, 6, false), '368y' => array($this->NUMERIC, 6, 6, false), '369y' => array($this->NUMERIC, 6, 6, false), '37' => array($this->NUMERIC, 1, 8, false), '390y' => array($this->NUMERIC, 1, 15, false), '391y' => array($this->NUMERIC, 4, 18, false), '392y' => array($this->NUMERIC, 1, 15, false), '393y' => array($this->NUMERIC, 4, 18, false), '400' => array($this->ALPHA_NUMERIC, 1, 30, false), '401' => array($this->ALPHA_NUMERIC, 1, 30, false), '402' => array($this->NUMERIC, 17, 17, false), '403' => array($this->ALPHA_NUMERIC, 1, 30, false), '410' => array($this->NUMERIC, 13, 13, true), '411' => array($this->NUMERIC, 13, 13, true), '412' => array($this->NUMERIC, 13, 13, true), '413' => array($this->NUMERIC, 13, 13, true), '414' => array($this->NUMERIC, 13, 13, true), '415' => array($this->NUMERIC, 13, 13, true), '420' => array($this->ALPHA_NUMERIC, 1, 20, false), '421' => array($this->ALPHA_NUMERIC, 4, 12, false), '422' => array($this->NUMERIC, 3, 3, false), '8001' => array($this->NUMERIC, 14, 14, false), '8002' => array($this->ALPHA_NUMERIC, 1, 20, false), '8003' => array($this->ALPHA_NUMERIC, 15, 30, false), '8004' => array($this->ALPHA_NUMERIC, 1, 30, false), '8005' => array($this->NUMERIC, 6, 6, false), '8006' => array($this->NUMERIC, 18, 18, false), '8007' => array($this->ALPHA_NUMERIC, 1, 30, false), '8018' => array($this->NUMERIC, 18, 18, false), '8020' => array($this->ALPHA_NUMERIC, 1, 25, false), '8100' => array($this->NUMERIC, 6, 6, false), '8101' => array($this->NUMERIC, 10, 10, false), '8102' => array($this->NUMERIC, 2, 2, false), '90' => array($this->ALPHA_NUMERIC, 1, 30, false), '91' => array($this->ALPHA_NUMERIC, 1, 30, false), '92' => array($this->ALPHA_NUMERIC, 1, 30, false), '93' => array($this->ALPHA_NUMERIC, 1, 30, false), '94' => array($this->ALPHA_NUMERIC, 1, 30, false), '95' => array($this->ALPHA_NUMERIC, 1, 30, false), '96' => array($this->ALPHA_NUMERIC, 1, 30, false), '97' => array($this->ALPHA_NUMERIC, 1, 30, false), '98' => array($this->ALPHA_NUMERIC, 1, 30, false), '99' => array($this->ALPHA_NUMERIC, 1, 30, false) ); $this->setStrictMode(true); $this->setTilde(true); } /** * Enables or disables the strict mode * * @param bool strictMode */ function setStrictMode($strictMode) { // public $this->strictMode = $strictMode; } /** * Parses Text * * @param string $text */ function parse($text) { // public parent::parse($this->parseGs1128($text)); $this->errorText .= $this->errorTextGS1128; } /** * Formats data for gs1-128 * * @return string */ function formatGs1128() { // private $formatedText = '~F1'; $formatedLabel = ''; $c = count($this->identifiersId); for($i = 0; $i < $c; $i++) { if($i > 0) { $formatedLabel .= ' '; } $formatedLabel .= '(' . $this->identifiersId[$i] . ')'; $formatedText .= $this->identifiersId[$i]; $formatedLabel .= $this->identifiersContent[$i]; $formatedText .= $this->identifiersContent[$i]; if(isset($this->identifiersAi[$this->identifiersId[$i]])) { $ai_data = $this->identifiersAi[$this->identifiersId[$i]]; } elseif(isset($this->identifiersId[$i][3])) { $identifierWithVar = substr($this->identifiersId[$i], 0, -1) . 'y'; $ai_data = isset($this->identifiersAi[$identifierWithVar]) ? $this->identifiersAi[$identifierWithVar] : NULL; } else { $ai_data = NULL; } /* We'll check if we need to add a ~F1 () char */ /* If we use the legacy mode, we always add a ~F1 () char between AIs */ if($ai_data !== NULL) { if(strlen($this->identifiersContent[$i]) < $ai_data[$this->MAXLENGTH] && ($i + 1) !== $c || !$this->strictMode && ($i + 1) !== $c) { $formatedText .= '~F1'; } } } if((strlen($formatedText) - 3) > $this->MAX_GS1128_CHARS) { $this->errorTextGS1128 = 'The barcode can\'t be bigger than ' . $this->MAX_GS1128_CHARS . ' characters.'; } $this->label = $formatedLabel; return $formatedText; } /** * Parses the text to gs1-128 * * @param mixed $text * @return mixed */ function parseGs1128($text) { // private /* We format correctly what the user gives */ if(is_array($text)) { $formatArray = array(); foreach($text as $content) { if(is_array($content)) { /* double array */ if(count($content) === 2) { if(is_array($content[$this->ID]) || is_array($content[$this->CONTENT])) { $this->errorTextGS1128 = 'Double arrays can\'t contain arrays.'; return false; } else { $formatArray[] = '(' . $content[$this->ID] . ')' . $content[$this->CONTENT]; } } else { $this->errorTextGS1128 = 'Double arrays must contain 2 values.'; return false; } } else { /* simple array */ $formatArray[] = $content; } } unset($text); $text = $formatArray; } else { /* string */ $text = array($text); } $textCount = count($text); for($cmpt = 0; $cmpt < $textCount; $cmpt++) { /* We parse the content of the array */ if(!$this->parseContent($text[$cmpt])) { return false; } } return $this->formatGs1128(); } /** * Splits the id and the content for each application identifiers (AIs) * * @param string $text * @param int $cmpt * * @return bool */ function parseContent($text) { // private /* $yAlreadySet has 3 states: */ /* null: There is no variable in the ID; true: the variable is already set; false: the variable is not set yet; */ $yAlreadySet = NULL; $realNameId = NULL; $separatorsFound = 0; $checksumAdded = 0; $decimalPointRemoved = 0; $toParse = str_replace('~F1' ,chr(29), $text); $nbCharToParse = strlen($toParse); $isFormated = $toParse[0] === '(' ? true : false; $maxCharId = $isFormated ? $this->MAX_ID_FORMATED : $this->MAX_ID_NOT_FORMATED; $id = strtolower(substr($toParse, 0, min($maxCharId, $nbCharToParse))); $id = $isFormated ? $this->findIdFormated($id, $yAlreadySet, $realNameId) : $this->findIdNotFormated($id, $yAlreadySet, $realNameId); if($id === false) { return false; } $nbCharId = $isFormated ? strlen($id) + 2 : strlen($id); $n = min($this->identifiersAi[$realNameId][$this->MAXLENGTH], $nbCharToParse); $content = substr($toParse, $nbCharId, $n); /* If we have an AI with an "y" var, we check if there is a decimal point in the next *MAXLENGTH* characters */ /* if there is one, we take an extra character */ if($yAlreadySet !== NULL) { if(strpos($content, '.') !== false || strpos($content, ',') !== false) { $n++; if($n <= $nbCharToParse) { /* We take an extra char */ $content = substr($toParse, $nbCharId, $n); } } } /* We check for separator */ $separator = strpos($content, chr(29)); if($separator !== false) { $content = substr($content, 0, $separator); $separatorsFound++; } /* We check the conformity */ if(!$this->checkConformity($content, $id, $realNameId)) { return false; } /* We check the checksum */ if(!$this->checkChecksum($content, $id, $realNameId, $checksumAdded)) { return false; } /* We check the vars */ if(!$this->checkVars($content, $id, $yAlreadySet, $decimalPointRemoved)) { return false; } $this->identifiersId[] = $id; $this->identifiersContent[] = $content; $nbCharLastContent = (((strlen($content) + $nbCharId) - $checksumAdded) + $decimalPointRemoved) + $separatorsFound; if($nbCharToParse - $nbCharLastContent > 0) { /* If there is more than one content in this array, we parse again */ $otherContent = substr($toParse, $nbCharLastContent, $nbCharToParse); $nbCharOtherContent = strlen($otherContent); if($otherContent[0] === chr(29)) { $otherContent = substr($otherContent, 1); $nbCharOtherContent--; } if($nbCharOtherContent > 0) { $text = $otherContent; $this->parseContent($text); } } return true; } /** * Checks if an id exists * * @param string $id * @param bool $yAlreadySet * @param string $realNameId * * @return bool */ function idExists($id, &$yAlreadySet, &$realNameId) { // private $yFound = isset($id[3]) && $id[3] === 'y'; $idVarAdded = substr($id, 0, -1) . 'y'; if(isset($this->identifiersAi[$id])) { if($yFound) { $yAlreadySet = false; } $realNameId = $id; return true; } elseif(!$yFound && isset($this->identifiersAi[$idVarAdded])) { /* if the id don't exist, we try to find this id with "y" at the last char */ $yAlreadySet = true; $realNameId = $idVarAdded; return true; } return false; } /** * Finds ID with formated content * * @param string $id * @param bool $yAlreadySet * @param string $realNameId * @return mixed */ function findIdFormated($id, &$yAlreadySet, &$realNameId) { // private $pos = strpos($id, ')'); if($pos === false) { $this->errorTextGS1128 = 'Identifiers must have no more than 4 characters.'; return false; } else { if($pos < 3) { $this->errorTextGS1128 = 'Identifiers must have at least 2 characters.'; return false; } $id = substr($id, 1, $pos - 1); if($this->idExists($id, $yAlreadySet, $realNameId)) { return $id; } else { $this->errorTextGS1128 = 'The identifier ' . $id . ' doesn\'t exist.'; return false; } } } /** * Finds ID with non-formated content * * @param string $id * @param bool $yAlreadySet * @param string $realNameId * @return mixed */ function findIdNotFormated($id, &$yAlreadySet, &$realNameId) { // private $tofind = $id; while(strlen($tofind) >= 2) { if($this->idExists($tofind, $yAlreadySet, $realNameId)) { return $tofind; } else { $tofind = substr($tofind, 0, -1); } } $this->errorTextGS1128 = 'Error in formatting, can\'t find an identifier.'; return false; } /** * Checks confirmity of the content * * @param string $content * @param string $id * @param string $realNameId * @return bool */ function checkConformity(&$content, $id, $realNameId) { // private switch($this->identifiersAi[$realNameId][$this->KIND_OF_DATA]) { case $this->NUMERIC: $content = str_replace(',', '.', $content); if(!preg_match("/^[0-9.]+$/", $content)) { $this->errorTextGS1128 = 'The value of "' . $id . '" must be numerical.'; return false; } break; case $this->DATE_YYMMDD: $valid_date = true; if(preg_match("/^[0-9]{6}$/", $content)) { $year = substr($content, 0, 2); $month = substr($content, 2, 2); $day = substr($content, 4, 2); /* day can be 00 if we only need month and year */ if(intval($month) < 1 || intval($month) > 12 || intval($day) < 0 || intval($day) > 31) { $valid_date = false; } } else { $valid_date = false; } if(!$valid_date) { $this->errorTextGS1128 = 'The value of "' . $id . '" must be in YYMMDD format.'; return false; } break; } /* We check the length of the content */ $nbCharContent = strlen($content); $checksumChar = 0; $minlengthContent = $this->identifiersAi[$realNameId][$this->MINLENGTH]; $maxlengthContent = $this->identifiersAi[$realNameId][$this->MAXLENGTH]; if($this->identifiersAi[$realNameId][$this->CHECKSUM]) { $checksumChar++; } if($nbCharContent < ($minlengthContent - $checksumChar)) { if($minlengthContent === $maxlengthContent) { $this->errorTextGS1128 = 'The value of "' . $id . '" must contain ' . $minlengthContent . ' character(s).'; return false; } else { $this->errorTextGS1128 = 'The value of "' . $id . '" must contain between ' . $minlengthContent . ' and ' . $maxlengthContent . ' character(s).'; return false; } } return true; } /** * Verifies the checksum * * @param string $content * @param string $id * @param int $realNameId * @param int $checksumAdded * @return bool */ function checkChecksum(&$content, $id, $realNameId, &$checksumAdded) { // private if($this->identifiersAi[$realNameId][$this->CHECKSUM]) { $nbCharContent = strlen($content); $minlengthContent = $this->identifiersAi[$realNameId][$this->MINLENGTH]; if($nbCharContent === ($minlengthContent - 1)) { /* we need to calculate the checksum */ $content .= $this->calculateChecksumMod10($content); $checksumAdded++; } elseif($nbCharContent === $minlengthContent) { /* we need to check the checksum */ $checksum = $this->calculateChecksumMod10(substr($content, 0, -1)); if(intval($content[$nbCharContent - 1]) !== $checksum) { $this->errorTextGS1128 = 'The checksum of "(' . $id . ') ' . $content . '" must be: ' . $checksum; return false; } } } return true; } /** * Checks vars "y" * * @param string $content * @param string $id * @param bool $yAlreadySet * @param int $decimalPointRemoved * @return bool */ function checkVars(&$content, &$id, $yAlreadySet, &$decimalPointRemoved) { // private $nbCharContent = strlen($content); /* We check for "y" var in AI */ if($yAlreadySet) { /* We'll check if we have a decimal point */ if(strpos($content, '.') !== false) { $this->errorTextGS1128 = 'If you do not use any "y" variable, you have to insert a whole number.'; return false; } } elseif($yAlreadySet !== NULL) { /* We need to replace the "y" var with the position of the decimal point */ $pos = strpos($content, '.'); if($pos === false) { $this->errorTextGS1128 = 'If you use a "y" variable, you have to insert a decimal number.'; return false; } else { $id = str_replace('y', $nbCharContent - ($pos + 1), strtolower($id)); $content = str_replace('.', '', $content); $decimalPointRemoved++; } } return true; } /** * Checksum Mod10 * @param int $content * @return int */ function calculateChecksumMod10($content) { // private // Calculating Checksum // Consider the right-most digit of the message to be in an "odd" position, // and assign odd/even to each character moving from right to left // Odd Position = 3, Even Position = 1 // Multiply it by the number // Add all of that and do 10-(?mod10) $odd = true; $checksumValue = 0; $c = strlen($content); for($i = $c; $i > 0; $i--) { if($odd === true) { $multiplier = 3; $odd = false; } else { $multiplier = 1; $odd = true; } $checksumValue += ($content[$i - 1] * $multiplier); } return (10 - $checksumValue % 10) % 10; } }; ?>