Passed
Push — main ( 31c7e7...eeec55 )
by Greg
06:50
created

IdFactory::uuid()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2022 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Factories;
21
22
use Fisharebest\Webtrees\Contracts\IdFactoryInterface;
23
24
use Ramsey\Uuid\Exception\RandomSourceException;
25
use Ramsey\Uuid\Uuid;
26
27
use function dechex;
28
use function hexdec;
29
use function str_pad;
30
use function strtoupper;
31
use function substr;
32
33
use const STR_PAD_LEFT;
34
35
/**
36
 * Create a unique identifier.
37
 */
38
class IdFactory implements IdFactoryInterface
39
{
40
    /**
41
     * @return string
42
     */
43
    public function uuid(): string
44
    {
45
        try {
46
            return strtolower(strtr(Uuid::uuid4()->toString(), ['-' => '']));
47
        } catch (RandomSourceException $ex) {
48
            // uuid4() can fail if there is insufficient entropy in the system.
49
            return '';
50
        }
51
    }
52
53
    /**
54
     * An identifier for use in CSS/HTML
55
     *
56
     * @return string
57
     */
58
    public function id(string $prefix = 'id-'): string
59
    {
60
        return $prefix . $this->uuid();
61
    }
62
63
    /**
64
     * A value for _UID fields, as created by PAF
65
     *
66
     * @return string
67
     */
68
    public function pafUid(): string
69
    {
70
        $uid = strtoupper(strtr($this->uuid(), ['-' => '']));
71
72
        if ($uid === '') {
73
            return '';
74
        }
75
76
        return $uid . $this->pafUidChecksum($uid);
77
    }
78
79
    /**
80
     * @param string $uid - exactly 32 hex characters
81
     *
82
     * @return string
83
     */
84
    public function pafUidChecksum(string $uid): string
85
    {
86
        $checksum_a = 0; // a sum of the bytes
87
        $checksum_b = 0; // a sum of the incremental values of $checksum_a
88
89
        for ($i = 0; $i < 32; $i += 2) {
90
            $checksum_a += hexdec(substr($uid, $i, 2));
91
            $checksum_b += $checksum_a & 0xff;
92
        }
93
94
        $digit1 = str_pad(dechex($checksum_a), 2, '0', STR_PAD_LEFT);
0 ignored issues
show
Bug introduced by
It seems like $checksum_a can also be of type double; however, parameter $num of dechex() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

94
        $digit1 = str_pad(dechex(/** @scrutinizer ignore-type */ $checksum_a), 2, '0', STR_PAD_LEFT);
Loading history...
95
        $digit2 = str_pad(dechex($checksum_b), 2, '0', STR_PAD_LEFT);
96
97
        return strtoupper($digit1 . $digit2);
98
    }
99
}
100