PageRenderTime 45ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/functions.php

https://github.com/aethernet/the-bootstrap
PHP | 1081 lines | 519 code | 152 blank | 410 comment | 50 complexity | f6d8ac5cd1a827abfc4762834095de45 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /** functions.php
  3. *
  4. * @author Konstantin Obenland
  5. * @package The Bootstrap
  6. * @since 1.0.0 - 05.02.2012
  7. */
  8. if ( ! function_exists( 'the_bootstrap_setup' ) ):
  9. /**
  10. * Sets up theme defaults and registers support for various WordPress features.
  11. *
  12. * @author WordPress.org
  13. * @since 1.0.0 - 05.02.2012
  14. *
  15. * @return void
  16. */
  17. function the_bootstrap_setup() {
  18. global $content_width;
  19. if ( ! isset( $content_width ) ) {
  20. $content_width = 770;
  21. }
  22. load_theme_textdomain( 'the-bootstrap', get_template_directory() . '/lang' );
  23. add_theme_support( 'automatic-feed-links' );
  24. add_theme_support( 'post-thumbnails' );
  25. add_theme_support( 'post-formats', array(
  26. 'aside',
  27. 'chat',
  28. 'link',
  29. 'gallery',
  30. 'status',
  31. 'quote',
  32. 'image',
  33. 'video'
  34. ) );
  35. add_theme_support( 'tha_hooks', array( 'all' ) );
  36. if ( version_compare( get_bloginfo( 'version' ), '3.4', '<' ) )
  37. // Custom Theme Options
  38. require_once( get_template_directory() . '/inc/theme-options.php' );
  39. else
  40. // Implement the Theme Customizer script
  41. require_once( get_template_directory() . '/inc/theme-customizer.php' );
  42. /**
  43. * Custom template tags for this theme.
  44. */
  45. require_once( get_template_directory() . '/inc/template-tags.php' );
  46. /**
  47. * Implement the Custom Header feature
  48. */
  49. require_once( get_template_directory() . '/inc/custom-header.php' );
  50. /**
  51. * Custom Nav Menu handler for the Navbar.
  52. */
  53. require_once( get_template_directory() . '/inc/nav-menu-walker.php' );
  54. /**
  55. * Theme Hook Alliance
  56. */
  57. require_if_theme_supports( 'tha_hooks', get_template_directory() . '/inc/tha-theme-hooks.php' );
  58. /**
  59. * Including three menu (header-menu, primary and footer-menu).
  60. * Primary is wrapping in a navbar containing div (wich support responsive variation)
  61. * Header-menu and Footer-menu are inside pills dropdown menu
  62. *
  63. * @since 1.2.2 - 07.04.2012
  64. * @see http://codex.wordpress.org/Function_Reference/register_nav_menus
  65. */
  66. register_nav_menus( array(
  67. 'primary' => __( 'Main Navigation', 'the-bootstrap' ),
  68. 'header-menu' => __( 'Header Menu', 'the-bootstrap' ),
  69. 'footer-menu' => __( 'Footer Menu', 'the-bootstrap' )
  70. ) );
  71. } // the_bootstrap_setup
  72. endif;
  73. add_action( 'after_setup_theme', 'the_bootstrap_setup' );
  74. /**
  75. * Returns the options object for The Bootstrap.
  76. *
  77. * @author Automattic
  78. * @since 1.3.0 - 06.04.2012
  79. *
  80. * @return stdClass Theme Options
  81. */
  82. function the_bootstrap_options() {
  83. return (object) wp_parse_args(
  84. get_option( 'the_bootstrap_theme_options', array() ),
  85. the_bootstrap_get_default_theme_options()
  86. );
  87. }
  88. /**
  89. * Returns the default options for The Bootstrap.
  90. *
  91. * @author Automattic
  92. * @since 1.3.0 - 06.04.2012
  93. *
  94. * @return void
  95. */
  96. function the_bootstrap_get_default_theme_options() {
  97. $default_theme_options = array(
  98. 'theme_layout' => 'content-sidebar',
  99. 'navbar_site_name' => false,
  100. 'navbar_searchform' => true,
  101. 'navbar_inverse' => true,
  102. 'navbar_position' => 'static',
  103. );
  104. return apply_filters( 'the_bootstrap_default_theme_options', $default_theme_options );
  105. }
  106. /**
  107. * Adds The Bootstrap layout classes to the array of body classes.
  108. *
  109. * @author WordPress.org
  110. * @since 1.3.0 - 06.04.2012
  111. *
  112. * @return void
  113. */
  114. function the_bootstrap_layout_classes( $existing_classes ) {
  115. $classes = array( the_bootstrap_options()->theme_layout );
  116. $classes = apply_filters( 'the_bootstrap_layout_classes', $classes );
  117. return array_merge( $existing_classes, $classes );
  118. }
  119. add_filter( 'body_class', 'the_bootstrap_layout_classes' );
  120. /**
  121. * Adds Custom Background support
  122. *
  123. * @author Konstantin Obenland
  124. * @since 1.2.5 - 11.04.2012
  125. *
  126. * @return void
  127. */
  128. function the_bootstrap_custom_background_setup() {
  129. $args = apply_filters( 'the_bootstrap_custom_background_args', array(
  130. 'default-color' => 'EFEFEF',
  131. ) );
  132. add_theme_support( 'custom-background', $args );
  133. if ( ! function_exists( 'wp_get_theme' ) ) {
  134. // Compat: Versions of WordPress prior to 3.4.
  135. define( 'BACKGROUND_COLOR', $args['default-color'] );
  136. add_custom_background();
  137. }
  138. }
  139. add_action( 'after_setup_theme', 'the_bootstrap_custom_background_setup' );
  140. /**
  141. * Register the sidebars.
  142. *
  143. * @author Konstantin Obenland
  144. * @since 1.0.0 - 05.02.2012
  145. *
  146. * @return void
  147. */
  148. function the_bootstrap_widgets_init() {
  149. register_sidebar( array(
  150. 'name' => __( 'Main Sidebar', 'the-bootstrap' ),
  151. 'id' => 'main',
  152. 'before_widget' => '<aside id="%1$s" class="widget well %2$s">',
  153. 'after_widget' => '</aside>',
  154. 'before_title' => '<h2 class="widget-title">',
  155. 'after_title' => '</h2>',
  156. ) );
  157. register_sidebar( array(
  158. 'name' => __( 'Image Sidebar', 'the-bootstrap' ),
  159. 'description' => __( 'Shown on image attachment pages.', 'the-bootstrap' ),
  160. 'id' => 'image',
  161. 'before_widget' => '<aside id="%1$s" class="widget well %2$s">',
  162. 'after_widget' => '</aside>',
  163. 'before_title' => '<h2 class="widget-title">',
  164. 'after_title' => '</h2>',
  165. ) );
  166. include_once( 'inc/the-bootstrap-image-meta-widget.php' );
  167. register_widget( 'The_Bootstrap_Image_Meta_Widget' );
  168. include_once( 'inc/the-bootstrap-gallery-widget.php' );
  169. register_widget( 'The_Bootstrap_Gallery_Widget' );
  170. }
  171. add_action( 'widgets_init', 'the_bootstrap_widgets_init' );
  172. /**
  173. * Registration of theme scripts and styles
  174. *
  175. * @author Konstantin Obenland
  176. * @since 1.0.0 - 05.02.2012
  177. *
  178. * @return void
  179. */
  180. function the_bootstrap_register_scripts_styles() {
  181. if ( ! is_admin() ) {
  182. $theme_version = _the_bootstrap_version();
  183. $suffix = ( defined('SCRIPT_DEBUG') AND SCRIPT_DEBUG ) ? '' : '.min';
  184. /**
  185. * Scripts
  186. */
  187. wp_register_script(
  188. 'tw-bootstrap',
  189. get_template_directory_uri() . "/js/bootstrap{$suffix}.js",
  190. array('jquery'),
  191. '2.0.3',
  192. true
  193. );
  194. wp_register_script(
  195. 'the-bootstrap',
  196. get_template_directory_uri() . "/js/the-bootstrap{$suffix}.js",
  197. array('tw-bootstrap'),
  198. $theme_version,
  199. true
  200. );
  201. /**
  202. * Styles
  203. */
  204. wp_register_style(
  205. 'tw-bootstrap',
  206. get_template_directory_uri() . "/css/bootstrap{$suffix}.css",
  207. array(),
  208. '2.0.3'
  209. );
  210. wp_register_style(
  211. 'the-bootstrap',
  212. get_template_directory_uri() . "/style{$suffix}.css",
  213. array('tw-bootstrap'),
  214. $theme_version
  215. );
  216. }
  217. }
  218. add_action( 'init', 'the_bootstrap_register_scripts_styles' );
  219. /**
  220. * Properly enqueue frontend scripts
  221. *
  222. * @author Konstantin Obenland
  223. * @since 1.0.0 - 05.02.2012
  224. *
  225. * @return void
  226. */
  227. function the_bootstrap_print_scripts() {
  228. wp_enqueue_script( 'the-bootstrap' );
  229. }
  230. add_action( 'wp_enqueue_scripts', 'the_bootstrap_print_scripts' );
  231. /**
  232. * Adds IE specific scripts
  233. *
  234. * Respond.js has to be loaded after Theme styles
  235. *
  236. * @author Konstantin Obenland
  237. * @since 1.7.0 - 11.06.2012
  238. *
  239. * @return void
  240. */
  241. function the_bootstrap_print_ie_scripts() {
  242. ?>
  243. <!--[if lt IE 9]>
  244. <script src="<?php echo get_template_directory_uri(); ?>/js/html5shiv.min.js" type="text/javascript"></script>
  245. <script src="<?php echo get_template_directory_uri(); ?>/js/respond.min.js" type="text/javascript"></script>
  246. <![endif]-->
  247. <?php
  248. }
  249. add_action( 'wp_head', 'the_bootstrap_print_ie_scripts', 11 );
  250. /**
  251. * Properly enqueue comment-reply script
  252. *
  253. * @author Konstantin Obenland
  254. * @since 1.4.0 - 08.05.2012
  255. *
  256. * @return void
  257. */
  258. function the_bootstrap_comment_reply() {
  259. if ( get_option( 'thread_comments' ) ) {
  260. wp_enqueue_script( 'comment-reply' );
  261. }
  262. }
  263. add_action( 'comment_form_before', 'the_bootstrap_comment_reply' );
  264. /**
  265. * Properly enqueue frontend styles
  266. *
  267. * Since 'tw-bootstrap' was registered as a dependency, it'll get enqueued
  268. * automatically
  269. *
  270. * @author Konstantin Obenland
  271. * @since 1.0.0 - 05.02.2012
  272. *
  273. * @return void
  274. */
  275. function the_bootstrap_print_styles() {
  276. if ( is_child_theme() ) {
  277. wp_enqueue_style( 'the-bootstrap-child', get_stylesheet_uri(), array( 'the-bootstrap' ) );
  278. } else {
  279. wp_enqueue_style( 'the-bootstrap' );
  280. }
  281. if ( 'static' != the_bootstrap_options()->navbar_position ) {
  282. $top_bottom = str_replace( 'navbar-fixed-', '', the_bootstrap_options()->navbar_position );
  283. $css = "body > .container{margin-{$top_bottom}:68px;}@media(min-width: 980px){body > .container{margin-{$top_bottom}:58px;}}";
  284. if ( is_admin_bar_showing() AND 'top' == $top_bottom )
  285. $css .= '.navbar.navbar-fixed-top{margin-top:28px;}';
  286. if ( function_exists( 'wp_add_inline_style' ) )
  287. wp_add_inline_style( 'the-bootstrap', $css );
  288. else
  289. echo "<style type='text/css'>\n{$css}\n</style>\n";
  290. }
  291. }
  292. add_action( 'wp_enqueue_scripts', 'the_bootstrap_print_styles' );
  293. if ( ! function_exists( 'the_bootstrap_credits' ) ) :
  294. /**
  295. * Prints HTML with meta information for the current post-date/time and author,
  296. * comment and edit link
  297. *
  298. * @author Konstantin Obenland
  299. * @since 1.2.2 - 07.04.2012
  300. *
  301. * @return void
  302. */
  303. function the_bootstrap_credits() {
  304. printf(
  305. '<span class="credits alignleft">' . __( '&copy; %1$s <a href="%2$s">%3$s</a>, all rights reserved.', 'the-bootstrap' ) . '</span>',
  306. date( 'Y' ),
  307. home_url( '/' ),
  308. get_bloginfo( 'name' )
  309. );
  310. }
  311. endif;
  312. /**
  313. * Returns the blogname if no title was set.
  314. *
  315. * @author Konstantin Obenland
  316. * @since 1.1.0 - 18.03.2012
  317. *
  318. * @param string $title
  319. * @param string $sep
  320. *
  321. * @return string
  322. */
  323. function the_bootstrap_wp_title( $title, $sep ) {
  324. if ( ! is_feed() ) {
  325. $title .= get_bloginfo( 'name' );
  326. if ( is_front_page() ) {
  327. $title .= " {$sep} " . get_bloginfo( 'description' );
  328. }
  329. }
  330. return $title;
  331. }
  332. add_filter( 'wp_title', 'the_bootstrap_wp_title', 1, 2 );
  333. /**
  334. * Returns a "Continue Reading" link for excerpts
  335. *
  336. * @author WordPress.org
  337. * @since 1.0.0 - 05.02.2012
  338. *
  339. * @param string $more
  340. *
  341. * @return string
  342. */
  343. function the_bootstrap_continue_reading_link() {
  344. return ' <a href="'. esc_url( get_permalink() ) . '">' . __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'the-bootstrap' ) . '</a>';
  345. }
  346. /**
  347. * Replaces "[...]" (appended to automatically generated excerpts) with an ellipsis and the_bootstrap_continue_reading_link().
  348. *
  349. * To override this in a child theme, remove the filter and add your own
  350. * function tied to the excerpt_more filter hook.
  351. *
  352. * @author WordPress.org
  353. * @since 1.0.0 - 05.02.2012
  354. *
  355. * @param string $more
  356. *
  357. * @return string
  358. */
  359. function the_bootstrap_auto_excerpt_more( $more ) {
  360. return '&hellip;' . the_bootstrap_continue_reading_link();
  361. }
  362. add_filter( 'excerpt_more', 'the_bootstrap_auto_excerpt_more' );
  363. /**
  364. * Adds a pretty "Continue Reading" link to custom post excerpts.
  365. *
  366. * To override this link in a child theme, remove the filter and add your own
  367. * function tied to the get_the_excerpt filter hook.
  368. *
  369. * @author WordPress.org
  370. * @since 1.0.0 - 05.02.2012
  371. *
  372. * @param string $output
  373. *
  374. * @return string
  375. */
  376. function the_bootstrap_custom_excerpt_more( $output ) {
  377. if ( has_excerpt() AND ! is_attachment() ) {
  378. $output .= the_bootstrap_continue_reading_link();
  379. }
  380. return $output;
  381. }
  382. add_filter( 'get_the_excerpt', 'the_bootstrap_custom_excerpt_more' );
  383. /**
  384. * Get the wp_nav_menu() fallback, wp_page_menu(), to show a home link.
  385. *
  386. * @author WordPress.org
  387. * @since 1.0.0 - 05.02.2012
  388. *
  389. * @param array $args
  390. *
  391. * @return array
  392. */
  393. function the_bootstrap_page_menu_args( $args ) {
  394. $args['show_home'] = true;
  395. return $args;
  396. }
  397. add_filter( 'wp_page_menu_args', 'the_bootstrap_page_menu_args' );
  398. /**
  399. * Filter in a link to a content ID attribute for the next/previous image links on image attachment pages
  400. *
  401. * @author Automattic
  402. * @since 1.0.0 - 05.02.2012
  403. *
  404. * @param string $url
  405. * @param int $id
  406. *
  407. * @return string
  408. */
  409. function the_bootstrap_enhanced_image_navigation( $url, $id ) {
  410. if ( is_attachment() AND wp_attachment_is_image( $id ) ) {
  411. $image = get_post( $id );
  412. if ( $image->post_parent AND $image->post_parent != $id )
  413. $url .= '#primary';
  414. }
  415. return $url;
  416. }
  417. add_filter( 'attachment_link', 'the_bootstrap_enhanced_image_navigation', 10, 2 );
  418. /**
  419. * Displays comment list, when there are any
  420. *
  421. * @author Konstantin Obenland
  422. * @since 1.7.0 - 16.06.2012
  423. *
  424. * @return void
  425. */
  426. function the_bootstrap_comments_list() {
  427. if ( post_password_required() ) : ?>
  428. <div id="comments">
  429. <p class="nopassword"><?php _e( 'This post is password protected. Enter the password to view any comments.', 'the-bootstrap' ); ?></p>
  430. </div><!-- #comments -->
  431. <?php
  432. return;
  433. endif;
  434. if ( have_comments() ) : ?>
  435. <div id="comments">
  436. <h2 id="comments-title">
  437. <?php printf( _n( 'One thought on &ldquo;%2$s&rdquo;', '%1$s thoughts on &ldquo;%2$s&rdquo;', get_comments_number(), 'the-bootstrap' ),
  438. number_format_i18n( get_comments_number() ), '<span>' . get_the_title() . '</span>' ); ?>
  439. </h2>
  440. <?php the_bootstrap_comment_nav(); ?>
  441. <ol class="commentlist unstyled">
  442. <?php wp_list_comments( array( 'callback' => 'the_bootstrap_comment' ) ); ?>
  443. </ol><!-- .commentlist .unstyled -->
  444. <?php the_bootstrap_comment_nav(); ?>
  445. </div><!-- #comments -->
  446. <?php endif;
  447. }
  448. add_action( 'comment_form_before', 'the_bootstrap_comments_list', 0 );
  449. add_action( 'comment_form_comments_closed', 'the_bootstrap_comments_list', 1 );
  450. /**
  451. * Echoes comments-are-closed message when post type supports comments and we're
  452. * not on a page
  453. *
  454. * @author Konstantin Obenland
  455. * @since 1.7.0 - 16.06.2012
  456. *
  457. * @return void
  458. */
  459. function the_bootstrap_comments_closed() {
  460. if ( ! is_page() AND post_type_supports( get_post_type(), 'comments' ) ) : ?>
  461. <p class="nocomments"><?php _e( 'Comments are closed.', 'the-bootstrap' ); ?></p>
  462. <?php endif;
  463. }
  464. add_action( 'comment_form_comments_closed', 'the_bootstrap_comments_closed' );
  465. /**
  466. * Filters comments_form() default arguments
  467. *
  468. * @author Konstantin Obenland
  469. * @since 1.7.0 - 16.06.2012
  470. *
  471. * @param array $defaults
  472. *
  473. * @return array
  474. */
  475. function the_bootstrap_comment_form_defaults( $defaults ) {
  476. return wp_parse_args( array(
  477. 'comment_field' => '<div class="comment-form-comment control-group"><label class="control-label" for="comment">' . _x( 'Comment', 'noun', 'the-bootstrap' ) . '</label><div class="controls"><textarea class="span7" id="comment" name="comment" rows="8" aria-required="true"></textarea></div></div>',
  478. 'comment_notes_before' => '',
  479. 'comment_notes_after' => '<div class="form-allowed-tags control-group"><label class="control-label">' . sprintf( __( 'You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: %s', 'the-bootstrap' ), '</label><div class="controls"><pre>' . allowed_tags() . '</pre></div>' ) . '</div>
  480. <div class="form-actions">',
  481. 'title_reply' => '<legend>' . __( 'Leave a reply', 'the-bootstrap' ) . '</legend>',
  482. 'title_reply_to' => '<legend>' . __( 'Leave a reply to %s', 'the-bootstrap' ). '</legend>',
  483. 'must_log_in' => '<div class="must-log-in control-group controls">' . sprintf( __( 'You must be <a href="%s">logged in</a> to post a comment.', 'the-bootstrap' ), wp_login_url( apply_filters( 'the_permalink', get_permalink( get_the_ID() ) ) ) ) . '</div>',
  484. 'logged_in_as' => '<div class="logged-in-as control-group controls">' . sprintf( __( 'Logged in as <a href="%1$s">%2$s</a>. <a href="%3$s" title="Log out of this account">Log out?</a>', 'the-bootstrap' ), admin_url( 'profile.php' ), wp_get_current_user()->display_name, wp_logout_url( apply_filters( 'the_permalink', get_permalink( get_the_ID() ) ) ) ) . '</div>',
  485. ), $defaults );
  486. }
  487. add_filter( 'comment_form_defaults', 'the_bootstrap_comment_form_defaults' );
  488. if ( ! function_exists( 'the_bootstrap_comment' ) ) :
  489. /**
  490. * Template for comments and pingbacks.
  491. *
  492. * To override this walker in a child theme without modifying the comments template
  493. * simply create your own the_bootstrap_comment(), and that function will be used instead.
  494. *
  495. * Used as a callback by wp_list_comments() for displaying the comments.
  496. *
  497. * @author Konstantin Obenland
  498. * @since 1.0.0 - 05.02.2012
  499. *
  500. * @param object $comment Comment data object.
  501. * @param array $args
  502. * @param int $depth Depth of comment in reference to parents.
  503. *
  504. * @return void
  505. */
  506. function the_bootstrap_comment( $comment, $args, $depth ) {
  507. $GLOBALS['comment'] = $comment;
  508. if ( 'pingback' == $comment->comment_type OR 'trackback' == $comment->comment_type ) : ?>
  509. <li id="li-comment-<?php comment_ID(); ?>" <?php comment_class(); ?>>
  510. <p class="row">
  511. <strong class="ping-label span1"><?php _e( 'Pingback:', 'the-bootstrap' ); ?></strong>
  512. <span class="span7"><?php comment_author_link(); edit_comment_link( __( 'Edit', 'the-bootstrap' ), '<span class="sep">&nbsp;</span><span class="edit-link label">', '</span>' ); ?></span>
  513. </p>
  514. <?php else:
  515. $offset = $depth - 1;
  516. $span = 7 - $offset; ?>
  517. <li id="li-comment-<?php comment_ID(); ?>" <?php comment_class(); ?>>
  518. <article id="comment-<?php comment_ID(); ?>" class="comment row">
  519. <div class="comment-author-avatar span1<?php if ($offset) echo " offset{$offset}"; ?>">
  520. <?php echo get_avatar( $comment, 70 ); ?>
  521. </div>
  522. <footer class="comment-meta span<?php echo $span; ?>">
  523. <p class="comment-author vcard">
  524. <?php
  525. /* translators: 1: comment author, 2: date and time */
  526. printf( __( '%1$s <span class="says">said</span> on %2$s:', 'the-bootstrap' ),
  527. sprintf( '<span class="fn">%s</span>', get_comment_author_link() ),
  528. sprintf( '<a href="%1$s"><time pubdate datetime="%2$s">%3$s</time></a>',
  529. esc_url( get_comment_link( $comment->comment_ID ) ),
  530. get_comment_time( 'c' ),
  531. /* translators: 1: date, 2: time */
  532. sprintf( __( '%1$s at %2$s', 'the-bootstrap' ), get_comment_date(), get_comment_time() )
  533. )
  534. );
  535. edit_comment_link( __( 'Edit', 'the-bootstrap' ), '<span class="sep">&nbsp;</span><span class="edit-link label">', '</span>' ); ?>
  536. </p><!-- .comment-author .vcard -->
  537. <?php if ( ! $comment->comment_approved ) : ?>
  538. <div class="comment-awaiting-moderation alert alert-info"><em><?php _e( 'Your comment is awaiting moderation.', 'the-bootstrap' ); ?></em></div>
  539. <?php endif; ?>
  540. </footer><!-- .comment-meta -->
  541. <div class="comment-content span<?php echo $span; ?>">
  542. <?php
  543. comment_text();
  544. comment_reply_link( array_merge( $args, array(
  545. 'reply_text' => __( 'Reply <span>&darr;</span>', 'the-bootstrap' ),
  546. 'depth' => $depth,
  547. 'max_depth' => $args['max_depth']
  548. ) ) ); ?>
  549. </div><!-- .comment-content -->
  550. </article><!-- #comment-<?php comment_ID(); ?> .comment -->
  551. <?php endif; // comment_type
  552. }
  553. endif; // ends check for the_bootstrap_comment()
  554. /**
  555. * Adds markup to the comment form which is needed to make it work with Bootstrap
  556. * needs
  557. *
  558. * @author Konstantin Obenland
  559. * @since 1.0.0 - 05.02.2012
  560. *
  561. * @param string $html
  562. *
  563. * @return string
  564. */
  565. function the_bootstrap_comment_form_top() {
  566. echo '<div class="form-horizontal">';
  567. }
  568. add_action( 'comment_form_top', 'the_bootstrap_comment_form_top' );
  569. /**
  570. * Adds markup to the comment form which is needed to make it work with Bootstrap
  571. * needs
  572. *
  573. * @author Konstantin Obenland
  574. * @since 1.0.0 - 05.02.2012
  575. *
  576. * @param string $html
  577. *
  578. * @return string
  579. */
  580. function the_bootstrap_comment_form() {
  581. echo '</div></div>';
  582. }
  583. add_action( 'comment_form', 'the_bootstrap_comment_form' );
  584. /**
  585. * Custom author form field for the comments form
  586. *
  587. * @author Konstantin Obenland
  588. * @since 1.0.0 - 05.02.2012
  589. *
  590. * @param string $html
  591. *
  592. * @return string
  593. */
  594. function the_bootstrap_comment_form_field_author( $html ) {
  595. $commenter = wp_get_current_commenter();
  596. $req = get_option( 'require_name_email' );
  597. $aria_req = ( $req ? " aria-required='true'" : '' );
  598. return '<div class="comment-form-author control-group">
  599. <label for="author" class="control-label">' . __( 'Name', 'the-bootstrap' ) . '</label>
  600. <div class="controls">
  601. <input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30"' . $aria_req . ' />
  602. ' . ( $req ? '<p class="help-inline"><span class="required">' . __('required', 'the-bootstrap') . '</span></p>' : '' ) . '
  603. </div>
  604. </div>';
  605. }
  606. add_filter( 'comment_form_field_author', 'the_bootstrap_comment_form_field_author');
  607. /**
  608. * Custom HTML5 email form field for the comments form
  609. *
  610. * @author Konstantin Obenland
  611. * @since 1.0.0 - 05.02.2012
  612. *
  613. * @param string $html
  614. *
  615. * @return string
  616. */
  617. function the_bootstrap_comment_form_field_email( $html ) {
  618. $commenter = wp_get_current_commenter();
  619. $req = get_option( 'require_name_email' );
  620. $aria_req = ( $req ? " aria-required='true'" : '' );
  621. return '<div class="comment-form-email control-group">
  622. <label for="email" class="control-label">' . __( 'Email', 'the-bootstrap' ) . '</label>
  623. <div class="controls">
  624. <input id="email" name="email" type="email" value="' . esc_attr( $commenter['comment_author_email'] ) . '" size="30"' . $aria_req . ' />
  625. <p class="help-inline">' . ( $req ? '<span class="required">' . __('required', 'the-bootstrap') . '</span>, ' : '' ) . __( 'will not be published', 'the-bootstrap' ) . '</p>
  626. </div>
  627. </div>';
  628. }
  629. add_filter( 'comment_form_field_email', 'the_bootstrap_comment_form_field_email');
  630. /**
  631. * Custom HTML5 url form field for the comments form
  632. *
  633. * @author Konstantin Obenland
  634. * @since 1.0.0 - 05.02.2012
  635. *
  636. * @param string $html
  637. *
  638. * @return string
  639. */
  640. function the_bootstrap_comment_form_field_url( $html ) {
  641. $commenter = wp_get_current_commenter();
  642. return '<div class="comment-form-url control-group">
  643. <label for="url" class="control-label">' . __( 'Website', 'the-bootstrap' ) . '</label>
  644. <div class="controls">
  645. <input id="url" name="url" type="url" value="' . esc_attr( $commenter['comment_author_url'] ) . '" size="30" />
  646. </div>
  647. </div>';
  648. }
  649. add_filter( 'comment_form_field_url', 'the_bootstrap_comment_form_field_url');
  650. /**
  651. * Adjusts an attechment link to hold the class of 'thumbnail' and make it look
  652. * pretty
  653. *
  654. * @author Konstantin Obenland
  655. * @since 1.0.0 - 05.02.2012
  656. *
  657. * @param string $link
  658. * @param int $id Post ID.
  659. * @param string $size Default is 'thumbnail'. Size of image, either array or string.
  660. * @param bool $permalink Default is false. Whether to add permalink to image.
  661. * @param bool $icon Default is false. Whether to include icon.
  662. * @param string $text Default is false. If string, then will be link text.
  663. *
  664. * @return string
  665. */
  666. function the_bootstrap_get_attachment_link( $link, $id, $size, $permalink, $icon, $text ) {
  667. return ( ! $text ) ? str_replace( '<a ', '<a class="thumbnail" ', $link ) : $link;
  668. }
  669. add_filter( 'wp_get_attachment_link', 'the_bootstrap_get_attachment_link', 10, 6 );
  670. /**
  671. * Adds the 'hero-unit' class for extra big font on sticky posts
  672. *
  673. * @author Konstantin Obenland
  674. * @since 1.0.0 - 05.02.2012
  675. *
  676. * @param array $classes
  677. *
  678. * @return array
  679. */
  680. function the_bootstrap_post_classes( $classes ) {
  681. if ( is_sticky() AND is_home() ) {
  682. $classes[] = 'hero-unit';
  683. }
  684. return $classes;
  685. }
  686. add_filter( 'post_class', 'the_bootstrap_post_classes' );
  687. /**
  688. * Callback function to display galleries (in HTML5)
  689. *
  690. * @author Konstantin Obenland
  691. * @since 1.0.0 - 05.02.2012
  692. *
  693. * @param string $content
  694. * @param array $attr
  695. *
  696. * @return string
  697. */
  698. function the_bootstrap_post_gallery( $content, $attr ) {
  699. global $instance, $post;
  700. $instance++;
  701. // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
  702. if ( isset( $attr['orderby'] ) ) {
  703. $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
  704. if ( ! $attr['orderby'] )
  705. unset( $attr['orderby'] );
  706. }
  707. extract( shortcode_atts( array(
  708. 'order' => 'ASC',
  709. 'orderby' => 'menu_order ID',
  710. 'id' => $post->ID,
  711. 'itemtag' => 'figure',
  712. 'icontag' => 'div',
  713. 'captiontag' => 'figcaption',
  714. 'columns' => 3,
  715. 'size' => 'thumbnail',
  716. 'include' => '',
  717. 'exclude' => ''
  718. ), $attr ) );
  719. $id = intval( $id );
  720. if ( 'RAND' == $order )
  721. $orderby = 'none';
  722. if ( $include ) {
  723. $include = preg_replace( '/[^0-9,]+/', '', $include );
  724. $_attachments = get_posts( array(
  725. 'include' => $include,
  726. 'post_status' => 'inherit',
  727. 'post_type' => 'attachment',
  728. 'post_mime_type' => 'image',
  729. 'order' => $order,
  730. 'orderby' => $orderby
  731. ) );
  732. $attachments = array();
  733. foreach ( $_attachments as $key => $val ) {
  734. $attachments[$val->ID] = $_attachments[$key];
  735. }
  736. } elseif ( $exclude ) {
  737. $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
  738. $attachments = get_children( array(
  739. 'post_parent' => $id,
  740. 'exclude' => $exclude,
  741. 'post_status' => 'inherit',
  742. 'post_type' => 'attachment',
  743. 'post_mime_type' => 'image',
  744. 'order' => $order,
  745. 'orderby' => $orderby
  746. ) );
  747. } else {
  748. $attachments = get_children( array(
  749. 'post_parent' => $id,
  750. 'post_status' => 'inherit',
  751. 'post_type' => 'attachment',
  752. 'post_mime_type' => 'image',
  753. 'order' => $order,
  754. 'orderby' => $orderby
  755. ) );
  756. }
  757. if ( empty( $attachments ) )
  758. return;
  759. if ( is_feed() ) {
  760. $output = "\n";
  761. foreach ( $attachments as $att_id => $attachment )
  762. $output .= wp_get_attachment_link( $att_id, $size, true ) . "\n";
  763. return $output;
  764. }
  765. $itemtag = tag_escape( $itemtag );
  766. $captiontag = tag_escape( $captiontag );
  767. $columns = intval( min( array( 8, $columns ) ) );
  768. $float = (is_rtl()) ? 'right' : 'left';
  769. if ( 4 > $columns )
  770. $size = 'full';
  771. $selector = "gallery-{$instance}";
  772. $size_class = sanitize_html_class( $size );
  773. $output = "<ul id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class} thumbnails'>";
  774. $i = 0;
  775. foreach ( $attachments as $id => $attachment ) {
  776. $comments = get_comments( array(
  777. 'post_id' => $id,
  778. 'count' => true,
  779. 'type' => 'comment',
  780. 'status' => 'approve'
  781. ) );
  782. $link = wp_get_attachment_link( $id, $size, ! ( isset( $attr['link'] ) AND 'file' == $attr['link'] ) );
  783. $clear_class = ( 0 == $i++ % $columns ) ? ' clear' : '';
  784. $span = 'span' . floor( 8 / $columns );
  785. $output .= "<li class='{$span}{$clear_class}'><{$itemtag} class='gallery-item'>";
  786. $output .= "<{$icontag} class='gallery-icon'>{$link}</{$icontag}>\n";
  787. if ( $captiontag AND ( 0 < $comments OR trim( $attachment->post_excerpt ) ) ) {
  788. $comments = ( 0 < $comments ) ? sprintf( _n('%d comment', '%d comments', $comments, 'the-bootstrap'), $comments ) : '';
  789. $excerpt = wptexturize( $attachment->post_excerpt );
  790. $out = ($comments AND $excerpt) ? " $excerpt <br /> $comments " : " $excerpt$comments ";
  791. $output .= "<{$captiontag} class='wp-caption-text gallery-caption'>{$out}</{$captiontag}>\n";
  792. }
  793. $output .= "</{$itemtag}></li>\n";
  794. }
  795. $output .= "</ul>\n";
  796. return $output;
  797. }
  798. add_filter( 'post_gallery', 'the_bootstrap_post_gallery', 10, 2 );
  799. /**
  800. * HTML 5 caption for pictures
  801. *
  802. * @author Konstantin Obenland
  803. * @since 1.0.0 - 05.02.2012
  804. *
  805. * @param string $empty
  806. * @param array $attr
  807. * @param string $content
  808. *
  809. * @return string
  810. */
  811. function the_bootstrap_img_caption_shortcode( $empty, $attr, $content ) {
  812. extract( shortcode_atts( array(
  813. 'id' => '',
  814. 'align' => 'alignnone',
  815. 'width' => '',
  816. 'caption' => ''
  817. ), $attr ) );
  818. if ( 1 > (int) $width OR empty( $caption ) ) {
  819. return $content;
  820. }
  821. if ( $id ) {
  822. $id = 'id="' . $id . '" ';
  823. }
  824. return '<figure ' . $id . 'class="wp-caption thumbnail ' . $align . '" style="width: '.$width.'px;">
  825. ' . do_shortcode( str_replace( 'class="thumbnail', 'class="', $content ) ) . '
  826. <figcaption class="wp-caption-text">' . $caption . '</figcaption>
  827. </figure>';
  828. }
  829. add_filter( 'img_caption_shortcode', 'the_bootstrap_img_caption_shortcode', 10, 3 );
  830. /**
  831. * Returns a password form which dispalys nicely with Bootstrap
  832. *
  833. * @author Konstantin Obenland
  834. * @since 1.0.0 - 05.02.2012
  835. *
  836. * @param string $form
  837. *
  838. * @return string The Bootstrap password form
  839. */
  840. function the_bootstrap_the_password_form( $form ) {
  841. return '<form class="post-password-form form-horizontal" action="' . home_url( 'wp-pass.php' ) . '" method="post"><legend>'. __( 'This post is password protected. To view it please enter your password below:', 'the-bootstrap' ) . '</legend><div class="control-group"><label class="control-label" for="post-password-' . get_the_ID() . '">' . __( 'Password:', 'the-bootstrap' ) .'</label><div class="controls"><input name="post_password" id="post-password-' . get_the_ID() . '" type="password" size="20" /></div></div><div class="form-actions"><button type="submit" class="post-password-submit submit btn btn-primary">' . __( 'Submit', 'the-bootstrap' ) . '</button></div></form>';
  842. }
  843. add_filter( 'the_password_form', 'the_bootstrap_the_password_form' );
  844. /**
  845. * Modifies the category dropdown args for widgets on 404 pages
  846. *
  847. * @author Konstantin Obenland
  848. * @since 1.5.0 - 19.05.2012
  849. *
  850. * @param array $args
  851. *
  852. * @return array
  853. */
  854. function the_bootstrap_widget_categories_dropdown_args( $args ) {
  855. if ( is_404() ) {
  856. $args = wp_parse_args( $args, array(
  857. 'orderby' => 'count',
  858. 'order' => 'DESC',
  859. 'show_count' => 1,
  860. 'title_li' => '',
  861. 'number' => 10
  862. ) );
  863. }
  864. return $args;
  865. }
  866. add_filter( 'widget_categories_dropdown_args', 'the_bootstrap_widget_categories_dropdown_args' );
  867. /**
  868. * Adds the .thumbnail class when images are sent to editor
  869. *
  870. * @author Konstantin Obenland
  871. * @since 2.0.0 - 29.08.2012
  872. *
  873. * @param string $html
  874. * @param int $id
  875. * @param string $caption
  876. * @param string $title
  877. * @param string $align
  878. * @param string $url
  879. * @param string $size
  880. * @param string $alt
  881. *
  882. * @return string Image HTML
  883. */
  884. function the_bootstrap_image_send_to_editor( $html, $id, $caption, $title, $align, $url, $size, $alt ) {
  885. if ( $url ) {
  886. $html = str_replace( '<a ', '<a class="thumbnail" ', $html );
  887. } else {
  888. $html = str_replace( 'class="', 'class="thumbnail ', $html );
  889. }
  890. return $html;
  891. }
  892. add_filter( 'image_send_to_editor', 'the_bootstrap_image_send_to_editor', 10, 8 );
  893. /**
  894. * Adjusts content_width value for full-width and single image attachment
  895. * templates, and when there are no active widgets in the sidebar.
  896. *
  897. * @author WordPress.org
  898. * @since 2.0.0 - 29.08.2012
  899. *
  900. * @return void
  901. */
  902. function the_bootstrap_content_width() {
  903. if ( is_attachment() ) {
  904. global $content_width;
  905. $content_width = 940;
  906. }
  907. }
  908. add_action( 'template_redirect', 'the_bootstrap_content_width' );
  909. /**
  910. * Returns the Theme version string
  911. *
  912. * @author Konstantin Obenland
  913. * @since 1.2.4 - 07.04.2012
  914. * @access private
  915. *
  916. * @return string The Bootstrap version
  917. */
  918. function _the_bootstrap_version() {
  919. if ( function_exists( 'wp_get_theme' ) ) {
  920. $theme_version = wp_get_theme()->get( 'Version' );
  921. }
  922. else {
  923. $theme_data = get_theme_data( get_template_directory() . '/style.css' );
  924. $theme_version = $theme_data['Version'];
  925. }
  926. return $theme_version;
  927. }
  928. /* End of file functions.php */
  929. /* Location: ./wp-content/themes/the-bootstrap/functions.php */