Timber - Version 1.1.5

Version Description

  • Removed change for custom loaders due to incompatability with Gantry
Download this release

Release Info

Developer jarednova
Plugin Icon 128x128 Timber
Version 1.1.5
Comparing to
See all releases

Code changes from version 1.1.2 to 1.1.5

README.md CHANGED
@@ -1,5 +1,5 @@
1
  <div style="text-align:center">
2
- <a href="http://timber.github.io/timber"><img src="http://i.imgur.com/oM1AHrz.jpg" style="display:block; margin:auto; width:100%; max-width:100%"/></a>
3
  <div>
4
  By Jared Novack (<a href="https://twitter.com/jarednova">@JaredNova</a>) and <a href="http://upstatement.com">Upstatement</a> (<a href="https://twitter.com/upstatement">@Upstatement</a>)</div>
5
  </div>
@@ -111,11 +111,12 @@ Documentation for Timber classes and functions is [auto generated](https://githu
111
  To publish docs:
112
  1. `composer install` if not already run
113
  2. Clone the [timber/slate](https://github.com/timber/slate) repo at the same directory level as Timber
114
- 3. From the root of the slate directory
115
- - `gem install bundler`
116
- - `bundle install` (you'll need at least Ruby 2.0 or newer)
117
- - `sh publish-docs.sh`
118
-
 
119
 
120
 
121
 
1
  <div style="text-align:center">
2
+ <a href="http://timber.github.io/timber"><img src="http://i.imgur.com/PbEwvZ9.png" style="display:block; margin:auto; width:100%; max-width:100%"/></a>
3
  <div>
4
  By Jared Novack (<a href="https://twitter.com/jarednova">@JaredNova</a>) and <a href="http://upstatement.com">Upstatement</a> (<a href="https://twitter.com/upstatement">@Upstatement</a>)</div>
5
  </div>
111
  To publish docs:
112
  1. `composer install` if not already run
113
  2. Clone the [timber/slate](https://github.com/timber/slate) repo at the same directory level as Timber
114
+ 3. From the root of the slate directory, run these commands:
115
+ ```bash
116
+ gem install bundler
117
+ bundle install
118
+ sh publish-docs.sh
119
+ ```
120
 
121
 
122
 
lib/Admin.php CHANGED
@@ -48,18 +48,18 @@ class Admin {
48
 
49
  if ( version_compare("1.0.0", $plugin_data['new_version']) <= 0 ) {
50
  //a version of 1.0.0 or greater is availalbe
51
- $m .= '<p><b>Warning:</b> Timber 1.0 removed a number of features and methods. Before upgrading please test your theme on a local or staging site to ensure that your theme will work with the newest version.</p>
52
 
53
- <p><strong>Is your theme in active development?</strong> That is, is someone actively in PHP files writing new code? If you answered "no", then <i>do not upgrade</i>. You will not benefit from Timber 1.0</p>';
54
 
55
- $m .= '<p>Read the <strong><a href="https://github.com/timber/timber/wiki/1.0-Upgrade-Guide">Upgrade Guide</a></strong> for more information</p>';
56
 
57
- $m .= "<p>You can also <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>upgrade to version 0.22.6</a></b> if you want to upgrade, but are unsure if you're ready for 1.0";
58
 
59
  }
60
 
61
  if ( version_compare("1.0.0", $plugin_data['Version']) <= 0 ) {
62
- $m .= "<p>Are you seeing errors since upgrading to 1.0? Download <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>Version 0.22.6</a></b> to bring things back to stability.";
63
  }
64
 
65
  // show message
48
 
49
  if ( version_compare("1.0.0", $plugin_data['new_version']) <= 0 ) {
50
  //a version of 1.0.0 or greater is availalbe
51
+ $m .= '<br><b>Warning:</b> Timber 1.0 removed a number of features and methods. Before upgrading please test your theme on a local or staging site to ensure that your theme will work with the newest version.<br>
52
 
53
+ <br><strong>Is your theme in active development?</strong> That is, is someone actively in PHP files writing new code? If you answered "no", then <i>do not upgrade</i>. You will not benefit from Timber 1.0<br>';
54
 
55
+ $m .= '<br>Read the <strong><a href="https://github.com/timber/timber/wiki/1.0-Upgrade-Guide">Upgrade Guide</a></strong> for more information<br>';
56
 
57
+ $m .= "<br>You can also <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>upgrade to version 0.22.6</a></b> if you want to upgrade, but are unsure if you're ready for 1.0<br>";
58
 
59
  }
60
 
61
  if ( version_compare("1.0.0", $plugin_data['Version']) <= 0 ) {
62
+ $m .= "<br>Are you seeing errors since upgrading to 1.0? Download <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>Version 0.22.6</a></b> to bring things back to stability.";
63
  }
64
 
65
  // show message
lib/Core.php CHANGED
@@ -117,4 +117,12 @@ abstract class Core {
117
  $ret['can_edit'] = $this->can_edit();
118
  return $ret;
119
  }
 
 
 
 
 
 
 
 
120
  }
117
  $ret['can_edit'] = $this->can_edit();
118
  return $ret;
119
  }
120
+
121
+ /**
122
+ * @param string $field_name
123
+ * @return mixed
124
+ */
125
+ public function get_field( $field_name ) {
126
+ return $this->get_meta_field($field_name);
127
+ }
128
  }
lib/Helper.php CHANGED
@@ -444,6 +444,25 @@ class Helper {
444
  return ($i % 2) != 0;
445
  }
446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  /* Links, Forms, Etc. Utilities
448
  ======================== */
449
 
@@ -465,7 +484,7 @@ class Helper {
465
  * @param array $args
466
  * @return array
467
  */
468
- public static function paginate_links( $args = '' ) {
469
  Helper::warn('Helper/paginate_links has been moved to Pagination/paginate_links');
470
  return Pagination::paginate_links($args);
471
  }
444
  return ($i % 2) != 0;
445
  }
446
 
447
+ /**
448
+ * Plucks the values of a certain key from an array of objects
449
+ * @param array $array
450
+ * @param string $key
451
+ */
452
+ public static function pluck( $array, $key ) {
453
+ $return = array();
454
+ foreach ( $array as $obj ) {
455
+ if ( is_object($obj) && method_exists($obj, $key) ) {
456
+ $return[] = $obj->$key();
457
+ } elseif ( is_object($obj) && property_exists($obj, $key) ) {
458
+ $return[] = $obj->$key;
459
+ } elseif ( isset($obj[$key]) ) {
460
+ $return[] = $obj[$key];
461
+ }
462
+ }
463
+ return $return;
464
+ }
465
+
466
  /* Links, Forms, Etc. Utilities
467
  ======================== */
468
 
484
  * @param array $args
485
  * @return array
486
  */
487
+ public static function paginate_links( $args = array() ) {
488
  Helper::warn('Helper/paginate_links has been moved to Pagination/paginate_links');
489
  return Pagination::paginate_links($args);
490
  }
lib/Integrations.php CHANGED
@@ -2,25 +2,33 @@
2
 
3
  namespace Timber;
4
 
5
- use Timber\Integrations\ACF;
6
-
7
  /**
8
  * This is for integrating external plugins into timber
9
  * @package timber
10
  */
11
  class Integrations {
 
 
 
 
 
 
 
12
 
13
- public static function init() {
14
- add_action('init', array(__CLASS__, 'maybe_init_acf'));
15
 
16
  if ( class_exists('WP_CLI_Command') ) {
17
  \WP_CLI::add_command('timber', 'Timber\Integrations\Timber_WP_CLI_Command');
18
  }
19
  }
20
 
21
- public static function maybe_init_acf() {
22
  if ( class_exists('ACF') ) {
23
- new ACF();
 
 
 
24
  }
25
  }
26
  }
2
 
3
  namespace Timber;
4
 
 
 
5
  /**
6
  * This is for integrating external plugins into timber
7
  * @package timber
8
  */
9
  class Integrations {
10
+
11
+ var $acf;
12
+ var $coauthors_plus;
13
+
14
+ public function __construct() {
15
+ $this->init();
16
+ }
17
 
18
+ public function init() {
19
+ add_action('init', array($this, 'maybe_init_integrations'));
20
 
21
  if ( class_exists('WP_CLI_Command') ) {
22
  \WP_CLI::add_command('timber', 'Timber\Integrations\Timber_WP_CLI_Command');
23
  }
24
  }
25
 
26
+ public function maybe_init_integrations() {
27
  if ( class_exists('ACF') ) {
28
+ $this->acf = new Integrations\ACF();
29
+ }
30
+ if ( class_exists('CoAuthors_Plus') ) {
31
+ $this->coauthors_plus = new Integrations\CoAuthorsPlus();
32
  }
33
  }
34
  }
lib/Integrations/CoAuthorsPlus.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Timber\Integrations;
4
+
5
+ class CoAuthorsPlus {
6
+
7
+ /**
8
+ * @codeCoverageIgnore
9
+ */
10
+ public function __construct() {
11
+ add_filter('timber/post/authors', array($this, 'authors'), 10, 2);
12
+ }
13
+
14
+ /**
15
+ * Filters {{ post.authors }} to return authors stored from Co-Authors Plus
16
+ * @since 1.1.4
17
+ * @param array $author
18
+ * @param Post $post
19
+ * @return array of User objects
20
+ */
21
+ public function authors( $author, $post ) {
22
+ $authors = array();
23
+ $cauthors = get_coauthors($post->ID);
24
+ foreach ( $cauthors as $author ) {
25
+ $authors[] = new \Timber\User($author);
26
+ }
27
+ return $authors;
28
+ }
29
+
30
+ }
lib/Loader.php CHANGED
@@ -35,10 +35,10 @@ class Loader {
35
  }
36
 
37
  /**
38
- * @param string $file
39
- * @param array $data
40
- * @param array|bool $expires
41
- * @param string $cache_mode
42
  * @return bool|string
43
  */
44
  public function render( $file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT ) {
@@ -120,6 +120,7 @@ class Loader {
120
  return new \Twig_Loader_Filesystem($paths);
121
  }
122
 
 
123
  /**
124
  * @return \Twig_Environment
125
  */
@@ -257,7 +258,7 @@ class Loader {
257
  * @param string $key
258
  * @param string|boolean $value
259
  * @param string $group
260
- * @param int $expires
261
  * @param string $cache_mode
262
  * @return string|boolean
263
  */
35
  }
36
 
37
  /**
38
+ * @param string $file
39
+ * @param array $data
40
+ * @param array|boolean $expires (array for options, false for none, integer for # of seconds)
41
+ * @param string $cache_mode
42
  * @return bool|string
43
  */
44
  public function render( $file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT ) {
120
  return new \Twig_Loader_Filesystem($paths);
121
  }
122
 
123
+
124
  /**
125
  * @return \Twig_Environment
126
  */
258
  * @param string $key
259
  * @param string|boolean $value
260
  * @param string $group
261
+ * @param integer $expires
262
  * @param string $cache_mode
263
  * @return string|boolean
264
  */
lib/Pagination.php CHANGED
@@ -85,6 +85,7 @@ class Pagination {
85
  if ( strpos($url, 's=') !== false ) {
86
  return true;
87
  }
 
88
  }
89
 
90
  /**
@@ -93,7 +94,7 @@ class Pagination {
93
  * @param array $args
94
  * @return array
95
  */
96
- public static function paginate_links( $args = '' ) {
97
  $defaults = array(
98
  'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
99
  'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
85
  if ( strpos($url, 's=') !== false ) {
86
  return true;
87
  }
88
+ return false;
89
  }
90
 
91
  /**
94
  * @param array $args
95
  * @return array
96
  */
97
+ public static function paginate_links( $args = array() ) {
98
  $defaults = array(
99
  'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
100
  'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
lib/Post.php CHANGED
@@ -389,9 +389,10 @@ class Post extends Core implements CoreInterface {
389
  */
390
  public function get_preview( $len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '&hellip;' ) {
391
  $text = '';
 
392
  $trimmed = false;
393
  $last_p_tag = null;
394
- if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
395
  if ( $force ) {
396
  $text = Helper::trim_words($this->post_excerpt, $len, false);
397
  $trimmed = true;
@@ -436,10 +437,11 @@ class Post extends Core implements CoreInterface {
436
  }
437
  $read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
438
  if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
439
- $text .= ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore_matches[1]).'</a>';
440
  } elseif ( $readmore ) {
441
- $text .= ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore).'</a>';
442
  }
 
443
  if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
444
  $text .= '</p>';
445
  }
@@ -753,7 +755,13 @@ class Post extends Core implements CoreInterface {
753
  * @return User|null A User object if found, false if not
754
  */
755
  public function author() {
756
- return $this->get_author();
 
 
 
 
 
 
757
  }
758
 
759
  /**
@@ -769,7 +777,7 @@ class Post extends Core implements CoreInterface {
769
  */
770
  public function modified_author() {
771
  $user_id = get_post_meta($this->ID, '_edit_last', true);
772
- return ($user_id ? new User($user_id) : $this->get_author());
773
  }
774
 
775
  /**
@@ -906,6 +914,20 @@ class Post extends Core implements CoreInterface {
906
  return $timber_comments;
907
  }
908
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909
  /**
910
  * Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
911
  * @api
@@ -920,6 +942,9 @@ class Post extends Core implements CoreInterface {
920
  * @return string
921
  */
922
  public function content( $page = 0, $len = -1 ) {
 
 
 
923
  if ( $len == -1 && $page == 0 && $this->_content ) {
924
  return $this->_content;
925
  }
@@ -1040,6 +1065,15 @@ class Post extends Core implements CoreInterface {
1040
  public function format() {
1041
  return get_post_format($this->ID);
1042
  }
 
 
 
 
 
 
 
 
 
1043
 
1044
  /**
1045
  * get the permalink for a post object
@@ -1504,9 +1538,7 @@ class Post extends Core implements CoreInterface {
1504
  * @return User|null
1505
  */
1506
  public function get_author() {
1507
- if ( isset($this->post_author) ) {
1508
- return new User($this->post_author);
1509
- }
1510
  }
1511
 
1512
  /**
389
  */
390
  public function get_preview( $len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '&hellip;' ) {
391
  $text = '';
392
+ $link = '';
393
  $trimmed = false;
394
  $last_p_tag = null;
395
+ if ( isset($this->post_excerpt) && strlen(trim($this->post_excerpt)) ) {
396
  if ( $force ) {
397
  $text = Helper::trim_words($this->post_excerpt, $len, false);
398
  $trimmed = true;
437
  }
438
  $read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
439
  if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
440
+ $link = ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore_matches[1]).'</a>';
441
  } elseif ( $readmore ) {
442
+ $link = ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore).'</a>';
443
  }
444
+ $text .= apply_filters('timber/post/get_preview/read_more_link', $link);
445
  if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
446
  $text .= '</p>';
447
  }
755
  * @return User|null A User object if found, false if not
756
  */
757
  public function author() {
758
+ if ( isset($this->post_author) ) {
759
+ return new User($this->post_author);
760
+ }
761
+ }
762
+
763
+ public function authors() {
764
+ return apply_filters('timber/post/authors', array($this->author()), $this);
765
  }
766
 
767
  /**
777
  */
778
  public function modified_author() {
779
  $user_id = get_post_meta($this->ID, '_edit_last', true);
780
+ return ($user_id ? new User($user_id) : $this->author());
781
  }
782
 
783
  /**
914
  return $timber_comments;
915
  }
916
 
917
+ /**
918
+ * If the Password form is to be shown, show it!
919
+ * @return string|void
920
+ */
921
+ protected function maybe_show_password_form(){
922
+ if ( $this->password_required() ) {
923
+ $show_pw = false;
924
+ $show_pw = apply_filters('timber/post/content/show_password_form_for_protected', $show_pw);
925
+ if ($show_pw) {
926
+ return apply_filters('timber/post/content/password_form', get_the_password_form($this->ID), $this);
927
+ }
928
+ }
929
+ }
930
+
931
  /**
932
  * Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
933
  * @api
942
  * @return string
943
  */
944
  public function content( $page = 0, $len = -1 ) {
945
+ if ( $form = $this->maybe_show_password_form() ) {
946
+ return $form;
947
+ }
948
  if ( $len == -1 && $page == 0 && $this->_content ) {
949
  return $this->_content;
950
  }
1065
  public function format() {
1066
  return get_post_format($this->ID);
1067
  }
1068
+
1069
+ /**
1070
+ * whether post requires password and correct password has been provided
1071
+ * @api
1072
+ * @return boolean
1073
+ */
1074
+ public function password_required() {
1075
+ return post_password_required($this->ID);
1076
+ }
1077
 
1078
  /**
1079
  * get the permalink for a post object
1538
  * @return User|null
1539
  */
1540
  public function get_author() {
1541
+ return $this->author();
 
 
1542
  }
1543
 
1544
  /**
lib/PostGetter.php CHANGED
@@ -9,12 +9,14 @@ class PostGetter {
9
 
10
  /**
11
  * @param mixed $query
12
- * @param string $PostClass
13
  * @return array|bool|null
14
  */
15
  public static function get_post( $query = false, $PostClass = '\Timber\Post' ) {
16
  // if a post id is passed, grab the post directly
17
  if ( is_numeric($query) ) {
 
 
18
  $post = new $PostClass($query);
19
  // get the latest revision if we're dealing with a preview
20
  $posts = PostsCollection::maybe_set_preview(array($post));
@@ -43,7 +45,7 @@ class PostGetter {
43
 
44
  /**
45
  * @param mixed $query
46
- * @param string $PostClass
47
  * @return array|bool|null
48
  */
49
  public static function query_posts( $query = false, $PostClass = '\Timber\Post' ) {
@@ -94,6 +96,35 @@ class PostGetter {
94
  return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
95
  }
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  /**
98
  * @param string|array $arg
99
  * @return boolean
9
 
10
  /**
11
  * @param mixed $query
12
+ * @param string|array $PostClass
13
  * @return array|bool|null
14
  */
15
  public static function get_post( $query = false, $PostClass = '\Timber\Post' ) {
16
  // if a post id is passed, grab the post directly
17
  if ( is_numeric($query) ) {
18
+ $post_type = get_post_type($query);
19
+ $PostClass = PostGetter::get_post_class($post_type, $PostClass);
20
  $post = new $PostClass($query);
21
  // get the latest revision if we're dealing with a preview
22
  $posts = PostsCollection::maybe_set_preview(array($post));
45
 
46
  /**
47
  * @param mixed $query
48
+ * @param string|array $PostClass
49
  * @return array|bool|null
50
  */
51
  public static function query_posts( $query = false, $PostClass = '\Timber\Post' ) {
96
  return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
97
  }
98
 
99
+ /**
100
+ * @param string $post_type
101
+ * @param string|array $post_class
102
+ *
103
+ * @return string
104
+ */
105
+ public static function get_post_class( $post_type, $post_class = '\Timber\Post' ) {
106
+ $post_class = apply_filters( 'Timber\PostClassMap', $post_class );
107
+ $post_class_use = '\Timber\Post';
108
+
109
+ if ( is_array($post_class) ) {
110
+ if ( isset( $post_class[$post_type]) ) {
111
+ $post_class_use = $post_class[$post_type];
112
+ } else {
113
+ Helper::error_log($post_type . ' not found in ' . print_r($post_class, true));
114
+ }
115
+ } elseif ( is_string($post_class) ) {
116
+ $post_class_use = $post_class;
117
+ } else {
118
+ Helper::error_log('Unexpeted value for PostClass: ' . print_r( $post_class, true));
119
+ }
120
+
121
+ if ( !class_exists( $post_class_use ) || !( is_subclass_of($post_class_use, '\Timber\Post') || is_a($post_class_use, '\Timber\Post', true) ) ) {
122
+ Helper::error_log('Class ' . $post_class_use . ' either does not exist or implement \Timber\Post');
123
+ }
124
+
125
+ return $post_class_use;
126
+ }
127
+
128
  /**
129
  * @param string|array $arg
130
  * @return boolean
lib/PostType.php CHANGED
@@ -8,6 +8,9 @@ namespace Timber;
8
  */
9
  class PostType {
10
 
 
 
 
11
  public function __construct( $post_type ) {
12
  $this->slug = $post_type;
13
  $this->init($post_type);
8
  */
9
  class PostType {
10
 
11
+ /**
12
+ * @param string $post_type
13
+ */
14
  public function __construct( $post_type ) {
15
  $this->slug = $post_type;
16
  $this->init($post_type);
lib/PostsCollection.php CHANGED
@@ -18,22 +18,9 @@ class PostsCollection extends \ArrayObject {
18
  $posts = array();
19
  }
20
  foreach ( $posts as $post_object ) {
21
- $post_class_use = $post_class;
22
- if ( is_array($post_class) ) {
23
- $post_type = get_post_type($post_object);
24
- $post_class_use = '\Timber\Post';
25
-
26
- if ( isset($post_class[$post_type]) ) {
27
- $post_class_use = $post_class[$post_type];
28
-
29
- } else {
30
- if ( is_array($post_class) ) {
31
- Helper::error_log($post_type.' of '.$post_object->ID.' not found in '.print_r($post_class, true));
32
- } else {
33
- Helper::error_log($post_type.' not found in '.$post_class);
34
- }
35
- }
36
- }
37
  // Don't create yet another object if $post_object is already of the right type
38
  if ( is_a($post_object, $post_class_use) ) {
39
  $post = $post_object;
18
  $posts = array();
19
  }
20
  foreach ( $posts as $post_object ) {
21
+ $post_type = get_post_type($post_object);
22
+ $post_class_use = PostGetter::get_post_class($post_type, $post_class);
23
+
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  // Don't create yet another object if $post_object is already of the right type
25
  if ( is_a($post_object, $post_class_use) ) {
26
  $post = $post_object;
lib/QueryIterator.php CHANGED
@@ -10,7 +10,7 @@ if ( !defined('ABSPATH') ) {
10
  exit;
11
  }
12
 
13
- class QueryIterator implements \Iterator {
14
 
15
  /**
16
  *
@@ -22,6 +22,7 @@ class QueryIterator implements \Iterator {
22
 
23
  public function __construct( $query = false, $posts_class = 'Timber\Post' ) {
24
  add_action('pre_get_posts', array($this, 'fix_number_posts_wp_quirk'));
 
25
  if ( $posts_class ) {
26
  $this->_posts_class = $posts_class;
27
  }
@@ -148,6 +149,16 @@ class QueryIterator implements \Iterator {
148
  return $query;
149
  }
150
 
 
 
 
 
 
 
 
 
 
 
151
  /**
152
  * this will test for whether a custom page to display posts is active, and if so, set the query to the default
153
  * @param WP_Query $query the original query recived from WordPress
@@ -162,4 +173,21 @@ class QueryIterator implements \Iterator {
162
  return $query;
163
  }
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  }
10
  exit;
11
  }
12
 
13
+ class QueryIterator implements \Iterator, \Countable {
14
 
15
  /**
16
  *
22
 
23
  public function __construct( $query = false, $posts_class = 'Timber\Post' ) {
24
  add_action('pre_get_posts', array($this, 'fix_number_posts_wp_quirk'));
25
+ add_action('pre_get_posts', array($this, 'fix_cat_wp_quirk'));
26
  if ( $posts_class ) {
27
  $this->_posts_class = $posts_class;
28
  }
149
  return $query;
150
  }
151
 
152
+ //get_posts uses category, WP_Query uses cat. Why? who knows...
153
+ public static function fix_cat_wp_quirk( $query ) {
154
+ if ( isset($query->query) && isset($query->query['category'])
155
+ && !isset($query->query['cat']) ) {
156
+ $query->set('cat', $query->query['category']);
157
+ unset($query->query['category']);
158
+ }
159
+ return $query;
160
+ }
161
+
162
  /**
163
  * this will test for whether a custom page to display posts is active, and if so, set the query to the default
164
  * @param WP_Query $query the original query recived from WordPress
173
  return $query;
174
  }
175
 
176
+ /**
177
+ * Count elements of an object.
178
+ *
179
+ * Necessary for some Twig `loop` variable properties.
180
+ * @see http://twig.sensiolabs.org/doc/tags/for.html#the-loop-variable
181
+ *
182
+ * @link http://php.net/manual/en/countable.count.php
183
+ * @return int The custom count as an integer.
184
+ * </p>
185
+ * <p>
186
+ * The return value is cast to an integer.
187
+ * @since 5.1.0
188
+ */
189
+ public function count()
190
+ {
191
+ return $this->post_count();
192
+ }
193
  }
lib/TermGetter.php CHANGED
@@ -11,7 +11,7 @@ class TermGetter {
11
  * @param string $taxonomy
12
  * @return Timber\Term|WP_Error|null
13
  */
14
- public static function get_term( $term, $taxonomy, $TermClass = 'Term' ) {
15
  $term = get_term($term, $taxonomy);
16
  return new $TermClass($term->term_id, $term->taxonomy);
17
  }
@@ -22,7 +22,7 @@ class TermGetter {
22
  * @param string $TermClass
23
  * @return mixed
24
  */
25
- public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'Term' ) {
26
  if ( is_string($maybe_args) && !strstr($maybe_args, '=') ) {
27
  //the user is sending the $TermClass in the second argument
28
  $TermClass = $maybe_args;
11
  * @param string $taxonomy
12
  * @return Timber\Term|WP_Error|null
13
  */
14
+ public static function get_term( $term, $taxonomy, $TermClass = '\Timber\Term' ) {
15
  $term = get_term($term, $taxonomy);
16
  return new $TermClass($term->term_id, $term->taxonomy);
17
  }
22
  * @param string $TermClass
23
  * @return mixed
24
  */
25
+ public static function get_terms( $args = null, $maybe_args = array(), $TermClass = '\Timber\Term' ) {
26
  if ( is_string($maybe_args) && !strstr($maybe_args, '=') ) {
27
  //the user is sending the $TermClass in the second argument
28
  $TermClass = $maybe_args;
lib/Timber.php CHANGED
@@ -35,7 +35,7 @@ use Timber\Loader;
35
  */
36
  class Timber {
37
 
38
- public static $version = '1.1.2';
39
  public static $locations;
40
  public static $dirname = 'views';
41
  public static $twig_cache = false;
@@ -56,7 +56,7 @@ class Timber {
56
  $this->test_compatibility();
57
  $this->backwards_compatibility();
58
  $this->init_constants();
59
- $this::init();
60
  }
61
  }
62
 
@@ -103,12 +103,12 @@ class Timber {
103
  /**
104
  * @codeCoverageIgnore
105
  */
106
- protected static function init() {
107
  if ( class_exists('\WP') && !defined('TIMBER_LOADED') ) {
108
  Twig::init();
109
  ImageHelper::init();
110
  Admin::init();
111
- Integrations::init();
112
  define('TIMBER_LOADED', true);
113
  }
114
  }
@@ -120,7 +120,7 @@ class Timber {
120
  * Get post.
121
  * @api
122
  * @param mixed $query
123
- * @param string $PostClass
124
  * @return array|bool|null
125
  */
126
  public static function get_post( $query = false, $PostClass = 'Timber\Post' ) {
@@ -225,7 +225,7 @@ class Timber {
225
  */
226
  public static function get_context() {
227
  if ( empty(self::$context_cache) ) {
228
- self::$context_cache['http_host'] = 'http://'.URLHelper::get_host();
229
  self::$context_cache['wp_title'] = Helper::get_wp_title();
230
  self::$context_cache['wp_head'] = Helper::function_wrapper('wp_head');
231
  self::$context_cache['wp_footer'] = Helper::function_wrapper('wp_footer');
@@ -252,7 +252,7 @@ class Timber {
252
  * @api
253
  * @param array $filenames
254
  * @param array $data
255
- * @param bool $expires
256
  * @param string $cache_mode
257
  * @param bool $via_render
258
  * @return bool|string
@@ -324,9 +324,9 @@ class Timber {
324
  * @api
325
  * @param array $filenames
326
  * @param array $data
327
- * @param bool $expires
328
  * @param string $cache_mode
329
- * @return bool|string
330
  */
331
  public static function render( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
332
  $output = self::fetch($filenames, $data, $expires, $cache_mode);
35
  */
36
  class Timber {
37
 
38
+ public static $version = '1.1.5';
39
  public static $locations;
40
  public static $dirname = 'views';
41
  public static $twig_cache = false;
56
  $this->test_compatibility();
57
  $this->backwards_compatibility();
58
  $this->init_constants();
59
+ $this->init();
60
  }
61
  }
62
 
103
  /**
104
  * @codeCoverageIgnore
105
  */
106
+ protected function init() {
107
  if ( class_exists('\WP') && !defined('TIMBER_LOADED') ) {
108
  Twig::init();
109
  ImageHelper::init();
110
  Admin::init();
111
+ new Integrations();
112
  define('TIMBER_LOADED', true);
113
  }
114
  }
120
  * Get post.
121
  * @api
122
  * @param mixed $query
123
+ * @param string|array $PostClass
124
  * @return array|bool|null
125
  */
126
  public static function get_post( $query = false, $PostClass = 'Timber\Post' ) {
225
  */
226
  public static function get_context() {
227
  if ( empty(self::$context_cache) ) {
228
+ self::$context_cache['http_host'] = URLHelper::get_scheme().'://'.URLHelper::get_host();
229
  self::$context_cache['wp_title'] = Helper::get_wp_title();
230
  self::$context_cache['wp_head'] = Helper::function_wrapper('wp_head');
231
  self::$context_cache['wp_footer'] = Helper::function_wrapper('wp_footer');
252
  * @api
253
  * @param array $filenames
254
  * @param array $data
255
+ * @param boolean|integer $expires
256
  * @param string $cache_mode
257
  * @param bool $via_render
258
  * @return bool|string
324
  * @api
325
  * @param array $filenames
326
  * @param array $data
327
+ * @param boolean|integer $expires
328
  * @param string $cache_mode
329
+ * @return boolean|string
330
  */
331
  public static function render( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
332
  $output = self::fetch($filenames, $data, $expires, $cache_mode);
lib/Twig.php CHANGED
@@ -61,6 +61,8 @@ class Twig {
61
  $twig->addFilter(new \Twig_SimpleFilter('wpautop', 'wpautop'));
62
  $twig->addFilter(new \Twig_SimpleFilter('list', array($this, 'add_list_separators')));
63
 
 
 
64
  $twig->addFilter(new \Twig_SimpleFilter('relative', function( $link ) {
65
  return URLHelper::get_rel_url($link, true);
66
  } ));
@@ -217,12 +219,20 @@ class Twig {
217
  */
218
  public function add_timber_escapers( $twig ) {
219
 
220
- $twig->getExtension( 'core' )->setEscaper( 'esc_url', function( \Twig_Environment $env, $string ) {
221
  return esc_url( $string );
222
- } );
223
- $twig->getExtension( 'core' )->setEscaper( 'wp_kses_post', function( \Twig_Environment $env, $string ) {
224
  return wp_kses_post( $string );
225
- } );
 
 
 
 
 
 
 
 
226
 
227
  return $twig;
228
 
61
  $twig->addFilter(new \Twig_SimpleFilter('wpautop', 'wpautop'));
62
  $twig->addFilter(new \Twig_SimpleFilter('list', array($this, 'add_list_separators')));
63
 
64
+ $twig->addFilter(new \Twig_SimpleFilter('pluck', array('Timber\Helper', 'pluck')));
65
+
66
  $twig->addFilter(new \Twig_SimpleFilter('relative', function( $link ) {
67
  return URLHelper::get_rel_url($link, true);
68
  } ));
219
  */
220
  public function add_timber_escapers( $twig ) {
221
 
222
+ $twig->getExtension('core')->setEscaper('esc_url', function( \Twig_Environment $env, $string ) {
223
  return esc_url( $string );
224
+ });
225
+ $twig->getExtension('core')->setEscaper('wp_kses_post', function( \Twig_Environment $env, $string ) {
226
  return wp_kses_post( $string );
227
+ });
228
+
229
+ $twig->getExtension('core')->setEscaper('esc_html', function( \Twig_Environment $env, $string ) {
230
+ return esc_html( $string );
231
+ });
232
+
233
+ $twig->getExtension('core')->setEscaper('esc_js', function( \Twig_Environment $env, $string ) {
234
+ return esc_js( $string );
235
+ });
236
 
237
  return $twig;
238
 
lib/URLHelper.php CHANGED
@@ -10,10 +10,7 @@ class URLHelper {
10
  * @return string
11
  */
12
  public static function get_current_url() {
13
- $pageURL = "http://";
14
- if ( isset($_SERVER['HTTPS']) && $_SERVER["HTTPS"] == "on" ) {
15
- $pageURL = "https://"; ;
16
- }
17
  if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
18
  $pageURL .= self::get_host().":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
19
  } else {
@@ -22,6 +19,17 @@ class URLHelper {
22
  return $pageURL;
23
  }
24
 
 
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  *
27
  *
10
  * @return string
11
  */
12
  public static function get_current_url() {
13
+ $pageURL = self::get_scheme()."://";
 
 
 
14
  if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
15
  $pageURL .= self::get_host().":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
16
  } else {
19
  return $pageURL;
20
  }
21
 
22
+ /**
23
+ *
24
+ * Get url scheme
25
+ * @return string
26
+ */
27
+ public static function get_scheme()
28
+ {
29
+ return isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
30
+ }
31
+
32
+
33
  /**
34
  *
35
  *
lib/User.php CHANGED
@@ -203,7 +203,7 @@ class User extends Core implements CoreInterface {
203
  * @return string the human-friendly name of the user (ex: "Buster Bluth")
204
  */
205
  public function name() {
206
- return $this->display_name;
207
  }
208
 
209
  /**
203
  * @return string the human-friendly name of the user (ex: "Buster Bluth")
204
  */
205
  public function name() {
206
+ return apply_filters('timber/user/name', $this->display_name, $this);
207
  }
208
 
209
  /**
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: jarednova, connorjburton, lggorman
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.7
5
- Stable tag: 1.1.2
6
- Tested up to: 4.5.1
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -41,6 +41,23 @@ Timber is great for any WordPress developer who cares about writing good, mainta
41
 
42
  == Changelog ==
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  = 1.1.2 =
45
  * Fix to how post IDs are retrieved (thanks @lggorman) 798acd90ee603de2d009828127bdeaab503beb10
46
  * Fixes to pagination in search (@jarednova) 1d1ab67f124b02d8c60646f7b133abdf68cedc38
2
  Contributors: jarednova, connorjburton, lggorman
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.7
5
+ Stable tag: 1.1.5
6
+ Tested up to: 4.6
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
41
 
42
  == Changelog ==
43
 
44
+ = 1.1.5 =
45
+ * Removed change for custom loaders due to incompatability with Gantry
46
+
47
+ = 1.1.4 =
48
+ * Native support for Co-Authors Plus! just use `{{ post.authors }}` 939331e282fd54bf3e210645964504304f2b071b
49
+ * New filter to enable PW propmpt for PW protected posts (`timber/post/content/show_password_form_for_protected`) 0f9b20ec90b34059634c25bc27671875c18f8fcb
50
+ * New filter for custom loaders (`timber/loader/custom`) (thanks @tnottu!) 9097984a7c3df23068056d7835465e0690338567
51
+ * Fixed some updating bugs with 4.6 (thanks @daronspence) 16b8bd71571be71b298e6306abe2cd4b95d8c9e8
52
+ * You can now count Query results (thanks Evan Mattson) 141624a0ac18d9dcce62a2a681134009a2b79814
53
+
54
+ = 1.1.3 =
55
+ * New escapers! (thanks @matgargano) c7e8ed34da6fcd13bdc9005c04045f3a6b33595b
56
+ * Fix to how categories work in Timber::get_posts 49f6007db3f829097f82ed41d389dd39053fb84a
57
+ * Fix to usage of class maps in Timber::get_posts (thanks @vilpersson) b1387e443850aa021a0a70203bc20d238d4b21cb
58
+ * Added Post::password_required method (thanks @marclarr) 2e685ce3d05c50e879817e51256202e032e77122
59
+ * You can filter the link markup for Post::get_preview (thanks @LiljebergXYZ) b8100d7f2601b4da40bcc0a873c071b6ecf267f1
60
+
61
  = 1.1.2 =
62
  * Fix to how post IDs are retrieved (thanks @lggorman) 798acd90ee603de2d009828127bdeaab503beb10
63
  * Fixes to pagination in search (@jarednova) 1d1ab67f124b02d8c60646f7b133abdf68cedc38
timber.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Timber
4
  Description: The WordPress Timber Library allows you to write themes using the power Twig templates.
5
  Plugin URI: http://timber.upstatement.com
6
  Author: Jared Novack + Upstatement
7
- Version: 1.1.2
8
  Author URI: http://upstatement.com/
9
  */
10
  // we look for Composer files first in the plugins dir.
4
  Description: The WordPress Timber Library allows you to write themes using the power Twig templates.
5
  Plugin URI: http://timber.upstatement.com
6
  Author: Jared Novack + Upstatement
7
+ Version: 1.1.5
8
  Author URI: http://upstatement.com/
9
  */
10
  // we look for Composer files first in the plugins dir.
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit3701eb9722a15708b95271247100bacc::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit9f0793d7d7bccbafe546583c0f31b05a::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit3701eb9722a15708b95271247100bacc
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit3701eb9722a15708b95271247100bacc
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit3701eb9722a15708b95271247100bacc', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit3701eb9722a15708b95271247100bacc', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit9f0793d7d7bccbafe546583c0f31b05a
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit9f0793d7d7bccbafe546583c0f31b05a', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit9f0793d7d7bccbafe546583c0f31b05a', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {