PluginProbe ʕ •ᴥ•ʔ
WP Job Manager / 2.4.6
WP Job Manager v2.4.6
2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.10.0 1.11.0 1.11.1 1.12.0 1.12.1 1.13.0 1.14.0 1.15.0 1.16.0 1.16.1 1.17.0 1.18.0 1.19.0 1.2.0 1.20.0 1.20.1 1.21.0 1.21.1 1.21.2 1.21.3 1.21.4 1.22.0 1.22.1 1.22.2 1.22.3 1.23.0 1.23.1 1.23.10 1.23.11 1.23.12 1.23.13 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.23.9 1.24.0 1.24.0.1 1.25.0 1.25.0.1 1.25.1 1.25.1.1 1.25.2 1.25.2.1 1.25.3 1.25.3.1 1.26.0 1.26.0.1 1.26.1 1.26.1.1 1.26.2 1.26.2.1 1.27.0 1.27.0.1 1.28.0 1.28.0.1 1.29.0 1.29.0.1 1.29.1 1.29.1.1 1.29.2 1.29.2.1 1.29.3 1.29.3.1 1.3.0 1.3.1 1.30.0 1.30.0.1 1.30.1 1.30.1.1 1.30.2 1.30.2.1 1.31.0 1.31.0.1 1.31.1 1.31.1.1 1.31.2 1.31.3 1.32.0 1.32.1 1.32.2 1.32.3 1.33.0 1.33.1 1.33.2 1.33.3 1.33.4 1.33.5 1.34.0 1.34.1 1.34.2 1.34.3 1.34.4 1.34.5 1.35.0 1.35.1 1.35.2 1.35.3 1.36.0 1.36.1 1.36.2 1.37.0 1.38.0 1.38.1 1.39.0 1.4.0 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.5.0 1.5.1 1.5.2 1.6.0 1.7.0 1.7.1 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 1.9.1 1.9.2 1.9.3 2.0.0 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.4.1
wp-job-manager / includes / ui / class-ui-elements.php
wp-job-manager / includes / ui Last commit date
class-modal-dialog.php 2 years ago class-notice.php 2 years ago class-redirect-message.php 2 years ago class-ui-elements.php 2 weeks ago class-ui-settings.php 2 years ago class-ui.php 2 years ago
class-ui-elements.php
272 lines
1 <?php
2 /**
3 * UI Elements.
4 *
5 * @package wp-job-manager
6 * @since 2.2.0
7 */
8
9 namespace WP_Job_Manager\UI;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly.
13 }
14
15 /**
16 * Collection of rendering functions for various UI elements.
17 *
18 * @since 2.2.0
19 *
20 * @internal This API is still under development and subject to change.
21 * @access private
22 */
23 class UI_Elements {
24
25 /**
26 * Generate HTML for a notice icon.
27 *
28 * @param string|null $icon Icon name or a safe SVG code.
29 * @param string $label Accessible icon label.
30 *
31 * @return string Icon HTML.
32 */
33 public static function icon( $icon, $label = '' ) {
34
35 if ( empty( $icon ) ) {
36 return '';
37 }
38
39 $html = '';
40
41 $is_classname = preg_match( '/^[\w-]+$/i', $icon );
42 $is_url = preg_match( '/^url\(/i', $icon );
43 $is_svg = preg_match( '/^<svg/i', $icon );
44
45 $html = '<span class="jm-ui-icon' . ( $is_svg ? ' jm-ui-icon--svg' : '' ) . '"';
46
47 if ( $is_classname ) {
48 $html .= ' data-icon="' . esc_attr( $icon ) . '"';
49 }
50
51 if ( $label ) {
52 $html .= ' aria-label="' . esc_attr( $label ) . '"';
53 }
54
55 if ( $is_url ) {
56 $html .= ' style="mask-image: ' . esc_attr( $icon ) . '"';
57 }
58
59 $html .= '>';
60
61 if ( $is_svg ) {
62 $html .= self::esc_svg( $icon );
63 }
64
65 $html .= '</span>';
66
67 return $html;
68 }
69
70 /**
71 * Generate HTML for a button or action link.
72 *
73 * @param array $args Button options.
74 * @param string $class Base classname.
75 *
76 * @return string Button HTML.
77 */
78 public static function button( $args, $class ) {
79
80 if ( empty( $args ) ) {
81 return '';
82 }
83
84 $args = wp_parse_args(
85 $args,
86 [
87 'label' => '',
88 'url' => '',
89 'onclick' => '',
90 'class' => '',
91 ]
92 );
93
94 if ( empty( $args['url'] ) ) {
95 $args['url'] = '#';
96 }
97
98 $attrs = [
99 'class' => implode( ' ', [ $class, $args['class'] ] ),
100 'href' => esc_url( $args['url'] ),
101 ];
102
103 if ( ! empty( $args['onclick'] ) ) {
104 $attrs['onclick'] = $args['onclick'];
105 $attrs['role'] = 'button';
106 }
107
108 return '<a ' . self::html_attrs( $attrs ) . '><span>' . esc_html( $args['label'] ) . '</span></a>';
109 }
110
111 /**
112 * Generate HTML for a row of actions. Can contain button and/or link actions.
113 *
114 * Unless set otherwise, the first button will be styled as primary, and the rest as outline.
115 * Links will match button dimensions if buttons are also present.
116 *
117 * @param array $buttons Button definitions.
118 * @param array $links Link definitions.
119 *
120 * @return string Actions HTML.
121 */
122 public static function actions( array $buttons = [], array $links = [] ) {
123
124 $actions_html = [];
125
126 if ( ! empty( $buttons ) ) {
127 foreach ( $buttons as $index => $button ) {
128 $primary = $button['primary'] ?? ( 0 === $index );
129 $class = $primary ? 'jm-ui-button' : 'jm-ui-button--outline';
130 $actions_html[] = self::button( $button, $class );
131 }
132 }
133
134 if ( ! empty( $links ) ) {
135 foreach ( $links as $link ) {
136 $class = $buttons ? 'jm-ui-button--link' : 'jm-ui-link';
137 $actions_html[] = self::button( $link, $class );
138 }
139 }
140
141 if ( empty( $actions_html ) ) {
142 return '';
143 }
144
145 return '<div class="jm-ui-actions-row">' . implode( '', $actions_html ) . '</div>';
146
147 }
148
149 /**
150 * Generate an actions button with a dropdown menu.
151 *
152 * @param string $content Escaped HTML content.
153 *
154 * @return string Actions menu HTML.
155 */
156 public static function actions_menu( $content ) {
157 $label = esc_attr__( 'Actions', 'wp-job-manager' );
158
159 return <<<HTML
160 <details class="jm-ui-actions-menu">
161 <summary tabindex="0" class="jm-ui-action-menu__open-button jm-ui-button--icon"
162 aria-label="{$label}">
163 <span class="jm-ui-button__icon"></span>
164 </summary>
165 <div class="jm-ui-action-menu__content">
166 {$content}
167 </div>
168 </details>
169 HTML;
170
171 }
172
173 /**
174 * Generate HTML for a relative time string.
175 *
176 * @param string|\DateTimeInterface|int $time DateTime object, Unix timestamp, or a date string. Strings without an explicit UTC offset are interpreted in the site timezone.
177 * @param string $format_string Sprintf-compatible format string. Should contain a %s placeholder for the time.
178 *
179 * @return string
180 */
181 public static function rel_time( $time, $format_string = '%s' ) {
182
183 // The three input kinds are mutually exclusive; resolve each to a true Unix timestamp.
184 $timestamp = false;
185
186 if ( $time instanceof \DateTimeInterface ) {
187 $timestamp = $time->getTimestamp();
188 } elseif ( is_numeric( $time ) ) {
189 $timestamp = (int) $time;
190 } elseif ( is_string( $time ) && '' !== trim( $time ) ) {
191 // Interpret a bare date string as a floating calendar date in the site timezone,
192 // so wp_date() renders the same calendar date regardless of the site's UTC offset.
193 $datetime = date_create( $time, wp_timezone() );
194
195 if ( $datetime ) {
196 $timestamp = $datetime->getTimestamp();
197 }
198 }
199
200 if ( empty( $timestamp ) ) {
201 return '';
202 }
203
204 // `datetime` must be machine-readable (a valid HTML datetime string); `title` is the localized display date.
205 // Emit a full ISO 8601 value with the site's UTC offset rather than a date-only one: the relative text is
206 // accurate to the hour, and a floating date would be resolved to midnight in the consumer's own timezone.
207 $machine_time = wp_date( 'c', $timestamp );
208 $abs_time = wp_date( get_option( 'date_format' ), $timestamp );
209 $rel_time = human_time_diff( $timestamp );
210
211 return '<time datetime="' . esc_attr( $machine_time ) . '" title="' . esc_attr( $abs_time ) . '">' . esc_html( sprintf( $format_string, $rel_time ) ) . '</time>';
212
213 }
214
215 /**
216 * Escape SVG code.
217 *
218 * TODO Extend rules to support more SVG tags and attributes.
219 *
220 * @param string $code SVG code.
221 *
222 * @return string Sanitized SVG code.
223 */
224 private static function esc_svg( $code ) {
225 $kses_defaults = wp_kses_allowed_html( 'post' );
226 $svg_args = [
227 'svg' => [
228 'class' => true,
229 'aria-hidden' => true,
230 'aria-labelledby' => true,
231 'role' => true,
232 'xmlns' => true,
233 'width' => true,
234 'height' => true,
235 'viewbox' => true,
236 'fill' => true,
237 ],
238 'path' => [
239 'd' => true,
240 'fill' => true,
241 'fill-rule' => true,
242 'stroke-width' => true,
243 'stroke' => true,
244 'clip-rule' => true,
245 ],
246 ];
247
248 $allowed_tags = array_merge( $kses_defaults, $svg_args );
249
250 return wp_kses( $code, $allowed_tags );
251 }
252
253 /**
254 * Generate HTML attributes string. Escapes attributes.
255 *
256 * @param array $attributes Attributes array with key => value pairs.
257 *
258 * @return string HTML attributes string.
259 */
260 private static function html_attrs( $attributes ) {
261 $attributes_html = array_map(
262 function( $key, $value ) {
263 return esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
264 },
265 array_keys( $attributes ),
266 array_values( $attributes )
267 );
268
269 return implode( ' ', $attributes_html );
270 }
271 }
272