ProgressIndicator::showProgressIndicator()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 4
nc 2
nop 0
1
<?php
2
3
namespace Robo\Common;
4
5
/**
6
 * Wrapper around \Symfony\Component\Console\Helper\ProgressBar
7
 */
8
class ProgressIndicator
9
{
10
    use Timer;
11
12
    /**
13
     * @var \Symfony\Component\Console\Helper\ProgressBar
14
     */
15
    protected $progressBar;
16
17
    /**
18
     * @var \Symfony\Component\Console\Output\OutputInterface
19
     */
20
    protected $output;
21
22
    /**
23
     * @var bool
24
     */
25
    protected $progressIndicatorRunning = false;
26
27
    /**
28
     * @var int
29
     */
30
    protected $autoDisplayInterval = 0;
31
32
    /**
33
     * @var int
34
     */
35
    protected $cachedSteps = 0;
36
37
    /**
38
     * @var int
39
     */
40
    protected $totalSteps = 0;
41
42
    /**
43
     * @var bool
44
     */
45
    protected $progressBarDisplayed = false;
46
47
    /**
48
     * @var \Robo\Contract\TaskInterface
49
     */
50
    protected $owner;
51
52
    /**
53
     * @param \Symfony\Component\Console\Helper\ProgressBar $progressBar
54
     * @param \Symfony\Component\Console\Output\OutputInterface $output
55
     */
56
    public function __construct($progressBar, \Symfony\Component\Console\Output\OutputInterface $output)
57
    {
58
        $this->progressBar = $progressBar;
59
        $this->output = $output;
60
    }
61
62
    /**
63
     * @param int $interval
64
     */
65
    public function setProgressBarAutoDisplayInterval($interval)
66
    {
67
        if ($this->progressIndicatorRunning) {
68
            return;
69
        }
70
        $this->autoDisplayInterval = $interval;
71
    }
72
73
    /**
74
     * @return bool
75
     */
76
    public function hideProgressIndicator()
77
    {
78
        $result = $this->progressBarDisplayed;
79
        if ($this->progressIndicatorRunning && $this->progressBarDisplayed) {
80
            $this->progressBar->clear();
81
            // Hack: progress indicator does not reset cursor to beginning of line on 'clear'
82
            $this->output->write("\x0D");
83
            $this->progressBarDisplayed = false;
84
        }
85
        return $result;
86
    }
87
88
    public function showProgressIndicator()
89
    {
90
        if ($this->progressIndicatorRunning && !$this->progressBarDisplayed && isset($this->progressBar)) {
91
            $this->progressBar->display();
92
            $this->progressBarDisplayed = true;
93
            $this->advanceProgressIndicatorCachedSteps();
94
        }
95
    }
96
97
    /**
98
     * @param bool $visible
99
     */
100
    public function restoreProgressIndicator($visible)
101
    {
102
        if ($visible) {
103
            $this->showProgressIndicator();
104
        }
105
    }
106
107
    /**
108
     * @param int $totalSteps
109
     * @param \Robo\Contract\TaskInterface $owner
110
     */
111
    public function startProgressIndicator($totalSteps, $owner)
112
    {
113
        if (!isset($this->progressBar)) {
114
            return;
115
        }
116
117
        $this->progressIndicatorRunning = true;
118
        if (!isset($this->owner)) {
119
            $this->owner = $owner;
120
            $this->startTimer();
121
            $this->totalSteps = $totalSteps;
122
            $this->autoShowProgressIndicator();
123
        }
124
    }
125
126
    public function autoShowProgressIndicator()
127
    {
128
        if (($this->autoDisplayInterval < 0) || !isset($this->progressBar) || !$this->output->isDecorated()) {
129
            return;
130
        }
131
        if ($this->autoDisplayInterval <= $this->getExecutionTime()) {
132
            $this->autoDisplayInterval = -1;
133
            $this->progressBar->start($this->totalSteps);
134
            $this->showProgressIndicator();
135
        }
136
    }
137
138
    /**
139
     * @return bool
140
     */
141
    public function inProgress()
142
    {
143
        return $this->progressIndicatorRunning;
144
    }
145
146
    /**
147
     * @param \Robo\Contract\TaskInterface $owner
148
     */
149
    public function stopProgressIndicator($owner)
150
    {
151
        if ($this->progressIndicatorRunning && ($this->owner === $owner)) {
152
            $this->cleanup();
153
        }
154
    }
155
156
    protected function cleanup()
157
    {
158
        $this->progressIndicatorRunning = false;
159
        $this->owner = null;
160
        if ($this->progressBarDisplayed) {
161
            $this->progressBar->finish();
162
            // Hack: progress indicator does not always finish cleanly
163
            $this->output->writeln('');
164
            $this->progressBarDisplayed = false;
165
        }
166
        $this->stopTimer();
167
    }
168
169
    /**
170
     * Erase progress indicator and ensure it never returns.  Used
171
     * only during error handlers or to permanently remove the progress bar.
172
     */
173
    public function disableProgressIndicator()
174
    {
175
        $this->cleanup();
176
        // ProgressIndicator is shared, so this permanently removes
177
        // the program's ability to display progress bars.
178
        $this->progressBar = null;
179
    }
180
181
    /**
182
     * @param int $steps
183
     */
184
    public function advanceProgressIndicator($steps = 1)
185
    {
186
        $this->cachedSteps += $steps;
187
        if ($this->progressIndicatorRunning) {
188
            $this->autoShowProgressIndicator();
189
            // We only want to call `advance` if the progress bar is visible,
190
            // because it always displays itself when it is advanced.
191
            if ($this->progressBarDisplayed) {
192
                return $this->advanceProgressIndicatorCachedSteps();
193
            }
194
        }
195
    }
196
197
    protected function advanceProgressIndicatorCachedSteps()
198
    {
199
        $this->progressBar->advance($this->cachedSteps);
200
        $this->cachedSteps = 0;
201
    }
202
}
203