1<?php
2/**
3 * LICENSE
4 *
5 * This source file is subject to the new BSD license that is bundled
6 * with this package in the file LICENSE.txt.
7 * It is also available through the world-wide-web at this URL:
8 * http://framework.zend.com/license/new-bsd
9 * If you did not receive a copy of the license and are unable to
10 * obtain it through the world-wide-web, please send an email
11 * to license@zend.com so we can send you a copy immediately.
12 *
13 * @category   Zend
14 * @package    Zend_ProgressBar
15 * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
16 * @license    http://framework.zend.com/license/new-bsd     New BSD License
17 * @version    $Id$
18 */
19
20/**
21 * Zend_ProgressBar offers an interface for multiple enviroments.
22 *
23 * @category  Zend
24 * @package   Zend_ProgressBar
25 * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
26 * @license   http://framework.zend.com/license/new-bsd     New BSD License
27 */
28class Zend_ProgressBar
29{
30    /**
31     * Min value
32     *
33     * @var float
34     */
35    protected $_min;
36
37    /**
38     * Max value
39     *
40     * @var float
41     */
42    protected $_max;
43
44    /**
45     * Current value
46     *
47     * @var float
48     */
49    protected $_current;
50
51    /**
52     * Start time of the progressbar, required for ETA
53     *
54     * @var integer
55     */
56    protected $_startTime;
57
58    /**
59     * Current status text
60     *
61     * @var string
62     */
63    protected $_statusText = null;
64
65    /**
66     * Adapter for the output
67     *
68     * @var Zend_ProgressBar_Adapter
69     */
70    protected $_adapter;
71
72    /**
73     * Namespace for keeping the progressbar persistent
74     *
75     * @var string
76     */
77    protected $_persistenceNamespace = null;
78
79    /**
80     * Create a new progressbar backend.
81     *
82     * @param  Zend_ProgressBar_Adapter $adapter
83     * @param  float                    $min
84     * @param  float                    $max
85     * @param  string                   $persistenceNamespace
86     * @throws Zend_ProgressBar_Exception When $min is greater than $max
87     */
88    public function __construct(Zend_ProgressBar_Adapter $adapter, $min = 0, $max = 100, $persistenceNamespace = null)
89    {
90        // Check min/max values and set them
91        if ($min > $max) {
92            throw new Zend_ProgressBar_Exception('$max must be greater than $min');
93        }
94
95        $this->_min     = (float) $min;
96        $this->_max     = (float) $max;
97        $this->_current = (float) $min;
98
99        // See if we have to open a session namespace
100        if ($persistenceNamespace !== null) {
101
102            $this->_persistenceNamespace = new Zend_Session_Namespace($persistenceNamespace);
103        }
104
105        // Set adapter
106        $this->_adapter = $adapter;
107
108        // Track the start time
109        $this->_startTime = time();
110
111        // See If a persistenceNamespace exists and handle accordingly
112        if ($this->_persistenceNamespace !== null) {
113            if (isset($this->_persistenceNamespace->isSet)) {
114                $this->_startTime  = $this->_persistenceNamespace->startTime;
115                $this->_current    = $this->_persistenceNamespace->current;
116                $this->_statusText = $this->_persistenceNamespace->statusText;
117            } else {
118                $this->_persistenceNamespace->isSet      = true;
119                $this->_persistenceNamespace->startTime  = $this->_startTime;
120                $this->_persistenceNamespace->current    = $this->_current;
121                $this->_persistenceNamespace->statusText = $this->_statusText;
122            }
123        } else {
124            $this->update();
125        }
126    }
127
128    /**
129     * Get the current adapter
130     *
131     * @return Zend_ProgressBar_Adapter
132     */
133    public function getAdapter()
134    {
135        return $this->_adapter;
136    }
137
138    /**
139     * Update the progressbar
140     *
141     * @param  float  $value
142     * @param  string $text
143     * @return void
144     */
145    public function update($value = null, $text = null)
146    {
147        // Update value if given
148        if ($value !== null) {
149            $this->_current = min($this->_max, max($this->_min, $value));
150        }
151
152        // Update text if given
153        if ($text !== null) {
154            $this->_statusText = $text;
155        }
156
157        // See if we have to update a namespace
158        if ($this->_persistenceNamespace !== null) {
159            $this->_persistenceNamespace->current    = $this->_current;
160            $this->_persistenceNamespace->statusText = $this->_statusText;
161        }
162
163        // Calculate percent
164        if ($this->_min === $this->_max) {
165            $percent = false;
166        } else {
167            $percent = (float) ($this->_current - $this->_min) / ($this->_max - $this->_min);
168        }
169
170        // Calculate ETA
171        $timeTaken = time() - $this->_startTime;
172
173        if ($percent === .0 || $percent === false) {
174            $timeRemaining = null;
175        } else {
176            $timeRemaining = round(((1 / $percent) * $timeTaken) - $timeTaken);
177        }
178
179        // Poll the adapter
180        $this->_adapter->notify($this->_current, $this->_max, $percent, $timeTaken, $timeRemaining, $this->_statusText);
181    }
182
183    /**
184     * Update the progressbar to the next value
185     *
186     * @param  string $text
187     * @return void
188     */
189    public function next($diff = 1, $text = null)
190    {
191        $this->update(max($this->_min, min($this->_max, $this->_current + $diff)), $text);
192    }
193
194    /**
195     * Call the adapters finish() behaviour
196     *
197     * @return void
198     */
199    public function finish()
200    {
201        if ($this->_persistenceNamespace !== null) {
202            unset($this->_persistenceNamespace->isSet);
203        }
204
205        $this->_adapter->finish();
206    }
207}
208