PluginProbe
Gutenberg / 16.6.0
Gutenberg v16.6.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / block-library / blocks / navigation-link.php

navigation-link.php in Gutenberg 16.6.0, at build/block-library/blocks/navigation-link.php

372 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/navigation-link` block.
4 *
5 * @package WordPress
6 */
7
8 /**
9 * Build an array with CSS classes and inline styles defining the colors
10 * which will be applied to the navigation markup in the front-end.
11 *
12 * @param array $context Navigation block context.
13 * @param array $attributes Block attributes.
14 * @param bool $is_sub_menu Whether the link is part of a sub-menu.
15 * @return array Colors CSS classes and inline styles.
16 */
17 function gutenberg_block_core_navigation_link_build_css_colors( $context, $attributes, $is_sub_menu = false ) {
18 $colors = array(
19 'css_classes' => array(),
20 'inline_styles' => '',
21 );
22
23 // Text color.
24 $named_text_color = null;
25 $custom_text_color = null;
26
27 if ( $is_sub_menu && array_key_exists( 'customOverlayTextColor', $context ) ) {
28 $custom_text_color = $context['customOverlayTextColor'];
29 } elseif ( $is_sub_menu && array_key_exists( 'overlayTextColor', $context ) ) {
30 $named_text_color = $context['overlayTextColor'];
31 } elseif ( array_key_exists( 'customTextColor', $context ) ) {
32 $custom_text_color = $context['customTextColor'];
33 } elseif ( array_key_exists( 'textColor', $context ) ) {
34 $named_text_color = $context['textColor'];
35 } elseif ( isset( $context['style']['color']['text'] ) ) {
36 $custom_text_color = $context['style']['color']['text'];
37 }
38
39 // If has text color.
40 if ( ! is_null( $named_text_color ) ) {
41 // Add the color class.
42 array_push( $colors['css_classes'], 'has-text-color', sprintf( 'has-%s-color', $named_text_color ) );
43 } elseif ( ! is_null( $custom_text_color ) ) {
44 // Add the custom color inline style.
45 $colors['css_classes'][] = 'has-text-color';
46 $colors['inline_styles'] .= sprintf( 'color: %s;', $custom_text_color );
47 }
48
49 // Background color.
50 $named_background_color = null;
51 $custom_background_color = null;
52
53 if ( $is_sub_menu && array_key_exists( 'customOverlayBackgroundColor', $context ) ) {
54 $custom_background_color = $context['customOverlayBackgroundColor'];
55 } elseif ( $is_sub_menu && array_key_exists( 'overlayBackgroundColor', $context ) ) {
56 $named_background_color = $context['overlayBackgroundColor'];
57 } elseif ( array_key_exists( 'customBackgroundColor', $context ) ) {
58 $custom_background_color = $context['customBackgroundColor'];
59 } elseif ( array_key_exists( 'backgroundColor', $context ) ) {
60 $named_background_color = $context['backgroundColor'];
61 } elseif ( isset( $context['style']['color']['background'] ) ) {
62 $custom_background_color = $context['style']['color']['background'];
63 }
64
65 // If has background color.
66 if ( ! is_null( $named_background_color ) ) {
67 // Add the background-color class.
68 array_push( $colors['css_classes'], 'has-background', sprintf( 'has-%s-background-color', $named_background_color ) );
69 } elseif ( ! is_null( $custom_background_color ) ) {
70 // Add the custom background-color inline style.
71 $colors['css_classes'][] = 'has-background';
72 $colors['inline_styles'] .= sprintf( 'background-color: %s;', $custom_background_color );
73 }
74
75 return $colors;
76 }
77
78 /**
79 * Build an array with CSS classes and inline styles defining the font sizes
80 * which will be applied to the navigation markup in the front-end.
81 *
82 * @param array $context Navigation block context.
83 * @return array Font size CSS classes and inline styles.
84 */
85 function gutenberg_block_core_navigation_link_build_css_font_sizes( $context ) {
86 // CSS classes.
87 $font_sizes = array(
88 'css_classes' => array(),
89 'inline_styles' => '',
90 );
91
92 $has_named_font_size = array_key_exists( 'fontSize', $context );
93 $has_custom_font_size = isset( $context['style']['typography']['fontSize'] );
94
95 if ( $has_named_font_size ) {
96 // Add the font size class.
97 $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $context['fontSize'] );
98 } elseif ( $has_custom_font_size ) {
99 // Add the custom font size inline style.
100 $font_sizes['inline_styles'] = sprintf(
101 'font-size: %s;',
102 gutenberg_get_typography_font_size_value(
103 array(
104 'size' => $context['style']['typography']['fontSize'],
105 )
106 )
107 );
108 }
109
110 return $font_sizes;
111 }
112
113 /**
114 * Returns the top-level submenu SVG chevron icon.
115 *
116 * @return string
117 */
118 function gutenberg_block_core_navigation_link_render_submenu_icon() {
119 return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" focusable="false"><path d="M1.50002 4L6.00002 8L10.5 4" stroke-width="1.5"></path></svg>';
120 }
121
122 /**
123 * Decodes a url if it's encoded, returning the same url if not.
124 *
125 * @param string $url The url to decode.
126 *
127 * @return string $url Returns the decoded url.
128 */
129 function gutenberg_block_core_navigation_link_maybe_urldecode( $url ) {
130 $is_url_encoded = false;
131 $query = parse_url( $url, PHP_URL_QUERY );
132 $query_params = wp_parse_args( $query );
133
134 foreach ( $query_params as $query_param ) {
135 if ( rawurldecode( $query_param ) !== $query_param ) {
136 $is_url_encoded = true;
137 break;
138 }
139 }
140
141 if ( $is_url_encoded ) {
142 return rawurldecode( $url );
143 }
144
145 return $url;
146 }
147
148
149 /**
150 * Renders the `core/navigation-link` block.
151 *
152 * @param array $attributes The block attributes.
153 * @param string $content The saved content.
154 * @param WP_Block $block The parsed block.
155 *
156 * @return string Returns the post content with the legacy widget added.
157 */
158 function gutenberg_render_block_core_navigation_link( $attributes, $content, $block ) {
159 $navigation_link_has_id = isset( $attributes['id'] ) && is_numeric( $attributes['id'] );
160 $is_post_type = isset( $attributes['kind'] ) && 'post-type' === $attributes['kind'];
161 $is_post_type = $is_post_type || isset( $attributes['type'] ) && ( 'post' === $attributes['type'] || 'page' === $attributes['type'] );
162
163 // Don't render the block's subtree if it is a draft or if the ID does not exist.
164 if ( $is_post_type && $navigation_link_has_id ) {
165 $post = get_post( $attributes['id'] );
166 if ( ! $post || 'publish' !== $post->post_status ) {
167 return '';
168 }
169 }
170
171 // Don't render the block's subtree if it has no label.
172 if ( empty( $attributes['label'] ) ) {
173 return '';
174 }
175
176 $font_sizes = gutenberg_block_core_navigation_link_build_css_font_sizes( $block->context );
177 $classes = array_merge(
178 $font_sizes['css_classes']
179 );
180 $style_attribute = $font_sizes['inline_styles'];
181
182 $css_classes = trim( implode( ' ', $classes ) );
183 $has_submenu = count( $block->inner_blocks ) > 0;
184 $kind = empty( $attributes['kind'] ) ? 'post_type' : str_replace( '-', '_', $attributes['kind'] );
185 $is_active = ! empty( $attributes['id'] ) && get_queried_object_id() === (int) $attributes['id'] && ! empty( get_queried_object()->$kind );
186
187 $wrapper_attributes = get_block_wrapper_attributes(
188 array(
189 'class' => $css_classes . ' wp-block-navigation-item' . ( $has_submenu ? ' has-child' : '' ) .
190 ( $is_active ? ' current-menu-item' : '' ),
191 'style' => $style_attribute,
192 )
193 );
194 $html = '<li ' . $wrapper_attributes . '>' .
195 '<a class="wp-block-navigation-item__content" ';
196
197 // Start appending HTML attributes to anchor tag.
198 if ( isset( $attributes['url'] ) ) {
199 $html .= ' href="' . esc_url( gutenberg_block_core_navigation_link_maybe_urldecode( $attributes['url'] ) ) . '"';
200 }
201
202 if ( $is_active ) {
203 $html .= ' aria-current="page"';
204 }
205
206 if ( isset( $attributes['opensInNewTab'] ) && true === $attributes['opensInNewTab'] ) {
207 $html .= ' target="_blank" ';
208 }
209
210 if ( isset( $attributes['rel'] ) ) {
211 $html .= ' rel="' . esc_attr( $attributes['rel'] ) . '"';
212 } elseif ( isset( $attributes['nofollow'] ) && $attributes['nofollow'] ) {
213 $html .= ' rel="nofollow"';
214 }
215
216 if ( isset( $attributes['title'] ) ) {
217 $html .= ' title="' . esc_attr( $attributes['title'] ) . '"';
218 }
219
220 // End appending HTML attributes to anchor tag.
221
222 // Start anchor tag content.
223 $html .= '>' .
224 // Wrap title with span to isolate it from submenu icon.
225 '<span class="wp-block-navigation-item__label">';
226
227 if ( isset( $attributes['label'] ) ) {
228 $html .= wp_kses_post( $attributes['label'] );
229 }
230
231 $html .= '</span>';
232
233 // Add description if available.
234 if ( ! empty( $attributes['description'] ) ) {
235 $html .= '<span class="wp-block-navigation-item__description">';
236 $html .= wp_kses_post( $attributes['description'] );
237 $html .= '</span>';
238 }
239
240 $html .= '</a>';
241 // End anchor tag content.
242
243 if ( isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon'] && $has_submenu ) {
244 // The submenu icon can be hidden by a CSS rule on the Navigation Block.
245 $html .= '<span class="wp-block-navigation__submenu-icon">' . gutenberg_block_core_navigation_link_render_submenu_icon() . '</span>';
246 }
247
248 if ( $has_submenu ) {
249 $inner_blocks_html = '';
250 foreach ( $block->inner_blocks as $inner_block ) {
251 $inner_blocks_html .= $inner_block->render();
252 }
253
254 $html .= sprintf(
255 '<ul class="wp-block-navigation__submenu-container">%s</ul>',
256 $inner_blocks_html
257 );
258 }
259
260 $html .= '</li>';
261
262 return $html;
263 }
264
265 /**
266 * Returns a navigation link variation
267 *
268 * @param WP_Taxonomy|WP_Post_Type $entity post type or taxonomy entity.
269 * @param string $kind string of value 'taxonomy' or 'post-type'.
270 *
271 * @return array
272 */
273 function gutenberg_build_variation_for_navigation_link( $entity, $kind ) {
274 $title = '';
275 $description = '';
276
277 if ( property_exists( $entity->labels, 'item_link' ) ) {
278 $title = $entity->labels->item_link;
279 }
280 if ( property_exists( $entity->labels, 'item_link_description' ) ) {
281 $description = $entity->labels->item_link_description;
282 }
283
284 $variation = array(
285 'name' => $entity->name,
286 'title' => $title,
287 'description' => $description,
288 'attributes' => array(
289 'type' => $entity->name,
290 'kind' => $kind,
291 ),
292 );
293
294 // Tweak some value for the variations.
295 $variation_overrides = array(
296 'post_tag' => array(
297 'name' => 'tag',
298 'attributes' => array(
299 'type' => 'tag',
300 'kind' => $kind,
301 ),
302 ),
303 'post_format' => array(
304 // The item_link and item_link_description for post formats is the
305 // same as for tags, so need to be overridden.
306 'title' => __( 'Post Format Link' ),
307 'description' => __( 'A link to a post format' ),
308 'attributes' => array(
309 'type' => 'post_format',
310 'kind' => $kind,
311 ),
312 ),
313 );
314
315 if ( array_key_exists( $entity->name, $variation_overrides ) ) {
316 $variation = array_merge(
317 $variation,
318 $variation_overrides[ $entity->name ]
319 );
320 }
321
322 return $variation;
323 }
324
325 /**
326 * Register the navigation link block.
327 *
328 * @uses render_block_core_navigation()
329 * @throws WP_Error An WP_Error exception parsing the block definition.
330 */
331 function gutenberg_register_block_core_navigation_link() {
332 $post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
333 $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );
334
335 // Use two separate arrays as a way to order the variations in the UI.
336 // Known variations (like Post Link and Page Link) are added to the
337 // `built_ins` array. Variations for custom post types and taxonomies are
338 // added to the `variations` array and will always appear after `built-ins.
339 $built_ins = array();
340 $variations = array();
341
342 if ( $post_types ) {
343 foreach ( $post_types as $post_type ) {
344 $variation = gutenberg_build_variation_for_navigation_link( $post_type, 'post-type' );
345 if ( $post_type->_builtin ) {
346 $built_ins[] = $variation;
347 } else {
348 $variations[] = $variation;
349 }
350 }
351 }
352 if ( $taxonomies ) {
353 foreach ( $taxonomies as $taxonomy ) {
354 $variation = gutenberg_build_variation_for_navigation_link( $taxonomy, 'taxonomy' );
355 if ( $taxonomy->_builtin ) {
356 $built_ins[] = $variation;
357 } else {
358 $variations[] = $variation;
359 }
360 }
361 }
362
363 register_block_type_from_metadata(
364 __DIR__ . '/navigation-link',
365 array(
366 'render_callback' => 'gutenberg_render_block_core_navigation_link',
367 'variations' => array_merge( $built_ins, $variations ),
368 )
369 );
370 }
371 add_action( 'init', 'gutenberg_register_block_core_navigation_link', 20 );
372