Passed
Push — master ( 71c82d...bff949 )
by xu
01:03 queued 11s
created

Sonyflake   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 111
Duplicated Lines 14.41 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 82.5%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 1
dl 16
loc 111
ccs 33
cts 40
cp 0.825
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 3
A id() 0 26 4
A setStartTimeStamp() 16 16 3
A parseId() 0 15 2
A elapsedTime() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * This file is part of the godruoyi/php-snowflake.
5
 *
6
 * (c) Godruoyi <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled.
9
 */
10
11
namespace Godruoyi\Snowflake;
12
13
class Sonyflake extends Snowflake
14
{
15
    const MAX_TIMESTAMP_LENGTH = 39;
16
17
    const MAX_MACHINEID_LENGTH = 16;
18
19
    const MAX_SEQUENCE_LENGTH = 8;
20
21
    /**
22
     * The machine ID.
23
     *
24
     * @var int
25
     */
26
    protected $machineid;
27
28
    /**
29
     * Build Sonyflake Instance.
30
     *
31
     * @param int $machineid machine ID 0 ~ 65535 (2^16)-1
32
     */
33 8
    public function __construct(int $machineid = 0)
34
    {
35 8
        $maxMachineID = -1 ^ (-1 << self::MAX_MACHINEID_LENGTH);
36
37 8
        $this->machineid = $machineid;
38 8
        if ($this->machineid < 0 || $this->machineid > $maxMachineID) {
39 1
            throw new \InvalidArgumentException("Invalid machine ID, must be between 0 ~ {$maxMachineID}.");
40
        }
41 8
    }
42
43
    /**
44
     * Get Sonyflake id.
45
     *
46
     * @return string
47
     */
48 2
    public function id()
49
    {
50 2
        $elapsedTime = $this->elapsedTime();
51
52 2
        while (($sequence = $this->callResolver($elapsedTime)) > (-1 ^ (-1 << self::MAX_SEQUENCE_LENGTH))) {
53
            $elapsedTime2 = $this->elapsedTime();
54
            // Get next timestamp
55
            while ($elapsedTime2 == $elapsedTime) {
56
                usleep(1);
57
                $elapsedTime2 = $this->elapsedTime();
58
            }
59
            $elapsedTime = $elapsedTime2;
60
        }
61
62 2
        $machineidLeftMoveLength = self::MAX_SEQUENCE_LENGTH;
63 2
        $timestampLeftMoveLength = self::MAX_MACHINEID_LENGTH + $machineidLeftMoveLength;
64
65 2
        if ($elapsedTime > (-1 ^ (-1 << self::MAX_TIMESTAMP_LENGTH))) {
66
            // The lifetime (174 years).
67
            throw new \Exception('Exceeding the maximum life cycle of the algorithm.');
68
        }
69
70 2
        return (string) ($elapsedTime << $timestampLeftMoveLength
71 2
            | ($this->machineid << $machineidLeftMoveLength)
72 2
            | ($sequence));
73
    }
74
75
    /**
76
     * Set start time (millisecond).
77
     */
78 2 View Code Duplication
    public function setStartTimeStamp(int $startTime)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
79
    {
80 2
        $elapsedTime = floor(($this->getCurrentMicrotime() - $startTime) / 10) | 0;
81 2
        if ($elapsedTime < 0) {
82
            throw new \Exception('The start time cannot be greater than the current time');
83
        }
84
85 2
        $maxTimeDiff = -1 ^ (-1 << self::MAX_TIMESTAMP_LENGTH);
86 2
        if ($elapsedTime > $maxTimeDiff) {
87 1
            throw new \Exception('Exceeding the maximum life cycle of the algorithm');
88
        }
89
90 1
        $this->startTime = $startTime;
91
92 1
        return $this;
93
    }
94
95
    /**
96
     * Parse snowflake id.
97
     */
98 1
    public function parseId(string $id, $transform = false): array
99
    {
100 1
        $id = decbin($id);
101 1
        $length = self::MAX_SEQUENCE_LENGTH + self::MAX_MACHINEID_LENGTH;
102
103
        $data = [
104 1
            'sequence' => substr($id, -1 * self::MAX_SEQUENCE_LENGTH),
105 1
            'machineid' => substr($id, -1 * $length, self::MAX_MACHINEID_LENGTH),
106 1
            'timestamp' => substr($id, 0, $length),
107
        ];
108
109
        return $transform ? array_map(function ($value) {
110 1
            return bindec($value);
111 1
        }, $data) : $data;
112
    }
113
114
    /**
115
     * The Elapsed Time.
116
     *
117
     * @return int
118
     */
119 2
    private function elapsedTime()
120
    {
121 2
        return floor(($this->getCurrentMicrotime() - $this->getStartTimeStamp()) / 10) | 0;
122
    }
123
}
124