1<?php
2/**
3 * Blocks API: WP_Block_List class
4 *
5 * @package WordPress
6 * @since 5.5.0
7 */
8
9/**
10 * Class representing a list of block instances.
11 *
12 * @since 5.5.0
13 */
14#[AllowDynamicProperties]
15class WP_Block_List implements Iterator, ArrayAccess, Countable {
16
17 /**
18 * Original array of parsed block data, or block instances.
19 *
20 * @since 5.5.0
21 * @var array[]|WP_Block[]
22 */
23 protected $blocks;
24
25 /**
26 * All available context of the current hierarchy.
27 *
28 * @since 5.5.0
29 * @var array
30 */
31 protected $available_context;
32
33 /**
34 * Block type registry to use in constructing block instances.
35 *
36 * @since 5.5.0
37 * @var WP_Block_Type_Registry
38 */
39 protected $registry;
40
41 /**
42 * Constructor.
43 *
44 * Populates object properties from the provided block instance argument.
45 *
46 * @since 5.5.0
47 *
48 * @param array[]|WP_Block[] $blocks Array of parsed block data, or block instances.
49 * @param array $available_context Optional array of ancestry context values.
50 * @param WP_Block_Type_Registry $registry Optional block type registry.
51 */
52 public function __construct( $blocks, $available_context = array(), $registry = null ) {
53 if ( ! $registry instanceof WP_Block_Type_Registry ) {
54 $registry = WP_Block_Type_Registry::get_instance();
55 }
56
57 $this->blocks = $blocks;
58 $this->available_context = $available_context;
59 $this->registry = $registry;
60 }
61
62 /**
63 * Returns true if a block exists by the specified block offset, or false
64 * otherwise.
65 *
66 * @since 5.5.0
67 *
68 * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
69 *
70 * @param int $offset Offset of block to check for.
71 * @return bool Whether block exists.
72 */
73 #[ReturnTypeWillChange]
74 public function offsetExists( $offset ) {
75 return isset( $this->blocks[ $offset ] );
76 }
77
78 /**
79 * Returns the value by the specified block offset.
80 *
81 * @since 5.5.0
82 *
83 * @link https://www.php.net/manual/en/arrayaccess.offsetget.php
84 *
85 * @param int $offset Offset of block value to retrieve.
86 * @return WP_Block|null Block value if exists, or null.
87 */
88 #[ReturnTypeWillChange]
89 public function offsetGet( $offset ) {
90 $block = $this->blocks[ $offset ];
91
92 if ( isset( $block ) && is_array( $block ) ) {
93 $block = new WP_Block( $block, $this->available_context, $this->registry );
94
95 $this->blocks[ $offset ] = $block;
96 }
97
98 return $block;
99 }
100
101 /**
102 * Assign a block value by the specified block offset.
103 *
104 * @since 5.5.0
105 *
106 * @link https://www.php.net/manual/en/arrayaccess.offsetset.php
107 *
108 * @param int $offset Offset of block value to set.
109 * @param array|WP_Block $value Block value.
110 */
111 #[ReturnTypeWillChange]
112 public function offsetSet( $offset, $value ) {
113 if ( is_null( $offset ) ) {
114 $this->blocks[] = $value;
115 } else {
116 $this->blocks[ $offset ] = $value;
117 }
118 }
119
120 /**
121 * Unset a block.
122 *
123 * @since 5.5.0
124 *
125 * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
126 *
127 * @param int $offset Offset of block value to unset.
128 */
129 #[ReturnTypeWillChange]
130 public function offsetUnset( $offset ) {
131 unset( $this->blocks[ $offset ] );
132 }
133
134 /**
135 * Rewinds back to the first element of the Iterator.
136 *
137 * @since 5.5.0
138 *
139 * @link https://www.php.net/manual/en/iterator.rewind.php
140 */
141 #[ReturnTypeWillChange]
142 public function rewind() {
143 reset( $this->blocks );
144 }
145
146 /**
147 * Returns the current element of the block list.
148 *
149 * @since 5.5.0
150 *
151 * @link https://www.php.net/manual/en/iterator.current.php
152 *
153 * @return WP_Block|null Current element.
154 */
155 #[ReturnTypeWillChange]
156 public function current() {
157 return $this->offsetGet( $this->key() );
158 }
159
160 /**
161 * Returns the key of the current element of the block list.
162 *
163 * @since 5.5.0
164 *
165 * @link https://www.php.net/manual/en/iterator.key.php
166 *
167 * @return int|null Key of the current element.
168 */
169 #[ReturnTypeWillChange]
170 public function key() {
171 return key( $this->blocks );
172 }
173
174 /**
175 * Moves the current position of the block list to the next element.
176 *
177 * @since 5.5.0
178 *
179 * @link https://www.php.net/manual/en/iterator.next.php
180 */
181 #[ReturnTypeWillChange]
182 public function next() {
183 next( $this->blocks );
184 }
185
186 /**
187 * Checks if current position is valid.
188 *
189 * @since 5.5.0
190 *
191 * @link https://www.php.net/manual/en/iterator.valid.php
192 */
193 #[ReturnTypeWillChange]
194 public function valid() {
195 return null !== key( $this->blocks );
196 }
197
198 /**
199 * Returns the count of blocks in the list.
200 *
201 * @since 5.5.0
202 *
203 * @link https://www.php.net/manual/en/countable.count.php
204 *
205 * @return int Block count.
206 */
207 #[ReturnTypeWillChange]
208 public function count() {
209 return count( $this->blocks );
210 }
211}
212