style-packs-core.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <?php
  2. /**
  3. * Style Packs core functionality
  4. */
  5. class Style_Packs_Core {
  6. var $config;
  7. var $theme_version;
  8. var $style;
  9. static $instance;
  10. public function __construct( $config=array() ) {
  11. self::$instance = $this;
  12. if ( is_array( $config['styles'] ) && ! empty( $config['styles'] ) ) {
  13. add_action( 'after_setup_theme', array( $this, 'init' ) );
  14. add_action( 'customize_register', array( $this, 'customize_register' ) );
  15. add_action( 'customize_preview_init', array( $this, 'customize_preview' ) );
  16. add_filter( 'body_class', array( $this, 'add_body_class' ) );
  17. $this->theme_version = wp_get_theme()->get( 'Version' );
  18. $this->config = wp_parse_args( $config, array(
  19. 'body_class_format' => 'style-pack-%s',
  20. 'styles_directory' => 'styles',
  21. 'js_directory' => 'js',
  22. 'style_thumbs' => array(),
  23. 'style_descriptions' => array(),
  24. 'default_headers' => array(),
  25. 'fonts' => array(),
  26. ) );
  27. if ( ! empty( $this->config['default_headers'] ) ) {
  28. add_filter( 'theme_mod_header_image', array( $this, 'header_image_mod_filter' ), 30 );
  29. add_action( 'after_setup_theme', array( $this, 'setup_default_header_images' ) );
  30. }
  31. }
  32. }
  33. public function init() {
  34. $this->style = get_theme_mod( 'active_style_pack' );
  35. if ( is_customize_preview() ) {
  36. $preview_style = $this->get_preview_style();
  37. if ( ! empty( $preview_style ) ) {
  38. $this->style = $preview_style;
  39. }
  40. } else if ( ! empty( $this->style ) ) {
  41. add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_fonts' ), 20 );
  42. add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ), 20 );
  43. }
  44. }
  45. public function get_preview_style() {
  46. if ( is_customize_preview() ) {
  47. global $wp_customize;
  48. $data = $wp_customize->changeset_data();
  49. $theme = wp_get_theme();
  50. $mod = sprintf( '%s::active_style_pack', $theme->get_template() );
  51. if ( array_key_exists( $mod, $data ) && is_array( $data[ $mod ] ) ) {
  52. $mod_data = $data[ $mod ];
  53. if ( isset( $mod_data['type'] ) && 'theme_mod' === $mod_data['type'] ) {
  54. return $mod_data['value'];
  55. }
  56. }
  57. }
  58. return $this->style;
  59. }
  60. public function enqueue_style() {
  61. if ( array_key_exists( $this->style, $this->config['styles'] ) ) {
  62. if ( 'default' === $this->style ) {
  63. return;
  64. }
  65. $stylesheet = $this->get_stylesheet_uri( $this->style );
  66. wp_enqueue_style( $this->get_style_pack_id( $this->style ), $stylesheet, array(), $this->theme_version );
  67. }
  68. }
  69. private function get_stylesheet_uri( $style ) {
  70. return sprintf( '%s/%s/%s.css', get_template_directory_uri(), $this->config['styles_directory'], $style );
  71. }
  72. private function get_style_pack_id( $style ) {
  73. return sprintf( '%s-style-pack', $style );
  74. }
  75. private function get_font_id( $name ) {
  76. return sanitize_title( $name );
  77. }
  78. public function enqueue_fonts() {
  79. if ( is_array( $this->config['fonts'] ) && array_key_exists( $this->style, $this->config['fonts'] ) ) {
  80. $fonts = $this->config['fonts'][ $this->style ];
  81. foreach( $fonts as $font => $url ) {
  82. wp_enqueue_style( $this->get_font_id( $font ), $url, array(), null );
  83. }
  84. }
  85. }
  86. public function customize_register( $wp_customize ) {
  87. $wp_customize->add_section( 'style_pack_theme_options', array(
  88. 'title' => esc_html__( 'Style Packs', 'style-packs-theme' )
  89. ) );
  90. $wp_customize->add_setting( 'active_style_pack', array(
  91. 'sanitize_callback' => array( $this, 'sanitize_style_pack_setting' ),
  92. 'transport' => 'postMessage',
  93. 'default' => 'default',
  94. ) );
  95. $pack_choices = array_merge( array(
  96. 'default' => esc_html__( 'Default', 'style-packs-theme' ),
  97. ), $this->config['styles'] );
  98. $pack_control_options = array(
  99. 'label' => esc_html__( 'Active Style', 'style-packs-theme' ),
  100. 'section' => 'style_pack_theme_options',
  101. 'choices' => $pack_choices,
  102. );
  103. if ( $this->has_thumbs_config() ) {
  104. $pack_control_options['choices'] = $this->style_pack_customizer_thumbnails( $pack_choices );
  105. $wp_customize->add_control( new Style_Pack_Customize_Control_Radio_Image( $wp_customize, 'active_style_pack', $pack_control_options ) );
  106. } else {
  107. $pack_control_options['type'] = 'radio';
  108. $wp_customize->add_control( 'active_style_pack', $pack_control_options );
  109. }
  110. }
  111. public function has_thumbs_config() {
  112. $config = $this->config['style_thumbs'];
  113. return ! empty( $config ) && isset( $config['width'] ) && isset( $config['height'] );
  114. }
  115. public function style_pack_customizer_thumbnails( $choices ) {
  116. $config = $this->config['style_thumbs'];
  117. if ( ! empty( $config ) && isset( $config['width'] ) && isset( $config['height'] ) ) {
  118. $base = sprintf( '%s/%s', get_template_directory(), $this->config['styles_directory'] );
  119. $ext_regex = '%\.(jpe?g|png)$%i';
  120. $files = preg_grep( $ext_regex, scandir( $base ) );
  121. if ( ! empty( $files ) ) {
  122. foreach ( $files as $file ) {
  123. $id = preg_replace( $ext_regex, '', $file );
  124. if ( array_key_exists( $id, $choices ) ) {
  125. $uri = sprintf( '%s/%s/%s', get_stylesheet_directory_uri(), $this->config['styles_directory'], $file );
  126. $choices[ $id ] = sprintf( '<img alt="%s" title="%s" width="%d" height="%d" src="%s" />', esc_attr( $id ), esc_attr( $choices[ $id ] ), esc_attr( $config['width'] ), esc_attr( $config['height'] ), esc_url( $uri ) );
  127. }
  128. }
  129. }
  130. }
  131. return $choices;
  132. }
  133. public function sanitize_style_pack_setting( $input ) {
  134. if ( ! in_array( $input, array_keys( $this->config['styles'] ) ) ) {
  135. $input = 'default';
  136. }
  137. return $input;
  138. }
  139. public function customize_preview() {
  140. $customizer_js_uri = sprintf( '%s/%s/style-packs-customizer.js', get_template_directory_uri(), $this->config['js_directory'] );
  141. wp_enqueue_script( 'style-packs-customizer', $customizer_js_uri, array( 'customize-preview' ), $this->theme_version, true );
  142. $style_pack_stylesheets = array();
  143. $style_pack_fonts = array();
  144. foreach ( array_keys( $this->config['styles'] ) as $style ) {
  145. $style_data = $style_pack_stylesheets[ $style ] = array(
  146. 'id' => sprintf( '%s-css', $this->get_style_pack_id( $style ) ),
  147. 'uri' => $this->get_stylesheet_uri( $style ),
  148. );
  149. }
  150. foreach( $this->config['fonts'] as $style => $fonts ) {
  151. if ( ! empty( $fonts ) ) {
  152. $style_pack_fonts[ $style ] = array();
  153. foreach( $fonts as $font => $uri ) {
  154. $style_pack_fonts[ $style ][ sprintf( '%s-css', $this->get_font_id( $font ) ) ] = $uri;
  155. }
  156. }
  157. }
  158. $style_packs_data = array(
  159. 'body_class_format' => $this->config['body_class_format'],
  160. 'preview_style' => $this->get_preview_style(),
  161. 'styles' => $style_pack_stylesheets,
  162. 'fonts' => $style_pack_fonts,
  163. );
  164. wp_localize_script( 'style-packs-customizer', 'stylePacksData', $style_packs_data );
  165. }
  166. public function add_body_class( $classes ) {
  167. $style = 'default';
  168. if ( is_customize_preview() ) {
  169. $preview_style = $this->get_preview_style();
  170. if ( ! empty( $preview_style ) ) {
  171. $style = $preview_style;
  172. }
  173. } else if ( ! empty( $this->style ) ) {
  174. $style = $this->style;
  175. }
  176. $classes[] = sprintf( $this->config['body_class_format'], $style );
  177. return $classes;
  178. }
  179. public function header_image_mod_filter( $url ) {
  180. if ( ! is_customize_preview() ) {
  181. if ( is_string( $url ) && 'default' !== $this->style && isset( $this->config['default_headers'][ $this->style ] ) ) {
  182. $default_header = sprintf( get_theme_support( 'custom-header', 'default-image' ), get_template_directory_uri(), get_stylesheet_directory_uri() );
  183. if ( empty( $default_header ) || $url === $default_header ) {
  184. $url = $this->get_style_header_image_url( $this->style );
  185. }
  186. }
  187. }
  188. return $url;
  189. }
  190. public function get_style_header_image_url( $style ) {
  191. if ( array_key_exists( $style, $this->config['default_headers'] ) && ! empty( $this->config['default_headers'][ $style ] ) ) {
  192. return sprintf( '%s/%s/%s', get_stylesheet_directory_uri(), $this->config['styles_directory'], $this->config['default_headers'][ $style ] );
  193. } else {
  194. $default_header = get_theme_support( 'custom-header', 'default-image' );
  195. if ( ! empty( $default_header ) ) {
  196. return sprintf( $default_header, get_template_directory_uri(), get_stylesheet_directory_uri() );
  197. }
  198. }
  199. return null;
  200. }
  201. public function setup_default_header_images() {
  202. $headers = array();
  203. foreach( $this->config['default_headers'] as $style => $image ) {
  204. $image = sprintf( '%%s/%s/%s', $this->config['styles_directory'], $image );
  205. $headers[ sprintf( '%s-style-header', $style ) ] = array(
  206. 'url' => $image,
  207. 'thumbnail_url' => $image,
  208. 'description' => sprintf( __( '%s Header Image', 'style-packs-theme' ), $this->config['styles'][ $style ]),
  209. );
  210. }
  211. register_default_headers( $headers );
  212. }
  213. static function get_description( $style ) {
  214. if ( array_key_exists( $style, self::$instance->config['style_descriptions'] ) ) {
  215. return self::$instance->config['style_descriptions'][ $style ];
  216. }
  217. return null;
  218. }
  219. }
  220. if ( class_exists( 'WP_Customize_Control' ) ) :
  221. class Style_Pack_Customize_Control_Radio_Image extends WP_Customize_Control {
  222. public $type = 'style-pack-option';
  223. public function render_content() { ?>
  224. <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
  225. <?php
  226. $config = Style_Packs_Core::$instance->config;
  227. foreach( $this->choices as $key => $val ) :
  228. $name = sprintf( '_customize-style-pack-option-%s', $this->id );
  229. $desc = Style_Packs_Core::get_description( $key );
  230. $has_thumb = preg_match( '%^<img%', $val ); ?>
  231. <label<?php echo ! $has_thumb ? ' class="style-pack-radio__no-thumb"' : ''; ?>>
  232. <?php if ( $has_thumb ) : ?>
  233. <input type="radio" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $key ); ?>" <?php $this->link(); checked( $this->value() ); ?>>
  234. <?php echo wp_kses( $val, array( 'img' => array( 'alt' => array(), 'title' => array(), 'width' => array(), 'height' => array(), 'src' => array() ) ) ); ?><br>
  235. <?php else: ?>
  236. <input type="radio" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $key ); ?>" <?php $this->link(); checked( $this->value() ); ?>> <?php echo wp_kses( $val, array() ); ?><br>
  237. <?php endif; ?>
  238. <?php
  239. if ( ! empty( $desc ) ) :
  240. if ( 'default' === $key ) {
  241. if ( array_key_exists( $key, $config['styles'] ) ) {
  242. $title = $config['styles'][ $key ];
  243. } else {
  244. $title = esc_html__( 'Default' );
  245. }
  246. } else {
  247. $title = $config['styles'][ $key ];
  248. }
  249. ?>
  250. <p class="style-pack-description">
  251. <strong><?php echo esc_html( $title ) ?></strong><br/>
  252. <span><?php echo wp_kses( $desc, array() ); ?></span>
  253. </p>
  254. <?php endif; ?>
  255. </label>
  256. <?php
  257. endforeach;
  258. }
  259. public function enqueue() {
  260. add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) );
  261. }
  262. public function print_styles() { ?>
  263. <style type="text/css">
  264. .customize-control-style-pack-option label input[type="radio"] + img {
  265. vertical-align: middle;
  266. display: inline-block;
  267. margin: 0.5em 0;
  268. line-height: 1;
  269. }
  270. .customize-control-style-pack-option label input[type="radio"]:checked + img {
  271. outline: solid 6px rgba(0,0,0,0.12);
  272. }
  273. .customize-control-style-pack-option label.style-pack-radio__no-thumb {
  274. margin: 1.1em 0;
  275. display: block;
  276. }
  277. .customize-control-style-pack-option label.style-pack-radio__no-thumb input + .style-pack-description {
  278. margin-top: -1.5em;
  279. }
  280. .customize-control-style-pack-option .style-pack-description {
  281. padding-left: 1.8em;
  282. margin-top: 0.2em;
  283. max-width: 250px;
  284. }
  285. @media ( max-width: 780px ) {
  286. .customize-control-style-pack-option .style-pack-description {
  287. padding-left: 2.4em;
  288. }
  289. }
  290. </style>
  291. <?php
  292. }
  293. }
  294. endif;