PluginProbe
Polylang / 3.8.10
Polylang v3.8.10
3.8.10 3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 All 234 releases
← All changes | src/modules/Blocks/Language_Switcher/Navigation/Block.php +124 -96 3.8.8 → 3.8.10 View file →
@@ -6,8 +6,9 @@
6 6 namespace WP_Syntex\Polylang\Blocks\Language_Switcher\Navigation;
7 7
8 8 use WP_Block;
9 9 use PLL_Switcher;
10 +use SplObjectStorage;
10 11 use WP_HTML_Tag_Processor;
11 12 use WP_Syntex\Polylang\Blocks\Language_Switcher\Abstract_Block;
12 13
13 14 /**
@@ -24,8 +25,30 @@
24 25 */
25 26 const PLACEHOLDER = '%pll%';
26 27
27 28 /**
29 + * Trusted locale and label, keyed by the inner navigation blocks created by this switcher.
30 + * Blocks parsed from saved content are never the same instances, so they can't be found here.
31 + *
32 + * @var SplObjectStorage
33 + * @phpstan-var SplObjectStorage<WP_Block, array{locale: string, label: string}>
34 + */
35 + private $internal_blocks;
36 +
37 + /**
38 + * Constructor.
39 + *
40 + * @since 3.8.10
41 + *
42 + * @param \PLL_Base $polylang Polylang object.
43 + */
44 + public function __construct( &$polylang ) {
45 + parent::__construct( $polylang );
46 +
47 + $this->internal_blocks = new SplObjectStorage();
48 + }
49 +
50 + /**
28 51 * Adds the required hooks specific to the navigation language switcher.
29 52 *
30 53 * @since 3.2
31 54 *
@@ -34,9 +57,8 @@
34 57 public function init() {
35 58 parent::init();
36 59
37 60 add_action( 'rest_api_init', array( $this, 'register_switcher_menu_item_options_meta_rest_field' ) );
38 - add_filter( 'block_type_metadata', array( $this, 'register_custom_attributes' ) );
39 61 add_filter( 'render_block_core/navigation-link', array( $this, 'render_custom_attributes' ), 10, 3 );
40 62 add_filter( 'render_block_core/navigation-submenu', array( $this, 'render_custom_attributes' ), 10, 3 );
41 63 add_action( 'init', array( $this, 'register_editor_style' ) );
42 64
@@ -59,8 +81,9 @@
59 81 array(),
60 82 POLYLANG_VERSION
61 83 );
62 84 }
85 +
63 86 /**
64 87 * Returns the navigation language switcher block name with the Polylang's namespace.
65 88 *
66 89 * @since 3.2
@@ -90,47 +113,51 @@
90 113 if ( empty( $switcher_elements ) ) {
91 114 return '';
92 115 }
93 116
117 + $generated_class = wp_apply_generated_classname_support( $block->block_type )['class'];
118 +
94 119 if ( $attributes['dropdown'] ) {
95 120 $inner_nav_link_blocks = array();
96 121 $top_level_lang = reset( $switcher_elements );
97 122 foreach ( $switcher_elements as $switcher_element ) {
98 - $nav_link_block_args = array(
99 - 'blockName' => 'core/navigation-link',
100 - 'attrs' => $this->get_core_block_attributes( $attributes, $switcher_element ),
123 + $inner_nav_link_blocks[] = $this->create_inner_block(
124 + 'core/navigation-link',
125 + $this->get_core_block_attributes( $switcher_element ),
126 + $switcher_element,
127 + $block->context,
128 + $attributes
101 129 );
102 130
103 - $inner_nav_link_blocks[] = new WP_Block( $nav_link_block_args, $block->context );
104 -
105 131 if ( $switcher_element['current_lang'] && ! $attributes['hide_current'] ) {
106 132 $top_level_lang = $switcher_element;
107 133 }
108 134 }
109 135
110 - $attributes = $this->get_core_block_attributes( $attributes, $top_level_lang );
111 - $attributes['className'] .= ' ' . wp_apply_generated_classname_support( $block->block_type )['class'];
112 - $submenu_block_args = array(
113 - 'blockName' => 'core/navigation-submenu',
114 - 'attrs' => $attributes,
115 - 'innerBlocks' => $inner_nav_link_blocks,
136 + $submenu_attributes = $this->get_core_block_attributes( $top_level_lang );
137 + $submenu_attributes['className'] .= ' ' . $generated_class;
138 + $submenu_block = $this->create_inner_block(
139 + 'core/navigation-submenu',
140 + $submenu_attributes,
141 + $top_level_lang,
142 + $block->context,
143 + $attributes,
144 + $inner_nav_link_blocks
116 145 );
117 -
118 - $submenu_block = new WP_Block( $submenu_block_args, $block->context );
119 - $output = $submenu_block->render();
146 + $output = $submenu_block->render();
120 147 } else {
121 148 $output = '';
122 149
123 150 foreach ( $switcher_elements as $switcher_element ) {
124 - $link_attributes = $this->get_core_block_attributes( $attributes, $switcher_element );
125 - $link_attributes['className'] .= ' ' . wp_apply_generated_classname_support( $block->block_type )['class'];
126 - $nav_link_block_args = array(
127 - 'blockName' => 'core/navigation-link',
128 - 'attrs' => $link_attributes,
129 - );
130 -
131 - $link_block = new WP_Block( $nav_link_block_args, $block->context );
132 - $output .= $link_block->render();
151 + $link_attributes = $this->get_core_block_attributes( $switcher_element );
152 + $link_attributes['className'] .= ' ' . $generated_class;
153 + $output .= $this->create_inner_block(
154 + 'core/navigation-link',
155 + $link_attributes,
156 + $switcher_element,
157 + $block->context,
158 + $attributes
159 + )->render();
133 160 }
134 161 }
135 162
136 163 return $output;
@@ -163,45 +190,8 @@
163 190 );
164 191 }
165 192
166 193 /**
167 - * Filters core/navigation-link and core/navigation-submenu attributes during registration to add our own.
168 - *
169 - * @since 3.6
170 - *
171 - * @param array $metadata Metadata for registering a block type.
172 - *
173 - * @return array The filtered metadata if about a core/navigation-link.
174 - */
175 - public function register_custom_attributes( $metadata ) {
176 - if ( 'core/navigation-link' === $metadata['name'] || 'core/navigation-submenu' === $metadata['name'] ) {
177 - $pll_attributes = array(
178 - 'hreflang' => array(
179 - 'type' => 'string',
180 - ),
181 - 'lang' => array(
182 - 'type' => 'string',
183 - ),
184 - 'pll_show_flags' => array(
185 - 'type' => 'boolean',
186 - ),
187 - 'pll_show_names' => array(
188 - 'type' => 'boolean',
189 - ),
190 - 'pll_flag' => array(
191 - 'type' => 'string',
192 - ),
193 - 'pll_name' => array(
194 - 'type' => 'string',
195 - ),
196 - );
197 - $metadata['attributes'] = array_merge( $metadata['attributes'], $pll_attributes );
198 - }
199 -
200 - return $metadata;
201 - }
202 -
203 - /**
204 194 * Renders a core/naviagation-link or core/naviagation-submenu block by adding hreflang and lang attributes to the <a> tag
205 195 * and also the language flag if required.
206 196 *
207 197 * @since 3.6
@@ -212,27 +202,22 @@
212 202 *
213 203 * @return string A formatted HTML string representing the core/navigation-link or core/navigation-submenu block.
214 204 */
215 205 public function render_custom_attributes( $block_content, $block, $instance ) {
216 - if ( ! isset(
217 - $instance->attributes['pll_show_flags'],
218 - $instance->attributes['pll_show_names'],
219 - $instance->attributes['pll_flag'],
220 - $instance->attributes['pll_name'],
221 - $instance->attributes['lang'],
222 - $instance->attributes['hreflang']
223 - )
224 - ) {
206 + if ( ! $this->internal_blocks->offsetExists( $instance ) ) {
225 207 return $block_content;
226 208 }
227 209
210 + $snapshot = $this->internal_blocks->offsetGet( $instance );
211 + $this->internal_blocks->offsetUnset( $instance );
212 +
228 213 $content_tags = new WP_HTML_Tag_Processor( $block_content );
229 214
230 215 if ( 'core/navigation-submenu' === $instance->name ) {
231 216 // If `openSubmenusOnClick`, the submenu is rendered as a button, so there are no `<a>` to process.
232 217 if ( empty( $instance->context['openSubmenusOnClick'] ) && $content_tags->next_tag( array( 'tag_name' => 'a' ) ) ) {
233 - $content_tags->set_attribute( 'hreflang', $instance->attributes['hreflang'] );
234 - $content_tags->set_attribute( 'lang', $instance->attributes['lang'] );
218 + $content_tags->set_attribute( 'hreflang', $snapshot['locale'] );
219 + $content_tags->set_attribute( 'lang', $snapshot['locale'] );
235 220 }
236 221 if ( $content_tags->next_tag( array( 'tag_name' => 'button' ) ) ) {
237 222 $content_tags->set_attribute(
238 223 'aria-label',
@@ -243,27 +228,17 @@
243 228 )
244 229 );
245 230 }
246 231 } elseif ( $content_tags->next_tag( array( 'tag_name' => 'a' ) ) ) {
247 - $content_tags->set_attribute( 'hreflang', $instance->attributes['hreflang'] );
248 - $content_tags->set_attribute( 'lang', $instance->attributes['lang'] );
232 + $content_tags->set_attribute( 'hreflang', $snapshot['locale'] );
233 + $content_tags->set_attribute( 'lang', $snapshot['locale'] );
249 234 }
250 235
251 236 $overridden_block_content = $content_tags->get_updated_html();
252 237
253 - $link_label = '';
254 -
255 - if ( $instance->attributes['pll_show_flags'] ) {
256 - $link_label .= $instance->attributes['pll_flag'];
257 - }
258 -
259 - if ( $instance->attributes['pll_show_names'] ) {
260 - $link_label .= $instance->attributes['pll_show_flags'] ? ' ' . $instance->attributes['pll_name'] : $instance->attributes['pll_name'];
261 - }
262 -
263 238 return str_replace(
264 239 static::PLACEHOLDER,
265 - $link_label,
240 + $snapshot['label'],
266 241 $overridden_block_content
267 242 );
268 243 }
269 244
@@ -279,26 +254,79 @@
279 254 return __DIR__;
280 255 }
281 256
282 257 /**
258 + * Creates an inner navigation block and stores the locale and label to render for it.
259 + *
260 + * @since 3.8.10
261 + *
262 + * @param string $block_name Core block name.
263 + * @param array $core_attributes Attributes to be rendered by core.
264 + * @param array $switcher_item Array of a switcher item data.
265 + * @param array $context Block context.
266 + * @param array $attributes Array of polylang/navigation-language-switcher attributes.
267 + * @param WP_Block[] $inner_blocks Optional inner blocks.
268 + * @return WP_Block
269 + */
270 + private function create_inner_block( $block_name, $core_attributes, $switcher_item, $context, $attributes, $inner_blocks = array() ) {
271 + $block = new WP_Block(
272 + array(
273 + 'blockName' => $block_name,
274 + 'attrs' => $core_attributes,
275 + 'innerBlocks' => $inner_blocks,
276 + ),
277 + $context
278 + );
279 +
280 + $this->internal_blocks->offsetSet(
281 + $block,
282 + array(
283 + 'locale' => $switcher_item['locale'],
284 + 'label' => $this->get_link_label( $switcher_item, $attributes ),
285 + )
286 + );
287 +
288 + return $block;
289 + }
290 +
291 + /**
292 + * Builds the language switcher link label from a trusted switcher item.
293 + *
294 + * @since 3.8.10
295 + *
296 + * @param array $switcher_item Array of a switcher item data.
297 + * @param array $attributes Array of polylang/navigation-language-switcher attributes.
298 + * @return string
299 + */
300 + private function get_link_label( $switcher_item, $attributes ) {
301 + $show_flags = ! empty( $attributes['show_flags'] );
302 + $show_names = ! empty( $attributes['show_names'] );
303 + $link_label = '';
304 +
305 + if ( $show_flags ) {
306 + $link_label .= $switcher_item['flag'];
307 + }
308 +
309 + if ( $show_names ) {
310 + $name = esc_html( $switcher_item['name'] );
311 + $link_label .= $show_flags ? ' ' . $name : $name;
312 + }
313 +
314 + return $link_label;
315 + }
316 +
317 + /**
283 318 * Returns attributes that fit for core/navigation-link or core/navigation-submenu and specific to polylang/navigation-language-switcher.
284 319 *
285 320 * @since 3.6
286 321 *
287 - * @param array $attributes Array of polylang/navigation-language-switcher attributes.
288 322 * @param array $switcher_item Array of a switcher item data.
289 323 * @return array Attributes to be rendered by core.
290 324 */
291 - private function get_core_block_attributes( $attributes, $switcher_item ) {
325 + private function get_core_block_attributes( $switcher_item ) {
292 326 return array(
293 - 'label' => static::PLACEHOLDER,
294 - 'url' => $switcher_item['url'],
295 - 'pll_show_flags' => $attributes['show_flags'],
296 - 'pll_show_names' => $attributes['show_names'],
297 - 'lang' => $switcher_item['locale'],
298 - 'hreflang' => $switcher_item['locale'],
299 - 'pll_flag' => $switcher_item['flag'],
300 - 'pll_name' => $switcher_item['name'],
301 - 'className' => trim( implode( ' ', (array) $switcher_item['classes'] ) ),
327 + 'label' => static::PLACEHOLDER,
328 + 'url' => $switcher_item['url'],
329 + 'className' => trim( implode( ' ', (array) $switcher_item['classes'] ) ),
302 330 );
303 331 }
304 332 }