Skip to content

Instantly share code, notes, and snippets.

@fernandosavio
Created July 17, 2018 20:26
Show Gist options
  • Save fernandosavio/8d27984d8d7b3ab0e8a75475aa4a8422 to your computer and use it in GitHub Desktop.
Save fernandosavio/8d27984d8d7b3ab0e8a75475aa4a8422 to your computer and use it in GitHub Desktop.
<?php
class Gtin
{
/**
* Testa se a string é um GTIN válido nos seguintes termos:
* - É uma string
* - Contém apenas dígitos numéricos
* - Possui 8, 12, 13 ou 14 dígitos
*
* @param string $gtin
* @return bool
*/
public static function isValidString(string $gtin) : bool
{
return is_string($gtin) and ctype_digit($gtin) and in_array(strlen($gtin), [8, 12, 13, 14]);
}
/**
* Transforma uma string numérica em um array contendo os dígitos que serão calculados
* e o dígito verificador.
* Ex.:
* >>> self::estractCheckDigit('12345678');
* array(
* array(1, 2, 3, 4, 5, 6, 7),
* 8
* );
*
* @param string $gtin
* @return array
*/
protected static function extractCheckDigit(string $gtin) : array
{
// Converte uma string numérica para um array de inteiros
$code_digits = array_map('intval', str_split($gtin));
// Separa o último dígito dos restantes
$check_digit = array_pop($code_digits);
return [$code_digits, $check_digit];
}
/**
* Calcula o dígito verificador do GTIN recebido
* @param array $digits Um array com números inteiros representando todos os dígitos do GTIN exceto o verificador
* @return int O dígito verificador, um número entre 0 e 9.
*/
protected static function calculateCheckDigit(array $digits) : int
{
$sum = 0;
$i = count($digits) - 1;
/*
Intercala multiplicação entre 3 e 1 enquanto soma os resultados.
Exemplo: EAN13 => 1234567X
1 | 2 | 3 | 4 | 5 | 6 | 7 | X
* | * | * | * | * | * | * |
3 | 1 | 3 | 1 | 3 | 1 | 3 |
= | = | = | = | = | = | = |
3 + 2 + 9 + 4 + 15+ 6 + 21| 60
*/
for ($i = 0, $l = count($digits) ; $i < $l ; $i++) {
$value = $digits[$l - $i - 1]; // do último ao primeiro
$mult = $i & 1 ? 1 : 3; // se for iteração ímpar multiplica por 3
$sum += $value * $mult; // soma o resultdo
}
// Subtrai o último dígito da soma de 10
$check_digit = 10 - ($sum % 10);
// O dígito verificador é o último dígito do resultado
return $check_digit % 10;
}
/**
* Calcula o dígito verificador do GTIN e retorna true se for válido.
* @param string $gtin
* @return boolean
*/
public static function validate(string $gtin) : bool
{
if (! self::isValidString($gtin)) {
return false;
}
list($digits, $check_digit) = self::extractCheckDigit($gtin);
$correct_check = self::calculateCheckDigit($digits);
return $correct_check === $check_digit;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment