PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/themes/news/library/extensions/theme-layouts.php

https://bitbucket.org/lgorence/quickpress
PHP | 553 lines | 172 code | 95 blank | 286 comment | 36 complexity | 6bc900d1e22e7a9008530cd54439d90a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-1.0
  1. <?php
  2. /**
  3. * Theme Layouts - A WordPress script for creating dynamic layouts.
  4. *
  5. * Theme Layouts was created to allow theme developers to easily style themes with dynamic layout
  6. * structures. It gives users the ability to control how each post (or any post type) is displayed on the
  7. * front end of the site. The layout can also be filtered for any page of a WordPress site.
  8. *
  9. * The script will filter the WordPress body_class to provide a layout class for the given page. Themes
  10. * must support this hook or its accompanying body_class() function for the Theme Layouts script to work.
  11. * Themes must also handle the CSS based on the layout class. This script merely provides the logic. The
  12. * design should be handled on a theme-by-theme basis.
  13. *
  14. * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
  15. * General Public License as published by the Free Software Foundation; either version 2 of the License,
  16. * or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  19. * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  20. *
  21. * @package ThemeLayouts
  22. * @version 0.4.0
  23. * @author Justin Tadlock <justin@justintadlock.com>
  24. * @copyright Copyright (c) 2010 - 2012, Justin Tadlock
  25. * @link http://justintadlock.com
  26. * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  27. */
  28. /* Register metadata with WordPress. */
  29. add_action( 'init', 'theme_layouts_register_meta' );
  30. /* Add post type support for theme layouts. */
  31. add_action( 'init', 'theme_layouts_add_post_type_support' );
  32. add_action( 'init', 'theme_layouts_remove_post_type_support' );
  33. /* Set up the custom post layouts. */
  34. add_action( 'admin_menu', 'theme_layouts_admin_setup' );
  35. /* Filters the body_class hook to add a custom class. */
  36. add_filter( 'body_class', 'theme_layouts_body_class' );
  37. /**
  38. * Registers the theme layouts meta key ('Layout') for specific object types and provides a function to sanitize
  39. * the metadata on update.
  40. *
  41. * @since 0.4.0
  42. * @return void
  43. */
  44. function theme_layouts_register_meta() {
  45. register_meta( 'post', theme_layouts_get_meta_key(), 'theme_layouts_sanitize_meta' );
  46. register_meta( 'user', theme_layouts_get_meta_key(), 'theme_layouts_sanitize_meta' );
  47. }
  48. /**
  49. * Callback function for sanitizing meta when add_metadata() or update_metadata() is called by WordPress.
  50. * If a developer wants to set up a custom method for sanitizing the data, they should use the
  51. * "sanitize_{$meta_type}_meta_{$meta_key}" filter hook to do so.
  52. *
  53. * @since 0.4.0
  54. * @param mixed $meta_value The value of the data to sanitize.
  55. * @param string $meta_key The meta key name.
  56. * @param string $meta_type The type of metadata (post, comment, user, etc.)
  57. * @return mixed $meta_value
  58. */
  59. function theme_layouts_sanitize_meta( $meta_value, $meta_key, $meta_type ) {
  60. return esc_attr( strip_tags( $meta_value ) );
  61. }
  62. /**
  63. * Adds post type support to all 'public' post types. This allows themes to remove support for the 'theme-layouts'
  64. * feature with remove_post_type_support().
  65. *
  66. * @since 0.4.0
  67. * @return void
  68. */
  69. function theme_layouts_add_post_type_support() {
  70. /* Gets available public post types. */
  71. $post_types = get_post_types( array( 'public' => true ) );
  72. /* For each available post type, create a meta box on its edit page if it supports '$prefix-post-settings'. */
  73. foreach ( $post_types as $type )
  74. add_post_type_support( $type, 'theme-layouts' );
  75. }
  76. /**
  77. * Removes theme layouts support from specific post types created by plugins.
  78. *
  79. * @since 0.4.0
  80. * @return void
  81. */
  82. function theme_layouts_remove_post_type_support() {
  83. /* Removes theme layouts support of the bbPress 'reply' post type. */
  84. if ( function_exists( 'bbp_get_reply_post_type' ) )
  85. remove_post_type_support( bbp_get_reply_post_type(), 'theme-layouts' );
  86. }
  87. /**
  88. * Gets the layout for the current post based off the 'Layout' custom field key if viewing a singular post
  89. * entry. All other pages are given a default layout of 'layout-default'.
  90. *
  91. * @since 0.2.0
  92. * @return string The layout for the given page.
  93. */
  94. function theme_layouts_get_layout() {
  95. /* Get the available post layouts. */
  96. $post_layouts = get_theme_support( 'theme-layouts' );
  97. /* Set the layout to an empty string. */
  98. $layout = '';
  99. /* If viewing a singular post, check if a layout has been specified. */
  100. if ( is_singular() ) {
  101. /* Get the current post ID. */
  102. $post_id = get_queried_object_id();
  103. /* Get the post layout. */
  104. $layout = get_post_layout( $post_id );
  105. }
  106. /* If viewing a user/author archive, check if a layout has been specified. */
  107. elseif ( is_author() ) {
  108. /* Get the current user ID. */
  109. $user_id = get_queried_object_id();
  110. /* Get the user layout. */
  111. $layout = get_user_layout( $user_id );
  112. }
  113. /* Make sure the given layout is in the array of available post layouts for the theme. */
  114. if ( empty( $layout ) || !in_array( $layout, $post_layouts[0] ) )
  115. $layout = 'default';
  116. /* If the theme set a default layout, use it if the layout should be set to default. */
  117. if ( 'default' == $layout && !empty( $post_layouts[1] ) && isset( $post_layouts[1]['default'] ) )
  118. $layout = $post_layouts[1]['default'];
  119. /* @deprecated 0.2.0. Use the 'get_theme_layout' hook. */
  120. $layout = apply_filters( 'get_post_layout', "layout-{$layout}" );
  121. /* Return the layout and allow plugin/theme developers to override it. */
  122. return esc_attr( apply_filters( 'get_theme_layout', $layout ) );
  123. }
  124. /**
  125. * Get the post layout based on the given post ID.
  126. *
  127. * @since 0.2.0
  128. * @param int $post_id The ID of the post to get the layout for.
  129. * @return string $layout The name of the post's layout.
  130. */
  131. function get_post_layout( $post_id ) {
  132. /* Get the post layout. */
  133. $layout = get_post_meta( $post_id, theme_layouts_get_meta_key(), true );
  134. /* Return the layout if one is found. Otherwise, return 'default'. */
  135. return ( !empty( $layout ) ? $layout : 'default' );
  136. }
  137. /**
  138. * Update/set the post layout based on the given post ID and layout.
  139. *
  140. * @since 0.2.0
  141. * @param int $post_id The ID of the post to set the layout for.
  142. * @param string $layout The name of the layout to set.
  143. * @return bool True on successful update, false on failure.
  144. */
  145. function set_post_layout( $post_id, $layout ) {
  146. return update_post_meta( $post_id, theme_layouts_get_meta_key(), $layout );
  147. }
  148. /**
  149. * Deletes a post layout.
  150. *
  151. * @since 0.4.0
  152. * @access public
  153. * @param int $post_id The ID of the post to delete the layout for.
  154. * @return bool True on successful delete, false on failure.
  155. */
  156. function delete_post_layout( $post_id ) {
  157. return delete_post_meta( $post_id, theme_layouts_get_meta_key() );
  158. }
  159. /**
  160. * Checks if a specific post's layout matches that of the given layout.
  161. *
  162. * @since 0.3.0
  163. * @param string $layout The name of the layout to check if the post has.
  164. * @param int $post_id The ID of the post to check the layout for.
  165. * @return bool Whether the given layout matches the post's layout.
  166. */
  167. function has_post_layout( $layout, $post_id = '' ) {
  168. /* If no post ID is given, use WP's get_the_ID() to get it and assume we're in the post loop. */
  169. if ( empty( $post_id ) )
  170. $post_id = get_the_ID();
  171. /* Return true/false based on whether the layout matches. */
  172. return ( $layout == get_post_layout( $post_id ) ? true : false );
  173. }
  174. /**
  175. * Get the layout for a user/author archive page based on a specific user ID.
  176. *
  177. * @since 0.3.0
  178. * @param int $user_id The ID of the user to get the layout for.
  179. * @return string The layout if one exists, 'default' if one doesn't.
  180. */
  181. function get_user_layout( $user_id ) {
  182. /* Get the user layout. */
  183. $layout = get_user_meta( $user_id, theme_layouts_get_meta_key(), true );
  184. /* Return the layout if one is found. Otherwise, return 'default'. */
  185. return ( !empty( $layout ) ? $layout : 'default' );
  186. }
  187. /**
  188. * Update/set the layout for a user/author archive paged based on the user ID.
  189. *
  190. * @since 0.3.0
  191. * @param int $user_id The ID of the user to set the layout for.
  192. * @param string $layout The name of the layout to set.
  193. * @return bool True on successful update, false on failure.
  194. */
  195. function set_user_layout( $user_id, $layout ) {
  196. return update_user_meta( $user_id, theme_layouts_get_meta_key(), $layout );
  197. }
  198. /**
  199. * Deletes a user layout.
  200. *
  201. * @since 0.4.0
  202. * @access public
  203. * @param int $user_id The ID of the user to delete the layout for.
  204. * @return bool True on successful delete, false on failure.
  205. */
  206. function delete_user_layout( $user_id ) {
  207. return delete_user_meta( $user_id, theme_layouts_get_meta_key() );
  208. }
  209. /**
  210. * Checks if a specific user's layout matches that of the given layout.
  211. *
  212. * @since 0.3.0
  213. * @param string $layout The name of the layout to check if the user has.
  214. * @param int $user_id The ID of the user to check the layout for.
  215. * @return bool Whether the given layout matches the user's layout.
  216. */
  217. function has_user_layout( $layout, $user_id = '' ) {
  218. /* If no user ID is given, assume we're viewing an author archive page and get the user ID. */
  219. if ( empty( $user_id ) )
  220. $user_id = get_query_var( 'author' );
  221. /* Return true/false based on whether the layout matches. */
  222. return ( $layout == get_user_layout( $user_id ) ? true : false );
  223. }
  224. /**
  225. * Adds the post layout class to the WordPress body class in the form of "layout-$layout". This allows
  226. * theme developers to design their theme layouts based on the layout class. If designing a theme with
  227. * this extension, the theme should make sure to handle all possible layout classes.
  228. *
  229. * @since 0.2.0
  230. * @param array $classes
  231. * @param array $classes
  232. */
  233. function theme_layouts_body_class( $classes ) {
  234. /* Adds the layout to array of body classes. */
  235. $classes[] = sanitize_html_class( theme_layouts_get_layout() );
  236. /* Return the $classes array. */
  237. return $classes;
  238. }
  239. /**
  240. * Creates default text strings based on the default post layouts. Theme developers that add custom
  241. * layouts should filter 'post_layouts_strings' to add strings to match the custom layouts, but it's not
  242. * required. The layout name will be used if no text string is found.
  243. *
  244. * @since 0.2.0
  245. * @return array $strings
  246. */
  247. function theme_layouts_strings() {
  248. /* Set up the default layout strings. */
  249. $strings = array(
  250. 'default' => __( 'Default', 'theme-layouts' ),
  251. '1c' => __( 'One Column', 'theme-layouts' ),
  252. '2c-l' => __( 'Two Columns, Left', 'theme-layouts' ),
  253. '2c-r' => __( 'Two Columns, Right', 'theme-layouts' ),
  254. '3c-l' => __( 'Three Columns, Left', 'theme-layouts' ),
  255. '3c-r' => __( 'Three Columns, Right', 'theme-layouts' ),
  256. '3c-c' => __( 'Three Columns, Center', 'theme-layouts' )
  257. );
  258. /* Allow devs to filter the strings for custom layouts. */
  259. return apply_filters( 'theme_layouts_strings', $strings );
  260. }
  261. /**
  262. * Get a specific layout's text string.
  263. *
  264. * @since 0.2.0
  265. * @param string $layout
  266. * @return string
  267. */
  268. function theme_layouts_get_string( $layout ) {
  269. /* Get an array of post layout strings. */
  270. $strings = theme_layouts_strings();
  271. /* Return the layout's string if it exists. Else, return the layout slug. */
  272. return ( ( isset( $strings[$layout] ) ) ? $strings[$layout] : $layout );
  273. }
  274. /**
  275. * Post layouts admin setup. Registers the post layouts meta box for the post editing screen. Adds the
  276. * metadata save function to the 'save_post' hook.
  277. *
  278. * @since 0.2.0
  279. * @return void
  280. */
  281. function theme_layouts_admin_setup() {
  282. /* Load the post meta boxes on the new post and edit post screens. */
  283. add_action( 'load-post.php', 'theme_layouts_load_meta_boxes' );
  284. add_action( 'load-post-new.php', 'theme_layouts_load_meta_boxes' );
  285. /* If the attachment post type supports 'theme-layouts', add form fields for it. */
  286. if ( post_type_supports( 'attachment', 'theme-layouts' ) ) {
  287. /* Adds a theme layout <select> element to the attachment edit form. */
  288. add_filter( 'attachment_fields_to_edit', 'theme_layouts_attachment_fields_to_edit', 10, 2 );
  289. /* Saves the theme layout for attachments. */
  290. add_filter( 'attachment_fields_to_save', 'theme_layouts_attachment_fields_to_save', 10, 2 );
  291. }
  292. }
  293. /**
  294. * Hooks into the 'add_meta_boxes' hook to add the theme layouts meta box and the 'save_post' hook
  295. * to save the metadata.
  296. *
  297. * @since 0.4.0
  298. * @return void
  299. */
  300. function theme_layouts_load_meta_boxes() {
  301. /* Add the layout meta box on the 'add_meta_boxes' hook. */
  302. add_action( 'add_meta_boxes', 'theme_layouts_add_meta_boxes', 10, 2 );
  303. /* Saves the post format on the post editing page. */
  304. add_action( 'save_post', 'theme_layouts_save_post', 10, 2 );
  305. }
  306. /**
  307. * Adds the theme layouts meta box if the post type supports 'theme-layouts' and the current user has
  308. * permission to edit post meta.
  309. *
  310. * @since 0.4.0
  311. * @param string $post_type The post type of the current post being edited.
  312. * @param object $post The current post object.
  313. * @return void
  314. */
  315. function theme_layouts_add_meta_boxes( $post_type, $post ) {
  316. /* Add the meta box if the post type supports 'post-stylesheets'. */
  317. if ( ( post_type_supports( $post_type, 'theme-layouts' ) ) && ( current_user_can( 'edit_post_meta', $post->ID ) || current_user_can( 'add_post_meta', $post->ID ) || current_user_can( 'delete_post_meta', $post->ID ) ) )
  318. add_meta_box( 'theme-layouts-post-meta-box', __( 'Layout', 'theme-layouts' ), 'theme_layouts_post_meta_box', $post_type, 'side', 'default' );
  319. }
  320. /**
  321. * Displays a meta box of radio selectors on the post editing screen, which allows theme users to select
  322. * the layout they wish to use for the specific post.
  323. *
  324. * @since 0.2.0
  325. * @access private
  326. * @param object $post The post object currently being edited.
  327. * @param array $box Specific information about the meta box being loaded.
  328. * @return void
  329. * @return void
  330. */
  331. function theme_layouts_post_meta_box( $post, $box ) {
  332. /* Get theme-supported theme layouts. */
  333. $layouts = get_theme_support( 'theme-layouts' );
  334. $post_layouts = $layouts[0];
  335. /* Get the current post's layout. */
  336. $post_layout = get_post_layout( $post->ID ); ?>
  337. <div class="post-layout">
  338. <?php wp_nonce_field( basename( __FILE__ ), 'theme-layouts-nonce' ); ?>
  339. <p><?php _e( 'Layout is a theme-specific structure for the single view of the post.', 'theme-layouts' ); ?></p>
  340. <div class="post-layout-wrap">
  341. <ul>
  342. <li><input type="radio" name="post-layout" id="post-layout-default" value="default" <?php checked( $post_layout, 'default' );?> /> <label for="post-layout-default"><?php echo esc_html( theme_layouts_get_string( 'default' ) ); ?></label></li>
  343. <?php foreach ( $post_layouts as $layout ) { ?>
  344. <li><input type="radio" name="post-layout" id="post-layout-<?php echo esc_attr( $layout ); ?>" value="<?php echo esc_attr( $layout ); ?>" <?php checked( $post_layout, $layout ); ?> /> <label for="post-layout-<?php echo esc_attr( $layout ); ?>"><?php echo esc_html( theme_layouts_get_string( $layout ) ); ?></label></li>
  345. <?php } ?>
  346. </ul>
  347. </div>
  348. </div><?php
  349. }
  350. /**
  351. * Saves the post layout metadata if on the post editing screen in the admin.
  352. *
  353. * @since 0.2.0
  354. * @access private
  355. * @param int $post_id The ID of the current post being saved.
  356. * @param object $post The post object currently being saved.
  357. * @return void|int
  358. */
  359. function theme_layouts_save_post( $post_id, $post ) {
  360. /* Verify the nonce for the post formats meta box. */
  361. if ( !isset( $_POST['theme-layouts-nonce'] ) || !wp_verify_nonce( $_POST['theme-layouts-nonce'], basename( __FILE__ ) ) )
  362. return $post_id;
  363. /* Get the meta key. */
  364. $meta_key = theme_layouts_get_meta_key();
  365. /* Get the previous post layout. */
  366. $meta_value = get_post_layout( $post_id );
  367. /* Get the submitted post layout. */
  368. $new_meta_value = $_POST['post-layout'];
  369. /* If there is no new meta value but an old value exists, delete it. */
  370. if ( current_user_can( 'delete_post_meta', $post_id, $meta_key ) && '' == $new_meta_value && $meta_value )
  371. delete_post_layout( $post_id );
  372. /* If a new meta value was added and there was no previous value, add it. */
  373. elseif ( current_user_can( 'add_post_meta', $post_id, $meta_key ) && $new_meta_value && '' == $meta_value )
  374. set_post_layout( $post_id, $new_meta_value );
  375. /* If the old layout doesn't match the new layout, update the post layout meta. */
  376. elseif ( current_user_can( 'edit_post_meta', $post_id, $meta_key ) && $meta_value !== $new_meta_value )
  377. set_post_layout( $post_id, $new_meta_value );
  378. }
  379. /**
  380. * Adds a select drop-down element to the attachment edit form for selecting the attachment layout.
  381. *
  382. * @since 0.3.0
  383. * @access private
  384. * @param array $fields Array of fields for the edit attachment form.
  385. * @param object $post The attachment post object.
  386. * @return array $fields
  387. */
  388. function theme_layouts_attachment_fields_to_edit( $fields, $post ) {
  389. /* Get theme-supported theme layouts. */
  390. $layouts = get_theme_support( 'theme-layouts' );
  391. $post_layouts = $layouts[0];
  392. /* Get the current post's layout. */
  393. $post_layout = get_post_layout( $post->ID );
  394. /* Set the default post layout. */
  395. $select = '<option id="post-layout-default" value="default" ' . selected( $post_layout, 'default', false ) . '>' . esc_html( theme_layouts_get_string( 'default' ) ) . '</option>';
  396. /* Loop through each theme-supported layout, adding it to the select element. */
  397. foreach ( $post_layouts as $layout )
  398. $select .= '<option id="post-layout-' . esc_attr( $layout ) . '" value="' . esc_attr( $layout ) . '" ' . selected( $post_layout, $layout, false ) . '>' . esc_html( theme_layouts_get_string( $layout ) ) . '</option>';
  399. /* Set the HTML for the post layout select drop-down. */
  400. $select = '<select name="attachments[' . $post->ID . '][theme-layouts-post-layout]" id="attachments[' . $post->ID . '][theme-layouts-post-layout]">' . $select . '</select>';
  401. /* Add the attachment layout field to the $fields array. */
  402. $fields['theme-layouts-post-layout'] = array(
  403. 'label' => __( 'Layout', 'theme-layouts' ),
  404. 'input' => 'html',
  405. 'html' => $select
  406. );
  407. /* Return the $fields array back to WordPress. */
  408. return $fields;
  409. }
  410. /**
  411. * Saves the attachment layout for the attachment edit form.
  412. *
  413. * @since 0.3.0
  414. * @access private
  415. * @param array $post The attachment post array (not the post object!).
  416. * @param array $fields Array of fields for the edit attachment form.
  417. * @return array $post
  418. */
  419. function theme_layouts_attachment_fields_to_save( $post, $fields ) {
  420. /* If the theme layouts field was submitted. */
  421. if ( isset( $fields['theme-layouts-post-layout'] ) ) {
  422. /* Get the meta key. */
  423. $meta_key = theme_layouts_get_meta_key();
  424. /* Get the previous post layout. */
  425. $meta_value = get_post_layout( $post['ID'] );
  426. /* Get the submitted post layout. */
  427. $new_meta_value = $fields['theme-layouts-post-layout'];
  428. /* If there is no new meta value but an old value exists, delete it. */
  429. if ( current_user_can( 'delete_post_meta', $post['ID'], $meta_key ) && '' == $new_meta_value && $meta_value )
  430. delete_post_layout( $post['ID'] );
  431. /* If a new meta value was added and there was no previous value, add it. */
  432. elseif ( current_user_can( 'add_post_meta', $post['ID'], $meta_key ) && $new_meta_value && '' == $meta_value )
  433. set_post_layout( $post['ID'], $new_meta_value );
  434. /* If the old layout doesn't match the new layout, update the post layout meta. */
  435. elseif ( current_user_can( 'edit_post_meta', $post['ID'], $meta_key ) && $meta_value !== $new_meta_value )
  436. set_post_layout( $post['ID'], $new_meta_value );
  437. }
  438. /* Return the attachment post array. */
  439. return $post;
  440. }
  441. /**
  442. * Wrapper function for returning the metadata key used for objects that can use layouts.
  443. *
  444. * @since 0.3.0
  445. * @access public
  446. * @return string The meta key used for theme layouts.
  447. */
  448. function theme_layouts_get_meta_key() {
  449. return apply_filters( 'theme_layouts_meta_key', 'Layout' );
  450. }
  451. /**
  452. * @since 0.1.0
  453. * @deprecated 0.2.0 Use theme_layouts_get_layout().
  454. */
  455. function post_layouts_get_layout() {
  456. return theme_layouts_get_layout();
  457. }
  458. ?>