PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
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 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
jetpack / modules / theme-tools / site-logo / inc / class-site-logo.php

class-site-logo.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.1, at modules/theme-tools/site-logo/inc/class-site-logo.php

424 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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();
424