An easy way to “test” my package on a new version of Laravel

Yesterday I received a PR (thanks Javier Núñez) to update one of my packages that I wrote some while ago to validate the European VAT.

I started to develop a Laravel Package [laravel-vat-eu-validator] for fun and testing my abilities.
Everything’s started when I saw this 💩:

public static function controllaPIVA($pi)
{
if ($pi === '') return false;
if (strlen($pi) != 11)
return false;
if (strlen($pi) == 11) {
if (preg_match("/^[0-9]+\$/D", $pi) != 1)
return false;
$s = 0;
for ($i = 0; $i <= 9; $i += 2)
$s += ord($pi[$i]) - ord('0');
for ($i = 1; $i <= 9; $i += 2) {
$c = 2 * (ord($pi[$i]) - ord('0'));
if ($c > 9) $c = $c - 9;
$s += $c;
}
if ((10 - $s % 10) % 10 != ord($pi[10]) - ord('0'))
return false;
}
return true;
}

wait.

I can’t even read it, at first look it’s impossible to understand, you wouldn’t either. My head is blowing up.

I spent a lot of time trying to understand the code above, finally today I realized it was wrong and a bad implementation of Luhn algorithm. I will talk about refactor in a new post (luhn-example).

It’s seems the Italian VAT is validated by Lhun Algo https://en.wikipedia.org/wiki/VAT_identification_number like the SIM serial number and the credit card number.

So I wrote this super clean and simple class:

<?php

namespace Danielebarbaro\LaravelVatEuValidator;

use Danielebarbaro\LaravelVatEuValidator\Vies\Client;

class VatValidator
{
/**
* Regular expression patterns per country code
*
* @var array
* @link http://ec.europa.eu/taxation_customs/vies/faq.html?locale=en#item_11
*/
protected static $pattern_expression = array(
'AT' => 'U[A-Z\d]{8}',
'BE' => '(0\d{9}|\d{10})',
'BG' => '\d{9,10}',
'CY' => '\d{8}[A-Z]',
'CZ' => '\d{8,10}',
'DE' => '\d{9}',
'DK' => '(\d{2} ?){3}\d{2}',
'EE' => '\d{9}',
'EL' => '\d{9}',
'ES' => '[A-Z]\d{7}[A-Z]|\d{8}[A-Z]|[A-Z]\d{8}',
'FI' => '\d{8}',
'FR' => '([A-Z]{2}|\d{2})\d{9}',
'GB' => '\d{9}|\d{12}|(GD|HA)\d{3}',
'HR' => '\d{11}',
'HU' => '\d{8}',
'IE' => '[A-Z\d]{8}|[A-Z\d]{9}',
'IT' => '\d{11}',
'LT' => '(\d{9}|\d{12})',
'LU' => '\d{8}',
'LV' => '\d{11}',
'MT' => '\d{8}',
'NL' => '\d{9}B\d{2}',
'PL' => '\d{10}',
'PT' => '\d{9}',
'RO' => '\d{2,10}',
'SE' => '\d{12}',
'SI' => '\d{8}',
'SK' => '\d{10}'
);

/**
* Vies Client.
*/
private $client;

/**
* VatValidator constructor.
* @param Client|null $client
*/
public function __construct(Client $client = null)
{
$this->client = $client;

if (!$this->client) {
$this->client = new Client();
}
}

/**
* Validate a VAT number format.
* @param string $vatNumber
* @return boolean
*/
public function validateFormat(string $vatNumber): bool
{
$vatNumber = $this->vatCleaner($vatNumber);
list($country, $number) = $this->splitVat($vatNumber);

if (!isset(self::$pattern_expression[$country])) {
return false;
}

return preg_match('/^' . self::$pattern_expression[$country] . '$/', $number) > 0;
}

/**
* Check existence VAT number
* @param string $vatNumber
* @return boolean
* @throws Vies\ViesException
*/
public function validateExistence(string $vatNumber): bool
{
$vatNumber = $this->vatCleaner($vatNumber);
$result = $this->validateFormat($vatNumber);
if ($result) {
list($country, $number) = $this->splitVat($vatNumber);
$result = $this->client->check($country, $number);
}
return $result;
}

/**
* Validates a VAT number .
*
* @param string $vatNumber Either the full VAT number (incl. country).
* @return boolean
* @throws Vies\ViesException
*/
public function validate(string $vatNumber): bool
{
return $this->validateFormat($vatNumber) && $this->validateExistence($vatNumber);
}

/**
* @param string $vatNumber
* @return string
*/
private function vatCleaner(string $vatNumber): string
{
$vatNumber_no_spaces = trim($vatNumber);
return strtoupper($vatNumber_no_spaces);
}

/**
* @param string $vatNumber
* @return array
*/
private function splitVat(string $vatNumber): array
{
return [
substr($vatNumber, 0, 2),
substr($vatNumber, 2)
];
}

}

