Timber - Version 0.20.2

Version Description

Download this release

Release Info

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

Code changes from version 0.20.1 to 0.20.2

functions/integrations/acf-timber.php CHANGED
@@ -50,7 +50,7 @@ class ACFTimber {
50
  return $fields;
51
  }
52
 
53
- function user_get_meta_field( $value, $field, $uid ) {
54
  return get_field( $field, 'user_' . $uid );
55
  }
56
  }
50
  return $fields;
51
  }
52
 
53
+ function user_get_meta_field( $value, $uid, $field ) {
54
  return get_field( $field, 'user_' . $uid );
55
  }
56
  }
functions/timber-helper.php CHANGED
@@ -222,6 +222,8 @@ class TimberHelper {
222
  unset( $closedtags[array_search( $openedtags[$i], $closedtags )] );
223
  }
224
  }
 
 
225
  return $html;
226
  }
227
 
222
  unset( $closedtags[array_search( $openedtags[$i], $closedtags )] );
223
  }
224
  }
225
+ $html = str_replace(array('</br>','</hr>','</wbr>'), '', $html);
226
+ $html = str_replace(array('<br>','<hr>','<wbr>'), array('<br />','<hr />','<wbr />'), $html);
227
  return $html;
228
  }
229
 
functions/timber-menu-item.php CHANGED
@@ -6,7 +6,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
6
  public $has_child_class = false;
7
 
8
  public $classes = array();
9
- public $class;
10
  public $post_name;
11
  public $type;
12
 
@@ -131,7 +131,9 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
131
  * @param object $data
132
  */
133
  function import_classes( $data ) {
134
- $this->class = trim( implode( ' ', $data->classes ) );
 
 
135
  }
136
 
137
  /**
6
  public $has_child_class = false;
7
 
8
  public $classes = array();
9
+ public $class = '';
10
  public $post_name;
11
  public $type;
12
 
131
  * @param object $data
132
  */
133
  function import_classes( $data ) {
134
+ $this->classes = array_merge($this->classes, $data->classes);
135
+ $this->classes = array_unique($this->classes);
136
+ $this->class = trim( implode( ' ', $this->classes ) );
137
  }
138
 
139
  /**
functions/timber-menu.php CHANGED
@@ -38,6 +38,7 @@ class TimberMenu extends TimberCore {
38
  */
39
  private function init($menu_id) {
40
  $menu = wp_get_nav_menu_items($menu_id);
 
41
  if (is_array($menu)){
42
  $menu = self::order_children($menu);
43
  }
@@ -46,6 +47,7 @@ class TimberMenu extends TimberCore {
46
  $this->import($menu_info);
47
  $this->ID = $this->term_id;
48
  $this->id = $this->term_id;
 
49
  }
50
 
51
  /**
@@ -115,9 +117,14 @@ class TimberMenu extends TimberCore {
115
  foreach ($items as $item) {
116
  if(isset($item->ID)){
117
  if (is_object($item) && get_class($item) == 'WP_Post'){
 
118
  $item = new $this->PostClass($item);
119
  }
120
- $index[$item->ID] = new $this->MenuItemClass($item);
 
 
 
 
121
  }
122
  }
123
  foreach ($index as $item) {
38
  */
39
  private function init($menu_id) {
40
  $menu = wp_get_nav_menu_items($menu_id);
41
+ _wp_menu_item_classes_by_context($menu);
42
  if (is_array($menu)){
43
  $menu = self::order_children($menu);
44
  }
47
  $this->import($menu_info);
48
  $this->ID = $this->term_id;
49
  $this->id = $this->term_id;
50
+ $this->title = $this->name;
51
  }
52
 
53
  /**
117
  foreach ($items as $item) {
118
  if(isset($item->ID)){
119
  if (is_object($item) && get_class($item) == 'WP_Post'){
120
+ $old_menu_item = $item;
121
  $item = new $this->PostClass($item);
122
  }
123
+ $menu_item = new $this->MenuItemClass($item);
124
+ if (isset($old_menu_item)){
125
+ $menu_item->import_classes($old_menu_item);
126
+ }
127
+ $index[$item->ID] = $menu_item;
128
  }
129
  }
130
  foreach ($index as $item) {
functions/timber-post-getter.php CHANGED
@@ -1,24 +1,31 @@
1
  <?php
2
 
3
- class TimberPostGetter
4
- {
5
 
6
  /**
7
  * @param mixed $query
8
  * @param string $PostClass
9
  * @return array|bool|null
10
  */
11
- public static function get_post($query = false, $PostClass = 'TimberPost') {
12
  $posts = self::get_posts( $query, $PostClass );
13
- if ( $post = reset( $posts ) ) {
14
  return $post;
15
  }
16
  return false;
17
  }
18
 
19
- public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
20
  $posts = self::query_posts( $query, $PostClass );
21
- return $posts->get_posts( $return_collection );
 
 
 
 
 
 
 
 
22
  }
23
 
24
  /**
@@ -26,7 +33,7 @@ class TimberPostGetter
26
  * @param string $PostClass
27
  * @return array|bool|null
28
  */
