Passed
Push — master ( 8f41fc...40640b )
by Manuel
02:36 queued 11s
created

loadValidatorMetadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 12
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 23
rs 9.8666
1
<?php
2
3
namespace Sprain\SwissQrBill\Reference;
4
5
use Sprain\SwissQrBill\Validator\Exception\InvalidQrPaymentReferenceException;
6
use Sprain\SwissQrBill\Validator\SelfValidatableInterface;
7
use Sprain\SwissQrBill\Validator\SelfValidatableTrait;
8
use Symfony\Component\Validator\Constraints as Assert;
9
use Symfony\Component\Validator\Context\ExecutionContextInterface;
10
use Symfony\Component\Validator\Mapping\ClassMetadata;
11
12
class QrPaymentReferenceGenerator implements SelfValidatableInterface
13
{
14
    use SelfValidatableTrait;
15
16
    /** @var string */
17
    private $customerIdentificationNumber;
18
19
    /** @var string */
20
    private $referenceNumber;
21
22
    public static function generate(?string $customerIdentificationNumber, string $referenceNumber)
23
    {
24
        $qrPaymentReferenceGenerator = new self();
25
26
        if (null !== $customerIdentificationNumber) {
27
            $qrPaymentReferenceGenerator->customerIdentificationNumber = $qrPaymentReferenceGenerator->removeWhitespace($customerIdentificationNumber);
28
        }
29
        $qrPaymentReferenceGenerator->referenceNumber = $qrPaymentReferenceGenerator->removeWhitespace($referenceNumber);
30
31
        return $qrPaymentReferenceGenerator->doGenerate();
32
    }
33
34
    public function getCustomerIdentificationNumber(): ?string
35
    {
36
        return $this->customerIdentificationNumber;
37
    }
38
39
    public function getReferenceNumber(): ?string
40
    {
41
        return $this->referenceNumber;
42
    }
43
44
    private function doGenerate()
45
    {
46
        if (!$this->isValid()) {
47
            throw new InvalidQrPaymentReferenceException(
48
                'The provided data is not valid to generate a qr payment reference number. Use getViolations() to find details.'
49
            );
50
        }
51
52
        $completeReferenceNumber  = $this->getCustomerIdentificationNumber();
53
        $completeReferenceNumber .= str_pad($this->getReferenceNumber(), 26 - strlen($completeReferenceNumber), '0', STR_PAD_LEFT);
54
        $completeReferenceNumber .= $this->modulo10($completeReferenceNumber);
55
56
        return $completeReferenceNumber;
57
    }
58
59
    public static function loadValidatorMetadata(ClassMetadata $metadata): void
60
    {
61
        $metadata->addPropertyConstraints('customerIdentificationNumber', [
62
            // Only numbers are allowed (including leading zeros)
63
            new Assert\Regex([
64
                'pattern' => '/^\d*$/',
65
                'match' => true
66
            ]),
67
            new Assert\Length([
68
                'max' => 11
69
            ]),
70
        ]);
71
72
        $metadata->addPropertyConstraints('referenceNumber', [
73
            // Only numbers are allowed (including leading zeros)
74
            new Assert\Regex([
75
                'pattern' => '/^\d*$/',
76
                'match' => true
77
            ]),
78
            new Assert\NotBlank()
79
        ]);
80
81
        $metadata->addConstraint(new Assert\Callback('validateFullReference'));
82
    }
83
84
    public function validateFullReference(ExecutionContextInterface $context, $payload)
0 ignored issues
show
Unused Code introduced by
The parameter $payload is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

84
    public function validateFullReference(ExecutionContextInterface $context, /** @scrutinizer ignore-unused */ $payload)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
85
    {
86
        if (strlen($this->customerIdentificationNumber) + strlen($this->referenceNumber) > 26) {
87
            $context->buildViolation('The length of customer identification number + reference number may not exceed 26 characters in total.')
88
                ->addViolation();
89
        }
90
    }
91
92
    private function removeWhitespace(string $string): string
93
    {
94
        return preg_replace('/\s+/', '', $string);
95
    }
96
97
    private function modulo10($number)
98
    {
99
        $table = array(0, 9, 4, 6, 8, 2, 7, 1, 3, 5);
100
        $next = 0;
101
        for ($i = 0; $i < strlen($number); $i++) {
102
            $next =  $table[($next + substr($number, $i, 1)) % 10];
103
        }
104
105
        return (10 - $next) % 10;
106
    }
107
}
108