1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Php;
4:
5: use IteratorAggregate;
6: use Override;
7: use PHPStan\ShouldNotHappenException;
8: use Traversable;
9: use function floor;
10:
11: /**
12: * @api
13: *
14: * @implements IteratorAggregate<PhpVersion>
15: */
16: final class PhpMinorVersionIterator implements IteratorAggregate
17: {
18:
19: private PhpVersion $currentVersion;
20:
21: /** @api */
22: public function __construct(
23: PhpVersion $startVersion,
24: private PhpVersion $endVersion,
25: )
26: {
27: if (
28: $startVersion->getMajorVersionId() < 5
29: || $startVersion->getMajorVersionId() > 8
30: ) {
31: throw new ShouldNotHappenException();
32: }
33: if (
34: $endVersion->getMajorVersionId() < 5
35: || $endVersion->getMajorVersionId() > 8
36: ) {
37: throw new ShouldNotHappenException();
38: }
39:
40: if ($startVersion->getVersionId() > $this->endVersion->getVersionId()
41: ) {
42: throw new ShouldNotHappenException();
43: }
44:
45: $this->currentVersion = $startVersion;
46: }
47:
48: #[Override]
49: public function getIterator(): Traversable
50: {
51: yield $this->currentVersion;
52:
53: while (true) {
54: if (
55: $this->currentVersion->getMajorVersionId() === 5
56: && $this->currentVersion->getMinorVersionId() === 6
57: ) {
58: $next = new PhpVersion(70000);
59: } elseif (
60: $this->currentVersion->getMajorVersionId() === 7
61: && $this->currentVersion->getMinorVersionId() === 4
62: ) {
63: $next = new PhpVersion(80000);
64: } else {
65: $nextMinorVersionId = $this->currentVersion->getVersionId() + 100;
66: $nextWithZeroPatch = (int) floor($nextMinorVersionId / 100) * 100;
67: $next = new PhpVersion($nextWithZeroPatch);
68: }
69:
70: if ($next->getVersionId() > $this->endVersion->getVersionId()) {
71: break;
72: }
73:
74: $this->currentVersion = $next;
75:
76: yield $this->currentVersion;
77: }
78:
79: if ($this->currentVersion->getVersionId() === $this->endVersion->getVersionId()) {
80: return;
81: }
82:
83: yield $this->endVersion;
84: }
85:
86: }
87: