/modules/theme-tools/site-logo/inc/class-site-logo.php

  1. <?php 
  2. /** 
  3. * Our Site Logo class for managing a theme-agnostic logo through the Customizer. 
  4. * 
  5. * @package Jetpack 
  6. */ 
  7. class Site_Logo { 
  8. /** 
  9. * Stores our single instance. 
  10. */ 
  11. private static $instance; 
  12.  
  13. /** 
  14. * Stores our current logo settings. 
  15. */ 
  16. public $logo; 
  17.  
  18. /** 
  19. * Return our instance, creating a new one if necessary. 
  20. * 
  21. * @uses Site_Logo::$instance 
  22. * @return object Site_Logo 
  23. */ 
  24. public static function instance() { 
  25. if ( ! isset( self::$instance ) ) { 
  26. self::$instance = new Site_Logo; 
  27. self::$instance->register_hooks(); 
  28.  
  29. return self::$instance; 
  30.  
  31. /** 
  32. * Get our current logo settings stored in options. 
  33. * 
  34. * @uses get_option() 
  35. */ 
  36. private function __construct() { 
  37. $this->logo = get_option( 'site_logo', null ); 
  38.  
  39. /** 
  40. * Register our actions and filters. 
  41. * 
  42. * @uses Site_Logo::head_text_styles() 
  43. * @uses Site_Logo::customize_register() 
  44. * @uses Site_Logo::preview_enqueue() 
  45. * @uses Site_Logo::body_classes() 
  46. * @uses Site_Logo::media_manager_image_sizes() 
  47. * @uses add_action 
  48. * @uses add_filter 
  49. */ 
  50. public function register_hooks() { 
  51. add_action( 'wp_head', array( $this, 'head_text_styles' ) ); 
  52. add_action( 'customize_register', array( $this, 'customize_register' ) ); 
  53. add_action( 'customize_preview_init', array( $this, 'preview_enqueue' ) ); 
  54. add_action( 'delete_attachment', array( $this, 'reset_on_attachment_delete' ) ); 
  55. add_filter( 'body_class', array( $this, 'body_classes' ) ); 
  56. add_filter( 'image_size_names_choose', array( $this, 'media_manager_image_sizes' ) ); 
  57. add_filter( 'display_media_states', array( $this, 'add_media_state' ) ); 
  58.  
  59. /** 
  60. * Add our logo uploader to the Customizer. 
  61. * 
  62. * @param object $wp_customize Customizer object. 
  63. * @uses current_theme_supports() 
  64. * @uses current_theme_supports() 
  65. * @uses WP_Customize_Manager::add_setting() 
  66. * @uses WP_Customize_Manager::add_control() 
  67. * @uses Site_Logo::sanitize_checkbox() 
  68. */ 
  69. public function customize_register( $wp_customize ) { 
  70. // Include our custom control. 
  71. require( dirname( __FILE__ ) . '/class-site-logo-control.php' ); 
  72.  
  73. //Update the Customizer section title for discoverability. 
  74. $wp_customize->get_section('title_tagline')->title = __( 'Site Title, Tagline, and Logo', 'jetpack' ); 
  75.  
  76. // Add a setting to hide header text if the theme isn't supporting the feature itself 
  77. if ( ! current_theme_supports( 'custom-header' ) ) { 
  78. $wp_customize->add_setting( 'site_logo_header_text', array( 
  79. 'default' => 1,  
  80. 'sanitize_callback' => array( $this, 'sanitize_checkbox' ),  
  81. 'transport' => 'postMessage',  
  82. ) ); 
  83.  
  84. $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'site_logo_header_text', array( 
  85. 'label' => __( 'Display Header Text', 'jetpack' ),  
  86. 'section' => 'title_tagline',  
  87. 'settings' => 'site_logo_header_text',  
  88. 'type' => 'checkbox',  
  89. ) ) ); 
  90.  
  91. // Add the setting for our logo value. 
  92. $wp_customize->add_setting( 'site_logo', array( 
  93. 'capability' => 'manage_options',  
  94. 'default' => array( 
  95. 'id' => 0,  
  96. 'sizes' => array(),  
  97. 'url' => false,  
  98. ),  
  99. 'sanitize_callback' => array( $this, 'sanitize_logo_setting' ),  
  100. 'transport' => 'postMessage',  
  101. 'type' => 'option',  
  102. ) ); 
  103.  
  104. // Add our image uploader. 
  105. $wp_customize->add_control( new Site_Logo_Image_Control( $wp_customize, 'site_logo', array( 
  106. 'label' => __( 'Logo', 'jetpack' ),  
  107. 'section' => 'title_tagline',  
  108. 'settings' => 'site_logo',  
  109. ) ) ); 
  110.  
  111. /** 
  112. * Enqueue scripts for the Customizer live preview. 
  113. * 
  114. * @uses wp_enqueue_script() 
  115. * @uses plugins_url() 
  116. * @uses current_theme_supports() 
  117. * @uses Site_Logo::header_text_classes() 
  118. * @uses wp_localize_script() 
  119. */ 
  120. public function preview_enqueue() { 
  121. wp_enqueue_script( 'site-logo-preview', plugins_url( '../js/site-logo.js', __FILE__ ), array( 'media-views' ), '', true ); 
  122.  
  123. // Don't bother passing in header text classes if the theme supports custom headers. 
  124. if ( ! current_theme_supports( 'custom-header' ) ) { 
  125. $classes = jetpack_sanitize_header_text_classes( $this->header_text_classes() ); 
  126. wp_enqueue_script( 'site-logo-header-text', plugins_url( '../js/site-logo-header-text.js', __FILE__ ), array( 'media-views' ), '', true ); 
  127. wp_localize_script( 'site-logo-header-text', 'site_logo_header_classes', $classes ); 
  128.  
  129. /** 
  130. * Get header text classes. If not defined in add_theme_support(), defaults from Underscores will be used. 
  131. * 
  132. * @uses get_theme_support 
  133. * @return string String of classes to hide 
  134. */ 
  135. public function header_text_classes() { 
  136. $args = get_theme_support( 'site-logo' ); 
  137.  
  138. if ( isset( $args[0][ 'header-text' ] ) ) { 
  139. // Use any classes defined in add_theme_support(). 
  140. $classes = $args[0][ 'header-text' ]; 
  141. } else { 
  142. // Otherwise, use these defaults, which will work with any Underscores-based theme. 
  143. $classes = array( 
  144. 'site-title',  
  145. 'site-description',  
  146. ); 
  147.  
  148. // If we've got an array, reduce them to a string for output 
  149. if ( is_array( $classes ) ) { 
  150. $classes = (string) '.' . implode( ', .', $classes ); 
  151. } else { 
  152. $classes = (string) '.' . $classes; 
  153.  
  154. return $classes; 
  155.  
  156. /** 
  157. * Hide header text on front-end if necessary. 
  158. * 
  159. * @uses current_theme_supports() 
  160. * @uses get_theme_mod() 
  161. * @uses Site_Logo::header_text_classes() 
  162. * @uses esc_html() 
  163. */ 
  164. public function head_text_styles() { 
  165. // Bail if our theme supports custom headers. 
  166. if ( current_theme_supports( 'custom-header' ) ) { 
  167. return; 
  168.  
  169. // Is Display Header Text unchecked? If so, we need to hide our header text. 
  170. if ( ! get_theme_mod( 'site_logo_header_text', 1 ) ) { 
  171. $classes = $this->header_text_classes(); 
  172. ?> 
  173. <!-- Site Logo: hide header text --> 
  174. <style type="text/css"> 
  175. <?php echo jetpack_sanitize_header_text_classes( $classes ); ?> { 
  176. position: absolute; 
  177. clip: rect(1px, 1px, 1px, 1px); 
  178. </style> 
  179. <?php 
  180.  
  181. /** 
  182. * Determine image size to use for the logo. 
  183. * 
  184. * @uses get_theme_support() 
  185. * @return string Size specified in add_theme_support declaration, or 'thumbnail' default 
  186. */ 
  187. public function theme_size() { 
  188. $args = get_theme_support( 'site-logo' ); 
  189. $valid_sizes = get_intermediate_image_sizes(); 
  190.  
  191. // Add 'full' to the list of accepted values. 
  192. $valid_sizes[] = 'full'; 
  193.  
  194. // If the size declared in add_theme_support is valid, use it; otherwise, just go with 'thumbnail'. 
  195. $size = ( isset( $args[0]['size'] ) && in_array( $args[0]['size'], $valid_sizes ) ) ? $args[0]['size'] : 'thumbnail'; 
  196.  
  197. return $size; 
  198.  
  199. /** 
  200. * Make custom image sizes available to the media manager. 
  201. * 
  202. * @param array $sizes 
  203. * @uses get_intermediate_image_sizes() 
  204. * @return array All default and registered custom image sizes. 
  205. */ 
  206. public function media_manager_image_sizes( $sizes ) { 
  207. // Get an array of all registered image sizes. 
  208. $intermediate = get_intermediate_image_sizes(); 
  209.  
  210. // Have we got anything fun to work with? 
  211. if ( is_array( $intermediate ) && ! empty( $intermediate ) ) { 
  212. foreach ( $intermediate as $key => $size ) { 
  213. // If the size isn't already in the $sizes array, add it. 
  214. if ( ! array_key_exists( $size, $sizes ) ) { 
  215. $sizes[ $size ] = $size; 
  216.  
  217. return $sizes; 
  218.  
  219. /** 
  220. * Add site logos to media states in the Media Manager. 
  221. * 
  222. * @return array The current attachment's media states. 
  223. */ 
  224. public function add_media_state( $media_states ) { 
  225. // Only bother testing if we have a site logo set. 
  226. if ( $this->has_site_logo() ) { 
  227. global $post; 
  228.  
  229. // If our attachment ID and the site logo ID match, this image is the site logo. 
  230. if ( $post->ID == $this->logo['id'] ) { 
  231. $media_states[] = __( 'Site Logo', 'jetpack' ); 
  232.  
  233. return $media_states; 
  234.  
  235. /** 
  236. * Reset the site logo if the current logo is deleted in the media manager. 
  237. * 
  238. * @param int $site_id 
  239. * @uses Site_Logo::remove_site_logo() 
  240. */ 
  241. public function reset_on_attachment_delete( $post_id ) { 
  242. if ( $this->logo['id'] == $post_id ) { 
  243. $this->remove_site_logo(); 
  244.  
  245. /** 
  246. * Determine if a site logo is assigned or not. 
  247. * 
  248. * @uses Site_Logo::$logo 
  249. * @return boolean True if there is an active logo, false otherwise 
  250. */ 
  251. public function has_site_logo() { 
  252. return ( isset( $this->logo['id'] ) && 0 !== $this->logo['id'] ) ? true : false; 
  253.  
  254. /** 
  255. * Reset the site logo option to zero (empty). 
  256. * 
  257. * @uses update_option() 
  258. */ 
  259. public function remove_site_logo() { 
  260. update_option( 'site_logo', array( 
  261. 'id' => (int) 0,  
  262. 'sizes' => array(),  
  263. 'url' => '',  
  264. ) ); 
  265.  
  266. /** 
  267. * Adds custom classes to the array of body classes. 
  268. * 
  269. * @uses Site_Logo::has_site_logo() 
  270. * @return array Array of <body> classes 
  271. */ 
  272. public function body_classes( $classes ) { 
  273. // Add a class if a Site Logo is active 
  274. if ( $this->has_site_logo() ) { 
  275. $classes[] = 'has-site-logo'; 
  276.  
  277. return $classes; 
  278.  
  279. /** 
  280. * Sanitize our header text Customizer setting. 
  281. * 
  282. * @param $input 
  283. * @return mixed 1 if checked, empty string if not checked. 
  284. */ 
  285. public function sanitize_checkbox( $input ) { 
  286. return ( 1 == $input ) ? 1 : ''; 
  287.  
  288. /** 
  289. * Validate and sanitize a new site logo setting. 
  290. * 
  291. * @param $input 
  292. * @return mixed 1 if checked, empty string if not checked. 
  293. */ 
  294. public function sanitize_logo_setting( $input ) { 
  295. $input['id'] = absint( $input['id'] ); 
  296. $input['url'] = esc_url_raw( $input['url'] ); 
  297.  
  298. // If the new setting doesn't point to a valid attachment, just reset the whole thing. 
  299. if ( false == wp_get_attachment_image_src( $input['id'] ) ) { 
  300. $input = array( 
  301. 'id' => (int) 0,  
  302. 'sizes' => array(),  
  303. 'url' => '',  
  304. ); 
  305.  
  306. return $input; 
  307.  
  308. /** 
  309. * Allow themes and plugins to access Site_Logo methods and properties. 
  310. * 
  311. * @uses Site_Logo::instance() 
  312. * @return object Site_Logo 
  313. */ 
  314. function site_logo() { 
  315. return Site_Logo::instance(); 
  316.  
  317. /** 
  318. * One site logo, please. 
  319. */ 
  320. site_logo(); 
.