-
Notifications
You must be signed in to change notification settings - Fork 144
/
post-stylesheets.php
424 lines (355 loc) · 15.5 KB
/
post-stylesheets.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
<?php
/**
* Post Stylesheets - A WordPress script for post-specific stylesheets.
*
* Post Stylesheets allows users and developers to add unique, per-post stylesheets. This script was
* created so that custom stylesheet files could be dropped into a theme folder or sub-folder and loaded
* for individual posts using the 'Stylesheet' post meta key and the stylesheet name as the post meta
* value. Custom stylesheets must have the 'Style Name: Value' header.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* @package PostStylesheets
* @version 0.6.0
* @author Justin Tadlock <justin@justintadlock.com>
* @copyright Copyright (c) 2010 - 2013, Justin Tadlock
* @link http://justintadlock.com
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
/* Register metadata with WordPress. */
add_action( 'init', 'post_stylesheets_register_meta' );
/* Add post type support for the 'post-stylesheets' feature. */
add_action( 'init', 'post_stylesheets_add_post_type_support' );
add_action( 'init', 'post_stylesheets_remove_post_type_support' );
/* Filters stylesheet_uri with a function for adding a new style. */
add_filter( 'stylesheet_uri', 'post_stylesheets_stylesheet_uri', 10, 2 );
/* Admin setup for the 'post-stylesheets' feature. */
add_action( 'admin_menu', 'post_stylesheets_admin_setup' );
/**
* Registers the post stylesheets meta key ('Stylesheet') for posts and provides a function to sanitize
* the metadata on update.
*
* @since 0.3.0
* @access public
* @return void
*/
function post_stylesheets_register_meta() {
register_meta( 'post', post_stylesheets_get_meta_key(), 'post_stylesheets_sanitize_meta' );
}
/**
* Callback function for sanitizing meta when add_metadata() or update_metadata() is called by WordPress.
* If a developer wants to set up a custom method for sanitizing the data, they should use the
* "sanitize_{$meta_type}_meta_{$meta_key}" filter hook to do so.
*
* @since 0.3.0
* @access public
* @param mixed $meta_value The value of the data to sanitize.
* @param string $meta_key The meta key name.
* @param string $meta_type The type of metadata (post, comment, user, etc.)
* @return mixed $meta_value
*/
function post_stylesheets_sanitize_meta( $meta_value, $meta_key, $meta_type ) {
return esc_attr( strip_tags( $meta_value ) );
}
/**
* Adds post type support for the 'post-stylesheets' feature to all 'public' post types.
*
* @since 0.3.0
* @access public
* @return void
*/
function post_stylesheets_add_post_type_support() {
/* Get all available 'public' post types. */
$post_types = get_post_types( array( 'public' => true ) );
/* Loop through each of the public post types and add support for post stylesheets. */
foreach ( $post_types as $type )
add_post_type_support( $type, 'post-stylesheets' );
}
/**
* Removes post stylesheets support for certain post types created by plugins.
*
* @since 0.3.0
* @access public
* @return void
*/
function post_stylesheets_remove_post_type_support() {
/* Removes post stylesheets support of the bbPress 'topic' post type. */
if ( function_exists( 'bbp_get_topic_post_type' ) )
remove_post_type_support( bbp_get_topic_post_type(), 'post-stylesheets' );
/* Removes post stylesheets support of the bbPress 'reply' post type. */
if ( function_exists( 'bbp_get_reply_post_type' ) )
remove_post_type_support( bbp_get_reply_post_type(), 'post-stylesheets' );
}
/**
* Checks if a post (or any post type) has the given meta key of 'Stylesheet' when on the singular view of
* the post on the front of the site. If found, the function checks within the '/css' folder of the stylesheet
* directory (child theme) and the template directory (parent theme). If the file exists, it is used rather
* than the typical style.css file.
*
* @since 0.1.0
* @todo Use features from Ticket #18302 when available. http://core.trac.wordpress.org/ticket/18302
* @access public
* @param string $stylesheet_uri The URI of the active theme's stylesheet.
* @param string $stylesheet_dir_uri The directory URI of the active theme's stylesheet.
* @return string $stylesheet_uri
*/
function post_stylesheets_stylesheet_uri( $stylesheet_uri, $stylesheet_dir_uri ) {
/* Check if viewing a singular post. */
if ( is_singular() ) {
/* If viewing a bbPress topic, use its forum object. */
if ( function_exists( 'bbp_is_single_topic' ) && bbp_is_single_topic() )
$post = get_post( bbp_get_topic_forum_id( get_queried_object_id() ) );
/* If viewing a bbPress reply, use its forum object. */
elseif ( function_exists( 'bbp_is_single_reply' ) && bbp_is_single_reply() )
$post = get_post( bbp_get_reply_forum_id( get_queried_object_id() ) );
/* Get the queried object (post). */
else
$post = get_queried_object();
/* Check if the post type supports 'post-stylesheets' before proceeding. */
if ( post_type_supports( $post->post_type, 'post-stylesheets' ) ) {
/* Check if the user has set a value for the post stylesheet. */
$stylesheet = get_post_stylesheet( $post->ID );
/* If a meta value was given and the file exists, set $stylesheet_uri to the new file. */
if ( !empty( $stylesheet ) ) {
/* If the stylesheet is found in the child theme, use it. */
if ( file_exists( trailingslashit( get_stylesheet_directory() ) . $stylesheet ) ) {
$stylesheet_uri = trailingslashit( $stylesheet_dir_uri ) . $stylesheet;
}
/* Else, if the stylesheet is found in the parent theme, use it. */
elseif ( file_exists( trailingslashit( get_template_directory() ) . $stylesheet ) ) {
$stylesheet_uri = trailingslashit( get_template_directory_uri() ) . $stylesheet;
}
/* @deprecated 0.4.0 Back compatibility. */
else {
/* If the stylesheet is found in the child theme '/css' folder, use it. */
if ( file_exists( trailingslashit( get_stylesheet_directory() ) . "css/{$stylesheet}" ) ) {
$stylesheet_uri = trailingslashit( $stylesheet_dir_uri ) . "css/{$stylesheet}";
/* Set the post stylesheet to the correct directory. */
set_post_stylesheet( $post->ID, str_replace( get_stylesheet_directory_uri(), 'css/', $stylesheet_uri ) );
}
/* Else, if the stylesheet is found in the parent theme '/css' folder, use it. */
elseif ( file_exists( trailingslashit( get_template_directory() ) . "css/{$stylesheet}" ) ) {
$stylesheet_uri = trailingslashit( get_template_directory_uri() ) . "css/{$stylesheet}";
/* Set the post stylesheet to the correct directory. */
set_post_stylesheet( $post->ID, str_replace( get_template_directory_uri(), 'css/', $stylesheet_uri ) );
}
}
}
}
}
/* Return the stylesheet URI. */
return $stylesheet_uri;
}
/**
* Returns the post stylesheet if one is saved as post metadata.
*
* @since 0.3.0
* @access public
* @param int $post_id The ID of the post to get the stylesheet for.
* @return string Stylesheet name if given. Empty string for no stylesheet.
*/
function get_post_stylesheet( $post_id ) {
return get_post_meta( $post_id, post_stylesheets_get_meta_key(), true );
}
/**
* Adds/updates the post stylesheet for a specific post.
*
* @since 0.3.0
* @access public
* @param int $post_id The ID of the post to set the stylesheet for.
* @param string $stylesheet The filename of the stylesheet.
* @return bool True on successful update, false on failure.
*/
function set_post_stylesheet( $post_id, $stylesheet ) {
return update_post_meta( $post_id, post_stylesheets_get_meta_key(), $stylesheet );
}
/**
* Deletes a post stylesheet.
*
* @since 0.3.0
* @access public
* @param int $post_id The ID of the post to delete the stylesheet for.
* @return bool True on successful delete, false on failure.
*/
function delete_post_stylesheet( $post_id ) {
return delete_post_meta( $post_id, post_stylesheets_get_meta_key() );
}
/**
* Checks if a post has a specific post stylesheet.
*
* @since 0.3.0
* @access public
* @param string $stylesheet The filename of the stylesheet.
* @param int $post_id The ID of the post to check.
* @return bool True|False depending on whether the post has the stylesheet.
*/
function has_post_stylesheet( $stylesheet, $post_id = '' ) {
/* If no post ID is given, use WP's get_the_ID() to get it and assume we're in the post loop. */
if ( empty( $post_id ) )
$post_id = get_the_ID();
/* Return true/false based on whether the stylesheet matches. */
return ( $stylesheet == get_post_stylesheet( $post_id ) ? true : false );
}
/**
* Admin setup for the post stylesheets script.
*
* @since 0.3.0
* @access public
* @return void
*/
function post_stylesheets_admin_setup() {
/* Load the post meta boxes on the new post and edit post screens. */
add_action( 'load-post.php', 'post_stylesheets_load_meta_boxes' );
add_action( 'load-post-new.php', 'post_stylesheets_load_meta_boxes' );
}
/**
* Hooks into the 'add_meta_boxes' hook to add the post stylesheets meta box and the 'save_post' hook
* to save the metadata.
*
* @since 0.3.0
* @access public
* @return void
*/
function post_stylesheets_load_meta_boxes() {
/* Add the post stylesheets meta box on the 'add_meta_boxes' hook. */
add_action( 'add_meta_boxes', 'post_stylesheets_create_meta_box', 10, 2 );
/* Saves the post meta box data. */
add_action( 'save_post', 'post_stylesheets_meta_box_save', 10, 2 );
add_action( 'add_attachment', 'post_stylesheets_meta_box_save' );
add_action( 'edit_attachment', 'post_stylesheets_meta_box_save' );
}
/**
* Adds the post stylesheets meta box if the post type supports 'post-stylesheets' and the current user has
* permission to edit post meta.
*
* @since 0.2.0
* @access public
* @param string $post_type The post type of the current post being edited.
* @param object $post The current post object.
* @return void
*/
function post_stylesheets_create_meta_box( $post_type, $post ) {
/* Get the post styles. */
$styles = post_stylesheets_get_styles( $post_type );
/* If there are no post styles, don't show the meta box. */
if ( empty( $styles ) )
return;
/* Add the meta box if the post type supports 'post-stylesheets'. */
if ( ( post_type_supports( $post_type, 'post-stylesheets' ) ) && ( current_user_can( 'edit_post_meta', $post->ID ) || current_user_can( 'add_post_meta', $post->ID ) || current_user_can( 'delete_post_meta', $post->ID ) ) )
add_meta_box( "post-stylesheets", __( 'Stylesheet', 'hybrid-core' ), 'post_stylesheets_meta_box', $post_type, 'side', 'default' );
}
/**
* Displays the input field for entering a custom stylesheet.
*
* @since 0.2.0
* @access public
* @param object $object The post object currently being edited.
* @param array $box Specific information about the meta box being loaded.
* @return void
*/
function post_stylesheets_meta_box( $object, $box ) { ?>
<p>
<?php wp_nonce_field( basename( __FILE__ ), 'post-stylesheets-nonce' ); ?>
<?php $styles = post_stylesheets_get_styles( $object->post_type ); ?>
<select name="post-stylesheets" id="post-stylesheets" class="widefat">
<option value=""></option>
<?php if ( !empty( $styles ) ) {
foreach ( $styles as $label => $file ) { ?>
<option value="<?php echo esc_attr( $file ); ?>" <?php selected( get_post_stylesheet( $object->ID ), esc_attr( $file ) ); ?>><?php echo esc_html( $label ); ?></option>
<?php }
} ?>
</select>
</p>
<?php
}
/**
* Saves the user-selected post stylesheet on the 'save_post' hook.
*
* @since 0.2.0
* @access public
* @param int $post_id The ID of the current post being saved.
* @param object $post The post object currently being saved.
*/
function post_stylesheets_meta_box_save( $post_id, $post = '' ) {
/* Fix for attachment save issue in WordPress 3.5. @link http://core.trac.wordpress.org/ticket/21963 */
if ( !is_object( $post ) )
$post = get_post();
/* Verify the nonce before proceeding. */
if ( !isset( $_POST['post-stylesheets-nonce'] ) || !wp_verify_nonce( $_POST['post-stylesheets-nonce'], basename( __FILE__ ) ) )
return;
/* Check if the post type supports 'post-stylesheets'. */
if ( !post_type_supports( $post->post_type, 'post-stylesheets' ) )
return;
/* Get the meta key. */
$meta_key = post_stylesheets_get_meta_key();
/* Get the previous post stylesheet. */
$meta_value = get_post_stylesheet( $post_id );
/* Get the submitted post stylesheet. */
$new_meta_value = $_POST['post-stylesheets'];
/* If there is no new meta value but an old value exists, delete it. */
if ( current_user_can( 'delete_post_meta', $post_id, $meta_key ) && '' == $new_meta_value && $meta_value )
delete_post_stylesheet( $post_id );
/* If a new meta value was added and there was no previous value, add it. */
elseif ( current_user_can( 'add_post_meta', $post_id, $meta_key ) && $new_meta_value && '' == $meta_value )
set_post_stylesheet( $post_id, $new_meta_value );
/* If the old layout doesn't match the new layout, update the post layout meta. */
elseif ( current_user_can( 'edit_post_meta', $post_id, $meta_key ) && $meta_value !== $new_meta_value )
set_post_stylesheet( $post_id, $new_meta_value );
}
/**
* Gets the stylesheet files within the parent or child theme and checks if they have the 'Style Name'
* header. If any files are found, they are returned in an array.
*
* @since 0.4.0
* @access public
* @global array $_post_stylesheets Array of post-type specific stylesheets.
* @return array
*/
function post_stylesheets_get_styles( $post_type = 'post' ) {
global $_post_stylesheets;
/* If stylesheets have already been loaded, return them. */
if ( !empty( $_post_stylesheets ) && isset( $_post_stylesheets[ $post_type ] ) )
return $_post_stylesheets[ $post_type ];
/* Set up an empty styles array. */
$_post_stylesheets[ $post_type ] = array();
/* Get the theme object. */
$theme = wp_get_theme();
/* Get the theme CSS files two levels deep. */
$files = (array) $theme->get_files( 'css', 2, true );
/* Loop through each of the CSS files and check if they are styles. */
foreach ( $files as $file => $path ) {
/* Get file data based on the 'Style Name' header. */
$headers = get_file_data(
$path,
array(
'Style Name' => 'Style Name',
"{$post_type} Style" => "{$post_type} Style"
)
);
/* Add the CSS filename and template name to the array. */
if ( !empty( $headers['Style Name'] ) )
$_post_stylesheets[ $post_type ][ $file ] = $headers['Style Name'];
elseif ( !empty( $headers["{$post_type} Style"] ) )
$_post_stylesheets[ $post_type ][ $file ] = $headers["{$post_type} Style"];
}
/* Flip the array of styles. */
$_post_stylesheets[ $post_type ] = array_flip( $_post_stylesheets[ $post_type ] );
/* Return array of styles. */
return $_post_stylesheets[ $post_type ];
}
/**
* Returns the meta key used by the script for post metadata.
*
* @since 0.3.0
* @access public
* @return string
*/
function post_stylesheets_get_meta_key() {
return apply_filters( 'post_stylesheets_meta_key', 'Stylesheet' );
}
?>