LBFormatter: Lebanon postal codes should accept 4 digits, not only 8

Description

The current LBFormatter only accepts 8-digit postal codes (regex ^[0-9]{8}$), but Lebanese postal codes are primarily 4 digits. Attempting to format a valid 4-digit Lebanese postal code like 1202 (Jdeidet Matn) results in an InvalidPostcodeException.

$formatter = new PostcodeFormatter();
$formatter->format('LB', '1202'); // throws InvalidPostcodeException

Current behavior

LBFormatter::format() requires exactly 8 digits:

if (preg_match('/^[0-9]{8}$/', $postcode) !== 1) {
    return null;
}

Expected behavior

The formatter should accept 4-digit postal codes (the standard format) and optionally the extended 8-digit format (NNNN NNNN, where the first 4 digits represent the postal zone and the last 4 represent the building).

Examples of valid 4-digit codes:

Code Location
1202 Jdeidet Matn
1200 Jounieh
1300 Tripoli
1801 Zahle
1600 Saida

Suggested fix

public function format(string $postcode) : ?string
{
    if (preg_match('/^[0-9]{4}$/', $postcode) === 1) {
        return $postcode;
    }

    if (preg_match('/^[0-9]{8}$/', $postcode) === 1) {
        return substr($postcode, 0, 4) . ' ' . substr($postcode, 4);
    }

    return null;
}

Sources

  • UPU (Universal Postal Union) official addressing guide for Lebanonupu.int/lbnEn.pdf — notably, the UPU guide does not include any postal code in Lebanese address examples at all, suggesting the format is loosely defined
  • youbianku.comLebanon postal codes — lists all Lebanese postal codes as 4-digit, and describes the format as "4 or 8 digits" where the last 4 digits (building-level) are optional
  • Precisely geocoding docsLBN — format described as NNNN NNNN, first 4 = postal zone, last 4 = building
  • worldpostalcode.comLebanon — lists 4-digit codes
  • postal-codes.netLebanon postal codes — all entries are 4-digit

The 8-digit format appears to be an extension where the additional 4 digits specify a building, but the base 4-digit code is the standard and widely used format.