29
- public static function query_posts($query = false, $PostClass = 'TimberPost'){
30
  if (self::is_post_class_or_class_map($query)) {
31
  $PostClass = $query;
32
  $query = false;
@@ -47,7 +54,7 @@ class TimberPostGetter
47
  }
48
  }
49
 
50
- public static function get_pids($query){
51
  $posts = self::get_posts($query);
52
  $pids = array();
53
  foreach($posts as $post){
@@ -88,6 +95,20 @@ class TimberPostGetter
88
  return new TimberPostsCollection( $posts, $PostClass );
89
  }
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  /**
92
  * @return bool
93
  */
@@ -113,4 +134,4 @@ class TimberPostGetter
113
  }
114
  return false;
115
  }
116
- }
1
  <?php
2
 
3
+ class TimberPostGetter {
 
4
 
5
  /**
6
  * @param mixed $query
7
  * @param string $PostClass
8
  * @return array|bool|null
9
  */
10
+ static function get_post($query = false, $PostClass = 'TimberPost') {
11
  $posts = self::get_posts( $query, $PostClass );
12
+ if ( $post = reset($posts ) ) {
13
  return $post;
14
  }
15
  return false;
16
  }
17
 
18
+ static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
19
  $posts = self::query_posts( $query, $PostClass );
20
+ return apply_filters('timber_post_getter_get_posts', $posts->get_posts( $return_collection ));
21
+ }
22
+
23
+ static function query_post( $query = false, $PostClass = 'TimberPost' ) {
24
+ $posts = self::query_posts( $query, $PostClass );
25
+ if ( $post = $posts->current() ) {
26
+ return $post;
27
+ }
28
+ return false;
29
  }
30
 
31
  /**
33
  * @param string $PostClass
34
  * @return array|bool|null
35
  */
36
+ static function query_posts($query = false, $PostClass = 'TimberPost' ){
37
  if (self::is_post_class_or_class_map($query)) {
38
  $PostClass = $query;
39
  $query = false;
54
  }
55
  }
56
 
57
+ static function get_pids($query){
58
  $posts = self::get_posts($query);
59
  $pids = array();
60
  foreach($posts as $post){
95
  return new TimberPostsCollection( $posts, $PostClass );
96
  }
97
 
98
+ static function loop_to_id() {
99
+ if (!self::wp_query_has_posts()) { return false; }
100
+
101
+ global $wp_query;
102
+ $post_num = property_exists($wp_query, 'current_post')
103
+ ? $wp_query->current_post + 1
104
+ : 0
105
+ ;
106
+
107
+ if (!isset($wp_query->posts[$post_num])) { return false; }
108
+
109
+ return $wp_query->posts[$post_num]->ID;
110
+ }
111
+
112
  /**
113
  * @return bool
114
  */
134
  }
135
  return false;
136
  }
137
+ }
functions/timber-post.php CHANGED
@@ -33,7 +33,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
33
  if ($pid === null && get_the_ID()) {
34
  $pid = get_the_ID();
35
  $this->ID = $pid;
36
- } else if ($pid === null && ($pid_from_loop = Timber::loop_to_id())) {
37
  $this->ID = $pid_from_loop;
38
  }
39
  if (is_numeric($pid)) {
@@ -42,6 +42,14 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
42
  $this->init($pid);
43
  }
44
 
 
 
 
 
 
 
 
 
45
  /**
46
  * @param int|bool $pid
47
  */
@@ -284,29 +292,28 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
284
  }
285
 
286
  /**
287
- * @param bool $by_taxonomy
288
  * @return mixed
289
  */
290
- function get_next($by_taxonomy = false) {
291
- if (!isset($this->_next) || !isset($this->_next[$by_taxonomy])) {
292
  global $post;
293
  $this->_next = array();
294
  $old_global = $post;
295
  $post = $this;
296
- if ($by_taxonomy == 'category' || $by_taxonomy == 'categories') {
297
- $in_same_cat = true;
298
  } else {
299
- $in_same_cat = false;
300
  }
301
- $adjacent = get_adjacent_post($in_same_cat, '', false);
302
  if ($adjacent) {
303
- $this->_next[$by_taxonomy] = new $this->PostClass($adjacent);
304
  } else {
305
- $this->_next[$by_taxonomy] = false;
306
  }
307
  $post = $old_global;
308
  }
309
- return $this->_next[$by_taxonomy];
310
  }
311
 
312
  /**
@@ -360,29 +367,30 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
360
  }
361
 
362
  /**
363
- * @param bool $by_taxonomy
364
  * @return mixed
365
  */
366
- function get_prev($by_taxonomy = false) {
367
- if (!isset($this->_prev) || !isset($this->_prev[$by_taxonomy])) {
368
  global $post;
369
  $this->_prev = array();
370
  $old_global = $post;
371
  $post = $this;
372
- if ($by_taxonomy == 'category' || $by_taxonomy == 'categories') {
373
- $in_same_cat = true;
 
374
  } else {
375
- $in_same_cat = false;
376
  }
377
- $adjacent = get_adjacent_post($in_same_cat, '', true);
378
  if ($adjacent) {
379
- $this->_prev[$by_taxonomy] = new $this->PostClass($adjacent);
380
  } else {
381
- $this->_prev[$by_taxonomy] = false;
382
  }
383
  $post = $old_global;
384
  }
385
- return $this->_prev[$by_taxonomy];
386
  }
