Skip to content

Commit

Permalink
Updated interface with missing methods and moved comments to interface.
Browse files Browse the repository at this point in the history
Made some minor fixes after sast recommendations.

Signed-off-by: Johannes Tegnér <johannes@jitesoft.com>
  • Loading branch information
Johannestegner committed Jan 18, 2024
1 parent 17529db commit 35a1d80
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 51 deletions.
2 changes: 1 addition & 1 deletion ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<!-- Run against the PHPCompatibility ruleset -->
<rule ref="PHPCompatibility"/>
<config name="testVersion" value="8.1-"/>
<config name="testVersion" value="8.1"/>

<!-- Run against a second ruleset -->
<rule ref="PSR12"/>
Expand Down
38 changes: 14 additions & 24 deletions src/Personnummer.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,20 @@
*/
final class Personnummer implements PersonnummerInterface
{
private $parts;
private array $parts;

private $options;
private array $options;

/**
*
* @param string $ssn
* @param array $options
*
* @return PersonnummerInterface
*
* @throws PersonnummerException
* @inheritDoc
*/
public static function parse(string $ssn, array $options = []): PersonnummerInterface
{
return new self($ssn, $options);
}

/**
* Check if a Swedish social security number is for a male.
*
* @return bool
* @inheritDoc
*/
public function isMale(): bool
{
Expand All @@ -52,25 +44,17 @@ public function isMale(): bool
return (bool)($genderDigit % 2);
}


/**
* Check if a Swedish social security number is for a female.
*
* @return bool
* @inheritDoc
*/
public function isFemale(): bool
{
return !$this->isMale();
}

/**
* Format a Swedish social security/coordination number as one of the official formats,
* A long format or a short format.
*
* If the input number could not be parsed an empty string will be returned.
*
* @param bool $longFormat short format YYMMDD-XXXX or long YYYYMMDDXXXX since the tax office says both are official
*
* @return string
* @inheritDoc
*/
public function format(bool $longFormat = false): string
{
Expand All @@ -94,18 +78,24 @@ public function format(bool $longFormat = false): string
);
}

/**
* @inheritDoc
*/
public function isCoordinationNumber(): bool
{
$parts = $this->parts;

return checkdate((int)$parts['month'], $parts['day'] - 60, $parts['fullYear']);
}

/**
* @inheritDoc
*/
public static function valid(string $ssn, array $options = []): bool
{
try {
return self::parse($ssn, $options)->isValid();
} catch (PersonnummerException $exception) {
} catch (PersonnummerException) {
return false;
}
}
Expand Down
51 changes: 51 additions & 0 deletions src/PersonnummerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Personnummer;

use Exception;

/**
* Interface PersonnummerInterface
*
Expand All @@ -18,17 +20,66 @@
*/
interface PersonnummerInterface
{
/**
* Parse a string representation of a Swedish social security number.
*
* @param string $ssn Social Security number to parse.
* @param array $options Parse options.
* @return PersonnummerInterface
* @throws PersonnummerException
*/
public static function parse(string $ssn, array $options = []): self;

/**
* Test a string representation of a Swedish social security number to see
* if it's valid.
*
* @param string $ssn Social Security number to parse.
* @param array $options Parse options.
* @return bool
*/
public static function valid(string $ssn, array $options = []): bool;

/**
* Format a Swedish social security/coordination number as one of the official formats,
* A long format or a short format.
*
* If the input number could not be parsed an empty string will be returned.
*
* @param bool $longFormat short format YYMMDD-XXXX or long YYYYMMDDXXXX since the tax office says both are official
* @return string
*/
public function format(bool $longFormat = false): string;

/**
* Check if a Swedish social security number is for a female.
*
* @return bool
*/
public function isFemale(): bool;

/**
* Check if a Swedish social security number is for a male.
*
* @return bool
*/
public function isMale(): bool;

/**
* Check if the Swedish social security number is a coordination number.
*
* @return bool
*/
public function isCoordinationNumber(): bool;

public function __construct(string $ssn, array $options = []);

/**
* Get age from a Swedish social security/coordination number.
*
* @return int
*
* @throws Exception When date is invalid or problems with DateTime library
*/
public function getAge(): int;
}
11 changes: 6 additions & 5 deletions tests/AssertError.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

