PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 12.6.4
Jetpack – WP Security, Backup, Speed, & Growth v12.6.4
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 13.7.2 13.8.3 All 506 releases
jetpack / modules / theme-tools / site-logo / inc / class-site-logo.php

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

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