Completed
Pull Request — master (#1984)
by Maciej
22:01
created

AlnumGenerator::generate()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.0119

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 10
cts 11
cp 0.9091
rs 9.6666
c 0
b 0
f 0
cc 4
nc 4
nop 2
crap 4.0119
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Id;
6
7
use Doctrine\ODM\MongoDB\DocumentManager;
8
use const STR_PAD_LEFT;
9
use function bccomp;
10
use function bcdiv;
11
use function bcmod;
12
use function is_numeric;
13
use function str_pad;
14
use function strlen;
15
16
/**
17
 * AlnumGenerator is responsible for generating cased alpha-numeric unique identifiers.
18
 * It extends IncrementGenerator in order to ensure uniqueness even with short strings.
19
 *
20
 * "Awkward safe mode" avoids combinations that results in 'dirty' words by removing
21
 * the vowels from chars index
22
 *
23
 * A minimum identifier length can be enforced by setting a numeric value to the "pad" option
24
 * (with only 6 chars you will have more than 56 billion unique id's, 15 billion in 'awkward safe mode')
25
 *
26
 * The character set used for ID generation can be explicitly set with the "chars" option (e.g. base36, etc.)
27
 */
28
final class AlnumGenerator extends IncrementGenerator
29
{
30
    /** @var int|null */
31
    protected $pad = null;
32
33
    /** @var bool */
34
    protected $awkwardSafeMode = false;
35
36
    /** @var string */
37
    protected $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
38
39
    /** @var string */
40
    protected $awkwardSafeChars = '0123456789BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz';
41
42
    /**
43
     * Set padding on generated id
44
     */
45
    public function setPad(int $pad) : void
46
    {
47
        $this->pad = $pad;
48
    }
49
50
    /**
51
     * Enable awkwardSafeMode character set
52
     */
53
    public function setAwkwardSafeMode(bool $awkwardSafeMode = false) : void
54
    {
55
        $this->awkwardSafeMode = $awkwardSafeMode;
56
    }
57
58
    /**
59
     * Set the character set used for ID generation
60
     */
61 1
    public function setChars(string $chars) : void
62
    {
63 1
        $this->chars = $chars;
64 1
    }
65
66
    /** @inheritDoc */
67 1
    public function generate(DocumentManager $dm, object $document)
68
    {
69 1
        $id    = (string) parent::generate($dm, $document);
70 1
        $index = $this->awkwardSafeMode ? $this->awkwardSafeChars : $this->chars;
71 1
        $base  = (string) strlen($index);
72
73 1
        $out = '';
74
        do {
75 1
            $out = $index[(int) bcmod($id, $base)] . $out;
76 1
            $id  = bcdiv($id, $base);
77 1
        } while (bccomp($id, '0') === 1);
78
79 1
        if (is_numeric($this->pad)) {
80
            $out = str_pad($out, $this->pad, '0', STR_PAD_LEFT);
81
        }
82
83 1
        return $out;
84
    }
85
}
86