387
 
388
  /**
@@ -560,6 +568,9 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
560
  * @return array
561
  */
562
  function get_terms($tax = '', $merge = true, $TermClass = 'TimberTerm') {
 
 
 
563
  if (is_string($tax)) {
564
  if (isset($this->_get_terms) && isset($this->_get_terms[$tax])) {
565
  return $this->_get_terms[$tax];
@@ -827,8 +838,8 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
827
  /**
828
  * @return array
829
  */
830
- public function children() {
831
- return $this->get_children();
832
  }
833
 
834
  /**
33
  if ($pid === null && get_the_ID()) {
34
  $pid = get_the_ID();
35
  $this->ID = $pid;
36
+ } else if ($pid === null && ($pid_from_loop = TimberPostGetter::loop_to_id())) {
37
  $this->ID = $pid_from_loop;
38
  }
39
  if (is_numeric($pid)) {
42
  $this->init($pid);
43
  }
44
 
45
+ /**
46
+ * @return string
47
+ */
48
+ function __toString() {
49
+ return $this->title();
50
+ }
51
+
52
+
53
  /**
54
  * @param int|bool $pid
55
  */
292
  }
293
 
294
  /**
295
+ * @param bool $taxonomy
296
  * @return mixed
297
  */
298
+ function get_next($taxonomy = false) {
299
+ if (!isset($this->_next) || !isset($this->_next[$taxonomy])) {
300
  global $post;
301
  $this->_next = array();
302
  $old_global = $post;
303
  $post = $this;
304
+ if ($taxonomy) {
305
+ $adjacent = get_adjacent_post(true, '', false, $taxonomy);
306
  } else {
307
+ $adjacent = get_adjacent_post(false, '', false);
308
  }
 
309
  if ($adjacent) {
310
+ $this->_next[$taxonomy] = new $this->PostClass($adjacent);
311
  } else {
312
+ $this->_next[$taxonomy] = false;
313
  }
314
  $post = $old_global;
315
  }
316
+ return $this->_next[$taxonomy];
317
  }
318
 
319
  /**
367
  }
368
 
369
  /**
370
+ * @param bool $taxonomy
371
  * @return mixed
372
  */
373
+ function get_prev($taxonomy = false) {
374
+ if (!isset($this->_prev) || !isset($this->_prev[$taxonomy])) {
375
  global $post;
376
  $this->_prev = array();
377
  $old_global = $post;
378
  $post = $this;
379
+ $in_same_cat = false;
380
+ if ($taxonomy) {
381
+ $adjacent = get_adjacent_post(true, '', true, $taxonomy);
382
  } else {
383
+ $adjacent = get_adjacent_post(false, '', true);
384
  }
385
+
386
  if ($adjacent) {
387
+ $this->_prev[$taxonomy] = new $this->PostClass($adjacent);
388
  } else {
389
+ $this->_prev[$taxonomy] = false;
390
  }
391
  $post = $old_global;
392
  }
393
+ return $this->_prev[$taxonomy];
394
  }
395
 
396
  /**
568
  * @return array
569
  */
570
  function get_terms($tax = '', $merge = true, $TermClass = 'TimberTerm') {
571
+ if (is_string($merge) && class_exists($merge)){
572
+ $TermClass = $merge;
573
+ }
574
  if (is_string($tax)) {
575
  if (isset($this->_get_terms) && isset($this->_get_terms[$tax])) {
576
  return $this->_get_terms[$tax];
838
  /**
839
  * @return array
840
  */
841
+ public function children( $post_type = 'any', $childPostClass = false ) {
842
+ return $this->get_children( $post_type, $childPostClass );
843
  }
844
 
845
  /**
functions/timber-query-iterator.php CHANGED
@@ -67,7 +67,7 @@ class TimberQueryIterator implements Iterator {
67
  'post_type'=> 'any',
68
  'post__in' => $query,
69
  'orderby' => 'post__in',
70
- 'numberposts' => -1
71
  ) );
72
  }
73
 
67
  'post_type'=> 'any',
68
  'post__in' => $query,
69
  'orderby' => 'post__in',
70
+ 'nopaging' => true
71
  ) );
72
  }
73
 
functions/timber-routes.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class TimberRoutes {
4
+
5
+ protected $router;
6
+
7
+ function __construct(){
8
+ add_action('init', array($this, 'init'));
9
+ }
10
+
11
+ function init() {
12
+ global $timber;
13
+ if (isset($timber->router)) {
14
+ $route = $timber->router->matchCurrentRequest();
15
+ if ($route) {
16
+ $callback = $route->getTarget();
17
+ $params = $route->getParameters();
18
+ $callback($params);
19
+ }
20
+ }
21
+ }
22
+
23
+ public static function add_route($route, $callback, $args = array()) {
24
+ global $timber;
25
+ if (!isset($timber->router)) {
26
+ if (class_exists('PHPRouter\Router')){
27
+ $timber->router = new PHPRouter\Router();
28
+ $site_url = get_bloginfo('url');
29
+ $site_url_parts = explode('/', $site_url);
30
+ $site_url_parts = array_slice($site_url_parts, 3);
31
+ $base_path = implode('/', $site_url_parts);
32
+ if (!$base_path || strpos($route, $base_path) === 0) {
33
+ $base_path = '/';
34
+ } else {
35
+ $base_path = '/' . $base_path . '/';
36
+ }
37
+ $timber->router->setBasePath($base_path);
38
+ }
39
+ }
40
+ if (class_exists('PHPRouter\Router')){
41
+ $timber->router->map($route, $callback, $args);
42
+ }
43
+ }
44
+
45
+ /**
46
+ * @param array $template
47
+ * @param mixed $query
48
+ * @param int $status_code
49
+ * @param bool $tparams
50
+ * @return bool
51
+ */
52
+ public static function load_view($template, $query = false, $status_code = 200, $tparams = false) {
53
+ $fullPath = is_readable($template);
54
+ if (!$fullPath) {
55
+ $template = locate_template($template);
56
+ }
57
+ if ($tparams){
58
+ global $params;
59
+ $params = $tparams;
60
+ }
61
+ if ($status_code) {
62
+ add_filter('status_header', function($status_header, $header, $text, $protocol) use ($status_code) {
63
+ $text = get_status_header_desc($status_code);
64
+ $header_string = "$protocol $status_code $text";
65
+ return $header_string;
66
+ }, 10, 4 );
67
+ if (404 != $status_code) {
68
+ add_action('parse_query', function($query) {
69
+ if ($query->is_main_query()){
70
+ $query->is_404 = false;
71
+ }
72
+ },1);
73
+ add_action('template_redirect', function(){
74
+ global $wp_query;
75
+ $wp_query->is_404 = false;
76
+ },1);
77
+ }
78
+ }
79
+
80
+ if ($query) {
81
+ add_action('do_parse_request', function() use ($query) {
82
+ global $wp;
83
+ if ( is_callable($query) )
84
+ $query = call_user_func($query);
85
+
86
+ if ( is_array($query) )
87
+ $wp->query_vars = $query;
88
+ elseif ( !empty($query) )
89
+ parse_str($query, $wp->query_vars);
90
+ else
91
+ return true; // Could not interpret query. Let WP try.
92
+
93
+ return false;
94
+ });
95
+ }
96
+ if ($template) {
97
+ add_filter('template_include', function($t) use ($template) {
98
+ return $template;
99
+ });
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ }
105
+
106
+ global $timberRoutes;
107
+ $timberRoutes = new TimberRoutes();
functions/timber-site.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  class TimberSite extends TimberCore implements TimberCoreInterface {
4
 
 
5
  public $blogname;
6
  public $charset;
7
  public $description;
@@ -55,6 +56,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
55
  }
56
 
57
  function init() {
 
58
  $this->name = get_bloginfo( 'name' );
59
  $this->title = $this->name;
60
  $this->description = get_bloginfo( 'description' );
2
 
3
  class TimberSite extends TimberCore implements TimberCoreInterface {
4
 
5
+ public $admin_email;
6
  public $blogname;
7
  public $charset;
8
  public $description;
56
  }
57
 
58
  function init() {
59
+ $this->admin_email = get_bloginfo( 'admin_email' );
60
  $this->name = get_bloginfo( 'name' );
61
  $this->title = $this->name;
62
  $this->description = get_bloginfo( 'description' );
functions/timber-url-helper.php CHANGED
@@ -55,10 +55,10 @@ class TimberURLHelper
55
  * @return string
56
  */
57
  public static function get_rel_url($url, $force = false) {
58
- if (!strstr($url, $_SERVER['HTTP_HOST']) && !$force) {
 
59
  return $url;
60
  }
61
- $url_info = parse_url($url);
62
  $link = $url_info['path'];
63
  if (isset($url_info['query']) && strlen($url_info['query'])) {
64
  $link .= '?' . $url_info['query'];
55
  * @return string
56
  */
57
  public static function get_rel_url($url, $force = false) {
58
+ $url_info = parse_url($url);
59
+ if (isset($url_info['host']) && $url_info['host'] != $_SERVER['HTTP_HOST'] && !$force) {
60
  return $url;
61
  }
 
62
  $link = $url_info['path'];
63
  if (isset($url_info['query']) && strlen($url_info['query'])) {
64
  $link .= '?' . $url_info['query'];
functions/timber-user.php CHANGED
@@ -38,13 +38,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
38
  * @return null
39
  */
40
  function get_meta($field_name) {
41
- $value = null;
42
- $value = apply_filters('timber_user_get_meta_field_pre', $value, $this->ID, $field_name, $this);
43
- if ($value === null) {
44
- $value = get_post_meta($this->ID, $field_name, true);
45
- }
46
- $value = apply_filters('timber_user_get_meta_field', $value, $this->ID, $field_name, $this);
47
- return $value;
48
  }
49
 
50
  /**
@@ -75,16 +69,26 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
75
  if ($uid === false) {
76
  $uid = get_current_user_id();
77
  }
78
- if ($uid) {
 
 
 
 
 
 
 
79
  $data = get_userdata($uid);
80
- if (is_object($data) && isset($data)) {
 
 
81
  $this->import($data->data);
 
 
82
  }
83
- $this->ID = $uid;
84
- $this->id = $uid;
85
- $this->name = $this->name();
86
- $this->import_custom();
87
  }
 
 
 
88
  }
89
 
90
  /**
38
  * @return null
39
  */
40
  function get_meta($field_name) {
41
+ return $this->get_meta_field( $field_name );
 
 
 
 
 
 
42
  }
43
 
44
  /**
69
  if ($uid === false) {
70
  $uid = get_current_user_id();
71
  }
72
+ if (is_object($uid) || is_array($uid)){
73
+ $data = $uid;
74
+ if (is_array($uid)){
75
+ $data = (object) $uid;
76
+ }
77
+ $uid = $data->ID;
78
+ }
79
+ if (is_numeric($uid)) {
80
  $data = get_userdata($uid);
81
+ }
82
+ if (isset($data) && is_object($data)) {
83
+ if (isset($data->data)){
84
  $this->import($data->data);
85
+ } else {
86
+ $this->import($data);
87
  }
 
 
 
 
88
  }
89
+ $this->id = $this->ID;
90
+ $this->name = $this->name();
91
+ $this->import_custom();
92
  }
93
 
94
  /**
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: jarednova
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.7
5
- Stable tag: 0.20.1
6
  Tested up to: 3.9.1
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
@@ -41,6 +41,11 @@ Timber is great for any WordPress developer who cares about writing good, mainta
41
 
42
  == Changelog ==
43
 
 
 
 
 
 
44
  = 0.20.1 =
45
  * Hotfix to ensure non-exitent properties don't throw exception (thanks @kylehotchkiss)
46
 
@@ -309,19 +314,23 @@ Then create a subdirectory called `views` in your theme folder. The make this fi
309
 
310
  That's Timber!
311
 
 
 
 
 
312
  == Frequently Asked Questions ==
313
 
314
  = Can it be used in an existing theme? =
315
  You bet! Watch these **[video tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)** to see how.
316
 
317
  = Is it used in production? =
318
- At Upstatement we've now used it on more than a dozen client sites. You can check them out in the showcase here: http://jarednova.github.io/timber/
319
 
320
  = Doesn't this all make WordPress harder since there's more to learn? =
321
  Does jQuery make JavaScript harder? Yes, it's an extra piece to learn -- but it super-charges your ability to write unencumbered JavaScript (and prevents you from having to learn lots of the messy internals). If your answer is "jQuery sucks and everyone should learn how to write vanilla JS or they're rotten stupid people," this tool isn't for you.
322
 
323
  = Oh, Timber is simple code so it's for making simple themes =
324
- Whatever. It simplifies the silly stuff so that you can focus on building more complicated sites and apps. Django simplifies Python, but you can still use the full range of Python's abilities.
325
 
326
  = Will you support it? =
327
  As stated above, we're using it in dozens of sites (and dozens more planned) -- dozens of other developers are using it too. This isn't going anywhere. Twig is the chosen language for other PHP platforms like Symfony, Drupal 8 and Craft. WordPress will eventually adopt Twig too, I promise you that.
2
  Contributors: jarednova
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.7
5
+ Stable tag: 0.20.2
6
  Tested up to: 3.9.1
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
41
 
42
  == Changelog ==
43
 
44
+ = 0.20.2
45
+ * Change default response code on load_view to be 200
46
+ * Fixed error with relpath and subdomains (thanks @jnweaver)
47
+ * Various bug fixes (thanks @andyford, @discern)
48
+
49
  = 0.20.1 =
50
  * Hotfix to ensure non-exitent properties don't throw exception (thanks @kylehotchkiss)
51
 
314
 
315
  That's Timber!
316
 
317
+ == Support ==
318
+
319
+ Please use the [GitHub repo](https://github.com/jarednova/timber/issues?state=open) to file bugs or questions.
320
+
321
  == Frequently Asked Questions ==
322
 
323
  = Can it be used in an existing theme? =
324
  You bet! Watch these **[video tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)** to see how.
325
 
326
  = Is it used in production? =
327
+ At Upstatement we've now used it on more than a dozen client sites. Hundreds of other sites use it too. You can check some of them out in the **[showcase](http://upstatement.com/timber/#showcase)**.
328
 
329
  = Doesn't this all make WordPress harder since there's more to learn? =
330
  Does jQuery make JavaScript harder? Yes, it's an extra piece to learn -- but it super-charges your ability to write unencumbered JavaScript (and prevents you from having to learn lots of the messy internals). If your answer is "jQuery sucks and everyone should learn how to write vanilla JS or they're rotten stupid people," this tool isn't for you.
331
 
332
  = Oh, Timber is simple code so it's for making simple themes =
333
+ Whatever. It simplifies the silly stuff so that you can focus on building more complicated sites and apps. jQuery simplifies Javascript, but you can still use the full range of JS's abilities.
334
 
335
  = Will you support it? =
336
  As stated above, we're using it in dozens of sites (and dozens more planned) -- dozens of other developers are using it too. This isn't going anywhere. Twig is the chosen language for other PHP platforms like Symfony, Drupal 8 and Craft. WordPress will eventually adopt Twig too, I promise you that.
timber-starter-theme/footer.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  * Third party plugins that hijack the theme will call wp_footer() to get the footer template.
4
- * We use this so end our output buffer (started in header.php) and render into the view/page-plugin.twig template.
5
  */
6
  $timberContext = $GLOBALS['timberContext'];
7
  if (!isset($timberContext)) {
1
  <?php
2
  /*
3
  * Third party plugins that hijack the theme will call wp_footer() to get the footer template.
4
+ * We use this to end our output buffer (started in header.php) and render into the view/page-plugin.twig template.
5
  */
6
  $timberContext = $GLOBALS['timberContext'];
7
  if (!isset($timberContext)) {
timber-starter-theme/functions.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  if (!class_exists('Timber')){
4
  add_action( 'admin_notices', function(){
5
- echo '<div class="error"><p>Timber not activated. Make sure you activate the plugin in <a href="/wp-admin/plugins.php#timber">/wp-admin/plugins.php</a></p></div>';
6
  });
7
  return;
8
  }
2
 
3
  if (!class_exists('Timber')){
4
  add_action( 'admin_notices', function(){
5
+ echo '<div class="error"><p>Timber not activated. Make sure you activate the plugin in <a href="' . admin_url('plugins.php#timber') . '">' . admin_url('plugins.php') . '</a></p></div>';
6
  });
7
  return;
8
  }
timber-starter-theme/header.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  * Third party plugins that hijack the theme will call wp_head() to get the header template.
4
- * We use this so start our output buffer and render into the view/page-plugin.twig template in footer.php
5
  */
6
  $GLOBALS['timberContext'] = Timber::get_context();
7
  ob_start();
1
  <?php
2
  /*
3
  * Third party plugins that hijack the theme will call wp_head() to get the header template.
4
+ * We use this to start our output buffer and render into the view/page-plugin.twig template in footer.php
5
  */
6
  $GLOBALS['timberContext'] = Timber::get_context();
7
  ob_start();
timber-starter-theme/index.php CHANGED
@@ -4,7 +4,7 @@
4
  * This is the most generic template file in a WordPress theme
5
  * and one of the two required files for a theme (the other being style.css).
6
  * It is used to display a page when nothing more specific matches a query.
7
- * E.g., it puts together the home page when no home.php file
8
  *
9
  * Methods for TimberHelper can be found in the /functions sub-directory
10
  *
4
  * This is the most generic template file in a WordPress theme
5
  * and one of the two required files for a theme (the other being style.css).
6
  * It is used to display a page when nothing more specific matches a query.
7
+ * E.g., it puts together the home page when no home.php file exists
8
  *
9
  * Methods for TimberHelper can be found in the /functions sub-directory
10
  *
timber-starter-theme/single.php CHANGED
@@ -10,7 +10,7 @@
10
  */
11
 
12
  $context = Timber::get_context();
13
- $post = new TimberPost();
14
  $context['post'] = $post;
15
  $context['wp_title'] .= ' - ' . $post->title();
16
  $context['comment_form'] = TimberHelper::get_comment_form();
10
  */
11
 
12
  $context = Timber::get_context();
13
+ $post = Timber::query_post();
14
  $context['post'] = $post;
15
  $context['wp_title'] .= ' - ' . $post->title();
16
  $context['comment_form'] = TimberHelper::get_comment_form();
timber.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Timber
4
  Plugin URI: http://timber.upstatement.com
5
  Description: The WordPress Timber Library allows you to write themes using the power Twig templates
6
  Author: Jared Novack + Upstatement
7
- Version: 0.20.1
8
  Author URI: http://upstatement.com/
9
  */
10
 
@@ -37,6 +37,7 @@ require_once(__DIR__ . '/functions/timber-posts-collection.php');
37
 
38
  //Other 2nd-class citizens
39
  require_once(__DIR__ . '/functions/timber-archives.php');
 
40
  require_once(__DIR__ . '/functions/timber-site.php');
41
  require_once(__DIR__ . '/functions/timber-theme.php');
42
  require_once(__DIR__ . '/functions/timber-loader.php');
@@ -54,7 +55,7 @@ require_once(__DIR__ . '/functions/timber-admin.php');
54
  * $posts = Timber::get_posts(array(23,24,35,67), 'InkwellArticle');
55
  *
56
  * $context = Timber::get_context(); // returns wp favorites!
57
- *
58
  * Timber::render('index.twig', $context);
59
  */
60
 
@@ -69,12 +70,9 @@ class Timber {
69
  public static $auto_meta = true;
70
  public static $autoescape = false;
71
 
72
- protected $router;
73
-
74
  public function __construct(){
75
  $this->test_compatibility();
76
  $this->init_constants();
77
- add_action('init', array($this, 'init_routes'));
78
  }
79
 
80
  protected function test_compatibility(){
@@ -114,6 +112,20 @@ class Timber {
114
  return TimberPostGetter::get_posts($query, $PostClass, $return_collection);
115
  }
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  public static function query_posts($query = false, $PostClass = 'TimberPost') {
118
  return TimberPostGetter::query_posts( $query, $PostClass );
119
  }
@@ -274,6 +286,8 @@ class Timber {
274
  */
275
  public static function compile($filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT, $via_render = false) {
276
  $caller = self::get_calling_script_dir();
 
 
277
  $loader = new TimberLoader($caller);
278
  $file = $loader->choose_template($filenames);
279
  $output = '';
@@ -399,43 +413,19 @@ class Timber {
399
  /* Routes
400
  ================================ */
401
 
402
- function init_routes() {
403
- global $timber;
404
- if (isset($timber->router)) {
405
- $route = $timber->router->matchCurrentRequest();
406
- if ($route) {
407
- $callback = $route->getTarget();
408
- $params = $route->getParameters();
409
- $callback($params);
410
- }
411
- }
412
  }
413
 
414
  /**
415
  * @param string $route
416
  * @param callable $callback
417
  * @param array $args
 
418
  */
419
  public static function add_route($route, $callback, $args = array()) {
420
- global $timber;
421
- if (!isset($timber->router)) {
422
- if (class_exists('PHPRouter\Router')){
423
- $timber->router = new PHPRouter\Router();
424
- $site_url = get_bloginfo('url');
425
- $site_url_parts = explode('/', $site_url);
426
- $site_url_parts = array_slice($site_url_parts, 3);
427
- $base_path = implode('/', $site_url_parts);
428
- if (!$base_path || strpos($route, $base_path) === 0) {
429
- $base_path = '/';
430
- } else {
431
- $base_path = '/' . $base_path . '/';
432
- }
433
- $timber->router->setBasePath($base_path);
434
- }
435
- }
436
- if (class_exists('PHPRouter\Router')){
437
- $timber->router->map($route, $callback, $args);
438
- }
439
  }
440
 
441
  public function cancel_query(){
@@ -451,70 +441,17 @@ class Timber {
451
  /**
452
  * @deprecated since 0.20.0
453
  */
454
- public static function load_template($template, $query = false, $force_header = 0, $tparams = false) {
455
- return self::load_view($template, $query, $force_header, $tparams);
456
  }
457
 
458
  /**
459
- * @param array $template
460
- * @param mixed $query
461
- * @param int $force_header
462
- * @param bool $tparams
463
- * @return bool
464
  */
465
- public static function load_view($template, $query = false, $force_header = 0, $tparams = false) {
466
-
467
- $fullPath = is_readable($template);
468
- if (!$fullPath) {
469
- $template = locate_template($template);
470
- }
471
- if ($tparams){
472
- global $params;
473
- $params = $tparams;
474
- }
475
- if ($force_header) {
476
- add_filter('status_header', function($status_header, $header, $text, $protocol) use ($force_header) {
477
- $text = get_status_header_desc($force_header);
478
- $header_string = "$protocol $force_header $text";
479
- return $header_string;
480
- }, 10, 4 );
481
- if (404 != $force_header) {
482
- add_action('parse_query', function($query) {
483
- if ($query->is_main_query()){
484
- $query->is_404 = false;
485
- }
486
- },1);
487
- add_action('template_redirect', function(){
488
- global $wp_query;
489
- $wp_query->is_404 = false;
490
- },1);
491
- }
492
- }
493
-
494
- if ($query) {
495
- add_action('do_parse_request', function() use ($query) {
496
- global $wp;
497
- if ( is_callable($query) )
498
- $query = call_user_func($query);
499
-
500
- if ( is_array($query) )
501
- $wp->query_vars = $query;
502
- elseif ( !empty($query) )
503
- parse_str($query, $wp->query_vars);
504
- else
505
- return true; // Could not interpret query. Let WP try.
506
-
507
- return false;
508
- });
509
- }
510
- if ($template) {
511
- add_filter('template_include', function($t) use ($template) {
512
- return $template;
513
- });
514
- return true;
515
- }
516
- return false;
517
  }
 
518
 
519
  /* Pagination
520
  ================================ */
@@ -577,12 +514,22 @@ class Timber {
577
  return str_replace(ABSPATH, '', realpath($dir));
578
  }
579
 
 
 
 
 
 
 
 
 
 
 
580
  /**
581
  * @param int $offset
582
  * @return string|null
583
  * @deprecated since 0.20.0
584
  */
585
- public static function get_calling_script_dir($offset = 0) {
586
  $caller = null;
587
  $backtrace = debug_backtrace();
588
  $i = 0;
@@ -596,12 +543,7 @@ class Timber {
596
  if ($offset){
597
  $caller = $backtrace[$i + $offset]['file'];
598
  }
599
- if ($caller !== null) {
600
- $pathinfo = pathinfo($caller);
601
- $dir = $pathinfo['dirname'];
602
- return $dir;
603
- }
604
- return null;
605
  }
606
 
607
  /**
4
  Plugin URI: http://timber.upstatement.com
5
  Description: The WordPress Timber Library allows you to write themes using the power Twig templates
6
  Author: Jared Novack + Upstatement
7
+ Version: 0.20.2
8
  Author URI: http://upstatement.com/
9
  */
10
 
37
 
38
  //Other 2nd-class citizens
39
  require_once(__DIR__ . '/functions/timber-archives.php');
40
+ require_once(__DIR__ . '/functions/timber-routes.php');
41
  require_once(__DIR__ . '/functions/timber-site.php');
42
  require_once(__DIR__ . '/functions/timber-theme.php');
43
  require_once(__DIR__ . '/functions/timber-loader.php');
55
  * $posts = Timber::get_posts(array(23,24,35,67), 'InkwellArticle');
56
  *
57
  * $context = Timber::get_context(); // returns wp favorites!
58
+ * $context['posts'] = $posts;
59
  * Timber::render('index.twig', $context);
60
  */
61
 
70
  public static $auto_meta = true;
71
  public static $autoescape = false;
72
 
 
 
73
  public function __construct(){
74
  $this->test_compatibility();
75
  $this->init_constants();
 
76
  }
77
 
78
  protected function test_compatibility(){
112
  return TimberPostGetter::get_posts($query, $PostClass, $return_collection);
113
  }
114
 
115
+ /**
116
+ * @param mixed $query
117
+ * @param string $PostClass
118
+ * @return array|bool|null
119
+ */
120
+ public static function query_post($query = false, $PostClass = 'TimberPost') {
121
+ return TimberPostGetter::query_post($query, $PostClass);
122
+ }
123
+
124
+ /**
125
+ * @param mixed $query
126
+ * @param string $PostClass
127
+ * @return array|bool|null
128
+ */
129
  public static function query_posts($query = false, $PostClass = 'TimberPost') {
130
  return TimberPostGetter::query_posts( $query, $PostClass );
131
  }
286
  */
287
  public static function compile($filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT, $via_render = false) {
288
  $caller = self::get_calling_script_dir();
289
+ $caller_file = self::get_calling_script_file();
290
+ $caller_file = apply_filters('timber_calling_php_file', $caller_file);
291
  $loader = new TimberLoader($caller);
292
  $file = $loader->choose_template($filenames);
293
  $output = '';
413
  /* Routes
414
  ================================ */
415
 
416
+ function init_routes(){
417
+ global $timberRoutes;
418
+ $timberRoutes->init();
 
 
 
 
 
 
 
419
  }
420
 
421
  /**
422
  * @param string $route
423
  * @param callable $callback
424
  * @param array $args
425
+ * @deprecated since 0.20.0
426
  */
427
  public static function add_route($route, $callback, $args = array()) {
428
+ TimberRoutes::add_route($route, $callback, $args);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
  }
430
 
431
  public function cancel_query(){
441
  /**
442
  * @deprecated since 0.20.0
443
  */
444
+ public static function load_template($template, $query = false, $status_code = 200, $tparams = false) {
445
+ return TimberRoutes::load_view($template, $query, $status_code, $tparams);
446
  }
447
 
448
  /**
449
+ * @deprecated since 0.20.2
 
 
 
 
450
  */
451
+ public static function load_view($template, $query = false, $status_code = 200, $tparams = false) {
452
+ return TimberRoutes::load_view($template, $query, $status_code, $tparams);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
  }
454
+
455
 
456
  /* Pagination
457
  ================================ */
514
  return str_replace(ABSPATH, '', realpath($dir));
515
  }
516
 
517
+ public static function get_calling_script_dir($offset = 0) {
518
+ $caller = self::get_calling_script_file($offset);
519
+ if (!is_null($caller)){
520
+ $pathinfo = pathinfo($caller);
521
+ $dir = $pathinfo['dirname'];
522
+ return $dir;
523
+ }
524
+ return null;
525
+ }
526
+
527
  /**
528
  * @param int $offset
529
  * @return string|null
530
  * @deprecated since 0.20.0
531
  */
532
+ public static function get_calling_script_file($offset = 0) {
533
  $caller = null;
534
  $backtrace = debug_backtrace();
535
  $i = 0;
543
  if ($offset){
544
  $caller = $backtrace[$i + $offset]['file'];
545
  }
546
+ return $caller;
 
 
 
 
 
547
  }
548
 
549
  /**
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInita784621e8158bb5d9dba8b8fc3bb9a00::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit06b3e892971e1bc7ad59039b3f146658::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInita784621e8158bb5d9dba8b8fc3bb9a00
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInita784621e8158bb5d9dba8b8fc3bb9a00
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInita784621e8158bb5d9dba8b8fc3bb9a00', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInita784621e8158bb5d9dba8b8fc3bb9a00', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(__DIR__);
27
  $baseDir = dirname($vendorDir);
@@ -47,7 +47,7 @@ class ComposerAutoloaderInita784621e8158bb5d9dba8b8fc3bb9a00
47
  }
48
  }
49
 
50
- function composerRequirea784621e8158bb5d9dba8b8fc3bb9a00($file)
51
  {
52
  require $file;
53
  }
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit06b3e892971e1bc7ad59039b3f146658
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit06b3e892971e1bc7ad59039b3f146658', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit06b3e892971e1bc7ad59039b3f146658', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(__DIR__);
27
  $baseDir = dirname($vendorDir);
47
  }
48
  }
49
 
50
+ function composerRequire06b3e892971e1bc7ad59039b3f146658($file)
51
  {
52
  require $file;
53
  }