Test Setup Failed
Push — develop ( 7cd2b2...750858 )
by Alec
03:42
created

AbstractCounter   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 96
rs 10
c 0
b 0
f 0
wmc 12

7 Methods

Rating   Name   Duplication   Size   Complexity  
A buildReport() 0 3 1
A setInitialValue() 0 8 2
A assertStep() 0 7 2
A __construct() 0 6 1
A assertTimes() 0 8 2
A bump() 0 10 2
A setStep() 0 9 2
1
<?php declare(strict_types=1);
2
3
namespace AlecRabbit\Tools;
4
5
use AlecRabbit\Tools\Contracts\CounterInterface;
6
use AlecRabbit\Tools\Contracts\Strings;
7
use AlecRabbit\Tools\Reports\Contracts\ReportableInterface;
8
use AlecRabbit\Tools\Reports\SimpleCounterReport;
9
use AlecRabbit\Tools\Reports\Traits\HasReport;
10
use AlecRabbit\Tools\Traits\SimpleCounterFields;
11
12
abstract class AbstractCounter implements CounterInterface, ReportableInterface
13
{
14
    use SimpleCounterFields, HasReport;
15
16
17
    protected const DEFAULT_STEP = 1;
18
19
    /**
20
     * Counter constructor
21
     * @param null|string $name
22
     * @param null|int $step
23
     * @param int $initialValue
24
     * @throws \Exception
25
     */
26
    public function __construct(?string $name = null, ?int $step = null, int $initialValue = 0)
27
    {
28
        $this->name = $this->defaultName($name);
29
        $this->setInitialValue($initialValue);
30
        $this->setStep($step);
31
        $this->buildReport();
32
    }
33
34
    /**
35
     * @throws \Exception
36
     */
37
    protected function buildReport(): void
38
    {
39
        $this->report = (new SimpleCounterReport())->buildOn($this);
40
    }
41
42
    /**
43
     * @param int $initialValue
44
     * @return AbstractCounter
45
     */
46
    public function setInitialValue(int $initialValue): AbstractCounter
47
    {
48
        if (false === $this->isStarted()) {
49
            $this->value = $this->initialValue = $initialValue;
50
        } else {
51
            throw new \RuntimeException('You can\'t set counter initial value, it has been bumped already.');
52
        }
53
        return $this;
54
    }
55
56
    /**
57
     * @param null|int $step
58
     * @return AbstractCounter
59
     */
60
    public function setStep(?int $step = null): AbstractCounter
61
    {
62
        $step = $this->assertStep($step);
63
        if (false === $this->isStarted()) {
64
            $this->step = $step;
65
        } else {
66
            throw new \RuntimeException('You can\'t set counter step value, it has been bumped already.');
67
        }
68
        return $this;
69
    }
70
71
    /**
72
     * @param null|int $step
73
     * @return int
74
     */
75
    protected function assertStep(?int $step = null): int
76
    {
77
        $step = $step ?? self::DEFAULT_STEP;
78
        if ($step === 0) {
79
            throw new \RuntimeException('Counter step should be non-zero integer.');
80
        }
81
        return $step;
82
    }
83
84
    /**
85
     * @param int $times
86
     * @return int
87
     */
88
    public function bump(int $times = 1): int
89
    {
90
        $times = $this->assertTimes($times);
91
        if ($this->isNotStarted()) {
92
            $this->start();
93
        }
94
        $this->value += $times * $this->step;
95
        $this->bumped++;
96
        return
97
            $this->value;
98
    }
99
100
    protected function assertTimes(int $times): int
101
    {
102
        if ($times < 1) {
103
            throw new \RuntimeException(
104
                'Parameter 0 for bump() or bumpBack() should be positive non-zero integer.'
105
            );
106
        }
107
        return $times;
108
    }
109
}
110