PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/themes/hatch/library/functions/context.php

https://bitbucket.org/broderboy/shannonbroder-wordpress
PHP | 602 lines | 271 code | 128 blank | 203 comment | 78 complexity | 84c0ded75aa2fa4cb500f85c29809a63 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, AGPL-1.0
  1. <?php
  2. /**
  3. * Functions for making various theme elements context-aware. Controls things such as the smart
  4. * and logical body, post, and comment CSS classes as well as context-based action and filter hooks.
  5. * The functions also integrate with WordPress' implementations of body_class, post_class, and
  6. * comment_class, so your theme won't have any trouble with plugin integration.
  7. *
  8. * @package HybridCore
  9. * @subpackage Functions
  10. * @author Justin Tadlock <justin@justintadlock.com>
  11. * @copyright Copyright (c) 2008 - 2013, Justin Tadlock
  12. * @link http://themehybrid.com/hybrid-core
  13. * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  14. */
  15. /**
  16. * Hybrid's main contextual function. This allows code to be used more than once without running
  17. * hundreds of conditional checks within the theme. It returns an array of contexts based on what
  18. * page a visitor is currently viewing on the site. This function is useful for making dynamic/contextual
  19. * classes, action and filter hooks, and handling the templating system.
  20. *
  21. * Note that time and date can be tricky because any of the conditionals may be true on time-/date-
  22. * based archives depending on several factors. For example, one could load an archive for a specific
  23. * second during a specific minute within a specific hour on a specific day and so on.
  24. *
  25. * @since 0.7.0
  26. * @access public
  27. * @global $wp_query The current page's query object.
  28. * @global $hybrid The global Hybrid object.
  29. * @return array $hybrid->context Several contexts based on the current page.
  30. */
  31. function hybrid_get_context() {
  32. global $hybrid;
  33. /* If $hybrid->context has been set, don't run through the conditionals again. Just return the variable. */
  34. if ( isset( $hybrid->context ) )
  35. return apply_filters( 'hybrid_context', $hybrid->context );
  36. /* Set some variables for use within the function. */
  37. $hybrid->context = array();
  38. $object = get_queried_object();
  39. $object_id = get_queried_object_id();
  40. /* Front page of the site. */
  41. if ( is_front_page() )
  42. $hybrid->context[] = 'home';
  43. /* Blog page. */
  44. if ( is_home() ) {
  45. $hybrid->context[] = 'blog';
  46. }
  47. /* Singular views. */
  48. elseif ( is_singular() ) {
  49. $hybrid->context[] = 'singular';
  50. $hybrid->context[] = "singular-{$object->post_type}";
  51. $hybrid->context[] = "singular-{$object->post_type}-{$object_id}";
  52. }
  53. /* Archive views. */
  54. elseif ( is_archive() ) {
  55. $hybrid->context[] = 'archive';
  56. /* Post type archives. */
  57. if ( is_post_type_archive() ) {
  58. $post_type = get_post_type_object( get_query_var( 'post_type' ) );
  59. $hybrid->context[] = "archive-{$post_type->name}";
  60. }
  61. /* Taxonomy archives. */
  62. if ( is_tax() || is_category() || is_tag() ) {
  63. $hybrid->context[] = 'taxonomy';
  64. $hybrid->context[] = "taxonomy-{$object->taxonomy}";
  65. $slug = ( ( 'post_format' == $object->taxonomy ) ? str_replace( 'post-format-', '', $object->slug ) : $object->slug );
  66. $hybrid->context[] = "taxonomy-{$object->taxonomy}-" . sanitize_html_class( $slug, $object->term_id );
  67. }
  68. /* User/author archives. */
  69. if ( is_author() ) {
  70. $user_id = get_query_var( 'author' );
  71. $hybrid->context[] = 'user';
  72. $hybrid->context[] = 'user-' . sanitize_html_class( get_the_author_meta( 'user_nicename', $user_id ), $user_id );
  73. }
  74. /* Date archives. */
  75. if ( is_date() ) {
  76. $hybrid->context[] = 'date';
  77. if ( is_year() )
  78. $hybrid->context[] = 'year';
  79. if ( is_month() )
  80. $hybrid->context[] = 'month';
  81. if ( get_query_var( 'w' ) )
  82. $hybrid->context[] = 'week';
  83. if ( is_day() )
  84. $hybrid->context[] = 'day';
  85. }
  86. /* Time archives. */
  87. if ( is_time() ) {
  88. $hybrid->context[] = 'time';
  89. if ( get_query_var( 'hour' ) )
  90. $hybrid->context[] = 'hour';
  91. if ( get_query_var( 'minute' ) )
  92. $hybrid->context[] = 'minute';
  93. }
  94. }
  95. /* Search results. */
  96. elseif ( is_search() ) {
  97. $hybrid->context[] = 'search';
  98. }
  99. /* Error 404 pages. */
  100. elseif ( is_404() ) {
  101. $hybrid->context[] = 'error-404';
  102. }
  103. return array_map( 'esc_attr', apply_filters( 'hybrid_context', array_unique( $hybrid->context ) ) );
  104. }
  105. /**
  106. * Outputs the attributes for the <body> element. By default, this is just the 'class' attribute, but
  107. * developers can filter this to add other attributes.
  108. *
  109. * @since 1.6.0
  110. * @access public
  111. * @return void
  112. */
  113. function hybrid_body_attributes() {
  114. $attributes = array();
  115. $output = '';
  116. $attributes['class'] = join( ' ', hybrid_get_body_class() );
  117. $attributes = apply_atomic( 'body_attributes', $attributes );
  118. foreach( $attributes as $attr => $value )
  119. $output .= " {$attr}='{$value}'";
  120. echo $output;
  121. }
  122. /**
  123. * Outputs classes for the <body> element depending on page context.
  124. *
  125. * @since 0.1.0
  126. * @access public
  127. * @param string|array $class Additional classes for more control.
  128. * @return void
  129. */
  130. function hybrid_body_class( $class = '' ) {
  131. /* Get the body class. */
  132. $classes = hybrid_get_body_class( $class );
  133. /* Print the body class. */
  134. echo apply_atomic( 'body_class', join( ' ', $classes ) );
  135. }
  136. /**
  137. * Returns classes for the <body> element depending on page context.
  138. *
  139. * @since 1.6.0
  140. * @access public
  141. * @param string|array $class Additional classes for more control.
  142. * @return array
  143. */
  144. function hybrid_get_body_class( $class = '' ) {
  145. global $wp_query;
  146. /* Text direction (which direction does the text flow). */
  147. $classes = array( 'wordpress', get_bloginfo( 'text_direction' ), get_locale() );
  148. /* Check if the current theme is a parent or child theme. */
  149. $classes[] = ( is_child_theme() ? 'child-theme' : 'parent-theme' );
  150. /* Multisite check adds the 'multisite' class and the blog ID. */
  151. if ( is_multisite() ) {
  152. $classes[] = 'multisite';
  153. $classes[] = 'blog-' . get_current_blog_id();
  154. }
  155. /* Date classes. */
  156. $time = time() + ( get_option( 'gmt_offset' ) * 3600 );
  157. $classes[] = strtolower( gmdate( '\yY \mm \dd \hH l', $time ) );
  158. /* Is the current user logged in. */
  159. $classes[] = ( is_user_logged_in() ) ? 'logged-in' : 'logged-out';
  160. /* WP admin bar. */
  161. if ( is_admin_bar_showing() )
  162. $classes[] = 'admin-bar';
  163. /* Use the '.custom-background' class to integrate with the WP background feature. */
  164. if ( get_background_image() || get_background_color() )
  165. $classes[] = 'custom-background';
  166. /* Add the '.custom-header' class if the user is using a custom header. */
  167. if ( get_header_image() )
  168. $classes[] = 'custom-header';
  169. /* Merge base contextual classes with $classes. */
  170. $classes = array_merge( $classes, hybrid_get_context() );
  171. /* Singular post (post_type) classes. */
  172. if ( is_singular() ) {
  173. /* Get the queried post object. */
  174. $post = get_queried_object();
  175. /* Checks for custom template. */
  176. $template = str_replace( array ( "{$post->post_type}-template-", "{$post->post_type}-" ), '', basename( get_post_meta( get_queried_object_id(), "_wp_{$post->post_type}_template", true ), '.php' ) );
  177. if ( !empty( $template ) )
  178. $classes[] = "{$post->post_type}-template-{$template}";
  179. /* Post format. */
  180. if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) ) {
  181. $post_format = get_post_format( get_queried_object_id() );
  182. $classes[] = ( ( empty( $post_format ) || is_wp_error( $post_format ) ) ? "{$post->post_type}-format-standard" : "{$post->post_type}-format-{$post_format}" );
  183. }
  184. /* Attachment mime types. */
  185. if ( is_attachment() ) {
  186. foreach ( explode( '/', get_post_mime_type() ) as $type )
  187. $classes[] = "attachment-{$type}";
  188. }
  189. }
  190. /* Paged views. */
  191. if ( ( ( $page = $wp_query->get( 'paged' ) ) || ( $page = $wp_query->get( 'page' ) ) ) && $page > 1 )
  192. $classes[] = 'paged paged-' . intval( $page );
  193. /* Input class. */
  194. if ( !empty( $class ) ) {
  195. if ( !is_array( $class ) )
  196. $class = preg_split( '#\s+#', $class );
  197. $classes = array_merge( $classes, $class );
  198. }
  199. /* Apply the filters for WP's 'body_class'. */
  200. return array_unique( apply_filters( 'body_class', $classes, $class ) );
  201. }
  202. /**
  203. * Outputs the attributes for the post wrapper. By default, this is the 'class' and 'id' attributes,
  204. * but developers can filter this to add other attributes.
  205. *
  206. * @since 1.6.0
  207. * @access public
  208. * @return void
  209. */
  210. function hybrid_post_attributes() {
  211. $attributes = array();
  212. $output = '';
  213. $attributes['id'] = 'post-' . get_the_ID();
  214. $attributes['class'] = join( ' ', hybrid_get_post_class() );
  215. $attributes = apply_atomic( 'post_attributes', $attributes );
  216. foreach( $attributes as $attr => $value )
  217. $output .= " {$attr}='{$value}'";
  218. echo $output;
  219. }
  220. /**
  221. * Outputs the class for the post wrapper.
  222. *
  223. * @since 1.6.0
  224. * @access public
  225. * @param string|array $class Additional classes for more control.
  226. * @param int $post_id ID of a specific post to get the class for.
  227. * @return void
  228. */
  229. function hybrid_post_class( $class = '', $post_id = null ) {
  230. /* Get the post class. */
  231. $classes = hybrid_get_post_class( $class, $post_id );
  232. /* Print the body class. */
  233. echo apply_atomic( 'post_class', join( ' ', $classes ) );
  234. }
  235. /**
  236. * Outputs the class for the post wrapper. Use hybrid_post_class() instead.
  237. *
  238. * @since 0.5.0
  239. * @deprecated 1.6.0
  240. * @access public
  241. * @param string|array $class Additional classes for more control.
  242. * @param int $post_id ID of a specific post to get the class for.
  243. * @return void
  244. */
  245. function hybrid_entry_class( $class = '', $post_id = null ) {
  246. /* Get the post class. */
  247. $classes = hybrid_get_post_class( $class );
  248. /* Print the entry class. */
  249. echo apply_atomic( 'entry_class', join( ' ', $classes ) );
  250. }
  251. /**
  252. * Creates a set of classes for each site entry upon display. Each entry is given the class of
  253. * 'hentry'. Posts are given category, tag, and author classes. Alternate post classes of odd,
  254. * even, and alt are added.
  255. *
  256. * @since 1.6.0
  257. * @access public
  258. * @param string|array $class Additional classes for more control.
  259. * @param int $post_id ID of a specific post to get the class for.
  260. * @return array
  261. */
  262. function hybrid_get_post_class( $class = '', $post_id = null ) {
  263. static $post_alt;
  264. $post = get_post( $post_id );
  265. /* Make sure we have a real post first. */
  266. if ( !empty( $post ) ) {
  267. $post_id = $post->ID;
  268. /* Add hentry for microformats compliance, the post type, and post status. */
  269. $classes = array( 'hentry', $post->post_type, $post->post_status );
  270. /* Post alt class. */
  271. $classes[] = 'post-' . ++$post_alt;
  272. $classes[] = ( $post_alt % 2 ) ? 'odd' : 'even alt';
  273. /* Author class. */
  274. $classes[] = 'author-' . sanitize_html_class( get_the_author_meta( 'user_nicename' ), get_the_author_meta( 'ID' ) );
  275. /* Sticky class (only on home/blog page). */
  276. if ( is_home() && is_sticky() && !is_paged() )
  277. $classes[] = 'sticky';
  278. /* Password-protected posts. */
  279. if ( post_password_required() )
  280. $classes[] = 'protected';
  281. /* Has excerpt. */
  282. if ( post_type_supports( $post->post_type, 'excerpt' ) && has_excerpt() )
  283. $classes[] = 'has-excerpt';
  284. /* Has <!--more--> link. */
  285. if ( !is_singular() && false !== strpos( $post->post_content, '<!--more-->' ) )
  286. $classes[] = 'has-more-link';
  287. /* Post format. */
  288. if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) ) {
  289. $post_format = get_post_format( $post_id );
  290. $classes[] = ( ( empty( $post_format ) || is_wp_error( $post_format ) ) ? 'format-standard' : "format-{$post_format}" );
  291. }
  292. /* Add category and post tag terms as classes. */
  293. if ( 'post' == $post->post_type ) {
  294. foreach ( array( 'category', 'post_tag' ) as $tax ) {
  295. foreach ( (array)get_the_terms( $post->ID, $tax ) as $term ) {
  296. if ( !empty( $term->slug ) )
  297. $classes[] = $tax . '-' . sanitize_html_class( $term->slug, $term->term_id );
  298. }
  299. }
  300. }
  301. }
  302. /* If not a post. */
  303. else {
  304. $classes = array( 'hentry', 'error' );
  305. }
  306. /* User-created classes. */
  307. if ( !empty( $class ) ) {
  308. if ( !is_array( $class ) )
  309. $class = preg_split( '#\s+#', $class );
  310. $classes = array_merge( $classes, $class );
  311. }
  312. /* Apply the filters for WP's 'post_class'. */
  313. return array_unique( apply_filters( 'post_class', $classes, $class, $post_id ) );
  314. }
  315. /**
  316. * Outputs the attributes for the comment wrapper. By default, this is the 'class' and 'id' attributes,
  317. * but developers can filter this to add other attributes.
  318. *
  319. * @since 1.6.0
  320. * @access public
  321. * @return void
  322. */
  323. function hybrid_comment_attributes() {
  324. $attributes = array();
  325. $output = '';
  326. $attributes['id'] = 'comment-' . get_comment_ID();
  327. $attributes['class'] = join( ' ', hybrid_get_comment_class() );
  328. $attributes = apply_atomic( 'comment_attributes', $attributes );
  329. foreach( $attributes as $attr => $value )
  330. $output .= " {$attr}='{$value}'";
  331. echo $output;
  332. }
  333. /**
  334. * Outputs the class for the current comment wrapper element.
  335. *
  336. * @since 0.2.0
  337. * @access public
  338. * @global $comment The current comment's DB object.
  339. * @return void
  340. */
  341. function hybrid_comment_class( $class = '' ) {
  342. global $hybrid;
  343. /* Join all the classes into one string and echo them. */
  344. $class = join( ' ', hybrid_get_comment_class( $class ) );
  345. echo apply_filters( "{$hybrid->prefix}_comment_class", $class );
  346. }
  347. /**
  348. * Sets a class for each comment. Sets alt, odd/even, and author/user classes. Adds author, user,
  349. * and reader classes. Needs more work because WP, by default, assigns even/odd backwards
  350. * (Odd should come first, even second).
  351. *
  352. * @since 1.6.0
  353. * @access public
  354. * @global $comment The current comment's DB object
  355. * @return void
  356. */
  357. function hybrid_get_comment_class( $class = '' ) {
  358. global $comment;
  359. /* Gets default WP comment classes. */
  360. $classes = get_comment_class( $class );
  361. /* Get the comment type. */
  362. $comment_type = get_comment_type();
  363. /* If the comment type is 'pingback' or 'trackback', add the 'ping' comment class. */
  364. if ( 'pingback' == $comment_type || 'trackback' == $comment_type )
  365. $classes[] = 'ping';
  366. /* User classes to match user role and user. */
  367. if ( $comment->user_id > 0 ) {
  368. /* Create new user object. */
  369. $user = new WP_User( $comment->user_id );
  370. /* Set a class with the user's role(s). */
  371. if ( is_array( $user->roles ) ) {
  372. foreach ( $user->roles as $role )
  373. $classes[] = sanitize_html_class( "role-{$role}" );
  374. }
  375. /* Set a class with the user's name. */
  376. $classes[] = sanitize_html_class( "user-{$user->user_nicename}", "user-{$user->ID}" );
  377. }
  378. /* If not a registered user */
  379. else {
  380. $classes[] = 'reader';
  381. }
  382. /* Comment by the entry/post author. */
  383. if ( $post = get_post( get_the_ID() ) ) {
  384. if ( $comment->user_id == $post->post_author )
  385. $classes[] = 'entry-author';
  386. }
  387. /* Get comment types that are allowed to have an avatar. */
  388. $avatar_comment_types = apply_filters( 'get_avatar_comment_types', array( 'comment' ) );
  389. /* If avatars are enabled and the comment types can display avatars, add the 'has-avatar' class. */
  390. if ( get_option( 'show_avatars' ) && in_array( $comment->comment_type, $avatar_comment_types ) )
  391. $classes[] = 'has-avatar';
  392. /* Make sure comment classes doesn't have any duplicates. */
  393. return array_unique( $classes );
  394. }
  395. /**
  396. * Function for handling what the browser/search engine title should be. Attempts to handle every
  397. * possible situation WordPress throws at it for the best optimization.
  398. *
  399. * @since 0.1.0
  400. * @access public
  401. * @global $wp_query
  402. * @return void
  403. */
  404. function hybrid_document_title() {
  405. global $wp_query;
  406. /* Set up some default variables. */
  407. $doctitle = '';
  408. $separator = ':';
  409. /* If viewing the front page and posts page of the site. */
  410. if ( is_front_page() && is_home() )
  411. $doctitle = get_bloginfo( 'name' ) . $separator . ' ' . get_bloginfo( 'description' );
  412. /* If viewing the posts page or a singular post. */
  413. elseif ( is_home() || is_singular() ) {
  414. $doctitle = get_post_meta( get_queried_object_id(), 'Title', true );
  415. if ( empty( $doctitle ) && is_front_page() )
  416. $doctitle = get_bloginfo( 'name' ) . $separator . ' ' . get_bloginfo( 'description' );
  417. elseif ( empty( $doctitle ) )
  418. $doctitle = single_post_title( '', false );
  419. }
  420. /* If viewing any type of archive page. */
  421. elseif ( is_archive() ) {
  422. /* If viewing a taxonomy term archive. */
  423. if ( is_category() || is_tag() || is_tax() ) {
  424. $doctitle = single_term_title( '', false );
  425. }
  426. /* If viewing a post type archive. */
  427. elseif ( is_post_type_archive() ) {
  428. $doctitle = post_type_archive_title( '', false );
  429. }
  430. /* If viewing an author/user archive. */
  431. elseif ( is_author() ) {
  432. $doctitle = get_user_meta( get_query_var( 'author' ), 'Title', true );
  433. if ( empty( $doctitle ) )
  434. $doctitle = get_the_author_meta( 'display_name', get_query_var( 'author' ) );
  435. }
  436. /* If viewing a date-/time-based archive. */
  437. elseif ( is_date () ) {
  438. if ( get_query_var( 'minute' ) && get_query_var( 'hour' ) )
  439. $doctitle = sprintf( __( 'Archive for %s', 'hybrid-core' ), get_the_time( __( 'g:i a', 'hybrid-core' ) ) );
  440. elseif ( get_query_var( 'minute' ) )
  441. $doctitle = sprintf( __( 'Archive for minute %s', 'hybrid-core' ), get_the_time( __( 'i', 'hybrid-core' ) ) );
  442. elseif ( get_query_var( 'hour' ) )
  443. $doctitle = sprintf( __( 'Archive for %s', 'hybrid-core' ), get_the_time( __( 'g a', 'hybrid-core' ) ) );
  444. elseif ( is_day() )
  445. $doctitle = sprintf( __( 'Archive for %s', 'hybrid-core' ), get_the_time( __( 'F jS, Y', 'hybrid-core' ) ) );
  446. elseif ( get_query_var( 'w' ) )
  447. $doctitle = sprintf( __( 'Archive for week %s of %s', 'hybrid-core' ), get_the_time( __( 'W', 'hybrid-core' ) ), get_the_time( __( 'Y', 'hybrid-core' ) ) );
  448. elseif ( is_month() )
  449. $doctitle = sprintf( __( 'Archive for %s', 'hybrid-core' ), single_month_title( ' ', false) );
  450. elseif ( is_year() )
  451. $doctitle = sprintf( __( 'Archive for %s', 'hybrid-core' ), get_the_time( __( 'Y', 'hybrid-core' ) ) );
  452. }
  453. /* For any other archives. */
  454. else {
  455. $doctitle = __( 'Archives', 'hybrid-core' );
  456. }
  457. }
  458. /* If viewing a search results page. */
  459. elseif ( is_search() )
  460. $doctitle = sprintf( __( 'Search results for "%s"', 'hybrid-core' ), esc_attr( get_search_query() ) );
  461. /* If viewing a 404 not found page. */
  462. elseif ( is_404() )
  463. $doctitle = __( '404 Not Found', 'hybrid-core' );
  464. /* If the current page is a paged page. */
  465. if ( ( ( $page = $wp_query->get( 'paged' ) ) || ( $page = $wp_query->get( 'page' ) ) ) && $page > 1 )
  466. $doctitle = sprintf( __( '%1$s Page %2$s', 'hybrid-core' ), $doctitle . $separator, number_format_i18n( $page ) );
  467. /* Apply the wp_title filters so we're compatible with plugins. */
  468. $doctitle = apply_filters( 'wp_title', strip_tags( $doctitle ), $separator, '' );
  469. /* Trim separator + space from beginning and end in case a plugin adds it. */
  470. $doctitle = trim( $doctitle, "{$separator} " );
  471. /* Print the title to the screen. */
  472. echo apply_atomic( 'document_title', esc_attr( $doctitle ) );
  473. }
  474. ?>