and then I have created a Laravel package.

When I received the PR I thought “Thanks God my package has tests”, thus it was super easy to extend the compatibility.

Every test passed so I merged the PR.

But for me it wasn’t enough, I would test it on a fresh L7 installation.

$ composer create-project --prefer-dist laravel/laravel laravel-seven

I added in composer.json just after "require-dev"

"repositories": {
"dev-laravel-vat-eu-validator": {
"type": "path",
"url": "laravel-vat-eu-validator",
"options": {
"symlink": true
}
}
},

I cloned in laravel-seven path my repo:

$ cd laravel-seven
$ git clone git@github.com:danielebarbaro/laravel-vat-eu-validator.git

So now I have my package in a specific folder and (eventually) I could switch branch easily directly in laravel-vat-eu-validator folder.

I wrote a simple controller:

<?php

namespace
App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class VatTesterController extends Controller
{

/**
* Show the form for creating a new resource.
*
*
@return Response
*/
public function
create()
{
return view('vat');
}

/**
* Store a newly created resource in storage.
*
*
@param Request $request
*
@return string
*/
public function
store(Request $request)
{
$request->validate([
'vat' => 'required|vat_number_exist|vat_number|vat_number_format',
]);

return 'Well Done.';
}
}

I wrote a clean blade:

<!DOCTYPE html>
<html>
<head>
<title>Package test</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"/>
</head>
<body class="bg-light">
<div class="container">
<div class="row">
<div class="col-md-6 offset-3 mt-5">
<div class="card ">
<div class="card-header bg-dark text-light">
<h5>VAT Form Tester</h5>
</div>
<div class="card-body">
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif

<form action="{{ route('vat.store') }}" method="POST">
@csrf
<div class="form-group">
<label>Vat : </label>
<input type="text" name="vat" class="form-control">
</div>
<div class="form-group text-center">
<input type="submit" class="btn btn-success" name="submit" value="Check">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

I added default routes:

Route::get('vat-verify','VatTesterController@create')->name('vat.create');
Route::post('vat-verify','VatTesterController@store')->name('vat.store');

I added in validation.php all necessary strings:

'vat_number' => 'The :attribute must be a valid VAT number.',
'vat_number_format' => 'The :attribute must be write in a valid number format {country_name}{vat_number}.',
'vat_number_exist' => 'VAT number :attribute not exist.',

and once I started the application with $ php artisan serve, on http://localhost:8000/vat-verify magic happened

After having understood Luhn Algo, today i added a little checker on my package, take a look at https://github.com/danielebarbaro/laravel-vat-eu-validator/commit/6a9ff5de6bb4dc5a147b2d1616765652210fad6c.

so now I’m ready to enjoy a ☕.

cheers, happy coding

--

--

--

Born in ’84, workaholic, engineer, clean code addicted. Always engaged in an endless battle to conquer the world. #Laravel #NestJs #Drupal #php #typescript

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

C# Delegates Revealed for Unity | Faramira

Introduction To Python (Beginner Lesson 1)

Apache Velocity

A Startup’s Guide to “the Cloud”

Pythonic way of storing your data

Python Data Structure- List, Tuple, Dictonary, Set

7. Reverse Integer

Hey there Creator Platform is here to service you better as Baas platform.

You’re a What? The Life of a Developer Relations Intern

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Daniele Barbaro

Daniele Barbaro

Born in ’84, workaholic, engineer, clean code addicted. Always engaged in an endless battle to conquer the world. #Laravel #NestJs #Drupal #php #typescript

More from Medium

How to create dynamic multiple instances of Filepond file upload library.

10 Resources to Learn Web Development with PHP

URLs manipulation in PHP (the easy way)

Change your URLs with a simple fluent PHP class

Why You Should Use Laravel Development For Skyrocket Your Business In 2022?