Completed
Push — master ( 0a4fc2...70ed4c )
by Ievgen
05:13 queued 03:11
created

Railway::always()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 5
ccs 0
cts 5
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace einfach\operation;
3
4
use function einfach\operation\response\isError;
5
use function einfach\operation\response\isOk;
6
use function einfach\operation\response\isValidResponse;
7
use const einfach\operation\response\RESPONSE_TYPE_ERROR;
8
use const einfach\operation\response\RESPONSE_TYPE_OK;
9
use einfach\operation\step\Step;
10
use einfach\operation\step\Failure;
11
use einfach\operation\step\AbstractStep;
12
use einfach\operation\step\Always;
13
use einfach\operation\step\TryCatch;
14
use einfach\operation\step\Wrap;
15
16
class Railway
17
{
18
    const TRACK_SUCCESS = 'success_track';
19
    const TRACK_FAILURE = 'failure_track';
20
21
    /**
22
     * @var \SplQueue
23
     */
24
    protected $stepsQueue;
25
26
    public function __construct()
27
    {
28
        $this->stepsQueue = new \SplQueue();
29
    }
30
31
    /**
32
     *
33
     * @param AbstractStep $stepObject
34
     * @param array $opt
35
     * @return $this
36
     */
37
    public function rawStep(AbstractStep $stepObject, $opt = [])
0 ignored issues
show
Unused Code introduced by
The parameter $opt is not used and could be removed.

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

Loading history...
38
    {
39
        $this->stepsQueue->enqueue($stepObject);
40
        return $this;
41
    }
42
43
    public function step(callable $callable, $opt = [])
44
    {
45
        $signature = $this->nextStepSignature($callable, 'Step', $opt);
46
        return $this->rawStep(new Step($callable, $signature), $opt);
47
    }
48
49
    public function always(callable $callable, $opt = [])
50
    {
51
        $signature = $this->nextStepSignature($callable, 'Always', $opt);
52
        return $this->rawStep(new Always($callable, $signature), $opt);
53
    }
54
55
    public function failure(callable $callable, $opt = [])
56
    {
57
        $signature = $this->nextStepSignature($callable, 'Failure', $opt);
58
        return $this->rawStep(new Failure($callable, $signature), $opt);
59
    }
60
61
    public function tryCatch(callable $callable, $opt = [])
62
    {
63
        $signature = $this->nextStepSignature($callable, 'TryCatch', $opt);
64
        return $this->rawStep(new TryCatch($callable, $signature), $opt);
65
    }
66
67
    public function wrap(callable $callable, $opt = [])
68
    {
69
        // check if Result -> evaluate
70
        // if bool -> passthrough
71
        $signature = $this->nextStepSignature($callable, 'Wrap', $opt);
72
        return $this->rawStep(new Wrap($callable, $signature), $opt);
73
    }
74
75
    public function nextStepSignature(callable $callable, $stepName, $opt)
76
    {
77
        is_callable($callable, false, $functionName);
78
        // assign custom step name from operation if provided
79
        $functionName = $opt['name'] ?? $functionName;
80
        $counter = $this->stepsQueue->count() + 1;
81
        return "#" . sprintf("%02d", $counter) . " | " . sprintf("%-10s", $stepName) . " | $functionName";
82
    }
83
84
    /**
85
     * @param $params
86
     * @return Result
87
     * @throws \Exception
88
     */
89
    public function runWithParams($params)
90
    {
91
        // a bit hardcoded, but let it be :)
92
        $params['errors'] = [];
93
        $signaturesPipeline = [];
94
95
        $track = self::TRACK_SUCCESS;
96
        foreach ($this->stepsQueue as $step) {
97
            /** @var $step AbstractStep */
98
            $track = $this->performStep($step, $params, $track, $signaturesPipeline);
99
        }
100
        return new Result($params, $track, $signaturesPipeline);
101
    }
102
103
    /**
104
     * @param $params
105
     * @param $step
106
     * @return string
107
     * @throws \Exception
108
     */
109
    protected function performStep($step, &$params, $track, &$signaturesPipeline)
110
    {
111
        $newTrack = $track;
112
        $stepResult = $step($params, $track);
113
//TODO: Extract method
114
        if (is_a($stepResult, Result::class)) {
115
            if ($stepResult->isSuccess()) {
116
                $stepResult = [
117
                    'type' => RESPONSE_TYPE_OK,
118
                    'appendParams' => $stepResult->params()
119
                ];
120
            } else {
121
                $stepResult = [
122
                    'type' => RESPONSE_TYPE_ERROR,
123
                    'appendError' => $stepResult->errors()
124
                ];
125
            }
126
        }
127
128
        if (!$step->isSkipped()) {
129
            if (isValidResponse($stepResult)) {
130
                $type = $stepResult['type'];
131
                if (isOk($type)) {
132
                    $newTrack = self::TRACK_SUCCESS;
133
                    $appendParams = $stepResult['appendParams'] ?? [];
134
                    $params = array_merge($params, $appendParams);
135
                } elseif (isError($type)) {
136
                    $newTrack = self::TRACK_FAILURE;
137
                    $appendError = [$stepResult['appendError']] ?? [];
138
                    // TODO: Fix errors merge
139
                    print_r($params['errors']);
140
                    print_r($appendError);
141
                    $params['errors'] = $params['errors'] + $appendError;
142
                }
143
144
                $signaturesPipeline[] = $step->signature;
145
            } else {
146
                $actualResult = var_export($stepResult, true);
147
                throw new \Exception("Step returned incorrectly formatted result: {$actualResult}");
148
            }
149
        }
150
151
        return $newTrack;
152
    }
153
}
154