PluginProbe
Polylang / 3.8.4
Polylang v3.8.4
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 3.0.3 All 233 releases
polylang / src / modules / Blocks / Language_Switcher / Navigation / Block.php

Block.php in Polylang 3.8.4, at src/modules/Blocks/Language_Switcher/Navigation/Block.php

305 lines 9.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 namespace WP_Syntex\Polylang\Blocks\Language_Switcher\Navigation;
7
8 use WP_Block;
9 use PLL_Switcher;
10 use WP_HTML_Tag_Processor;
11 use WP_Syntex\Polylang\Blocks\Language_Switcher\Abstract_Block;
12
13 /**
14 * Language switcher block for navigation.
15 *
16 * @since 3.2
17 * @since 3.8 Moved to Polylang Core and renamed to Language_Switcher\Navigation\Block.
18 */
19 class Block extends Abstract_Block {
20 /**
21 * Placeholder used to add language name or flag after WordPress renders the link labels.
22 *
23 * @var string
24 */
25 const PLACEHOLDER = '%pll%';
26
27 /**
28 * Adds the required hooks specific to the navigation language switcher.
29 *
30 * @since 3.2
31 *
32 * @return self
33 */
34 public function init() {
35 parent::init();
36
37 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 add_filter( 'render_block_core/navigation-link', array( $this, 'render_custom_attributes' ), 10, 3 );
40 add_filter( 'render_block_core/navigation-submenu', array( $this, 'render_custom_attributes' ), 10, 3 );
41 add_action( 'init', array( $this, 'register_editor_style' ) );
42
43 return $this;
44 }
45
46 /**
47 * Registers the editor style for the navigation language switcher block.
48 *
49 * @since 3.8
50 *
51 * @return void
52 */
53 public function register_editor_style(): void {
54 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
55
56 wp_register_style(
57 'pll-navigation-language-switcher-editor-style',
58 plugins_url( 'css/build/navigation-language-switcher-editor-style' . $suffix . '.css', POLYLANG_ROOT_FILE ),
59 array(),
60 POLYLANG_VERSION
61 );
62 }
63 /**
64 * Returns the navigation language switcher block name with the Polylang's namespace.
65 *
66 * @since 3.2
67 *
68 * @return string The block name.
69 */
70 protected function get_block_name() {
71 return 'polylang/navigation-language-switcher';
72 }
73
74 /**
75 * Renders the `polylang/navigation-language-switcher` block on server.
76 *
77 * @since 3.1
78 * @since 3.3 Accepts two new parameters, $content and $block.
79 *
80 * @param array $attributes The block attributes.
81 * @param string $content The saved content. Unused.
82 * @param WP_Block $block The parsed block.
83 * @return string The HTML string output to serve.
84 */
85 public function render( $attributes, $content, $block ) {
86 $attributes = $this->set_attributes_for_block( $attributes );
87 $switcher = new PLL_Switcher();
88 $switcher_elements = (array) $switcher->the_languages( $this->links, array_merge( $attributes, array( 'raw' => true ) ) );
89
90 if ( empty( $switcher_elements ) ) {
91 return '';
92 }
93
94 if ( $attributes['dropdown'] ) {
95 $inner_nav_link_blocks = array();
96 $top_level_lang = reset( $switcher_elements );
97 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 ),
101 );
102
103 $inner_nav_link_blocks[] = new WP_Block( $nav_link_block_args, $block->context );
104
105 if ( $switcher_element['current_lang'] && ! $attributes['hide_current'] ) {
106 $top_level_lang = $switcher_element;
107 }
108 }
109
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,
116 );
117
118 $submenu_block = new WP_Block( $submenu_block_args, $block->context );
119 $output = $submenu_block->render();
120 } else {
121 $output = '';
122
123 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();
133 }
134 }
135
136 return $output;
137 }
138
139 /**
140 * Register switcher menu item meta options as a REST API field.
141 *
142 * @since 3.2
143 *
144 * @return void
145 */
146 public function register_switcher_menu_item_options_meta_rest_field() {
147 register_post_meta(
148 'nav_menu_item',
149 '_pll_menu_item',
150 array(
151 'object_subtype' => 'nav_menu_item',
152 'description' => __( 'Language switcher settings', 'polylang' ),
153 'single' => true,
154 'show_in_rest' => array(
155 'schema' => array(
156 'type' => 'object',
157 'additionalProperties' => array(
158 'type' => 'boolean',
159 ),
160 ),
161 ),
162 )
163 );
164 }
165
166 /**
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 * Renders a core/naviagation-link or core/naviagation-submenu block by adding hreflang and lang attributes to the <a> tag
205 * and also the language flag if required.
206 *
207 * @since 3.6
208 *
209 * @param string $block_content The block content.
210 * @param array $block The full block, including name and attributes.
211 * @param WP_Block $instance The block instance.
212 *
213 * @return string A formatted HTML string representing the core/navigation-link or core/navigation-submenu block.
214 */
215 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 ) {
225 return $block_content;
226 }
227
228 $content_tags = new WP_HTML_Tag_Processor( $block_content );
229
230 if ( 'core/navigation-submenu' === $instance->name ) {
231 // If `openSubmenusOnClick`, the submenu is rendered as a button, so there are no `<a>` to process.
232 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'] );
235 }
236 if ( $content_tags->next_tag( array( 'tag_name' => 'button' ) ) ) {
237 $content_tags->set_attribute(
238 'aria-label',
239 str_replace(
240 static::PLACEHOLDER,
241 __( 'Languages', 'polylang' ),
242 (string) $content_tags->get_attribute( 'aria-label' )
243 )
244 );
245 }
246 } 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'] );
249 }
250
251 $overridden_block_content = $content_tags->get_updated_html();
252
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 return str_replace(
264 static::PLACEHOLDER,
265 $link_label,
266 $overridden_block_content
267 );
268 }
269
270 /**
271 * Returns the path to the block JSON file directory.
272 * The directory name being used to register a block.
273 *
274 * @since 3.8
275 *
276 * @return string The path to the block.
277 */
278 protected function get_path(): string {
279 return __DIR__;
280 }
281
282 /**
283 * Returns attributes that fit for core/navigation-link or core/navigation-submenu and specific to polylang/navigation-language-switcher.
284 *
285 * @since 3.6
286 *
287 * @param array $attributes Array of polylang/navigation-language-switcher attributes.
288 * @param array $switcher_item Array of a switcher item data.
289 * @return array Attributes to be rendered by core.
290 */
291 private function get_core_block_attributes( $attributes, $switcher_item ) {
292 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'] ) ),
302 );
303 }
304 }
305