trait AssertError
{
private $errors;
private array $errors;

/**
* AssertError.
Expand Down Expand Up @@ -37,9 +37,10 @@ public function assertError(
$callable();
restore_error_handler();

$comparisons = array_filter(compact('error_type', 'error_msg', 'error_file', 'error_line'), function ($value) {
return !is_null($value);
});
$comparisons = array_filter(
compact('error_type', 'error_msg', 'error_file', 'error_line'),
static fn ($value) => !is_null($value),
);

$matchingErrors = [];
foreach ($this->errors as $error) {
Expand All @@ -51,7 +52,7 @@ public function assertError(
if (empty($matchingErrors)) {
$failMessage = 'Expected error was not found';
$failMessage .= $comparisons ? ': ' : '';
$failMessage .= implode(', ', array_map(function ($value, $key) {
$failMessage .= implode(', ', array_map(static function ($value, $key) {
return $key . ': ' . $value;
}, $comparisons, array_keys($comparisons)));

Expand Down
42 changes: 21 additions & 21 deletions tests/PersonnummerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ class PersonnummerTest extends TestCase
use AssertThrows;
use AssertError;

private static $testdataList;
private static array $testdataList;

private static $testdataStructured;
private static array $testdataStructured;

private static $availableListFormats = [
private static array $availableListFormats = [
'integer',
'long_format',
'short_format',
Expand All @@ -29,17 +29,17 @@ class PersonnummerTest extends TestCase

public static function setUpBeforeClass(): void
{
self::$testdataList = json_decode(file_get_contents('https://raw.githubusercontent.com/personnummer/meta/master/testdata/list.json'), true); // phpcs:ignore
self::$testdataStructured = json_decode(file_get_contents('https://raw.githubusercontent.com/personnummer/meta/master/testdata/structured.json'), true); // phpcs:ignore
self::$testdataList = json_decode(file_get_contents('https://raw.githubusercontent.com/personnummer/meta/master/testdata/list.json'), true, 512, JSON_THROW_ON_ERROR); // phpcs:ignore
self::$testdataStructured = json_decode(file_get_contents('https://raw.githubusercontent.com/personnummer/meta/master/testdata/structured.json'), true, 512, JSON_THROW_ON_ERROR); // phpcs:ignore
}

public function testParse()
public function testParse(): void
{
$this->assertSame(Personnummer::class, get_class(Personnummer::parse('1212121212')));
$this->assertEquals(new Personnummer('1212121212'), Personnummer::parse('1212121212'));
}

public function testOptions()
public function testOptions(): void
{
new Personnummer('1212621211');

Expand All @@ -51,7 +51,7 @@ public function testOptions()
}, E_USER_WARNING);
}

public function testPersonnummerData()
public function testPersonnummerData(): void
{
foreach (self::$testdataList as $testdata) {
foreach (self::$availableListFormats as $format) {
Expand All @@ -69,7 +69,7 @@ public function testPersonnummerData()
}

foreach (self::$testdataStructured as $ssnType => $testdataInputs) {
foreach ($testdataInputs as $testdataType => $testdata) {
foreach ($testdataInputs as $testdata) {
foreach ($testdata as $valid => $ssns) {
foreach ($ssns as $ssn) {
$this->assertSame(
Expand All @@ -87,12 +87,12 @@ public function testPersonnummerData()
}
}

public function testFormat()
public function testFormat(): void
{
foreach (self::$testdataList as $testdata) {
if ($testdata['valid']) {
foreach (self::$availableListFormats as $format) {
if ($format === 'short_format' && strpos($testdata['separated_format'], '+') !== false) {
if ($format === 'short_format' && str_contains($testdata['separated_format'], '+')) {
continue;
}

Expand All @@ -104,7 +104,7 @@ public function testFormat()
}
}

public function testThrowsErrorOnInvalid()
public function testThrowsErrorOnInvalid(): void
{
foreach (self::$testdataList as $testdata) {
if (!$testdata['valid']) {
Expand Down Expand Up @@ -144,20 +144,20 @@ public function testThrowsErrorOnInvalid()
}
}

public function testAge()
public function testAge(): void
{
foreach (self::$testdataList as $testdata) {
if ($testdata['valid']) {
$birthdate = substr($testdata['separated_long'], 0, 8);
if ($testdata['type'] === 'con') {
$birthdate = substr($birthdate, 0, 6) .
str_pad(intval(substr($birthdate, -2)) - 60, 2, "0", STR_PAD_LEFT);
str_pad((int)substr($birthdate, -2) - 60, 2, "0", STR_PAD_LEFT);
}

$expected = intval((new DateTime($birthdate))->diff(new DateTime())->format('%y'));
$expected = (int)(new DateTime($birthdate))->diff(new DateTime())->format('%y');

foreach (self::$availableListFormats as $format) {
if ($format === 'short_format' && strpos($testdata['separated_format'], '+') !== false) {
if ($format === 'short_format' && str_contains($testdata['separated_format'], '+')) {
continue;
}

Expand All @@ -167,10 +167,10 @@ public function testAge()
}
}

public function testAgeOnBirthday()
public function testAgeOnBirthday(): void
{
$date = (new DateTime())->modify('-30 years midnight');
$expected = intval($date->diff(new DateTime())->format('%y'));
$expected = (int)$date->diff(new DateTime())->format('%y');

$ssn = $date->format('Ymd') . '999';

Expand All @@ -183,7 +183,7 @@ public function testAgeOnBirthday()
$this->assertSame($expected, Personnummer::parse($ssn)->getAge());
}

public function testSex()
public function testSex(): void
{
foreach (self::$testdataList as $testdata) {
if ($testdata['valid']) {
Expand All @@ -195,7 +195,7 @@ public function testSex()
}
}

public function testProperties()
public function testProperties(): void
{
// Parts, as position and length
$separatedLongParts = [
Expand All @@ -220,7 +220,7 @@ public function testProperties()
}
}

public function testMissingProperties()
public function testMissingProperties(): void
{
$this->assertError(function () {
Personnummer::parse('1212121212')->missingProperty;
Expand Down

0 comments on commit 35a1d80

Please sign in to comment.