PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | modules/theme-tools/site-logo/inc/class-site-logo.php +423 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,423 @@
1 +<?php
2 +/**
3 + * Site Logo class main class file.
4 + *
5 + * @package automattic/jetpack
6 + */
7 +
8 +if ( ! defined( 'ABSPATH' ) ) {
9 + exit( 0 );
10 +}
11 +
12 +/**
13 + * Site Logo class for managing a theme-agnostic logo through the Customizer.
14 + */
15 +class Site_Logo {
16 + /**
17 + * Stores our single instance.
18 + *
19 + * @var Site_Logo
20 + */
21 + private static $instance;
22 +
23 + /**
24 + * Stores the attachment ID of the site logo.
25 + *
26 + * @var int
27 + */
28 + public $logo;
29 +
30 + /**
31 + * Return our instance, creating a new one if necessary.
32 + *
33 + * @uses Site_Logo::$instance
34 + * @return object Site_Logo
35 + */
36 + public static function instance() {
37 + if ( ! isset( self::$instance ) ) {
38 + self::$instance = new Site_Logo();
39 + self::$instance->register_hooks();
40 + }
41 +
42 + return self::$instance;
43 + }
44 +
45 + /**
46 + * Get our current logo settings stored in options.
47 + *
48 + * @uses get_option()
49 + */
50 + private function __construct() {
51 + $this->logo = (int) get_option( 'site_logo', null );
52 + }
53 +
54 + /**
55 + * Register our actions and filters.
56 + *
57 + * @uses Site_Logo::head_text_styles()
58 + * @uses Site_Logo::customize_register()
59 + * @uses Site_Logo::preview_enqueue()
60 + * @uses Site_Logo::body_classes()
61 + * @uses Site_Logo::media_manager_image_sizes()
62 + * @uses add_action
63 + * @uses add_filter
64 + */
65 + public function register_hooks() {
66 + // This would only happen if a theme supports BOTH site-logo and custom-logo for some reason
67 + if ( current_theme_supports( 'custom-logo' ) ) {
68 + return;
69 + }
70 +
71 + add_action( 'wp_head', array( $this, 'head_text_styles' ) );
72 + add_action( 'customize_register', array( $this, 'customize_register' ) );
73 + add_action( 'customize_preview_init', array( $this, 'preview_enqueue' ) );
74 + add_action( 'delete_attachment', array( $this, 'reset_on_attachment_delete' ) );
75 + add_filter( 'body_class', array( $this, 'body_classes' ) );
76 + add_filter( 'image_size_names_choose', array( $this, 'media_manager_image_sizes' ) );
77 + add_filter( 'display_media_states', array( $this, 'add_media_state' ) );
78 + }
79 +
80 + /**
81 + * Add our logo uploader to the Customizer.
82 + *
83 + * @param object $wp_customize Customizer object.
84 + * @uses current_theme_supports()
85 + * @uses current_theme_supports()
86 + * @uses WP_Customize_Manager::add_setting()
87 + * @uses WP_Customize_Manager::add_control()
88 + * @uses Site_Logo::sanitize_checkbox()
89 + */
90 + public function customize_register( $wp_customize ) {
91 + // Add a setting to hide header text if the theme isn't supporting the feature itself
92 + if ( ! current_theme_supports( 'custom-header' ) ) {
93 + $wp_customize->add_setting(
94 + 'site_logo_header_text',
95 + array(
96 + 'default' => 1,
97 + 'sanitize_callback' => array( $this, 'sanitize_checkbox' ),
98 + 'transport' => 'postMessage',
99 + )
100 + );
101 +
102 + $wp_customize->add_control(
103 + new WP_Customize_Control(
104 + $wp_customize,
105 + 'site_logo_header_text',
106 + array(
107 + 'label' => __( 'Display Header Text', 'jetpack' ),
108 + 'section' => 'title_tagline',
109 + 'settings' => 'site_logo_header_text',
110 + 'type' => 'checkbox',
111 + )
112 + )
113 + );
114 + }
115 +
116 + // Add the setting for our logo value.
117 + $wp_customize->add_setting(
118 + 'site_logo',
119 + array(
120 + 'capability' => 'manage_options',
121 + 'default' => 0,
122 + 'sanitize_callback' => array( $this, 'sanitize_logo_setting' ),
123 + 'transport' => 'postMessage',
124 + 'type' => 'option',
125 + )
126 + );
127 +
128 + // By default, not setting width and height will suggest a square crop.
129 + $width = null;
130 + $height = null;
131 + $logo_size = jetpack_get_site_logo_dimensions();
132 +
133 + // Only suggested a different crop if the theme declares both dimensions.
134 + if ( false !== $logo_size && $logo_size['width'] && $logo_size['height'] ) {
135 + $width = $logo_size['width'];
136 + $height = $logo_size['height'];
137 + }
138 +
139 + // Add our image uploader.
140 + $wp_customize->add_control(
141 + new WP_Customize_Cropped_Image_Control(
142 + $wp_customize,
143 + 'site_logo',
144 + array(
145 + 'label' => __( 'Logo', 'jetpack' ),
146 + 'section' => 'title_tagline',
147 + 'settings' => 'site_logo',
148 + 'width' => $width,
149 + 'height' => $height,
150 + 'flex_width' => true,
151 + 'flex_height' => true,
152 + 'button_labels' => array(
153 + 'select' => __( 'Add logo', 'jetpack' ),
154 + 'change' => __( 'Change logo', 'jetpack' ),
155 + 'remove' => __( 'Remove logo', 'jetpack' ),
156 + 'placeholder' => __( 'No logo set', 'jetpack' ),
157 + 'frame_title' => __( 'Set as logo', 'jetpack' ),
158 + 'frame_button' => __( 'Choose logo', 'jetpack' ),
159 + ),
160 + )
161 + )
162 + );
163 +
164 + $wp_customize->selective_refresh->add_partial(
165 + 'site_logo',
166 + array(
167 + 'settings' => 'site_logo',
168 + 'selector' => '.site-logo-link',
169 + 'render_callback' => array( $this, 'customizer_preview' ),
170 + 'container_inclusive' => true,
171 + )
172 + );
173 + }
174 +
175 + /**
176 + * Enqueue scripts for the Customizer live preview.
177 + *
178 + * @uses wp_enqueue_script()
179 + * @uses plugins_url()
180 + * @uses current_theme_supports()
181 + * @uses Site_Logo::header_text_classes()
182 + * @uses wp_localize_script()
183 + */
184 + public function preview_enqueue() {
185 + // Don't bother passing in header text classes if the theme supports custom headers.
186 + if ( ! current_theme_supports( 'custom-header' ) ) {
187 + $classes = jetpack_sanitize_header_text_classes( $this->header_text_classes() );
188 + wp_enqueue_script(
189 + 'site-logo-header-text',
190 + plugins_url( '../js/site-logo-header-text.js', __FILE__ ),
191 + array( 'jquery', 'media-views' ),
192 + JETPACK__VERSION,
193 + true
194 + );
195 + wp_localize_script( 'site-logo-header-text', 'site_logo_header_classes', array( 'classes' => $classes ) );
196 + }
197 + }
198 +
199 + /**
200 + * Get header text classes. If not defined in add_theme_support(), defaults from Underscores will be used.
201 + *
202 + * @uses get_theme_support
203 + * @return string String of classes to hide
204 + */
205 + public function header_text_classes() {
206 + $args = get_theme_support( 'site-logo' );
207 +
208 + if ( isset( $args[0]['header-text'] ) ) {
209 + // Use any classes defined in add_theme_support().
210 + $classes = $args[0]['header-text'];
211 + } else {
212 + // Otherwise, use these defaults, which will work with any Underscores-based theme.
213 + $classes = array(
214 + 'site-title',
215 + 'site-description',
216 + );
217 + }
218 +
219 + // If we've got an array, reduce them to a string for output
220 + if ( is_array( $classes ) ) {
221 + $classes = '.' . implode( ', .', $classes );
222 + } else {
223 + $classes = '.' . $classes;
224 + }
225 +
226 + return $classes;
227 + }
228 +
229 + /**
230 + * Hide header text on front-end if necessary.
231 + *
232 + * @uses current_theme_supports()
233 + * @uses get_theme_mod()
234 + * @uses Site_Logo::header_text_classes()
235 + * @uses esc_html()
236 + */
237 + public function head_text_styles() {
238 + // Bail if our theme supports custom headers.
239 + if ( current_theme_supports( 'custom-header' ) ) {
240 + return;
241 + }
242 +
243 + // Is Display Header Text unchecked? If so, we need to hide our header text.
244 + if ( ! get_theme_mod( 'site_logo_header_text', 1 ) ) {
245 + $classes = $this->header_text_classes();
246 + ?>
247 + <!-- Site Logo: hide header text -->
248 + <style type="text/css">
249 + <?php echo jetpack_sanitize_header_text_classes( $classes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> {
250 + position: absolute;
251 + clip: rect(1px, 1px, 1px, 1px);
252 + }
253 + </style>
254 + <?php
255 + }
256 + }
257 +
258 + /**
259 + * Determine image size to use for the logo.
260 + *
261 + * @uses get_theme_support()
262 + * @return string Size specified in add_theme_support declaration, or 'thumbnail' default
263 + */
264 + public function theme_size() {
265 + $args = get_theme_support( 'site-logo' );
266 + $valid_sizes = get_intermediate_image_sizes();
267 +
268 + // Add 'full' to the list of accepted values.
269 + $valid_sizes[] = 'full';
270 +
271 + // If the size declared in add_theme_support is valid, use it; otherwise, just go with 'thumbnail'.
272 + $size = ( isset( $args[0]['size'] ) && in_array( $args[0]['size'], $valid_sizes, true ) ) ? $args[0]['size'] : 'thumbnail';
273 +
274 + return $size;
275 + }
276 +
277 + /**
278 + * Make custom image sizes available to the media manager.
279 + *
280 + * @param array $sizes List of image sizes.
281 + * @uses get_intermediate_image_sizes()
282 + * @return array All default and registered custom image sizes.
283 + */
284 + public function media_manager_image_sizes( $sizes ) {
285 + // Get an array of all registered image sizes.
286 + $intermediate = get_intermediate_image_sizes();
287 +
288 + // Have we got anything fun to work with?
289 + if ( is_array( $intermediate ) && ! empty( $intermediate ) ) {
290 + foreach ( $intermediate as $size ) {
291 + // If the size isn't already in the $sizes array, add it.
292 + if ( ! array_key_exists( $size, $sizes ) ) {
293 + $sizes[ $size ] = $size;
294 + }
295 + }
296 + }
297 +
298 + return $sizes;
299 + }
300 +
301 + /**
302 + * Add site logos to media states in the Media Manager.
303 + *
304 + * @param array $media_states An array of media states.
305 + *
306 + * @return array The current attachment's media states.
307 + */
308 + public function add_media_state( $media_states ) {
309 + // Only bother testing if we have a site logo set.
310 + if ( $this->has_site_logo() ) {
311 + global $post;
312 +
313 + // If our attachment ID and the site logo ID match, this image is the site logo.
314 + if ( $post && $post->ID === $this->logo ) {
315 + $media_states[] = __( 'Site Logo', 'jetpack' );
316 + }
317 + }
318 +
319 + return $media_states;
320 + }
321 +
322 + /**
323 + * Reset the site logo if the current logo is deleted in the media manager.
324 + *
325 + * @param int $post_id Attachment ID.
326 + * @uses Site_Logo::remove_site_logo()
327 + */
328 + public function reset_on_attachment_delete( $post_id ) {
329 + if ( $this->logo === $post_id ) {
330 + $this->remove_site_logo();
331 + }
332 + }
333 +
334 + /**
335 + * Determine if a site logo is assigned or not.
336 + *
337 + * @uses Site_Logo::$logo
338 + * @return boolean True if there is an active logo, false otherwise
339 + */
340 + public function has_site_logo() {
341 + return (bool) $this->logo;
342 + }
343 +
344 + /**
345 + * Reset the site logo option to zero (empty).
346 + *
347 + * @uses update_option()
348 + */
349 + public function remove_site_logo() {
350 + update_option( 'site_logo', null );
351 + }
352 +
353 + /**
354 + * Adds custom classes to the array of body classes.
355 + *
356 + * @uses Site_Logo::has_site_logo()
357 + * @param array $classes Classes for the body element.
358 + * @return array Array of <body> classes
359 + */
360 + public function body_classes( $classes ) {
361 + // Add a class if a Site Logo is active
362 + if ( $this->has_site_logo() ) {
363 + $classes[] = 'has-site-logo';
364 + }
365 +
366 + return $classes;
367 + }
368 +
369 + /**
370 + * Sanitize our header text Customizer setting.
371 + *
372 + * @param mixed $input The input value to sanitize.
373 + * @return bool|string 1 if checked, empty string if not checked.
374 + */
375 + public function sanitize_checkbox( $input ) {
376 + return ( 1 === (int) $input ) ? 1 : '';
377 + }
378 +
379 + /**
380 + * Validate and sanitize a new site logo setting.
381 + *
382 + * @param mixed $input Logo setting value to sanitize.
383 + * @return int Attachment post ID, or 0 if invalid.
384 + */
385 + public function sanitize_logo_setting( $input ) {
386 + $input = absint( $input );
387 +
388 + // If the new setting doesn't point to a valid attachment, just reset the whole thing.
389 + if ( false === wp_get_attachment_image_src( $input ) ) {
390 + $input = 0;
391 + }
392 +
393 + return $input;
394 + }
395 +
396 + /**
397 + * This function returns the updated HTML in the Customizer preview when the logo is added, updated, or removed.
398 + *
399 + * @return string
400 + */
401 + public function customizer_preview() {
402 + ob_start();
403 + jetpack_the_site_logo();
404 + return ob_get_clean();
405 + }
406 +}
407 +
408 +// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file.
409 +
410 +/**
411 + * Allow themes and plugins to access Site_Logo methods and properties.
412 + *
413 + * @uses Site_Logo::instance()
414 + * @return object Site_Logo
415 + */
416 +function site_logo() {
417 + return Site_Logo::instance();
418 +}
419 +
420 +/**
421 + * One site logo, please.
422 + */
423 +site_logo();