PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.0-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.0-beta
16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / theme-tools / site-logo / inc / class-site-logo.php
jetpack / modules / theme-tools / site-logo / inc Last commit date
class-site-logo.php 7 months ago compat.php 5 years ago functions.php 1 year ago
class-site-logo.php
424 lines
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