StopwatchIterator::__construct()   B
last analyzed

Complexity

Conditions 7
Paths 7

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 38
rs 8.3786
c 0
b 0
f 0
cc 7
nc 7
nop 2
1
<?php
2
3
namespace itertools;
4
5
use DateInterval;
6
use DateTime;
7
use InvalidArgumentException;
8
use IteratorIterator;
9
10
11
class StopwatchIterator extends IteratorIterator
12
{
13
	protected $startTime;
14
	protected $stopTime;
15
	protected $iterationCount;
16
	protected $options;
17
	protected $printToFileHandle;
18
	protected $closePrintToFileHandleOnDestruct;
19
	protected $previousPrintTime;
20
21
	public function __construct($iterable, $options = array())
22
	{
23
		parent::__construct(IterUtil::asTraversable($iterable));
24
25
		$this->iterationCount = 0;
26
27
		$defaultOptions = array(
28
			'autoPrint' => false,
29
			'printTo' => 'php://stdout',
30
			'printInterval' => DateInterval::createFromDateString('5 seconds'),
31
		);
32
		$this->options = array_merge($defaultOptions, $options);
33
34
		if(! $this->options['printInterval'] instanceof DateInterval) {
35
			throw new InvalidArgumentException('printInterval must be an instance of DateInterval');
36
		}
37
38
		$unknownOptions = array_diff(array_keys($options), array_keys($defaultOptions));
39
		if(count($unknownOptions) != 0) {
40
			throw new InvalidArgumentException('Unknown options specified: ' . implode(', ', $unknownOptions));
41
		}
42
43
		if($this->options['autoPrint']) {
44
			$file = $this->options['printTo'];
45
			if(is_resource($file)) {
46
				$this->printToFileHandle = $file;
47
				$this->closePrintToFileHandleOnDestruct = false;
48
			} else if(is_string($file)) {
49
				$this->printToFileHandle = @fopen($file, 'a');
50
				if($this->printToFileHandle === false) {
51
					throw new InvalidArgumentException("Could not open file with path: '$file'");
52
				}
53
				$this->closePrintToFileHandleOnDestruct = true;
54
			} else {
55
				throw new InvalidArgumentException('You must provide either a stream or filename as printTo argument, you provided a ' . gettype($file));
56
			}
57
		}
58
	}
59
60
	public function __destruct()
61
	{
62
		if(null !== $this->printToFileHandle && $this->closePrintToFileHandleOnDestruct) {
63
			fclose($this->printToFileHandle);
64
			$this->printToFileHandle = null;
65
		}
66
	}
67
68
	protected function autoPrintSpeed()
69
	{
70
		if(date_create('now')->sub($this->options['printInterval']) < $this->previousPrintTime) {
71
			return;
72
		}
73
		fputs($this->printToFileHandle, "Speed (iterations/second): {$this->getFormattedSpeed()}, Elapsed time (second): {$this->getFormattedElapsedTime()}\n");
74
		$this->previousPrintTime = new DateTime('now');
75
	}
76
	
77
78
	public function rewind()
79
	{
80
		$this->startTime = microtime(true);
81
		$this->stopTime = null;
82
		$this->previousPrintTime = new DateTime('now');
83
		$this->iterationCount = 0;
84
		parent::rewind();
85
	}
86
87
	public function next()
88
	{
89
		if($this->options['autoPrint']) {
90
			$this->autoPrintSpeed();
91
		}
92
		$this->iterationCount += 1;
93
		parent::next();
94
	}
95
96
	public function valid()
97
	{
98
		$isValid = parent::valid();
99
		if(! $isValid) {
100
			$this->stopTime = microtime(true);
101
		}
102
		return $isValid;
103
	}
104
105
	public function getFormattedSpeed()
106
	{
107
		return number_format($this->getSpeed(), 4);
108
	}
109
110
	public function getSpeed()
111
	{
112
		$elapsedTime = $this->getElapsedTime();
113
		if(0. == $elapsedTime) {
114
			return NAN;
115
		}
116
		return $this->iterationCount / $elapsedTime;
117
	}
118
119
	public function getFormattedElapsedTime()
120
	{
121
		return number_format($this->getElapsedTime(), 4);
122
	}
123
124
	public function getElapsedTime()
125
	{
126
		if(null !== $this->stopTime) {
127
			return $this->stopTime - $this->startTime;
128
		}
129
		if(null === $this->startTime) {
130
			return 0.;
131
		}
132
		return microtime(true) - $this->startTime;
133
	}
134
 
135
 	public function getIterationCount()
136
 	{
137
 		return $this->iterationCount;
138
 	}
139
 
140
 	public function getStartTime()
141
 	{
142
 		return $this->startTime;
143
 	}
144
 
145
 	public function getStopTime()
146
 	{
147
 		return $this->stopTime;
148
 	}
149
}
150
151