1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the league/commonmark package.
7 *
8 * (c) Colin O'Dell <colinodell@gmail.com>
9 *
10 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
11 *  - (c) John MacFarlane
12 *
13 * For the full copyright and license information, please view the LICENSE
14 * file that was distributed with this source code.
15 */
16
17namespace League\CommonMark\Util;
18
19/**
20 * @internal
21 *
22 * @phpstan-template T
23 * @phpstan-implements \IteratorAggregate<T>
24 */
25final class PrioritizedList implements \IteratorAggregate
26{
27    /**
28     * @var array<int, array<mixed>>
29     * @phpstan-var array<int, array<T>>
30     */
31    private array $list = [];
32
33    /**
34     * @var \Traversable<mixed>|null
35     * @phpstan-var \Traversable<T>|null
36     */
37    private ?\Traversable $optimized = null;
38
39    /**
40     * @param mixed $item
41     *
42     * @phpstan-param T $item
43     */
44    public function add($item, int $priority): void
45    {
46        $this->list[$priority][] = $item;
47        $this->optimized         = null;
48    }
49
50    /**
51     * @return \Traversable<int, mixed>
52     *
53     * @phpstan-return \Traversable<int, T>
54     */
55    #[\ReturnTypeWillChange]
56    public function getIterator(): \Traversable
57    {
58        if ($this->optimized === null) {
59            \krsort($this->list);
60
61            $sorted = [];
62            foreach ($this->list as $group) {
63                foreach ($group as $item) {
64                    $sorted[] = $item;
65                }
66            }
67
68            $this->optimized = new \ArrayIterator($sorted);
69        }
70
71        return $this->optimized;
72    }
73}
74