Timber - Version 0.21.4

Version Description

  • Fixed issue with multisite variables
  • Fixed issue with string conversion on function output *
Download this release

Release Info

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

Code changes from version 0.21.3 to 0.21.4

Files changed (56) hide show
  1. lib/image/timber-image-operation-resize.php +0 -1
  2. lib/image/timber-image-operation-retina.php +4 -5
  3. lib/timber-admin.php +2 -2
  4. lib/timber-comment.php +9 -0
  5. lib/timber-core.php +2 -9
  6. lib/timber-function-wrapper.php +62 -55
  7. lib/timber-helper.php +18 -24
  8. lib/timber-image-helper.php +2 -15
  9. lib/timber-image.php +4 -5
  10. lib/timber-menu-item.php +243 -236
  11. lib/timber-post-getter.php +86 -120
  12. lib/timber-post.php +947 -931
  13. lib/timber-site.php +11 -6
  14. lib/timber-twig.php +291 -288
  15. lib/timber-url-helper.php +283 -235
  16. readme.txt +6 -1
  17. timber-starter-theme/composer.json +1 -1
  18. timber-starter-theme/single.php +0 -1
  19. timber-starter-theme/{js → static}/site.js +0 -0
  20. timber-starter-theme/tests/test-timber-starter-theme.php +1 -3
  21. timber.php +3 -11
  22. vendor/autoload.php +1 -1
  23. vendor/composer/autoload_real.php +4 -4
  24. vendor/composer/installed.json +6 -6
  25. vendor/twig/twig/.travis.yml +0 -4
  26. vendor/twig/twig/CHANGELOG +5 -0
  27. vendor/twig/twig/doc/api.rst +25 -9
  28. vendor/twig/twig/doc/tags/if.rst +10 -2
  29. vendor/twig/twig/doc/tags/spaceless.rst +1 -1
  30. vendor/twig/twig/doc/templates.rst +6 -0
  31. vendor/twig/twig/ext/twig/php_twig.h +1 -1
  32. vendor/twig/twig/ext/twig/twig.c +40 -12
  33. vendor/twig/twig/lib/Twig/Environment.php +7 -8
  34. vendor/twig/twig/lib/Twig/ExpressionParser.php +5 -1
  35. vendor/twig/twig/lib/Twig/Extension/Core.php +12 -6
  36. vendor/twig/twig/lib/Twig/Extension/Escaper.php +2 -0
  37. vendor/twig/twig/lib/Twig/LoaderInterface.php +2 -1
  38. vendor/twig/twig/lib/Twig/Node.php +17 -17
  39. vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php +2 -0
  40. vendor/twig/twig/lib/Twig/NodeTraverser.php +2 -0
  41. vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php +4 -0
  42. vendor/twig/twig/lib/Twig/Template.php +32 -11
  43. vendor/twig/twig/lib/Twig/TokenParser.php +1 -1
  44. vendor/twig/twig/lib/Twig/TokenParser/Block.php +1 -1
  45. vendor/twig/twig/lib/Twig/TokenParser/Macro.php +1 -1
  46. vendor/twig/twig/lib/Twig/TokenParser/Set.php +2 -2
  47. vendor/twig/twig/lib/Twig/TokenParserInterface.php +1 -1
  48. vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php +4 -4
  49. vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/syntax_error_in_reused_template.test +10 -0
  50. vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in.test +3 -1
  51. vendor/twig/twig/test/Twig/Tests/LexerTest.php +1 -1
  52. vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php +2 -2
  53. vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php +1 -1
  54. vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php +82 -26
  55. vendor/twig/twig/test/Twig/Tests/TemplateTest.php +5 -1
  56. vendor/twig/twig/test/Twig/Tests/escapingTest.php +2 -1
lib/image/timber-image-operation-resize.php CHANGED
@@ -114,6 +114,5 @@ class TimberImageOperationResize extends TimberImageOperation {
114
  } else {
115
  TimberHelper::error_log( $image );
116
  }
117
- return false;
118
  }
119
  }
114
  } else {
115
  TimberHelper::error_log( $image );
116
  }
 
117
  }
118
  }
lib/image/timber-image-operation-retina.php CHANGED
@@ -19,7 +19,7 @@ class TimberImageOperationRetina extends TimberImageOperation {
19
  /**
20
  * @param string $src_filename the basename of the file (ex: my-awesome-pic)
21
  * @param string $src_extension the extension (ex: .jpg)
22
- * @return string the final filename to be used (ex: my-awesome-pic@2x.jpg)
23
  */
24
  function filename($src_filename, $src_extension) {
25
  $newbase = $src_filename . '@' . $this->factor . 'x'; // add @2x, @3x, @1.5x, etc.
@@ -30,10 +30,10 @@ class TimberImageOperationRetina extends TimberImageOperation {
30
  /**
31
  * Performs the actual image manipulation,
32
  * including saving the target file.
33
- *
34
- * @param string $load_filename filepath (not URL) to source file
35
  * (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
36
- * @param string $save_filename filepath (not URL) where result file should be saved
37
  * (ex: /src/var/www/wp-content/uploads/my-pic@2x.jpg)
38
  * @return bool true if everything went fine, false otherwise
39
  */
@@ -43,7 +43,6 @@ class TimberImageOperationRetina extends TimberImageOperation {
43
  $current_size = $image->get_size();
44
  $src_w = $current_size['width'];
45
  $src_h = $current_size['height'];
46
- $src_ratio = $src_w / $src_h;
47
  // Get ratios
48
  $w = $src_w * $this->factor;
49
  $h = $src_h * $this->factor;
19
  /**
20
  * @param string $src_filename the basename of the file (ex: my-awesome-pic)
21
  * @param string $src_extension the extension (ex: .jpg)
22
+ * @return string the final filename to be used (ex: my-awesome-pic@2x.jpg)
23
  */
24
  function filename($src_filename, $src_extension) {
25
  $newbase = $src_filename . '@' . $this->factor . 'x'; // add @2x, @3x, @1.5x, etc.
30
  /**
31
  * Performs the actual image manipulation,
32
  * including saving the target file.
33
+ *
34
+ * @param string $load_filename filepath (not URL) to source file
35
  * (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
36
+ * @param string $save_filename filepath (not URL) where result file should be saved
37
  * (ex: /src/var/www/wp-content/uploads/my-pic@2x.jpg)
38
  * @return bool true if everything went fine, false otherwise
39
  */
43
  $current_size = $image->get_size();
44
  $src_w = $current_size['width'];
45
  $src_h = $current_size['height'];
 
46
  // Get ratios
47
  $w = $src_w * $this->factor;
48
  $h = $src_h * $this->factor;
lib/timber-admin.php CHANGED
@@ -3,7 +3,7 @@
3
  class TimberAdmin {
4
 
5
  public static function init() {
6
- add_filter( 'plugin_row_meta', array( __CLASS__, 'meta_links' ), 10, 2 );
7
  }
8
 
9
  /**
@@ -23,4 +23,4 @@ class TimberAdmin {
23
  return $links;
24
  }
25
 
26
- }
3
  class TimberAdmin {
4
 
5
  public static function init() {
6
+ return add_filter( 'plugin_row_meta', array( __CLASS__, 'meta_links' ), 10, 2 );
7
  }
8
 
9
  /**
23
  return $links;
24
  }
25
 
26
+ }
lib/timber-comment.php CHANGED
@@ -16,6 +16,8 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
16
  public $user_id;
17
  public $comment_author;
18
 
 
 
19
  /**
20
  * @param int $cid
21
  */
@@ -120,6 +122,13 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
120
  return $this->get_meta_field($field_name);
121
  }
122
 
 
 
 
 
 
 
 
123
  /**
124
  * @param int $comment_id
125
  * @return mixed
16
  public $user_id;
17
  public $comment_author;
18
 
19
+ public $children = array();
20
+
21
  /**
22
  * @param int $cid
23
  */
122
  return $this->get_meta_field($field_name);
123
  }
124
 
125
+ /**
126
+ * @return bool
127
+ */
128
+ public function is_child() {
129
+ return $this->comment_parent > 0;
130
+ }
131
+
132
  /**
133
  * @param int $comment_id
134
  * @return mixed
lib/timber-core.php CHANGED
@@ -5,7 +5,6 @@ abstract class TimberCore {
5
  public $id;
6
  public $ID;
7
  public $object_type;
8
- public $_can_edit;
9
 
10
  /**
11
  *
@@ -77,22 +76,16 @@ abstract class TimberCore {
77
  }
78
 
79
  /**
80
- *
81
- *
82
  * @return bool
83
  */
84
  function can_edit() {
85
- if ( isset( $this->_can_edit ) ) {
86
- return $this->_can_edit;
87
- }
88
- $this->_can_edit = false;
89
  if ( !function_exists( 'current_user_can' ) ) {
90
  return false;
91
  }
92
  if ( current_user_can( 'edit_post', $this->ID ) ) {
93
- $this->_can_edit = true;
94
  }
95
- return $this->_can_edit;
96
  }
97
 
98
  /**
5
  public $id;
6
  public $ID;
7
  public $object_type;
 
8
 
9
  /**
10
  *
76
  }
77
 
78
  /**
 
 
79
  * @return bool
80
  */
81
  function can_edit() {
 
 
 
 
82
  if ( !function_exists( 'current_user_can' ) ) {
83
  return false;
84
  }
85
  if ( current_user_can( 'edit_post', $this->ID ) ) {
86
+ return true;
87
  }
88
+ return false;
89
  }
90
 
91
  /**
lib/timber-function-wrapper.php CHANGED
@@ -1,70 +1,77 @@
1
  <?php
2
 
3
- class TimberFunctionWrapper
4
- {
5
 
6
- private $_function;
7
- private $_args;
8
- private $_use_ob;
9
 
10
- public function __toString() {
11
- return $this->call();
12
- }
13
 
14
- /**
15
- * @param callable $function
16
- * @param array $args
17
- * @param bool $return_output_buffer
18
- */
19
- public function __construct($function, $args = array(), $return_output_buffer = false) {
20
- $this->_function = $function;
21
- $this->_args = $args;
22
- $this->_use_ob = $return_output_buffer;
 
 
23
 
24
- add_filter('get_twig', array(&$this, 'add_to_twig'));
25
- }
26
 
27
- /**
28
- * @param Twig_Environment $twig
29
- * @return Twig_Environment
30
- */
31
- public function add_to_twig($twig) {
32
- $wrapper = $this;
 
 
33
 
34
- $twig->addFunction(new Twig_SimpleFunction($this->_function, function () use ($wrapper) {
35
- return call_user_func_array(array($wrapper, 'call'), func_get_args());
36
- }));
37
 
38
- return $twig;
39
- }
40
 
41
- /**
42
- * @return string
43
- */
44
- public function call() {
45
- $args = $this->_parse_args(func_get_args(), $this->_args);
 
 
46
 
47
- if ($this->_use_ob) {
48
- return TimberHelper::ob_function($this->_function, $args);
49
- } else {
50
- return (string)call_user_func_array($this->_function, $args);
51
- }
52
- }
53
 
54
- /**
55
- * @param array $args
56
- * @param array $defaults
57
- * @return array
58
- */
59
- private function _parse_args($args, $defaults) {
60
- $_arg = reset($defaults);
 
 
61
 
62
- foreach ($args as $index => $arg) {
63
- $defaults[$index] = is_null($arg) ? $_arg : $arg;
64
- $_arg = next($defaults);
65
- }
66
 
67
- return $defaults;
68
- }
69
 
70
- }
1
  <?php
2
 
3
+ class TimberFunctionWrapper {
 
4
 
5
+ private $_function;
6
+ private $_args;
7
+ private $_use_ob;
8
 
9
+ public function __toString() {
10
+ return (string)$this->call();
11
+ }
12
 
13
+ /**
14
+ *
15
+ *
16
+ * @param callable $function
17
+ * @param array $args
18
+ * @param bool $return_output_buffer
19
+ */
20
+ public function __construct( $function, $args = array(), $return_output_buffer = false ) {
21
+ $this->_function = $function;
22
+ $this->_args = $args;
23
+ $this->_use_ob = $return_output_buffer;
24
 
25
+ add_filter( 'get_twig', array( &$this, 'add_to_twig' ) );
26
+ }
27
 
28
+ /**
29
+ *
30
+ *
31
+ * @param Twig_Environment $twig
32
+ * @return Twig_Environment
33
+ */
34
+ public function add_to_twig( $twig ) {
35
+ $wrapper = $this;
36
 
37
+ $twig->addFunction( new Twig_SimpleFunction( $this->_function, function () use ( $wrapper ) {
38
+ return call_user_func_array( array( $wrapper, 'call' ), func_get_args() );
39
+ } ) );
40
 
41
+ return $twig;
42
+ }
43
 
44
+ /**
45
+ *
46
+ *
47
+ * @return string
48
+ */
49
+ public function call() {
50
+ $args = $this->_parse_args( func_get_args(), $this->_args );
51
 
52
+ if ( $this->_use_ob ) {
53
+ return TimberHelper::ob_function( $this->_function, $args );
54
+ } else {
55
+ return call_user_func_array( $this->_function, $args );
56
+ }
57
+ }
58
 
59
+ /**
60
+ *
61
+ *
62
+ * @param array $args
63
+ * @param array $defaults
64
+ * @return array
65
+ */
66
+ private function _parse_args( $args, $defaults ) {
67
+ $_arg = reset( $defaults );
68
 
69
+ foreach ( $args as $index => $arg ) {
70
+ $defaults[$index] = is_null( $arg ) ? $_arg : $arg;
71
+ $_arg = next( $defaults );
72
+ }
73
 
74
+ return $defaults;
75
+ }
76
 
77
+ }
lib/timber-helper.php CHANGED
@@ -135,7 +135,7 @@ class TimberHelper {
135
  /**
136
  *
137
  *
138
- * @param unknown $arg
139
  * @return void
140
  */
141
  public static function error_log( $arg ) {
@@ -145,7 +145,7 @@ class TimberHelper {
145
  if ( is_object( $arg ) || is_array( $arg ) ) {
146
  $arg = print_r( $arg, true );
147
  }
148
- error_log( $arg );
149
  }
150
 
151
  /**
@@ -168,7 +168,7 @@ class TimberHelper {
168
  *
169
  * @param string $text
170
  * @param int $num_words
171
- * @param string $more
172
  * @param string $allowed_tags
173
  * @return string
174
  */
@@ -237,8 +237,6 @@ class TimberHelper {
237
  }
238
 
239
  /**
240
- *
241
- *
242
  * @param string $ret
243
  * @return string
244
  * @deprecated since 0.20.0
@@ -251,15 +249,13 @@ class TimberHelper {
251
  $ret = preg_replace( $pattern, '<a href="mailto:\\1">\\1</a>', $ret );
252
  $ret = preg_replace( "/\B@(\w+)/", " <a href=\"http://www.twitter.com/\\1\" target=\"_blank\">@\\1</a>", $ret );
253
  $ret = preg_replace( "/\B#(\w+)/", " <a href=\"http://twitter.com/search?q=\\1\" target=\"_blank\">#\\1</a>", $ret );
254
- return $ret;
255
  }
256
 
257
  /* WordPress Query Utilities
258
  ======================== */
259
 
260
  /**
261
- *
262
- *
263
  * @param string $key
264
  * @param string $value
265
  * @return array|int
@@ -583,101 +579,99 @@ class TimberHelper {
583
  return $page_links;
584
  }
585
 
586
- /* LEGACY These have since been re-organized; but keeping linkages for backwards-compatibility */
587
-
588
  /**
589
- * @deprecated
590
  */
591
  static function get_image_path( $iid ) {
592
  return TimberImageHelper::get_image_path( $iid );
593
  }
594
 
595
  /**
596
- * @deprecated
597
  */
598
  static function get_current_url() {
599
  return TimberURLHelper::get_current_url();
600
  }
601
 
602
  /**
603
- * @deprecated
604
  */
605
  static function is_url( $url ) {
606
  return TimberURLHelper::is_url( $url );
607
  }
608
 
609
  /**
610
- * @deprecated
611
  */
612
  static function get_path_base() {
613
  return TimberURLHelper::get_path_base();
614
  }
615
 
616
  /**
617
- * @deprecated
618
  */
619
  static function get_rel_url( $url, $force = false ) {
620
  return TimberURLHelper::get_rel_url( $url, $force );
621
  }
622
 
623
  /**
624
- * @deprecated
625
  */
626
  static function is_local( $url ) {
627
  return TimberURLHelper::is_local( $url );
628
  }
629
 
630
  /**
631
- * @deprecated
632
  */
633
  static function get_full_path( $src ) {
634
  return TimberURLHelper::get_full_path( $src );
635
  }
636
 
637
  /**
638
- * @deprecated
639
  */
640
  static function get_rel_path( $src ) {
641
  return TimberURLHelper::get_rel_path( $src );
642
  }
643
 
644
  /**
645
- * @deprecated
646
  */
647
  static function remove_double_slashes( $url ) {
648
  return TimberURLHelper::remove_double_slashes( $url );
649
  }
650
 
651
  /**
652
- * @deprecated
653
  */
654
  static function prepend_to_url( $url, $path ) {
655
  return TimberURLHelper::prepend_to_url( $url, $path );
656
  }
657
 
658
  /**
659
- * @deprecated
660
  */
661
  static function preslashit( $path ) {
662
  return TimberURLHelper::preslashit( $path );
663
  }
664
 
665
  /**
666
- * @deprecated
667
  */
668
  static function is_external( $url ) {
669
  return TimberURLHelper::is_external( $url );
670
  }
671
 
672
  /**
673
- * @deprecated
674
  */
675
  static function download_url( $url, $timeout = 300 ) {
676
  return TimberURLHelper::download_url( $url, $timeout );
677
  }
678
 
679
  /**
680
- * @deprecated
681
  */
682
  static function get_params( $i = -1 ) {
683
  return TimberURLHelper::get_params( $i );
135
  /**
136
  *
137
  *
138
+ * @param mixed $arg that you want to error_log
139
  * @return void
140
  */
141
  public static function error_log( $arg ) {
145
  if ( is_object( $arg ) || is_array( $arg ) ) {
146
  $arg = print_r( $arg, true );
147
  }
148
+ return error_log( $arg );
149
  }
150
 
151
  /**
168
  *
169
  * @param string $text
170
  * @param int $num_words
171
+ * @param string|null|false $more text to appear in "Read more...". Null to use default, false to hide
172
  * @param string $allowed_tags
173
  * @return string
174
  */
237
  }
238
 
239
  /**
 
 
240
  * @param string $ret
241
  * @return string
242
  * @deprecated since 0.20.0
249
  $ret = preg_replace( $pattern, '<a href="mailto:\\1">\\1</a>', $ret );
250
  $ret = preg_replace( "/\B@(\w+)/", " <a href=\"http://www.twitter.com/\\1\" target=\"_blank\">@\\1</a>", $ret );
251
  $ret = preg_replace( "/\B#(\w+)/", " <a href=\"http://twitter.com/search?q=\\1\" target=\"_blank\">#\\1</a>", $ret );
252
+ return trim($ret);
253
  }
254
 
255
  /* WordPress Query Utilities
256
  ======================== */
257
 
258
  /**
 
 
259
  * @param string $key
260
  * @param string $value
261
  * @return array|int
579
  return $page_links;
580
  }
581
 
 
 
582
  /**
583
+ * @deprecated since 0.18.0
584
  */
585
  static function get_image_path( $iid ) {
586
  return TimberImageHelper::get_image_path( $iid );
587
  }
588
 
589
  /**
590
+ * @deprecated since 0.18.0
591
  */
592
  static function get_current_url() {
593
  return TimberURLHelper::get_current_url();
594
  }
595
 
596
  /**
597
+ * @deprecated since 0.18.0
598
  */
599
  static function is_url( $url ) {
600
  return TimberURLHelper::is_url( $url );
601
  }
602
 
603
  /**
604
+ * @deprecated since 0.18.0
605
  */
606
  static function get_path_base() {
607
  return TimberURLHelper::get_path_base();
608
  }
609
 
610
  /**
611
+ * @deprecated since 0.18.0
612
  */
613
  static function get_rel_url( $url, $force = false ) {
614
  return TimberURLHelper::get_rel_url( $url, $force );
615
  }
616
 
617
  /**
618
+ * @deprecated since 0.18.0
619
  */
620
  static function is_local( $url ) {
621
  return TimberURLHelper::is_local( $url );
622
  }
623
 
624
  /**
625
+ * @deprecated since 0.18.0
626
  */
627
  static function get_full_path( $src ) {
628
  return TimberURLHelper::get_full_path( $src );
629
  }
630
 
631
  /**
632
+ * @deprecated since 0.18.0
633
  */
634
  static function get_rel_path( $src ) {
635
  return TimberURLHelper::get_rel_path( $src );
636
  }
637
 
638
  /**
639
+ * @deprecated since 0.18.0
640
  */
641
  static function remove_double_slashes( $url ) {
642
  return TimberURLHelper::remove_double_slashes( $url );
643
  }
644
 
645
  /**
646
+ * @deprecated since 0.18.0
647
  */
648
  static function prepend_to_url( $url, $path ) {
649
  return TimberURLHelper::prepend_to_url( $url, $path );
650
  }
651
 
652
  /**
653
+ * @deprecated since 0.18.0
654
  */
655
  static function preslashit( $path ) {
656
  return TimberURLHelper::preslashit( $path );
657
  }
658
 
659
  /**
660
+ * @deprecated since 0.18.0
661
  */
662
  static function is_external( $url ) {
663
  return TimberURLHelper::is_external( $url );
664
  }
665
 
666
  /**
667
+ * @deprecated since 0.18.0
668
  */
669
  static function download_url( $url, $timeout = 300 ) {
670
  return TimberURLHelper::download_url( $url, $timeout );
671
  }
672
 
673
  /**
674
+ * @deprecated since 0.18.0
675
  */
676
  static function get_params( $i = -1 ) {
677
  return TimberURLHelper::get_params( $i );
lib/timber-image-helper.php CHANGED
@@ -158,22 +158,9 @@ class TimberImageHelper {
158
  } );
159
  }
160
 
161
- //-- end of public methods --//
162
 
163
 
164
-
165
-
166
- /**
167
- * @return boolean true if $path is an external url, false if relative or local.
168
- */
169
- protected static function is_external($path) {
170
- $is_external = TimberURLHelper::is_absolute($path) && !strstr($path, site_url());
171
- if ($is_external) {
172
- $is_external = TimberURLHelper::is_absolute($path) && !strstr($path, home_url());
173
- }
174
- return $is_external;
175
- }
176
-
177
  /**
178
  * Deletes resized versions of the supplied file name.
179
  * So if passed a value like my-pic.jpg, this function will delete my-pic-500x200-c-left.jpg, my-pic-400x400-c-default.jpg, etc.
@@ -420,7 +407,7 @@ class TimberImageHelper {
420
  return '';
421
  }
422
  // if external image, load it first
423
- if ( self::is_external( $src ) ) {
424
  $src = self::sideload_image( $src );
425
  }
426
  // break down URL into components
158
  } );
159
  }
160
 
161
+ //-- end of public methods --//
162
 
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  /**
165
  * Deletes resized versions of the supplied file name.
166
  * So if passed a value like my-pic.jpg, this function will delete my-pic-500x200-c-left.jpg, my-pic-400x400-c-default.jpg, etc.
407
  return '';
408
  }
409
  // if external image, load it first
410
+ if ( TimberURLHelper::is_external_content( $src ) ) {
411
  $src = self::sideload_image( $src );
412
  }
413
  // break down URL into components
lib/timber-image.php CHANGED
@@ -25,13 +25,12 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
25
  }
26
 
27
  /**
28
- * @return string
29
  */
30
  function __toString() {
31
  if ($this->get_src()) {
32
  return $this->get_src();
33
  }
34
- return '';
35
  }
36
 
37
  /**
@@ -57,11 +56,11 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
57
  }
58
 
59
  /**
60
- * @param string $dim
61
  * @return array|int
62
  */
63
- function get_dimensions_loaded($dim) {
64
- if ($dim == null) {
65
  return $this->_dimensions;
66
  }
67
  if ($dim == 'w' || $dim == 'width') {
25
  }
26
 
27
  /**
28
+ * @return string|null
29
  */
30
  function __toString() {
31
  if ($this->get_src()) {
32
  return $this->get_src();
33
  }
 
34
  }
35
 
36
  /**
56
  }
57
 
58
  /**
59
+ * @param string|null $dim
60
  * @return array|int
61
  */
62
+ protected function get_dimensions_loaded($dim) {
63
+ if ($dim === null) {
64
  return $this->_dimensions;
65
  }
66
  if ($dim == 'w' || $dim == 'width') {
lib/timber-menu-item.php CHANGED
@@ -2,241 +2,248 @@
2
 
3
  class TimberMenuItem extends TimberCore implements TimberCoreInterface {
4
 
5
- public $children;
6
- public $has_child_class = false;
7
-
8
- public $classes = array();
9
- public $class = '';
10
- public $post_name;
11
- public $type;
12
-
13
- public $PostClass = 'TimberPost';
14
-
15
- private $menu_object;
16
- private $parent_object;
17
-
18
- /**
19
- *
20
- *
21
- * @param array|object $data
22
- */
23
- function __construct( $data ) {
24
- $this->import( $data );
25
- $this->import_classes( $data );
26
- if ( isset( $this->name ) ) {
27
- $this->_name = $this->name;
28
- }
29
- $this->name = $this->name();
30
- $this->add_class( 'menu-item-' . $this->ID );
31
- $this->menu_object = $data;
32
- }
33
-
34
- function __toString() {
35
- return $this->name();
36
- }
37
-
38
- /**
39
- *
40
- *
41
- * @param string $class_name
42
- */
43
- function add_class( $class_name ) {
44
- $this->classes[] = $class_name;
45
- $this->class .= ' ' . $class_name;
46
- }
47
-
48
- /**
49
- *
50
- *
51
- * @return string
52
- */
53
- function name() {
54
- if ( isset( $this->title ) ) {
55
- return $this->title;
56
- }
57
- if ( isset( $this->_name ) ) {
58
- return $this->_name;
59
- }
60
- return '';
61
- }
62
-
63
- /**
64
- *
65
- *
66
- * @return string
67
- */
68
- function slug() {
69
- if ( !isset( $this->parent_object ) ) {
70
- $this->parent_object = $this->get_parent_object();
71
- }
72
- if ( isset( $this->parent_object->post_name ) && $this->parent_object->post_name ) {
73
- return $this->parent_object->post_name;
74
- }
75
- return $this->post_name;
76
- }
77
-
78
- function get_parent_object() {
79
- if ( isset( $this->_menu_item_object_id ) ) {
80
- return new $this->PostClass( $this->_menu_item_object_id );
81
- }
82
- }
83
-
84
- /**
85
- *
86
- *
87
- * @return string
88
- */
89
- function get_link() {
90
- if ( !isset( $this->url ) || !$this->url ) {
91
- if ( isset( $this->_menu_item_type ) && $this->_menu_item_type == 'custom' ) {
92
- $this->url = $this->_menu_item_url;
93
- } else if ( isset( $this->menu_object ) && method_exists( $this->menu_object, 'get_link' ) ) {
94
- $this->url = $this->menu_object->get_link();
95
- }
96
- }
97
- return $this->url;
98
- }
99
-
100
- /**
101
- *
102
- *
103
- * @return string
104
- */
105
- function get_path() {
106
- return TimberURLHelper::get_rel_url( $this->get_link() );
107
- }
108
-
109
- /**
110
- *
111
- *
112
- * @param TimberMenuItem $item
113
- */
114
- function add_child( $item ) {
115
- if ( !$this->has_child_class ) {
116
- $this->add_class( 'menu-item-has-children' );
117
- $this->has_child_class = true;
118
- }
119
- if ( !isset( $this->children ) ) {
120
- $this->children = array();
121
- }
122
- $this->children[] = $item;
123
- }
124
-
125
- /**
126
- *
127
- *
128
- * @param object $data
129
- */
130
- function import_classes( $data ) {
131
- $this->classes = array_merge($this->classes, $data->classes);
132
- $this->classes = array_unique($this->classes);
133
- $this->classes = apply_filters( 'nav_menu_css_class', $this->classes, $this );
134
- $this->class = trim( implode( ' ', $this->classes ) );
135
- }
136
-
137
- /**
138
- *
139
- *
140
- * @return array|bool
141
- */
142
- function get_children() {
143
- if ( isset( $this->children ) ) {
144
- return $this->children;
145
- }
146
- return false;
147
- }
148
-
149
- /**
150
- *
151
- *
152
- * @return bool
153
- */
154
- function is_external() {
155
- if ( $this->type != 'custom' ) {
156
- return false;
157
- }
158
- return TimberURLHelper::is_external( $this->url );
159
- }
160
-
161
- /**
162
- *
163
- * @param $key string lookup key
164
- * @return mixed whatever value is storied in the database
165
- */
166
- public function meta( $key ) {
167
- if ( is_object( $this->menu_object ) && method_exists( $this->menu_object, 'meta' ) ) {
168
- return $this->menu_object->meta( $key );
169
- }
170
- if ( isset( $this->$key ) ) {
171
- return $this->$key;
172
- }
173
- }
174
-
175
- /* Aliases */
176
-
177
- /**
178
- *
179
- *
180
- * @return array|bool
181
- */
182
- public function children() {
183
- return $this->get_children();
184
- }
185
-
186
- /**
187
- *
188
- *
189
- * @return bool
190
- */
191
- public function external() {
192
- return $this->is_external();
193
- }
194
-
195
- /**
196
- *
197
- *
198
- * @return string a full URL like http://mysite.com/thing/
199
- */
200
- public function link() {
201
- return $this->get_link();
202
- }
203
-
204
- /**
205
- *
206
- * @see get_path()
207
- * @return string the path of a URL like /foo
208
- */
209
- public function path() {
210
- return $this->get_path();
211
- }
212
-
213
- /**
214
- *
215
- * @see link()
216
- * @return string a full URL like http://mysite.com/thing/
217
- */
218
- public function permalink() {
219
- return $this->get_link();
220
- }
221
-
222
- /**
223
- *
224
- * @see link()
225
- * @return string a full URL like http://mysite.com/thing/
226
- */
227
- public function get_permalink() {
228
- return $this->get_link();
229
- }
230
-
231
- /**
232
- *
233
- *
234
- * @return string the public label like Foo
235
- */
236
- public function title() {
237
- if (isset($this->__title)){
238
- return $this->__title;
239
- }
240
- }
 
 
 
 
 
 
 
241
 
242
  }
2
 
3
  class TimberMenuItem extends TimberCore implements TimberCoreInterface {
4
 
5
+ public $children;
6
+ public $has_child_class = false;
7
+ public $classes = array();
8
+ public $class = '';
9
+ public $post_name;
10
+ public $type;
11
+ public $url;
12
+
13
+ public $PostClass = 'TimberPost';
14
+
15
+ protected $_name;
16
+ protected $_menu_item_object_id;
17
+ protected $_menu_item_url;
18
+ protected $menu_object;
19
+ protected $parent_object;
20
+
21
+ /**
22
+ *
23
+ *
24
+ * @param array|object $data
25
+ */
26
+ function __construct( $data ) {
27
+ $this->import( $data );
28
+ $this->import_classes( $data );
29
+ if ( isset( $this->name ) ) {
30
+ $this->_name = $this->name;
31
+ }
32
+ $this->name = $this->name();
33
+ $this->add_class( 'menu-item-' . $this->ID );
34
+ $this->menu_object = $data;
35
+ }
36
+
37
+ function __toString() {
38
+ return $this->name();
39
+ }
40
+
41
+ /**
42
+ *
43
+ *
44
+ * @param string $class_name
45
+ */
46
+ function add_class( $class_name ) {
47
+ $this->classes[] = $class_name;
48
+ $this->class .= ' ' . $class_name;
49
+ }
50
+
51
+ /**
52
+ *
53
+ *
54
+ * @return string
55
+ */
56
+ function name() {
57
+ if ( isset( $this->title ) ) {
58
+ return $this->title;
59
+ }
60
+ if ( isset( $this->_name ) ) {
61
+ return $this->_name;
62
+ }
63
+ return '';
64
+ }
65
+
66
+ /**
67
+ *
68
+ *
69
+ * @return string
70
+ */
71
+ function slug() {
72
+ if ( !isset( $this->parent_object ) ) {
73
+ $this->parent_object = $this->get_parent_object();
74
+ }
75
+ if ( isset( $this->parent_object->post_name ) && $this->parent_object->post_name ) {
76
+ return $this->parent_object->post_name;
77
+ }
78
+ return $this->post_name;
79
+ }
80
+
81
+ function get_parent_object() {
82
+ if ( isset( $this->_menu_item_object_id ) ) {
83
+ return new $this->PostClass( $this->_menu_item_object_id );
84
+ }
85
+ }
86
+
87
+ /**
88
+ *
89
+ *
90
+ * @return string
91
+ */
92
+ function get_link() {
93
+ if ( !isset( $this->url ) || !$this->url ) {
94
+ if ( isset( $this->_menu_item_type ) && $this->_menu_item_type == 'custom' ) {
95
+ $this->url = $this->_menu_item_url;
96
+ } else if ( isset( $this->menu_object ) && method_exists( $this->menu_object, 'get_link' ) ) {
97
+ $this->url = $this->menu_object->get_link();
98
+ }
99
+ }
100
+ return $this->url;
101
+ }
102
+
103
+ /**
104
+ *
105
+ *
106
+ * @return string
107
+ */
108
+ function get_path() {
109
+ return TimberURLHelper::get_rel_url( $this->get_link() );
110
+ }
111
+
112
+ /**
113
+ *
114
+ *
115
+ * @param TimberMenuItem $item
116
+ */
117
+ function add_child( $item ) {
118
+ if ( !$this->has_child_class ) {
119
+ $this->add_class( 'menu-item-has-children' );
120
+ $this->has_child_class = true;
121
+ }
122
+ if ( !isset( $this->children ) ) {
123
+ $this->children = array();
124
+ }
125
+ $this->children[] = $item;
126
+ }
127
+
128
+ /**
129
+ *
130
+ *
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->classes = apply_filters( 'nav_menu_css_class', $this->classes, $this );
137
+ $this->class = trim( implode( ' ', $this->classes ) );
138
+ }
139
+
140
+ /**
141
+ *
142
+ *
143
+ * @return array|bool
144
+ */
145
+ function get_children() {
146
+ if ( isset( $this->children ) ) {
147
+ return $this->children;
148
+ }
149
+ return false;
150
+ }
151
+
152
+ /**
153
+ *
154
+ *
155
+ * @return bool
156
+ */
157
+ function is_external() {
158
+ if ( $this->type != 'custom' ) {
159
+ return false;
160
+ }
161
+ return TimberURLHelper::is_external( $this->url );
162
+ }
163
+
164
+ /**
165
+ *
166
+ *
167
+ * @param unknown $key string lookup key
168
+ * @return mixed whatever value is storied in the database
169
+ */
170
+ public function meta( $key ) {
171
+ if ( is_object( $this->menu_object ) && method_exists( $this->menu_object, 'meta' ) ) {
172
+ return $this->menu_object->meta( $key );
173
+ }
174
+ if ( isset( $this->$key ) ) {
175
+ return $this->$key;
176
+ }
177
+ }
178
+
179
+ /* Aliases */
180
+
181
+ /**
182
+ *
183
+ *
184
+ * @return array|bool
185
+ */
186
+ public function children() {
187
+ return $this->get_children();
188
+ }
189
+
190
+ /**
191
+ *
192
+ *
193
+ * @return bool
194
+ */
195
+ public function external() {
196
+ return $this->is_external();
197
+ }
198
+
199
+ /**
200
+ *
201
+ *
202
+ * @return string a full URL like http://mysite.com/thing/
203
+ */
204
+ public function link() {
205
+ return $this->get_link();
206
+ }
207
+
208
+ /**
209
+ *
210
+ *
211
+ * @see get_path()
212
+ * @return string the path of a URL like /foo
213
+ */
214
+ public function path() {
215
+ return $this->get_path();
216
+ }
217
+
218
+ /**
219
+ *
220
+ *
221
+ * @see link()
222
+ * @return string a full URL like http://mysite.com/thing/
223
+ */
224
+ public function permalink() {
225
+ return $this->get_link();
226
+ }
227
+
228
+ /**
229
+ *
230
+ *
231
+ * @see link()
232
+ * @return string a full URL like http://mysite.com/thing/
233
+ */
234
+ public function get_permalink() {
235
+ return $this->get_link();
236
+ }
237
+
238
+ /**
239
+ *
240
+ *
241
+ * @return string the public label like Foo
242
+ */
243
+ public function title() {
244
+ if ( isset( $this->__title ) ) {
245
+ return $this->__title;
246
+ }
247
+ }
248
 
249
  }
lib/timber-post-getter.php CHANGED
@@ -2,137 +2,103 @@
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
  /**
32
- * @param mixed $query
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;
40
- }
41
-
42
- if (is_object($query) && !is_a($query, 'WP_Query') ){
43
- // The only object other than a query is a type of post object
44
- $query = array( $query );
45
- }
46
 
47
- if ( is_array( $query ) && count( $query ) && isset( $query[0] ) && is_object( $query[0] ) ) {
48
- // We have an array of post objects that already have data
49
- return new TimberPostsCollection( $query, $PostClass );
50
- } else {
51
- // We have a query (of sorts) to work with
52
- $tqi = new TimberQueryIterator( $query, $PostClass );
53
- return $tqi;
54
- }
55
- }
56
 
57
- static function get_pids($query){
58
- $posts = self::get_posts($query);
59
- $pids = array();
60
- foreach($posts as $post){
61
- if (isset($post->ID)){
62
- $pids[] = $post->ID;
63
- }
64
- }
65
- return $pids;
66
- }
67
 
68
- /**
69
- * @param array $results
70
- * @param string $PostClass
71
- * @return TimberPostsCollection
72
- * @deprecated since 0.21.1
73
- */
74
- static function handle_post_results($results, $PostClass = 'TimberPost') {
75
- $posts = array();
76
- foreach ($results as $rid) {
77
- $PostClassUse = $PostClass;
78
- if (is_array($PostClass)) {
79
- $post_type = get_post_type($rid);
80
- $PostClassUse = 'TimberPost';
81
- if (isset($PostClass[$post_type])) {
82
- $PostClassUse = $PostClass[$post_type];
83
- } else {
84
- if (is_array($PostClass)) {
85
- TimberHelper::error_log($post_type.' of '.$rid.' not found in ' . print_r($PostClass, true));
86
- } else {
87
- TimberHelper::error_log($post_type.' not found in '.$PostClass);
88
- }
89
- }
90
- }
91
- $post = new $PostClassUse($rid);
92
- if (isset($post->ID)) {
93
- $posts[] = $post;
94
- }
95
- }
96
- return new TimberPostsCollection( $posts, $PostClass );
97
- }
98
 
99
- static function loop_to_id() {
100
- if (!self::wp_query_has_posts()) { return false; }
101
 
102
- global $wp_query;
103
- $post_num = property_exists($wp_query, 'current_post')
104
- ? $wp_query->current_post + 1
105
- : 0
106
- ;
107
 
108
- if (!isset($wp_query->posts[$post_num])) { return false; }
109
 
110
- return $wp_query->posts[$post_num]->ID;
111
- }
112
 
113
- /**
114
- * @return bool
115
- */
116
- static function wp_query_has_posts() {
117
- global $wp_query;
118
- return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
119
- }
120
 
121
- /**
122
- * @param string|array $arg
123
- * @return bool
124
- */
125
- static function is_post_class_or_class_map($arg){
126
- if (is_string($arg) && class_exists($arg)) {
127
- return true;
128
- }
129
- if (is_array($arg)) {
130
- foreach ($arg as $item) {
131
- if (is_string($item) && class_exists($item)) {
132
- return true;
133
- }
134
- }
135
- }
136
- return false;
137
- }
138
  }
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
+ }
 
16
 
17
+ static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
18
+ $posts = self::query_posts( $query, $PostClass );
19
+ return apply_filters('timber_post_getter_get_posts', $posts->get_posts( $return_collection ));
20
+ }
21
 
22
+ static function query_post( $query = false, $PostClass = 'TimberPost' ) {
23
+ $posts = self::query_posts( $query, $PostClass );
24
+ if ( $post = $posts->current() ) {
25
+ return $post;
26
+ }
27
+ }
 
28
 
29
  /**
30
+ * @param mixed $query
31
+ * @param string $PostClass
32
+ * @return array|bool|null
33
+ */
34
+ static function query_posts($query = false, $PostClass = 'TimberPost' ) {
35
+ if (self::is_post_class_or_class_map($query)) {
36
+ $PostClass = $query;
37
+ $query = false;
38
+ }
 
 
 
 
 
39
 
40
+ if (is_object($query) && !is_a($query, 'WP_Query') ){
41
+ // The only object other than a query is a type of post object
42
+ $query = array( $query );
43
+ }
 
 
 
 
 
44
 
45
+ if ( is_array( $query ) && count( $query ) && isset( $query[0] ) && is_object( $query[0] ) ) {
46
+ // We have an array of post objects that already have data
47
+ return new TimberPostsCollection( $query, $PostClass );
48
+ } else {
49
+ // We have a query (of sorts) to work with
50
+ $tqi = new TimberQueryIterator( $query, $PostClass );
51
+ return $tqi;
52
+ }
53
+ }
 
54
 
55
+ static function get_pids($query){
56
+ $posts = self::get_posts($query);
57
+ $pids = array();
58
+ foreach($posts as $post){
59
+ if (isset($post->ID)){
60
+ $pids[] = $post->ID;
61
+ }
62
+ }
63
+ return $pids;
64
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
+ static function loop_to_id() {
67
+ if (!self::wp_query_has_posts()) { return false; }
68
 
69
+ global $wp_query;
70
+ $post_num = property_exists($wp_query, 'current_post')
71
+ ? $wp_query->current_post + 1
72
+ : 0
73
+ ;
74
 
75
+ if (!isset($wp_query->posts[$post_num])) { return false; }
76
 
77
+ return $wp_query->posts[$post_num]->ID;
78
+ }
79
 
80
+ /**
81
+ * @return bool
82
+ */
83
+ static function wp_query_has_posts() {
84
+ global $wp_query;
85
+ return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
86
+ }
87
 
88
+ /**
89
+ * @param string|array $arg
90
+ * @return bool
91
+ */
92
+ static function is_post_class_or_class_map($arg){
93
+ if (is_string($arg) && class_exists($arg)) {
94
+ return true;
95
+ }
96
+ if (is_array($arg)) {
97
+ foreach ($arg as $item) {
98
+ if (is_string($item) && class_exists($item)) {
99
+ return true;
100
+ }
101
+ }
102
+ }
103
+ }
 
104
  }
lib/timber-post.php CHANGED
@@ -2,99 +2,99 @@
2
 
3
  class TimberPost extends TimberCore implements TimberCoreInterface {
4
 
5
- public $ImageClass = 'TimberImage';
6
- public $PostClass = 'TimberPost';
7
-
8
- public $object_type = 'post';
9
- public static $representation = 'post';
10
-
11
- public $_can_edit;
12
- public $_custom_imported = false;
13
- public $_content;
14
- public $_get_terms;
15
-
16
- private $_next = array();
17
- private $_prev = array();
18
-
19
- public $class;
20
- public $display_date;
21
- public $id;
22
- public $ID;
23
- public $post_content;
24
- public $post_date;
25
- public $post_parent;
26
- public $post_title;
27
- public $post_type;
28
- public $slug;
29
-
30
- /**
31
- * If you send the constructor nothing it will try to figure out the current post id based on being inside The_Loop
32
- * @param mixed $pid
33
- * @return \TimberPost TimberPost object -- woo!
34
- */
35
- function __construct($pid = null) {
36
- $pid = $this->determine_id( $pid );
37
- $this->init($pid);
38
- }
39
 
40
- /**
41
- * @param mixed a value to test against
42
- * @return int the numberic id we should be using for this post object
43
- */
44
-
45
- protected function determine_id($pid) {
46
- global $wp_query;
47
- if ($pid === null &&
48
- isset($wp_query->queried_object_id)
49
- && $wp_query->queried_object_id
50
- && isset($wp_query->queried_object)
51
- && is_object($wp_query->queried_object)
52
- && get_class($wp_query->queried_object) == 'WP_Post'
53
- ) {
54
- $pid = $wp_query->queried_object_id;
55
- } else if ($pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
56
- //hack for static page as home page
57
- $pid = $wp_query->queried_object_id;
58
- } else if ($pid === null) {
59
- $gtid = false;
60
- $maybe_post = get_post();
61
- if (isset($maybe_post->ID)){
62
- $gtid = true;
63
- }
64
- if ( $gtid ) {
65
- $pid = get_the_ID();
66
- }
67
- if ( !$pid ) {
68
- global $wp_query;
69
- if ( isset($wp_query->query['p']) ) {
70
- $pid = $wp_query->query['p'];
71
- }
72
- }
73
- }
74
- if ($pid === null && ($pid_from_loop = TimberPostGetter::loop_to_id())) {
75
- $pid = $pid_from_loop;
76
- }
77
- return $pid;
78
- }
79
 
80
- /**
81
- * @return string
82
- */
83
- function __toString() {
84
- return $this->title();
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
 
88
- /**
89
- * @param int|bool $pid
90
- */
91
- function init($pid = false) {
92
  if ($pid === false) {
93
  $pid = get_the_ID();
94
  }
95
  if (is_numeric($pid)) {
96
- $this->ID = $pid;
97
- }
98
  $post_info = $this->get_info($pid);
99
  $this->import($post_info);
100
  /* deprecated, adding for support for older themes */
@@ -104,931 +104,947 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
104
  $this->class = $post_class;
105
  }
106
 
107
- /**
108
- * Get the URL that will edit the current post/object
109
- *
110
- * @return bool|string
111
- */
112
- function get_edit_url() {
113
- if ($this->can_edit()) {
114
- return get_edit_post_link($this->ID);
115
- }
116
- }
117
 
118
- /**
119
- * updates the post_meta of the current object with the given value
120
- *
121
- * @param string $field
122
- * @param mixed $value
123
- */
124
- public function update($field, $value) {
125
- if (isset($this->ID)) {
126
- update_post_meta($this->ID, $field, $value);
127
- $this->$field = $value;
128
- }
129
- }
130
 
131
 
132
- /**
133
- * takes a mix of integer (post ID), string (post slug), or object to return a WordPress post object from WP's built-in get_post() function
134
- *
135
- * @param mixed $pid
136
- * @return WP_Post on success
137
- */
138
- private function prepare_post_info($pid = 0) {
139
- if (is_string($pid) || is_numeric($pid) || (is_object($pid) && !isset($pid->post_title)) || $pid === 0) {
140
- $pid = self::check_post_id($pid);
141
- $post = get_post($pid);
142
- if ($post) {
143
- return $post;
144
- } else {
145
- $post = get_page($pid);
146
- return $post;
147
- }
148
- }
149
- //we can skip if already is WP_Post
150
- return $pid;
151
- }
152
 
153
 
154
- /**
155
- * helps you find the post id regardless of whether you send a string or whatever
156
- *
157
- * @param integer $pid ;
158
- * @return integer ID number of a post
159
- */
160
- protected function check_post_id($pid) {
161
- if (is_numeric($pid) && $pid === 0) {
162
- $pid = get_the_ID();
163
- return $pid;
164
- }
165
- if (!is_numeric($pid) && is_string($pid)) {
166
- $pid = self::get_post_id_by_name($pid);
167
- return $pid;
168
- }
169
- if (!$pid) {
170
- return null;
171
- }
172
- return $pid;
173
- }
174
 
175
 
176
- /**
177
- * get_post_id_by_name($post_name)
178
- *
179
- * @param string $post_name
180
- * @return int
181
- */
182
- public static function get_post_id_by_name($post_name) {
183
- global $wpdb;
184
- $query = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s LIMIT 1", $post_name);
185
- $result = $wpdb->get_row($query);
186
- if (!$result) {
187
- return null;
188
- }
189
- return $result->ID;
190
- }
191
 
192
 
193
- /**
194
- * ## get a preview of your post, if you have an excerpt it will use that,
195
- * ## otherwise it will pull from the post_content.
196
- * ## If there's a <!-- more --> tag it will use that to mark where to pull through.
197
- * <p>{{post.get_preview(50)}}</p>
198
- */
199
-
200
- /**
201
- * @param int $len
202
- * @param bool $force
203
- * @param string $readmore
204
- * @param bool $strip
205
- * @return string
206
- */
207
- function get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true) {
208
- $text = '';
209
- $trimmed = false;
210
- if (isset($this->post_excerpt) && strlen($this->post_excerpt)) {
211
- if ($force) {
212
- $text = TimberHelper::trim_words($this->post_excerpt, $len, false);
213
- $trimmed = true;
214
- } else {
215
- $text = $this->post_excerpt;
216
- }
217
- }
218
- if (!strlen($text) && strpos($this->post_content, '<!--more-->') !== false) {
219
- $pieces = explode('<!--more-->', $this->post_content);
220
- $text = $pieces[0];
221
- if ($force) {
222
- $text = TimberHelper::trim_words($text, $len, false);
223
- $trimmed = true;
224
- }
225
- }
226
- if (!strlen($text)) {
227
- $text = TimberHelper::trim_words($this->get_content(), $len, false);
228
- $trimmed = true;
229
- }
230
- if (!strlen(trim($text))) {
231
- return $text;
232
- }
233
- if ($strip) {
234
- $text = trim(strip_tags($text));
235
- }
236
- if (strlen($text)) {
237
- $text = trim($text);
238
- $last = $text[strlen($text) - 1];
239
- if ($last != '.' && $trimmed) {
240
- $text .= ' &hellip; ';
241
- }
242
- if (!$strip) {
243
- $last_p_tag = strrpos($text, '</p>');
244
- if ($last_p_tag !== false) {
245
- $text = substr($text, 0, $last_p_tag);
246
- }
247
- if ($last != '.' && $trimmed) {
248
- $text .= ' &hellip; ';
249
- }
250
- }
251
 
252
- if ($readmore) {
253
- $text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . $readmore . '</a>';
254
- }
255
- if (!$strip) {
256
- $text .= '</p>';
257
- }
258
- }
259
- return $text;
260
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
- /**
263
- * gets the post custom and attaches it to the current object
264
- * @param bool|int $pid a post ID number
265
- * @nodoc
266
- */
267
- function import_custom($pid = false) {
268
- if (!$pid) {
269
- $pid = $this->ID;
270
- }
271
- $customs = $this->get_post_custom($pid);
272
- $this->import($customs);
273
- }
274
 
275
- /**
276
- * @param int $pid
277
- * @return array
278
- */
279
- function get_post_custom($pid) {
280
- apply_filters('timber_post_get_meta_pre', array(), $pid, $this);
281
- $customs = get_post_custom($pid);
282
- if (!is_array($customs) || empty($customs)) {
283
- return array();
284
- }
285
- foreach ($customs as $key => $value) {
286
- if (is_array($value) && count($value) == 1 && isset($value[0])) {
287
- $value = $value[0];
288
- }
289
- $customs[$key] = maybe_unserialize($value);
290
- }
291
- $customs = apply_filters('timber_post_get_meta', $customs, $pid, $this);
292
- return $customs;
293
- }
294
 
295
- /**
296
- * ## get the featured image as a TimberImage
297
- * <img src="{{post.get_thumbnail.get_src}}" />
298
- */
299
-
300
- /**
301
- * @return null|TimberImage
302
- */
303
- function get_thumbnail() {
304
- if (function_exists('get_post_thumbnail_id')) {
305
- $tid = get_post_thumbnail_id($this->ID);
306
- if ($tid) {
307
- return new $this->ImageClass($tid);
308
- }
309
- }
310
- }
311
 
312
- /**
313
- * @return string
314
- */
315
- function get_permalink() {
316
- if (isset($this->permalink)) {
317
- return $this->permalink;
318
- }
319
- $this->permalink = get_permalink($this->ID);
320
- return $this->permalink;
321
- }
 
322
 
323
- /**
324
- * @return string
325
- */
326
- function get_link() {
327
- return $this->get_permalink();
328
- }
 
 
 
 
329
 
330
- /**
331
- * @param bool $taxonomy
332
- * @return mixed
333
- */
334
- function get_next($taxonomy = false) {
335
- if (!isset($this->_next) || !isset($this->_next[$taxonomy])) {
336
- global $post;
337
- $this->_next = array();
338
- $old_global = $post;
339
- $post = $this;
340
- if ($taxonomy) {
341
- $adjacent = get_adjacent_post(true, '', false, $taxonomy);
342
- } else {
343
- $adjacent = get_adjacent_post(false, '', false);
344
- }
345
 
346
- if ($adjacent) {
347
- $this->_next[$taxonomy] = new $this->PostClass($adjacent);
348
- } else {
349
- $this->_next[$taxonomy] = false;
350
- }
351
- $post = $old_global;
352
- }
353
- return $this->_next[$taxonomy];
354
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
 
356
- /**
357
- * @return array
358
- */
359
- public function get_pagination() {
360
- global $post, $page, $numpages, $multipage;
361
- $post = $this;
362
- $ret = array();
363
- if ($multipage) {
364
- for ($i = 1; $i <= $numpages; $i++) {
365
- $link = self::get_wp_link_page($i);
366
- $data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
367
- if ($i == $page) {
368
- $data['current'] = true;
369
- }
370
- $ret['pages'][] = $data;
371
- }
372
- $i = $page - 1;
373
- if ($i) {
374
- $link = self::get_wp_link_page($i);
375
- $ret['prev'] = array('link' => $link);
376
- }
377
- $i = $page + 1;
378
- if ($i <= $numpages) {
379
- $link = self::get_wp_link_page($i);
380
- $ret['next'] = array('link' => $link);
381
- }
382
- }
383
- return $ret;
384
- }
385
 
386
- /**
387
- * @param int $i
388
- * @return string
389
- */
390
- private static function get_wp_link_page($i) {
391
- $link = _wp_link_page($i);
392
- $link = new SimpleXMLElement($link . '</a>');
393
- if (isset($link['href'])) {
394
- return $link['href'];
395
- }
396
- return '';
397
- }
398
 
399
- /**
400
- * @return string
401
- */
402
- function get_path() {
403
- return TimberURLHelper::get_rel_url($this->get_link());
404
- }
405
 
406
- /**
407
- * @param bool $taxonomy
408
- * @return mixed
409
- */
410
- function get_prev($taxonomy = false) {
411
- if (isset($this->_prev) && isset($this->_prev[$taxonomy])) {
412
- return $this->_prev[$taxonomy];
413
- }
414
- global $post;
415
- $old_global = $post;
416
- $post = $this;
417
- $within_taxonomy = ($taxonomy) ? $taxonomy : 'category';
418
- $adjacent = get_adjacent_post(($taxonomy), '', true, $within_taxonomy);
419
-
420
- $prev_in_taxonomy = false;
421
- if ($adjacent) {
422
- $prev_in_taxonomy = new $this->PostClass($adjacent);
423
- }
424
- $this->_prev[$taxonomy] = $prev_in_taxonomy;
425
- $post = $old_global;
426
- return $this->_prev[$taxonomy];
427
- }
428
 
429
- /**
430
- * @return bool|TimberPost
431
- */
432
- function get_parent() {
433
- if (!$this->post_parent) {
434
- return false;
435
- }
436
- return new $this->PostClass($this->post_parent);
437
- }
438
 
439
- /**
440
- * ## Gets a User object from the author of the post
441
- * <p class="byline">{{post.get_author.name}}</p>
442
- */
443
-
444
- /**
445
- * @return bool|TimberUser
446
- */
447
- function get_author() {
448
- if (isset($this->post_author)) {
449
- return new TimberUser($this->post_author);
450
- }
451
- }
452
 
453
- /**
454
- * @return bool|TimberUser
455
- */
456
- function get_modified_author() {
457
- $user_id = get_post_meta($this->ID, '_edit_last', true);
458
- return ($user_id ? new TimberUser($user_id) : $this->get_author());
459
- }
 
460
 
461
- /**
462
- * @param int $pid
463
- * @return null|object|WP_Post
464
- */
465
- function get_info($pid) {
466
- $post = $this->prepare_post_info($pid);
467
- if (!isset($post->post_status)) {
468
- return null;
469
- }
470
- $post->status = $post->post_status;
471
- $post->id = $post->ID;
472
- $post->slug = $post->post_name;
473
- $customs = $this->get_post_custom($post->ID);
474
- $post->custom = $customs;
475
- $post = (object)array_merge((array)$customs, (array)$post);
476
- return $post;
477
- }
478
 
479
- /**
480
- * This is deprecated!
481
- * @param string $use
482
- * @return string
483
- */
484
- function get_display_date($use = 'post_date') {
485
- return date(get_option('date_format'), strtotime($this->$use));
486
- }
 
 
 
 
 
 
 
 
 
487
 
488
- /**
489
- * @param string $date_format
490
- * @return string
491
- */
492
- function get_date($date_format = '') {
493
- $df = $date_format ? $date_format : get_option('date_format');
494
- $the_date = (string)mysql2date($df, $this->post_date);
495
- return apply_filters('get_the_date', $the_date, $date_format);
496
- }
497
 
498
- /**
499
- * @param string $date_format
500
- * @return string
501
- */
502
- function get_modified_date($date_format = '') {
503
- $df = $date_format ? $date_format : get_option('date_format');
504
- $the_time = $this->get_modified_time($df, null, $this->ID, true);
505
- return apply_filters('get_the_modified_date', $the_time, $date_format);
506
- }
507
 
508
- /**
509
- * @param string $time_format
510
- * @return string
511
- */
512
- function get_modified_time($time_format = '') {
513
- $tf = $time_format ? $time_format : get_option('time_format');
514
- $the_time = get_post_modified_time($tf, false, $this->ID, true);
515
- return apply_filters('get_the_modified_time', $the_time, $time_format);
516
- }
517
 
518
- /**
519
- * @param string $post_type
520
- * @param bool $childPostClass
521
- * @return array
522
- */
523
- function get_children($post_type = 'any', $childPostClass = false) {
524
- if ($childPostClass == false) {
525
- $childPostClass = $this->PostClass;
526
- }
527
- if ($post_type == 'parent') {
528
- $post_type = $this->post_type;
529
- }
530
- $children = get_children('post_parent=' . $this->ID . '&post_type=' . $post_type . '&numberposts=-1&orderby=menu_order title&order=ASC');
531
- foreach ($children as &$child) {
532
- $child = new $childPostClass($child->ID);
533
- }
534
- $children = array_values($children);
535
- return $children;
536
- }
537
 
538
- /**
539
- * {% for comment in post.get_comments %}
540
- * <p>{{comment.content}}</p>
541
- * {% endfor %}
542
- */
543
-
544
- /**
545
- * @param int $ct
546
- * @param string $order
547
- * @param string $type
548
- * @param string $status
549
- * @param string $CommentClass
550
- * @return mixed
551
- */
552
- function get_comments($ct = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment') {
553
- $args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
554
- if ($ct > 0) {
555
- $args['number'] = $ct;
556
- }
557
- if ($order == 'wp') {
558
- $args['order'] = get_option('comment_order');
559
- }
560
- $comments = get_comments($args);
561
- foreach ($comments as &$comment) {
562
- $comment = new $CommentClass($comment);
563
- }
564
- return $comments;
565
- }
566
 
567
- /**
568
- * <ul class="categories">
569
- * {% for category in post.get_categories %}
570
- * <li>{{category.name}}</li>
571
- * {% endfor %}
572
- * </ul>
573
- */
574
-
575
- /**
576
- * @return array
577
- */
578
- function get_categories() {
579
- return $this->get_terms('category');
580
- }
581
 
582
- /**
583
- * @return mixed
584
- */
585
- function get_category() {
586
- $cats = $this->get_categories();
587
- if (count($cats) && isset($cats[0])) {
588
- return $cats[0];
589
- }
590
- }
 
 
 
 
 
 
 
591
 
592
- /** # get terms is good
593
- *
594
- */
595
-
596
- /**
597
- * @param string $tax
598
- * @param bool $merge
599
- * @param string $TermClass
600
- * @return array
601
- */
602
- function get_terms($tax = '', $merge = true, $TermClass = 'TimberTerm') {
603
- if (is_string($merge) && class_exists($merge)){
604
- $TermClass = $merge;
605
- }
606
- if (is_string($tax)) {
607
- if (isset($this->_get_terms) && isset($this->_get_terms[$tax])) {
608
- return $this->_get_terms[$tax];
609
- }
610
- }
611
- if (!strlen($tax) || $tax == 'all' || $tax == 'any') {
612
- $taxs = get_object_taxonomies($this->post_type);
613
- } else if (is_array($tax)) {
614
- $taxs = $tax;
615
- } else {
616
- $taxs = array($tax);
617
- }
618
- $ret = array();
619
- foreach ($taxs as $tax) {
620
- if ($tax == 'tags' || $tax == 'tag') {
621
- $tax = 'post_tag';
622
- } else if ($tax == 'categories') {
623
- $tax = 'category';
624
- }
625
- $terms = wp_get_post_terms($this->ID, $tax);
626
- if (!is_array($terms) && is_object($terms) && get_class($terms) == 'WP_Error') {
627
- //something is very wrong
628
- TimberHelper::error_log('You have an error retrieving terms on a post in timber-post.php:367');
629
- TimberHelper::error_log('tax = ' . $tax);
630
- TimberHelper::error_log($terms);
631
-
632
- } else {
633
- foreach ($terms as &$term) {
634
- $term = new $TermClass($term->term_id, $tax);
635
- }
636
- if ($merge && is_array($terms)) {
637
- $ret = array_merge($ret, $terms);
638
- } else if (count($terms)) {
639
- $ret[$tax] = $terms;
640
- }
641
- }
642
- }
643
- if (!isset($this->_get_terms)) {
644
- $this->_get_terms = array();
645
  }
646
- $this->_get_terms[$tax] = $ret;
647
- return $ret;
648
- }
649
 
650
- /**
651
- * @param string|int $term_name_or_id
652
- * @param string $taxonomy
653
- * @return bool
654
- */
655
- function has_term($term_name_or_id, $taxonomy = 'all') {
656
- if ($taxonomy == 'all' || $taxonomy == 'any') {
657
- $taxes = get_object_taxonomies($this->post_type, 'names');
658
- $ret = false;
659
- foreach ($taxes as $tax) {
660
- if (has_term($term_name_or_id, $tax, $this->ID)) {
661
- $ret = true;
662
- break;
663
  }
664
  }
665
- return $ret;
666
  }
667
- return has_term($term_name_or_id, $taxonomy, $this->ID);
668
- }
669
 
670
- /**
671
- * @param string $field
672
- * @return TimberImage
673
- */
674
- function get_image($field) {
675
- return new $this->ImageClass($this->$field);
676
  }
677
 
678
- /**
679
- * ## Gets an array of tags for you to use
680
- * <ul class="tags">
681
- * {% for tag in post.tags %}
682
- * <li>{{tag.name}}</li>
683
- * {% endfor %}
684
- * </ul>
685
- */
686
-
687
- /**
688
- * @return array
689
- */
690
- function get_tags() {
691
- return $this->get_terms('tags');
692
- }
693
 
694
- /**
695
- * ## Outputs the title with filters applied
696
- * <h1>{{post.get_title}}</h1>
697
- */
 
 
698
 
699
- /**
700
- * @return string
701
- */
702
- function get_title() {
703
- return apply_filters('the_title', $this->post_title, $this->ID);
704
- }
 
 
 
705
 
706
- /**
707
- * ## Displays the content of the post with filters, shortcodes and wpautop applied
708
- * <div class="article-text">{{post.get_content}}</div>
709
- */
710
-
711
- /**
712
- * @param int $len
713
- * @param int $page
714
- * @return string
715
- */
716
- function get_content($len = 0, $page = 0) {
717
- if ($len == 0 && $page == 0 && $this->_content) {
718
- return $this->_content;
719
- }
720
- $content = $this->post_content;
721
- if ($len) {
722
- $content = wp_trim_words($content, $len);
723
- }
724
- if ($page) {
725
- $contents = explode('<!--nextpage-->', $content);
726
- $page--;
727
- if (count($contents) > $page) {
728
- $content = $contents[$page];
729
- }
730
- }
731
- $content = apply_filters('the_content', ($content));
732
- if ($len == 0 && $page == 0) {
733
- $this->_content = $content;
734
- }
735
- return $content;
736
- }
737
 
738
- /**
739
- * @return string
740
- */
741
- function get_paged_content() {
742
- global $page;
743
- return $this->get_content(0, $page);
744
- }
745
- /**
746
- * @return mixed
747
- */
748
- public function get_post_type() {
749
- return get_post_type_object($this->post_type);
750
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
751
 
752
- /**
753
- * @return int
754
- */
755
- public function get_comment_count() {
756
- if (isset($this->ID)) {
757
- return get_comments_number($this->ID);
758
- } else {
759
- return 0;
760
- }
761
- }
 
 
 
 
 
 
 
 
 
762
 
763
- /**
764
- * @param string $field_name
765
- * @return mixed
766
- */
767
- public function get_field($field_name) {
768
- $value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
769
- if ($value === null) {
770
- $value = get_post_meta($this->ID, $field_name);
771
- if (is_array($value) && count($value) == 1) {
772
- $value = $value[0];
773
- }
774
- if (is_array($value) && count($value) == 0) {
775
- $value = null;
776
- }
777
- }
778
- $value = apply_filters('timber_post_get_meta_field', $value, $this->ID, $field_name, $this);
779
- return $value;
780
- }
781
 
782
- /**
783
- * @param string $field_name
784
- */
785
- function import_field($field_name) {
786
- $this->$field_name = $this->get_field($field_name);
787
- }
 
 
788
 
789
- /**
790
- * @return mixed
791
- */
792
- function get_format() {
793
- return get_post_format($this->ID);
794
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
795
 
796
  /**
797
- * @param string $class
798
- * @return string
799
- */
800
- public function post_class($class='') {
801
- global $post;
802
- $old_global_post = $post;
803
- $post = $this;
804
  $class_array = get_post_class($class, $this->ID);
805
  $post = $old_global_post;
806
- if (is_array($class_array)){
807
- return implode(' ', $class_array);
808
- }
809
- return $class_array;
810
- }
811
-
812
- // Docs
813
-
814
- /**
815
- * @return array
816
- */
817
- public function get_method_values() {
818
- $ret = parent::get_method_values();
819
- $ret['author'] = $this->author();
820
- $ret['categories'] = $this->categories();
821
- $ret['category'] = $this->category();
822
- $ret['children'] = $this->children();
823
- $ret['comments'] = $this->comments();
824
- $ret['content'] = $this->content();
825
- $ret['edit_link'] = $this->edit_link();
826
- $ret['format'] = $this->format();
827
- $ret['link'] = $this->link();
828
- $ret['next'] = $this->next();
829
- $ret['pagination'] = $this->pagination();
830
- $ret['parent'] = $this->parent();
831
- $ret['path'] = $this->path();
832
- $ret['prev'] = $this->prev();
833
- $ret['terms'] = $this->terms();
834
- $ret['tags'] = $this->tags();
835
- $ret['thumbnail'] = $this->thumbnail();
836
- $ret['title'] = $this->title();
837
- return $ret;
838
- }
839
 
840
- // Aliases
841
- /**
842
- * @return bool|TimberUser
843
- */
844
- public function author() {
845
- return $this->get_author();
846
- }
847
 
848
- /**
849
- * @return bool|TimberUser
850
- */
851
- public function modified_author() {
852
- return $this->get_modified_author();
853
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
854
 
855
- /**
856
- * @return array
857
- */
858
- public function categories() {
859
- return $this->get_terms('category');
860
- }
 
861
 
862
- /**
863
- * @return mixed
864
- */
865
- public function category() {
866
- return $this->get_category();
867
- }
868
 
869
- /**
870
- * @return array
871
- */
872
- public function children( $post_type = 'any', $childPostClass = false ) {
873
- return $this->get_children( $post_type, $childPostClass );
874
- }
875
 
876
- /**
877
- * @return mixed
878
- */
879
- public function comments() {
880
- return $this->get_comments();
881
- }
882
 
883
- /**
884
- * @param int $page
885
- * @return string
886
- */
887
- public function content($page = 0) {
888
- return $this->get_content(0, $page);
889
- }
890
 
891
- /**
892
- * @return string
893
- */
894
- public function paged_content() {
895
- return $this->get_paged_content();
896
- }
897
 
898
- /**
899
- * @param string $date_format
900
- * @return string
901
- */
902
- public function date($date_format = '') {
903
- return $this->get_date($date_format);
904
- }
905
 
906
- /**
907
- * @return bool|string
908
- */
909
- public function edit_link() {
910
- return $this->get_edit_url();
911
- }
912
 
913
- /**
914
- * @return mixed
915
- */
916
- public function format() {
917
- return $this->get_format();
918
- }
 
919
 
920
- /**
921
- * @return string
922
- */
923
- public function link() {
924
- return $this->get_permalink();
925
- }
926
 
927
- /**
928
- * @param string $field_name
929
- * @return mixed
930
- */
931
- public function meta($field_name = null) {
932
- if ($field_name == null) {
933
- $field_name = 'meta';
934
- }
935
- return $this->get_field($field_name);
936
- }
937
 
938
- /**
939
- * @return string
940
- */
941
- public function name(){
942
- return $this->title();
943
- }
944
 
945
- /**
946
- * @param string $date_format
947
- * @return string
948
- */
949
- public function modified_date($date_format = '') {
950
- return $this->get_modified_date($date_format);
951
- }
 
 
 
952
 
953
- /**
954
- * @param string $time_format
955
- * @return string
956
- */
957
- public function modified_time($time_format = '') {
958
- return $this->get_modified_time($time_format);
959
- }
960
 
961
- /**
962
- * @param bool $in_same_cat
963
- * @return mixed
964
- */
965
- public function next($in_same_cat = false) {
966
- return $this->get_next($in_same_cat);
967
- }
968
 
969
- /**
970
- * @return array
971
- */
972
- public function pagination() {
973
- return $this->get_pagination();
974
- }
 
975
 
976
- /**
977
- * @return bool|TimberPost
978
- */
979
- public function parent() {
980
- return $this->get_parent();
981
- }
 
982
 
983
- /**
984
- * @return string
985
- */
986
- public function path() {
987
- return $this->get_path();
988
- }
989
 
990
- /**
991
- * @return string
992
- */
993
- public function permalink() {
994
- return $this->get_permalink();
995
- }
996
 
997
- /**
998
- * @param bool $in_same_cat
999
- * @return mixed
1000
- */
1001
- public function prev($in_same_cat = false) {
1002
- return $this->get_prev($in_same_cat);
1003
- }
1004
 
1005
- /**
1006
- * @param string $tax
1007
- * @return array
1008
- */
1009
- public function terms($tax = '') {
1010
- return $this->get_terms($tax);
1011
- }
1012
 
1013
- /**
1014
- * @return array
1015
- */
1016
- public function tags() {
1017
- return $this->get_tags();
1018
- }
 
1019
 
1020
- /**
1021
- * @return null|TimberImage
1022
- */
1023
- public function thumbnail() {
1024
- return $this->get_thumbnail();
1025
- }
 
1026
 
1027
- /**
1028
- * @return string
1029
- */
1030
- public function title() {
1031
- return $this->get_title();
1032
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1033
 
1034
  }
2
 
3
  class TimberPost extends TimberCore implements TimberCoreInterface {
4
 
5
+ public $ImageClass = 'TimberImage';
6
+ public $PostClass = 'TimberPost';
7
+
8
+ public $object_type = 'post';
9
+ public static $representation = 'post';
10
+
11
+ private $_custom_imported = false;
12
+ private $_content;
13
+ private $_get_terms;
14
+ private $_permalink;
15
+ private $_next = array();
16
+ private $_prev = array();
17
+
18
+ public $class;
19
+ public $display_date;
20
+ public $id;
21
+ public $ID;
22
+ public $post_author;
23
+ public $post_content;
24
+ public $post_date;
25
+ public $post_excerpt;
26
+ public $post_parent;
27
+ public $post_title;
28
+ public $post_type;
29
+ public $slug;
 
 
 
 
 
 
 
 
 
30
 
31
+ /**
32
+ * If you send the constructor nothing it will try to figure out the current post id based on being inside The_Loop
33
+ * @param mixed $pid
34
+ */
35
+ function __construct($pid = null) {
36
+ $pid = $this->determine_id( $pid );
37
+ $this->init($pid);
38
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
+ /**
41
+ * @param mixed a value to test against
42
+ * @return int the numberic id we should be using for this post object
43
+ */
44
+
45
+ protected function determine_id($pid) {
46
+ global $wp_query;
47
+ if ($pid === null &&
48
+ isset($wp_query->queried_object_id)
49
+ && $wp_query->queried_object_id
50
+ && isset($wp_query->queried_object)
51
+ && is_object($wp_query->queried_object)
52
+ && get_class($wp_query->queried_object) == 'WP_Post'
53
+ ) {
54
+ $pid = $wp_query->queried_object_id;
55
+ } else if ($pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
56
+ //hack for static page as home page
57
+ $pid = $wp_query->queried_object_id;
58
+ } else if ($pid === null) {
59
+ $gtid = false;
60
+ $maybe_post = get_post();
61
+ if (isset($maybe_post->ID)){
62
+ $gtid = true;
63
+ }
64
+ if ( $gtid ) {
65
+ $pid = get_the_ID();
66
+ }
67
+ if ( !$pid ) {
68
+ global $wp_query;
69
+ if ( isset($wp_query->query['p']) ) {
70
+ $pid = $wp_query->query['p'];
71
+ }
72
+ }
73
+ }
74
+ if ($pid === null && ($pid_from_loop = TimberPostGetter::loop_to_id())) {
75
+ $pid = $pid_from_loop;
76
+ }
77
+ return $pid;
78
+ }
79
+
80
+ /**
81
+ * @return string
82
+ */
83
+ function __toString() {
84
+ return $this->title();
85
+ }
86
 
87
 
88
+ /**
89
+ * @param int|bool $pid
90
+ */
91
+ function init($pid = false) {
92
  if ($pid === false) {
93
  $pid = get_the_ID();
94
  }
95
  if (is_numeric($pid)) {
96
+ $this->ID = $pid;
97
+ }
98
  $post_info = $this->get_info($pid);
99
  $this->import($post_info);
100
  /* deprecated, adding for support for older themes */
104
  $this->class = $post_class;
105
  }
106
 
107
+ /**
108
+ * Get the URL that will edit the current post/object
109
+ *
110
+ * @return bool|string
111
+ */
112
+ function get_edit_url() {
113
+ if ($this->can_edit()) {
114
+ return get_edit_post_link($this->ID);
115
+ }
116
+ }
117
 
118
+ /**
119
+ * updates the post_meta of the current object with the given value
120
+ *
121
+ * @param string $field
122
+ * @param mixed $value
123
+ */
124
+ public function update($field, $value) {
125
+ if (isset($this->ID)) {
126
+ update_post_meta($this->ID, $field, $value);
127
+ $this->$field = $value;
128
+ }
129
+ }
130
 
131
 
132
+ /**
133
+ * takes a mix of integer (post ID), string (post slug), or object to return a WordPress post object from WP's built-in get_post() function
134
+ *
135
+ * @param mixed $pid
136
+ * @return WP_Post on success
137
+ */
138
+ private function prepare_post_info($pid = 0) {
139
+ if (is_string($pid) || is_numeric($pid) || (is_object($pid) && !isset($pid->post_title)) || $pid === 0) {
140
+ $pid = self::check_post_id($pid);
141
+ $post = get_post($pid);
142
+ if ($post) {
143
+ return $post;
144
+ } else {
145
+ $post = get_page($pid);
146
+ return $post;
147
+ }
148
+ }
149
+ //we can skip if already is WP_Post
150
+ return $pid;
151
+ }
152
 
153
 
154
+ /**
155
+ * helps you find the post id regardless of whether you send a string or whatever
156
+ *
157
+ * @param integer $pid ;
158
+ * @return integer ID number of a post
159
+ */
160
+ protected function check_post_id($pid) {
161
+ if (is_numeric($pid) && $pid === 0) {
162
+ $pid = get_the_ID();
163
+ return $pid;
164
+ }
165
+ if (!is_numeric($pid) && is_string($pid)) {
166
+ $pid = self::get_post_id_by_name($pid);
167
+ return $pid;
168
+ }
169
+ if (!$pid) {
170
+ return null;
171
+ }
172
+ return $pid;
173
+ }
174
 
175
 
176
+ /**
177
+ * get_post_id_by_name($post_name)
178
+ *
179
+ * @param string $post_name
180
+ * @return int
181
+ */
182
+ public static function get_post_id_by_name($post_name) {
183
+ global $wpdb;
184
+ $query = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s LIMIT 1", $post_name);
185
+ $result = $wpdb->get_row($query);
186
+ if (!$result) {
187
+ return null;
188
+ }
189
+ return $result->ID;
190
+ }
191
 
192
 
193
+ /**
194
+ * ## get a preview of your post, if you have an excerpt it will use that,
195
+ * ## otherwise it will pull from the post_content.
196
+ * ## If there's a <!-- more --> tag it will use that to mark where to pull through.
197
+ * <p>{{post.get_preview(50)}}</p>
198
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
+ /**
201
+ * @param int $len
202
+ * @param bool $force
203
+ * @param string $readmore
204
+ * @param bool $strip
205
+ * @return string
206
+ */
207
+ function get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true) {
208
+ $text = '';
209
+ $trimmed = false;
210
+ if (isset($this->post_excerpt) && strlen($this->post_excerpt)) {
211
+ if ($force) {
212
+ $text = TimberHelper::trim_words($this->post_excerpt, $len, false);
213
+ $trimmed = true;
214
+ } else {
215
+ $text = $this->post_excerpt;
216
+ }
217
+ }
218
+ if (!strlen($text) && strpos($this->post_content, '<!--more-->') !== false) {
219
+ $pieces = explode('<!--more-->', $this->post_content);
220
+ $text = $pieces[0];
221
+ if ($force) {
222
+ $text = TimberHelper::trim_words($text, $len, false);
223
+ $trimmed = true;
224
+ }
225
+ }
226
+ if (!strlen($text)) {
227
+ $text = TimberHelper::trim_words($this->get_content(), $len, false);
228
+ $trimmed = true;
229
+ }
230
+ if (!strlen(trim($text))) {
231
+ return trim($text);
232
+ }
233
+ if ($strip) {
234
+ $text = trim(strip_tags($text));
235
+ }
236
+ if (strlen($text)) {
237
+ $text = trim($text);
238
+ $last = $text[strlen($text) - 1];
239
+ if ($last != '.' && $trimmed) {
240
+ $text .= ' &hellip; ';
241
+ }
242
+ if (!$strip) {
243
+ $last_p_tag = strrpos($text, '</p>');
244
+ if ($last_p_tag !== false) {
245
+ $text = substr($text, 0, $last_p_tag);
246
+ }
247
+ if ($last != '.' && $trimmed) {
248
+ $text .= ' &hellip; ';
249
+ }
250
+ }
251
+
252
+ if ($readmore) {
253
+ $text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . $readmore . '</a>';
254
+ }
255
+ if (!$strip) {
256
+ $text .= '</p>';
257
+ }
258
+ }
259
+ return trim($text);
260
+ }
261
 
262
+ /**
263
+ * gets the post custom and attaches it to the current object
264
+ * @param bool|int $pid a post ID number
265
+ * @nodoc
266
+ */
267
+ function import_custom($pid = false) {
268
+ if (!$pid) {
269
+ $pid = $this->ID;
270
+ }
271
+ $customs = $this->get_post_custom($pid);
272
+ $this->import($customs);
273
+ }
274
 
275
+ /**
276
+ * @param int $pid
277
+ * @return array
278
+ */
279
+ function get_post_custom($pid) {
280
+ apply_filters('timber_post_get_meta_pre', array(), $pid, $this);
281
+ $customs = get_post_custom($pid);
282
+ if (!is_array($customs) || empty($customs)) {
283
+ return array();
284
+ }
285
+ foreach ($customs as $key => $value) {
286
+ if (is_array($value) && count($value) == 1 && isset($value[0])) {
287
+ $value = $value[0];
288
+ }
289
+ $customs[$key] = maybe_unserialize($value);
290
+ }
291
+ $customs = apply_filters('timber_post_get_meta', $customs, $pid, $this);
292
+ return $customs;
293
+ }
294
 
295
+ /**
296
+ * ## get the featured image as a TimberImage
297
+ * <img src="{{post.get_thumbnail.get_src}}" />
298
+ */
 
 
 
 
 
 
 
 
 
 
 
 
299
 
300
+ /**
301
+ * @return null|TimberImage
302
+ */
303
+ function get_thumbnail() {
304
+ if (function_exists('get_post_thumbnail_id')) {
305
+ $tid = get_post_thumbnail_id($this->ID);
306
+ if ($tid) {
307
+ return new $this->ImageClass($tid);
308
+ }
309
+ }
310
+ }
311
 
312
+ /**
313
+ * @return string
314
+ */
315
+ function get_permalink() {
316
+ if (isset($this->_permalink)) {
317
+ return $this->_permalink;
318
+ }
319
+ $this->_permalink = get_permalink($this->ID);
320
+ return $this->_permalink;
321
+ }
322
 
323
+ /**
324
+ * @return string
325
+ */
326
+ function get_link() {
327
+ return $this->get_permalink();
328
+ }
 
 
 
 
 
 
 
 
 
329
 
330
+ /**
331
+ * @param bool $taxonomy
332
+ * @return mixed
333
+ */
334
+ function get_next($taxonomy = false) {
335
+ if (!isset($this->_next) || !isset($this->_next[$taxonomy])) {
336
+ global $post;
337
+ $this->_next = array();
338
+ $old_global = $post;
339
+ $post = $this;
340
+ if ($taxonomy) {
341
+ $adjacent = get_adjacent_post(true, '', false, $taxonomy);
342
+ } else {
343
+ $adjacent = get_adjacent_post(false, '', false);
344
+ }
345
+
346
+ if ($adjacent) {
347
+ $this->_next[$taxonomy] = new $this->PostClass($adjacent);
348
+ } else {
349
+ $this->_next[$taxonomy] = false;
350
+ }
351
+ $post = $old_global;
352
+ }
353
+ return $this->_next[$taxonomy];
354
+ }
355
 
356
+ /**
357
+ * @return array
358
+ */
359
+ public function get_pagination() {
360
+ global $post, $page, $numpages, $multipage;
361
+ $post = $this;
362
+ $ret = array();
363
+ if ($multipage) {
364
+ for ($i = 1; $i <= $numpages; $i++) {
365
+ $link = self::get_wp_link_page($i);
366
+ $data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
367
+ if ($i == $page) {
368
+ $data['current'] = true;
369
+ }
370
+ $ret['pages'][] = $data;
371
+ }
372
+ $i = $page - 1;
373
+ if ($i) {
374
+ $link = self::get_wp_link_page($i);
375
+ $ret['prev'] = array('link' => $link);
376
+ }
377
+ $i = $page + 1;
378
+ if ($i <= $numpages) {
379
+ $link = self::get_wp_link_page($i);
380
+ $ret['next'] = array('link' => $link);
381
+ }
382
+ }
383
+ return $ret;
384
+ }
385
 
386
+ /**
387
+ * @param int $i
388
+ * @return string
389
+ */
390
+ private static function get_wp_link_page($i) {
391
+ $link = _wp_link_page($i);
392
+ $link = new SimpleXMLElement($link . '</a>');
393
+ if (isset($link['href'])) {
394
+ return $link['href'];
395
+ }
396
+ return '';
397
+ }
398
 
399
+ /**
400
+ * @return string
401
+ */
402
+ function get_path() {
403
+ return TimberURLHelper::get_rel_url($this->get_link());
404
+ }
405
 
406
+ /**
407
+ * @param bool $taxonomy
408
+ * @return mixed
409
+ */
410
+ function get_prev($taxonomy = false) {
411
+ if (isset($this->_prev) && isset($this->_prev[$taxonomy])) {
412
+ return $this->_prev[$taxonomy];
413
+ }
414
+ global $post;
415
+ $old_global = $post;
416
+ $post = $this;
417
+ $within_taxonomy = ($taxonomy) ? $taxonomy : 'category';
418
+ $adjacent = get_adjacent_post(($taxonomy), '', true, $within_taxonomy);
419
+
420
+ $prev_in_taxonomy = false;
421
+ if ($adjacent) {
422
+ $prev_in_taxonomy = new $this->PostClass($adjacent);
423
+ }
424
+ $this->_prev[$taxonomy] = $prev_in_taxonomy;
425
+ $post = $old_global;
426
+ return $this->_prev[$taxonomy];
427
+ }
428
 
429
+ /**
430
+ * @return bool|TimberPost
431
+ */
432
+ function get_parent() {
433
+ if (!$this->post_parent) {
434
+ return false;
435
+ }
436
+ return new $this->PostClass($this->post_parent);
437
+ }
438
 
439
+ /**
440
+ * ## Gets a User object from the author of the post
441
+ * <p class="byline">{{post.get_author.name}}</p>
442
+ */
 
 
 
 
 
 
 
 
 
443
 
444
+ /**
445
+ * @return bool|TimberUser
446
+ */
447
+ function get_author() {
448
+ if (isset($this->post_author)) {
449
+ return new TimberUser($this->post_author);
450
+ }
451
+ }
452
 
453
+ /**
454
+ * @return bool|TimberUser
455
+ */
456
+ function get_modified_author() {
457
+ $user_id = get_post_meta($this->ID, '_edit_last', true);
458
+ return ($user_id ? new TimberUser($user_id) : $this->get_author());
459
+ }
 
 
 
 
 
 
 
 
 
 
460
 
461
+ /**
462
+ * @param int $pid
463
+ * @return null|object|WP_Post
464
+ */
465
+ function get_info($pid) {
466
+ $post = $this->prepare_post_info($pid);
467
+ if (!isset($post->post_status)) {
468
+ return null;
469
+ }
470
+ $post->status = $post->post_status;
471
+ $post->id = $post->ID;
472
+ $post->slug = $post->post_name;
473
+ $customs = $this->get_post_custom($post->ID);
474
+ $post->custom = $customs;
475
+ $post = (object)array_merge((array)$customs, (array)$post);
476
+ return $post;
477
+ }
478
 
479
+ /**
480
+ * This is deprecated!
481
+ * @param string $use
482
+ * @return string
483
+ */
484
+ function get_display_date($use = 'post_date') {
485
+ return date(get_option('date_format'), strtotime($this->$use));
486
+ }
 
487
 
488
+ /**
489
+ * @param string $date_format
490
+ * @return string
491
+ */
492
+ function get_date($date_format = '') {
493
+ $df = $date_format ? $date_format : get_option('date_format');
494
+ $the_date = (string)mysql2date($df, $this->post_date);
495
+ return apply_filters('get_the_date', $the_date, $date_format);
496
+ }
497
 
498
+ /**
499
+ * @param string $date_format
500
+ * @return string
501
+ */
502
+ function get_modified_date($date_format = '') {
503
+ $df = $date_format ? $date_format : get_option('date_format');
504
+ $the_time = $this->get_modified_time($df, null, $this->ID, true);
505
+ return apply_filters('get_the_modified_date', $the_time, $date_format);
506
+ }
507
 
508
+ /**
509
+ * @param string $time_format
510
+ * @return string
511
+ */
512
+ function get_modified_time($time_format = '') {
513
+ $tf = $time_format ? $time_format : get_option('time_format');
514
+ $the_time = get_post_modified_time($tf, false, $this->ID, true);
515
+ return apply_filters('get_the_modified_time', $the_time, $time_format);
516
+ }
 
 
 
 
 
 
 
 
 
 
517
 
518
+ /**
519
+ * @param string $post_type
520
+ * @param bool $childPostClass
521
+ * @return array
522
+ */
523
+ function get_children($post_type = 'any', $childPostClass = false) {
524
+ if ($childPostClass === false) {
525
+ $childPostClass = $this->PostClass;
526
+ }
527
+ if ($post_type == 'parent') {
528
+ $post_type = $this->post_type;
529
+ }
530
+ $children = get_children('post_parent=' . $this->ID . '&post_type=' . $post_type . '&numberposts=-1&orderby=menu_order title&order=ASC');
531
+ foreach ($children as &$child) {
532
+ $child = new $childPostClass($child->ID);
533
+ }
534
+ $children = array_values($children);
535
+ return $children;
536
+ }
 
 
 
 
 
 
 
 
 
537
 
538
+ /**
539
+ * {% for comment in post.get_comments %}
540
+ * <p>{{comment.content}}</p>
541
+ * {% endfor %}
542
+ */
 
 
 
 
 
 
 
 
 
543
 
544
+ /**
545
+ * @param int $ct
546
+ * @param string $order
547
+ * @param string $type
548
+ * @param string $status
549
+ * @param string $CommentClass
550
+ * @return mixed
551
+ */
552
+ function get_comments($ct = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment') {
553
+ $args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
554
+ if ($ct > 0) {
555
+ $args['number'] = $ct;
556
+ }
557
+ if ($order == 'wp') {
558
+ $args['order'] = get_option('comment_order');
559
+ }
560
 
561
+ $comments = get_comments($args);
562
+ $tComments = array();
563
+
564
+ foreach($comments as $key => &$comment) {
565
+ $tComment = new $CommentClass($comment);
566
+ $tComments[$tComment->id] = $tComment;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  }
 
 
 
568
 
569
+ foreach($tComments as $key => $comment) {
570
+ if ($comment->is_child()) {
571
+ unset($tComments[$comment->id]);
572
+
573
+ if (isset($tComments[$comment->comment_parent])) {
574
+ $tComments[$comment->comment_parent]->children[] = $comment;
 
 
 
 
 
 
 
575
  }
576
  }
 
577
  }
578
+ $tComments = array_values($tComments);
 
579
 
580
+ return $tComments;
 
 
 
 
 
581
  }
582
 
583
+ /**
584
+ * <ul class="categories">
585
+ * {% for category in post.get_categories %}
586
+ * <li>{{category.name}}</li>
587
+ * {% endfor %}
588
+ * </ul>
589
+ */
 
 
 
 
 
 
 
 
590
 
591
+ /**
592
+ * @return array
593
+ */
594
+ function get_categories() {
595
+ return $this->get_terms('category');
596
+ }
597
 
598
+ /**
599
+ * @return mixed
600
+ */
601
+ function get_category() {
602
+ $cats = $this->get_categories();
603
+ if (count($cats) && isset($cats[0])) {
604
+ return $cats[0];
605
+ }
606
+ }
607
 
608
+ /** # get terms is good
609
+ *
610
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
 
612
+ /**
613
+ * @param string $tax
614
+ * @param bool $merge
615
+ * @param string $TermClass
616
+ * @return array
617
+ */
618
+ function get_terms($tax = '', $merge = true, $TermClass = 'TimberTerm') {
619
+ if (is_string($merge) && class_exists($merge)){
620
+ $TermClass = $merge;
621
+ }
622
+ if (is_string($tax)) {
623
+ if (isset($this->_get_terms) && isset($this->_get_terms[$tax])) {
624
+ return $this->_get_terms[$tax];
625
+ }
626
+ }
627
+ if (!strlen($tax) || $tax == 'all' || $tax == 'any') {
628
+ $taxs = get_object_taxonomies($this->post_type);
629
+ } else if (is_array($tax)) {
630
+ $taxs = $tax;
631
+ } else {
632
+ $taxs = array($tax);
633
+ }
634
+ $ret = array();
635
+ foreach ($taxs as $tax) {
636
+ if ($tax == 'tags' || $tax == 'tag') {
637
+ $tax = 'post_tag';
638
+ } else if ($tax == 'categories') {
639
+ $tax = 'category';
640
+ }
641
+ $terms = wp_get_post_terms($this->ID, $tax);
642
+ if (!is_array($terms) && is_object($terms) && get_class($terms) == 'WP_Error') {
643
+ //something is very wrong
644
+ TimberHelper::error_log('You have an error retrieving terms on a post in timber-post.php:628');
645
+ TimberHelper::error_log('tax = ' . $tax);
646
+ TimberHelper::error_log($terms);
647
+ } else {
648
+ foreach ($terms as &$term) {
649
+ $term = new $TermClass($term->term_id, $tax);
650
+ }
651
+ if ($merge && is_array($terms)) {
652
+ $ret = array_merge($ret, $terms);
653
+ } else if (count($terms)) {
654
+ $ret[$tax] = $terms;
655
+ }
656
+ }
657
+ }
658
+ if (!isset($this->_get_terms)) {
659
+ $this->_get_terms = array();
660
+ }
661
+ $this->_get_terms[$tax] = $ret;
662
+ return $ret;
663
+ }
664
 
665
+ /**
666
+ * @param string|int $term_name_or_id
667
+ * @param string $taxonomy
668
+ * @return bool
669
+ */
670
+ function has_term($term_name_or_id, $taxonomy = 'all') {
671
+ if ($taxonomy == 'all' || $taxonomy == 'any') {
672
+ $taxes = get_object_taxonomies($this->post_type, 'names');
673
+ $ret = false;
674
+ foreach ($taxes as $tax) {
675
+ if (has_term($term_name_or_id, $tax, $this->ID)) {
676
+ $ret = true;
677
+ break;
678
+ }
679
+ }
680
+ return $ret;
681
+ }
682
+ return has_term($term_name_or_id, $taxonomy, $this->ID);
683
+ }
684
 
685
+ /**
686
+ * @param string $field
687
+ * @return TimberImage
688
+ */
689
+ function get_image($field) {
690
+ return new $this->ImageClass($this->$field);
691
+ }
 
 
 
 
 
 
 
 
 
 
 
692
 
693
+ /**
694
+ * ## Gets an array of tags for you to use
695
+ * <ul class="tags">
696
+ * {% for tag in post.tags %}
697
+ * <li>{{tag.name}}</li>
698
+ * {% endfor %}
699
+ * </ul>
700
+ */
701
 
702
+ /**
703
+ * @return array
704
+ */
705
+ function get_tags() {
706
+ return $this->get_terms('tags');
707
+ }
708
+
709
+ /**
710
+ * ## Outputs the title with filters applied
711
+ * <h1>{{post.get_title}}</h1>
712
+ */
713
+
714
+ /**
715
+ * @return string
716
+ */
717
+ function get_title() {
718
+ return apply_filters('the_title', $this->post_title, $this->ID);
719
+ }
720
+
721
+ /**
722
+ * ## Displays the content of the post with filters, shortcodes and wpautop applied
723
+ * <div class="article-text">{{post.get_content}}</div>
724
+ */
725
+
726
+ /**
727
+ * @param int $len
728
+ * @param int $page
729
+ * @return string
730
+ */
731
+ function get_content($len = 0, $page = 0) {
732
+ if ($len == 0 && $page == 0 && $this->_content) {
733
+ return $this->_content;
734
+ }
735
+ $content = $this->post_content;
736
+ if ($len) {
737
+ $content = wp_trim_words($content, $len);
738
+ }
739
+ if ($page) {
740
+ $contents = explode('<!--nextpage-->', $content);
741
+ $page--;
742
+ if (count($contents) > $page) {
743
+ $content = $contents[$page];
744
+ }
745
+ }
746
+ $content = apply_filters('the_content', ($content));
747
+ if ($len == 0 && $page == 0) {
748
+ $this->_content = $content;
749
+ }
750
+ return $content;
751
+ }
752
+
753
+ /**
754
+ * @return string
755
+ */
756
+ function get_paged_content() {
757
+ global $page;
758
+ return $this->get_content(0, $page);
759
+ }
760
+ /**
761
+ * @return mixed
762
+ */
763
+ public function get_post_type() {
764
+ return get_post_type_object($this->post_type);
765
+ }
766
+
767
+ /**
768
+ * @return int
769
+ */
770
+ public function get_comment_count() {
771
+ if (isset($this->ID)) {
772
+ return get_comments_number($this->ID);
773
+ } else {
774
+ return 0;
775
+ }
776
+ }
777
+
778
+ /**
779
+ * @param string $field_name
780
+ * @return mixed
781
+ */
782
+ public function get_field($field_name) {
783
+ $value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
784
+ if ($value === null) {
785
+ $value = get_post_meta($this->ID, $field_name);
786
+ if (is_array($value) && count($value) == 1) {
787
+ $value = $value[0];
788
+ }
789
+ if (is_array($value) && count($value) == 0) {
790
+ $value = null;
791
+ }
792
+ }
793
+ $value = apply_filters('timber_post_get_meta_field', $value, $this->ID, $field_name, $this);
794
+ return $value;
795
+ }
796
+
797
+ /**
798
+ * @param string $field_name
799
+ */
800
+ function import_field($field_name) {
801
+ $this->$field_name = $this->get_field($field_name);
802
+ }
803
+
804
+ /**
805
+ * @return mixed
806
+ */
807
+ function get_format() {
808
+ return get_post_format($this->ID);
809
+ }
810
 
811
  /**
812
+ * @param string $class
813
+ * @return string
814
+ */
815
+ public function post_class($class='') {
816
+ global $post;
817
+ $old_global_post = $post;
818
+ $post = $this;
819
  $class_array = get_post_class($class, $this->ID);
820
  $post = $old_global_post;
821
+ if (is_array($class_array)){
822
+ return implode(' ', $class_array);
823
+ }
824
+ return $class_array;
825
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
 
827
+ // Docs
 
 
 
 
 
 
828
 
829
+ /**
830
+ * @return array
831
+ * @codeCoverageIgnore
832
+ */
833
+ public function get_method_values() {
834
+ $ret = parent::get_method_values();
835
+ $ret['author'] = $this->author();
836
+ $ret['categories'] = $this->categories();
837
+ $ret['category'] = $this->category();
838
+ $ret['children'] = $this->children();
839
+ $ret['comments'] = $this->comments();
840
+ $ret['content'] = $this->content();
841
+ $ret['edit_link'] = $this->edit_link();
842
+ $ret['format'] = $this->format();
843
+ $ret['link'] = $this->link();
844
+ $ret['next'] = $this->next();
845
+ $ret['pagination'] = $this->pagination();
846
+ $ret['parent'] = $this->parent();
847
+ $ret['path'] = $this->path();
848
+ $ret['prev'] = $this->prev();
849
+ $ret['terms'] = $this->terms();
850
+ $ret['tags'] = $this->tags();
851
+ $ret['thumbnail'] = $this->thumbnail();
852
+ $ret['title'] = $this->title();
853
+ return $ret;
854
+ }
855
 
856
+ // Aliases
857
+ /**
858
+ * @return bool|TimberUser
859
+ */
860
+ public function author() {
861
+ return $this->get_author();
862
+ }
863
 
864
+ /**
865
+ * @return bool|TimberUser
866
+ */
867
+ public function modified_author() {
868
+ return $this->get_modified_author();
869
+ }
870
 
871
+ /**
872
+ * @return array
873
+ */
874
+ public function categories() {
875
+ return $this->get_terms('category');
876
+ }
877
 
878
+ /**
879
+ * @return mixed
880
+ */
881
+ public function category() {
882
+ return $this->get_category();
883
+ }
884
 
885
+ /**
886
+ * @return array
887
+ */
888
+ public function children( $post_type = 'any', $childPostClass = false ) {
889
+ return $this->get_children( $post_type, $childPostClass );
890
+ }
 
891
 
892
+ /**
893
+ * @return mixed
894
+ */
895
+ public function comments() {
896
+ return $this->get_comments();
897
+ }
898
 
899
+ /**
900
+ * @param int $page
901
+ * @return string
902
+ */
903
+ public function content($page = 0) {
904
+ return $this->get_content(0, $page);
905
+ }
906
 
907
+ /**
908
+ * @return string
909
+ */
910
+ public function paged_content() {
911
+ return $this->get_paged_content();
912
+ }
913
 
914
+ /**
915
+ * @param string $date_format
916
+ * @return string
917
+ */
918
+ public function date($date_format = '') {
919
+ return $this->get_date($date_format);
920
+ }
921
 
922
+ /**
923
+ * @return bool|string
924
+ */
925
+ public function edit_link() {
926
+ return $this->get_edit_url();
927
+ }
928
 
929
+ /**
930
+ * @return mixed
931
+ */
932
+ public function format() {
933
+ return $this->get_format();
934
+ }
 
 
 
 
935
 
936
+ /**
937
+ * @return string
938
+ */
939
+ public function link() {
940
+ return $this->get_permalink();
941
+ }
942
 
943
+ /**
944
+ * @param string $field_name
945
+ * @return mixed
946
+ */
947
+ public function meta($field_name = null) {
948
+ if ($field_name == null) {
949
+ $field_name = 'meta';
950
+ }
951
+ return $this->get_field($field_name);
952
+ }
953
 
954
+ /**
955
+ * @return string
956
+ */
957
+ public function name(){
958
+ return $this->title();
959
+ }
 
960
 
961
+ /**
962
+ * @param string $date_format
963
+ * @return string
964
+ */
965
+ public function modified_date($date_format = '') {
966
+ return $this->get_modified_date($date_format);
967
+ }
968
 
969
+ /**
970
+ * @param string $time_format
971
+ * @return string
972
+ */
973
+ public function modified_time($time_format = '') {
974
+ return $this->get_modified_time($time_format);
975
+ }
976
 
977
+ /**
978
+ * @param bool $in_same_cat
979
+ * @return mixed
980
+ */
981
+ public function next($in_same_cat = false) {
982
+ return $this->get_next($in_same_cat);
983
+ }
984
 
985
+ /**
986
+ * @return array
987
+ */
988
+ public function pagination() {
989
+ return $this->get_pagination();
990
+ }
991
 
992
+ /**
993
+ * @return bool|TimberPost
994
+ */
995
+ public function parent() {
996
+ return $this->get_parent();
997
+ }
998
 
999
+ /**
1000
+ * @return string
1001
+ */
1002
+ public function path() {
1003
+ return $this->get_path();
1004
+ }
 
1005
 
1006
+ /**
1007
+ * @return string
1008
+ */
1009
+ public function permalink() {
1010
+ return $this->get_permalink();
1011
+ }
 
1012
 
1013
+ /**
1014
+ * @param bool $in_same_cat
1015
+ * @return mixed
1016
+ */
1017
+ public function prev($in_same_cat = false) {
1018
+ return $this->get_prev($in_same_cat);
1019
+ }
1020
 
1021
+ /**
1022
+ * @param string $tax
1023
+ * @return array
1024
+ */
1025
+ public function terms($tax = '') {
1026
+ return $this->get_terms($tax);
1027
+ }
1028
 
1029
+ /**
1030
+ * @return array
1031
+ */
1032
+ public function tags() {
1033
+ return $this->get_tags();
1034
+ }
1035
+
1036
+ /**
1037
+ * @return null|TimberImage
1038
+ */
1039
+ public function thumbnail() {
1040
+ return $this->get_thumbnail();
1041
+ }
1042
+
1043
+ /**
1044
+ * @return string
1045
+ */
1046
+ public function title() {
1047
+ return $this->get_title();
1048
+ }
1049
 
1050
  }
lib/timber-site.php CHANGED
@@ -35,7 +35,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
35
  *
36
  * @param string|int $site_name_or_id
37
  */
38
- function init_with_multisite( $site_name_or_id ) {
39
  if ( $site_name_or_id === null ) {
40
  //this is necessary for some reason, otherwise returns 1 all the time
41
  if ( is_multisite() ) {
@@ -48,15 +48,20 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
48
  $this->ID = $info->blog_id;
49
  $this->name = $this->blogname;
50
  $this->title = $this->blogname;
51
- $this->url = $this->siteurl;
52
  $this->id = $this->ID;
53
  $theme_slug = get_blog_option( $info->blog_id, 'stylesheet' );
54
  $this->theme = new TimberTheme( $theme_slug );
 
 
 
 
55
  $this->description = get_blog_option( $info->blog_id, 'blogdescription' );
56
  $this->multisite = true;
 
57
  }
58
 
59
- function init() {
60
  $this->admin_email = get_bloginfo( 'admin_email' );
61
  $this->name = get_bloginfo( 'name' );
62
  $this->title = $this->name;
@@ -110,14 +115,14 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
110
  *
111
  * @return string
112
  */
113
- function link() {
114
  return $this->get_link();
115
  }
116
 
117
  /**
118
  *
119
  */
120
- function meta( $field ) {
121
  return $this->__get( $field );
122
  }
123
 
@@ -127,7 +132,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
127
  * @param string $key
128
  * @param mixed $value
129
  */
130
- function update( $key, $value ) {
131
  $value = apply_filters( 'timber_site_set_meta', $value, $key, $this->ID, $this );
132
  if ( is_multisite() ) {
133
  update_blog_option( $this->ID, $key, $value );
35
  *
36
  * @param string|int $site_name_or_id
37
  */
38
+ protected function init_with_multisite( $site_name_or_id ) {
39
  if ( $site_name_or_id === null ) {
40
  //this is necessary for some reason, otherwise returns 1 all the time
41
  if ( is_multisite() ) {
48
  $this->ID = $info->blog_id;
49
  $this->name = $this->blogname;
50
  $this->title = $this->blogname;
51
+ $this->url = get_bloginfo( 'url' );
52
  $this->id = $this->ID;
53
  $theme_slug = get_blog_option( $info->blog_id, 'stylesheet' );
54
  $this->theme = new TimberTheme( $theme_slug );
55
+ $this->language = get_bloginfo( 'language' );
56
+ $this->charset = get_bloginfo( 'charset' );
57
+ $this->pingback_url = get_bloginfo( 'pingback_url' );
58
+ $this->language_attributes = TimberHelper::function_wrapper( 'language_attributes' );
59
  $this->description = get_blog_option( $info->blog_id, 'blogdescription' );
60
  $this->multisite = true;
61
+ $this->admin_email = get_blog_option( $info->blog_id, 'admin_email' );
62
  }
63
 
64
+ protected function init() {
65
  $this->admin_email = get_bloginfo( 'admin_email' );
66
  $this->name = get_bloginfo( 'name' );
67
  $this->title = $this->name;
115
  *
116
  * @return string
117
  */
118
+ public function link() {
119
  return $this->get_link();
120
  }
121
 
122
  /**
123
  *
124
  */
125
+ public function meta( $field ) {
126
  return $this->__get( $field );
127
  }
128
 
132
  * @param string $key
133
  * @param mixed $value
134
  */
135
+ public function update( $key, $value ) {
136
  $value = apply_filters( 'timber_site_set_meta', $value, $key, $this->ID, $this );
137
  if ( is_multisite() ) {
138
  update_blog_option( $this->ID, $key, $value );
lib/timber-twig.php CHANGED
@@ -2,293 +2,296 @@
2
 
3
  class TimberTwig {
4
 
5
- public static $dir_name;
6
-
7
- /**
8
- * Initialization
9
- */
10
- public static function init() {
11
- new TimberTwig();
12
- }
13
-
14
- function __construct() {
15
- add_action( 'twig_apply_filters', array( $this, 'add_timber_filters_deprecated' ) );
16
- add_action( 'twig_apply_filters', array( $this, 'add_timber_filters' ) );
17
- }
18
-
19
- /**
20
- * These are all deprecated and will be removed in 0.21.0
21
- *
22
- * @param Twig_Environment $twig
23
- * @deprecated since 0.20.7
24
- * @return Twig_Environment
25
- */
26
- function add_timber_filters_deprecated( $twig ) {
27
- $twig->addFilter( new Twig_SimpleFilter( 'get_src_from_attachment_id', 'twig_get_src_from_attachment_id' ) );
28
- $twig->addFilter( new Twig_SimpleFilter( 'wp_body_class', array( $this, 'body_class' ) ) );
29
- $twig->addFilter( new Twig_SimpleFilter( 'twitterify', array( 'TimberHelper', 'twitterify' ) ) );
30
- $twig->addFilter( new Twig_SimpleFilter( 'twitterfy', array( 'TimberHelper', 'twitterify' ) ) );
31
- return $twig;
32
- }
33
-
34
- /**
35
- *
36
- *
37
- * @param Twig_Environment $twig
38
- * @return Twig_Environment
39
- */
40
- function add_timber_filters( $twig ) {
41
- /* image filters */
42
- $twig->addFilter( new Twig_SimpleFilter( 'resize', array( 'TimberImageHelper', 'resize' ) ) );
43
- $twig->addFilter( new Twig_SimpleFilter( 'retina', array( 'TimberImageHelper', 'retina_resize' ) ) );
44
- $twig->addFilter( new Twig_SimpleFilter( 'letterbox', array( 'TimberImageHelper', 'letterbox' ) ) );
45
- $twig->addFilter( new Twig_SimpleFilter( 'tojpg', array( 'TimberImageHelper', 'img_to_jpg' ) ) );
46
-
47
- /* debugging filters */
48
- $twig->addFilter( new Twig_SimpleFilter( 'docs', 'twig_object_docs' ) );
49
- $twig->addFilter( new Twig_SimpleFilter( 'get_class', 'get_class' ) );
50
- $twig->addFilter( new Twig_SimpleFilter( 'get_type', 'get_type' ) );
51
- $twig->addFilter( new Twig_SimpleFilter( 'print_r', function( $arr ) {
52
- return print_r( $arr, true );
53
- } ) );
54
- $twig->addFilter( new Twig_SimpleFilter( 'print_a', function( $arr ) {
55
- return '<pre>' . self::object_docs( $arr, true ) . '</pre>';
56
- } ) );
57
-
58
- /* other filters */
59
- $twig->addFilter( new Twig_SimpleFilter( 'stripshortcodes', 'strip_shortcodes' ) );
60
- $twig->addFilter( new Twig_SimpleFilter( 'array', array( $this, 'to_array' ) ) );
61
- $twig->addFilter( new Twig_SimpleFilter( 'string', array( $this, 'to_string' ) ) );
62
- $twig->addFilter( new Twig_SimpleFilter( 'excerpt', 'wp_trim_words' ) );
63
- $twig->addFilter( new Twig_SimpleFilter( 'function', array( $this, 'exec_function' ) ) );
64
- $twig->addFilter( new Twig_SimpleFilter( 'pretags', array( $this, 'twig_pretags' ) ) );
65
- $twig->addFilter( new Twig_SimpleFilter( 'sanitize', 'sanitize_title' ) );
66
- $twig->addFilter( new Twig_SimpleFilter( 'shortcodes', 'do_shortcode' ) );
67
- $twig->addFilter( new Twig_SimpleFilter( 'time_ago', array( $this, 'time_ago' ) ) );
68
- $twig->addFilter( new Twig_SimpleFilter( 'wpautop', 'wpautop' ) );
69
-
70
- $twig->addFilter( new Twig_SimpleFilter( 'relative', function ( $link ) {
71
- return TimberURLHelper::get_rel_url( $link, true );
72
- } ) );
73
-
74
- $twig->addFilter( new Twig_SimpleFilter( 'date', array( $this, 'intl_date' ) ) );
75
-
76
- $twig->addFilter( new Twig_SimpleFilter( 'truncate', function ( $text, $len ) {
77
- return TimberHelper::trim_words( $text, $len );
78
- } ) );
79
-
80
- /* actions and filters */
81
- $twig->addFunction( new Twig_SimpleFunction( 'action', function ( $context ) {
82
- $args = func_get_args();
83
- array_shift( $args );
84
- $args[] = $context;
85
- call_user_func_array( 'do_action', $args );
86
- }, array( 'needs_context' => true ) ) );
87
-
88
- $twig->addFilter( new Twig_SimpleFilter( 'apply_filters', function () {
89
- $args = func_get_args();
90
- $tag = current( array_splice( $args, 1, 1 ) );
91
-
92
- return apply_filters_ref_array( $tag, $args );
93
- } ) );
94
- $twig->addFunction( new Twig_SimpleFunction( 'function', array( &$this, 'exec_function' ) ) );
95
- $twig->addFunction( new Twig_SimpleFunction( 'fn', array( &$this, 'exec_function' ) ) );
96
-
97
- /* TimberObjects */
98
- $twig->addFunction( new Twig_SimpleFunction( 'TimberPost', function ( $pid, $PostClass = 'TimberPost' ) {
99
- if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
100
- foreach ( $pid as &$p ) {
101
- $p = new $PostClass( $p );
102
- }
103
- return $pid;
104
- }
105
- return new $PostClass( $pid );
106
- } ) );
107
- $twig->addFunction( new Twig_SimpleFunction( 'TimberImage', function ( $pid, $ImageClass = 'TimberImage' ) {
108
- if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
109
- foreach ( $pid as &$p ) {
110
- $p = new $ImageClass( $p );
111
- }
112
- return $pid;
113
- }
114
- return new $ImageClass( $pid );
115
- } ) );
116
- $twig->addFunction( new Twig_SimpleFunction( 'TimberTerm', function ( $pid, $TermClass = 'TimberTerm' ) {
117
- if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
118
- foreach ( $pid as &$p ) {
119
- $p = new $TermClass( $p );
120
- }
121
- return $pid;
122
- }
123
- return new $TermClass( $pid );
124
- } ) );
125
- $twig->addFunction( new Twig_SimpleFunction( 'TimberUser', function ( $pid, $UserClass = 'TimberUser' ) {
126
- if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
127
- foreach ( $pid as &$p ) {
128
- $p = new $UserClass( $p );
129
- }
130
- return $pid;
131
- }
132
- return new $UserClass( $pid );
133
- } ) );
134
-
135
- /* bloginfo and translate */
136
- $twig->addFunction( 'bloginfo', new Twig_SimpleFunction( 'bloginfo', function ( $show = '', $filter = 'raw' ) {
137
- return get_bloginfo( $show, $filter );
138
- } ) );
139
- $twig->addFunction( '__', new Twig_SimpleFunction( '__', function ( $text, $domain = 'default' ) {
140
- return __( $text, $domain );
141
- } ) );
142
-
143
- $twig = apply_filters( 'get_twig', $twig );
144
-
145
- return $twig;
146
- }
147
-
148
- /**
149
- *
150
- *
151
- * @param mixed $arr
152
- * @return array
153
- */
154
- function to_array( $arr ) {
155
- if ( is_array( $arr ) ) {
156
- return $arr;
157
- }
158
- $arr = array( $arr );
159
- return $arr;
160
- }
161
-
162
- /**
163
- *
164
- *
165
- * @param mixed $arr
166
- * @param string $glue
167
- * @return string
168
- */
169
- function to_string( $arr, $glue = ' ' ) {
170
- if ( is_string( $arr ) ) {
171
- return $arr;
172
- }
173
- if ( is_array( $arr ) && count( $arr ) == 1 ) {
174
- return $arr[0];
175
- }
176
- if ( is_array( $arr ) ) {
177
- return implode( $glue, $arr );
178
- }
179
- return null;
180
- }
181
-
182
- /**
183
- *
184
- *
185
- * @param string $function_name
186
- * @return mixed
187
- */
188
- function exec_function( $function_name ) {
189
- $args = func_get_args();
190
- array_shift( $args );
191
- return call_user_func_array( trim( $function_name ), ( $args ) );
192
- }
193
-
194
- /**
195
- *
196
- *
197
- * @param string $content
198
- * @return string
199
- */
200
- function twig_pretags( $content ) {
201
- return preg_replace_callback( '|<pre.*>(.*)</pre|isU', array( &$this, 'convert_pre_entities' ), $content );
202
- }
203
-
204
- /**
205
- *
206
- *
207
- * @param array $matches
208
- * @return string
209
- */
210
- function convert_pre_entities( $matches ) {
211
- return str_replace( $matches[1], htmlentities( $matches[1] ), $matches[0] );
212
- }
213
-
214
- /**
215
- *
216
- *
217
- * @param mixed $body_classes
218
- * @return string
219
- */
220
- function body_class( $body_classes ) {
221
- ob_start();
222
- if ( is_array( $body_classes ) ) {
223
- $body_classes = explode( ' ', $body_classes );
224
- }
225
- body_class( $body_classes );
226
- $return = ob_get_contents();
227
- ob_end_clean();
228
- return $return;
229
- }
230
-
231
- /**
232
- *
233
- *
234
- * @param string $date
235
- * @param string $format (optional)
236
- * @return string
237
- */
238
- function intl_date( $date, $format = null ) {
239
- if ( $format === null ) {
240
- $format = get_option( 'date_format' );
241
- }
242
-
243
- if ( $date instanceof DateTime ) {
244
- $timestamp = $date->getTimestamp();
245
- } else {
246
- $timestamp = strtotime( $date );
247
- }
248
-
249
- return date_i18n( $format, $timestamp );
250
- }
251
-
252
- //debug
253
-
254
- /**
255
- *
256
- *
257
- * @param mixed $obj
258
- * @param bool $methods
259
- * @return string
260
- */
261
- function object_docs( $obj, $methods = true ) {
262
- $class = get_class( $obj );
263
- $properties = (array)$obj;
264
- if ( $methods ) {
265
- /** @var array $methods */
266
- $methods = $obj->get_method_values();
267
- }
268
- $rets = array_merge( $properties, $methods );
269
- ksort( $rets );
270
- $str = print_r( $rets, true );
271
- $str = str_replace( 'Array', $class . ' Object', $str );
272
- return $str;
273
- }
274
-
275
- /**
276
- * @param int|string $from
277
- * @param int|string $to
278
- * @param string $format_past
279
- * @param string $format_future
280
- * @return string
281
- */
282
- function time_ago( $from, $to = null, $format_past = '%s ago', $format_future = '%s from now' ) {
283
- $to = $to === null ? time() : $to;
284
- $to = is_int( $to ) ? $to : strtotime( $to );
285
- $from = is_int( $from ) ? $from : strtotime( $from );
286
-
287
- if ( $from < $to ) {
288
- return sprintf( $format_past, human_time_diff( $from, $to ) );
289
- } else {
290
- return sprintf( $format_future, human_time_diff( $to, $from ) );
291
- }
292
- }
 
 
 
293
 
294
  }
2
 
3
  class TimberTwig {
4
 
5
+ public static $dir_name;
6
+
7
+ /**
8
+ * Initialization
9
+ */
10
+ public static function init() {
11
+ new TimberTwig();
12
+ }
13
+
14
+ function __construct() {
15
+ add_action( 'twig_apply_filters', array( $this, 'add_timber_filters_deprecated' ) );
16
+ add_action( 'twig_apply_filters', array( $this, 'add_timber_filters' ) );
17
+ }
18
+
19
+ /**
20
+ * These are all deprecated and will be removed in 0.21.0
21
+ *
22
+ * @param Twig_Environment $twig
23
+ * @deprecated since 0.20.7
24
+ * @return Twig_Environment
25
+ */
26
+ function add_timber_filters_deprecated( $twig ) {
27
+ $twig->addFilter( new Twig_SimpleFilter( 'get_src_from_attachment_id', 'twig_get_src_from_attachment_id' ) );
28
+ $twig->addFilter( new Twig_SimpleFilter( 'wp_body_class', array( $this, 'body_class' ) ) );
29
+ $twig->addFilter( new Twig_SimpleFilter( 'twitterify', array( 'TimberHelper', 'twitterify' ) ) );
30
+ $twig->addFilter( new Twig_SimpleFilter( 'twitterfy', array( 'TimberHelper', 'twitterify' ) ) );
31
+ return $twig;
32
+ }
33
+
34
+ /**
35
+ *
36
+ *
37
+ * @param Twig_Environment $twig
38
+ * @return Twig_Environment
39
+ */
40
+ function add_timber_filters( $twig ) {
41
+ /* image filters */
42
+ $twig->addFilter( new Twig_SimpleFilter( 'resize', array( 'TimberImageHelper', 'resize' ) ) );
43
+ $twig->addFilter( new Twig_SimpleFilter( 'retina', array( 'TimberImageHelper', 'retina_resize' ) ) );
44
+ $twig->addFilter( new Twig_SimpleFilter( 'letterbox', array( 'TimberImageHelper', 'letterbox' ) ) );
45
+ $twig->addFilter( new Twig_SimpleFilter( 'tojpg', array( 'TimberImageHelper', 'img_to_jpg' ) ) );
46
+
47
+ /* debugging filters */
48
+ $twig->addFilter( new Twig_SimpleFilter( 'docs', 'twig_object_docs' ) );
49
+ $twig->addFilter( new Twig_SimpleFilter( 'get_class', 'get_class' ) );
50
+ $twig->addFilter( new Twig_SimpleFilter( 'get_type', 'get_type' ) );
51
+ $twig->addFilter( new Twig_SimpleFilter( 'print_r', function( $arr ) {
52
+ return print_r( $arr, true );
53
+ } ) );
54
+ $twig->addFilter( new Twig_SimpleFilter( 'print_a', function( $arr ) {
55
+ return '<pre>' . self::object_docs( $arr, true ) . '</pre>';
56
+ } ) );
57
+
58
+ /* other filters */
59
+ $twig->addFilter( new Twig_SimpleFilter( 'stripshortcodes', 'strip_shortcodes' ) );
60
+ $twig->addFilter( new Twig_SimpleFilter( 'array', array( $this, 'to_array' ) ) );
61
+ $twig->addFilter( new Twig_SimpleFilter( 'string', array( $this, 'to_string' ) ) );
62
+ $twig->addFilter( new Twig_SimpleFilter( 'excerpt', 'wp_trim_words' ) );
63
+ $twig->addFilter( new Twig_SimpleFilter( 'function', array( $this, 'exec_function' ) ) );
64
+ $twig->addFilter( new Twig_SimpleFilter( 'pretags', array( $this, 'twig_pretags' ) ) );
65
+ $twig->addFilter( new Twig_SimpleFilter( 'sanitize', 'sanitize_title' ) );
66
+ $twig->addFilter( new Twig_SimpleFilter( 'shortcodes', 'do_shortcode' ) );
67
+ $twig->addFilter( new Twig_SimpleFilter( 'time_ago', array( $this, 'time_ago' ) ) );
68
+ $twig->addFilter( new Twig_SimpleFilter( 'wpautop', 'wpautop' ) );
69
+
70
+ $twig->addFilter( new Twig_SimpleFilter( 'relative', function ( $link ) {
71
+ return TimberURLHelper::get_rel_url( $link, true );
72
+ } ) );
73
+
74
+ $twig->addFilter( new Twig_SimpleFilter( 'date', array( $this, 'intl_date' ) ) );
75
+
76
+ $twig->addFilter( new Twig_SimpleFilter( 'truncate', function ( $text, $len ) {
77
+ return TimberHelper::trim_words( $text, $len );
78
+ } ) );
79
+
80
+ /* actions and filters */
81
+ $twig->addFunction( new Twig_SimpleFunction( 'action', function ( $context ) {
82
+ $args = func_get_args();
83
+ array_shift( $args );
84
+ $args[] = $context;
85
+ call_user_func_array( 'do_action', $args );
86
+ }, array( 'needs_context' => true ) ) );
87
+
88
+ $twig->addFilter( new Twig_SimpleFilter( 'apply_filters', function () {
89
+ $args = func_get_args();
90
+ $tag = current( array_splice( $args, 1, 1 ) );
91
+
92
+ return apply_filters_ref_array( $tag, $args );
93
+ } ) );
94
+ $twig->addFunction( new Twig_SimpleFunction( 'function', array( &$this, 'exec_function' ) ) );
95
+ $twig->addFunction( new Twig_SimpleFunction( 'fn', array( &$this, 'exec_function' ) ) );
96
+
97
+ /* TimberObjects */
98
+ $twig->addFunction( new Twig_SimpleFunction( 'TimberPost', function ( $pid, $PostClass = 'TimberPost' ) {
99
+ if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
100
+ foreach ( $pid as &$p ) {
101
+ $p = new $PostClass( $p );
102
+ }
103
+ return $pid;
104
+ }
105
+ return new $PostClass( $pid );
106
+ } ) );
107
+ $twig->addFunction( new Twig_SimpleFunction( 'TimberImage', function ( $pid, $ImageClass = 'TimberImage' ) {
108
+ if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
109
+ foreach ( $pid as &$p ) {
110
+ $p = new $ImageClass( $p );
111
+ }
112
+ return $pid;
113
+ }
114
+ return new $ImageClass( $pid );
115
+ } ) );
116
+ $twig->addFunction( new Twig_SimpleFunction( 'TimberTerm', function ( $pid, $TermClass = 'TimberTerm' ) {
117
+ if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
118
+ foreach ( $pid as &$p ) {
119
+ $p = new $TermClass( $p );
120
+ }
121
+ return $pid;
122
+ }
123
+ return new $TermClass( $pid );
124
+ } ) );
125
+ $twig->addFunction( new Twig_SimpleFunction( 'TimberUser', function ( $pid, $UserClass = 'TimberUser' ) {
126
+ if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
127
+ foreach ( $pid as &$p ) {
128
+ $p = new $UserClass( $p );
129
+ }
130
+ return $pid;
131
+ }
132
+ return new $UserClass( $pid );
133
+ } ) );
134
+
135
+ /* bloginfo and translate */
136
+ $twig->addFunction( 'bloginfo', new Twig_SimpleFunction( 'bloginfo', function ( $show = '', $filter = 'raw' ) {
137
+ return get_bloginfo( $show, $filter );
138
+ } ) );
139
+ $twig->addFunction( '__', new Twig_SimpleFunction( '__', function ( $text, $domain = 'default' ) {
140
+ return __( $text, $domain );
141
+ } ) );
142
+
143
+ $twig = apply_filters( 'get_twig', $twig );
144
+
145
+ return $twig;
146
+ }
147
+
148
+ /**
149
+ *
150
+ *
151
+ * @param mixed $arr
152
+ * @return array
153
+ */
154
+ function to_array( $arr ) {
155
+ if ( is_array( $arr ) ) {
156
+ return $arr;
157
+ }
158
+ $arr = array( $arr );
159
+ return $arr;
160
+ }
161
+
162
+ /**
163
+ *
164
+ *
165
+ * @param mixed $arr
166
+ * @param string $glue
167
+ * @return string
168
+ */
169
+ function to_string( $arr, $glue = ' ' ) {
170
+ if ( is_string( $arr ) ) {
171
+ return $arr;
172
+ }
173
+ if ( is_array( $arr ) && count( $arr ) == 1 ) {
174
+ return $arr[0];
175
+ }
176
+ if ( is_array( $arr ) ) {
177
+ return implode( $glue, $arr );
178
+ }
179
+ return null;
180
+ }
181
+
182
+ /**
183
+ *
184
+ *
185
+ * @param string $function_name
186
+ * @return mixed
187
+ */
188
+ function exec_function( $function_name ) {
189
+ $args = func_get_args();
190
+ array_shift( $args );
191
+ if ( is_string($function_name) ) {
192
+ $function_name = trim( $function_name );
193
+ }
194
+ return call_user_func_array( $function_name, ( $args ) );
195
+ }
196
+
197
+ /**
198
+ *
199
+ *
200
+ * @param string $content
201
+ * @return string
202
+ */
203
+ function twig_pretags( $content ) {
204
+ return preg_replace_callback( '|<pre.*>(.*)</pre|isU', array( &$this, 'convert_pre_entities' ), $content );
205
+ }
206
+
207
+ /**
208
+ *
209
+ *
210
+ * @param array $matches
211
+ * @return string
212
+ */
213
+ function convert_pre_entities( $matches ) {
214
+ return str_replace( $matches[1], htmlentities( $matches[1] ), $matches[0] );
215
+ }
216
+
217
+ /**
218
+ *
219
+ *
220
+ * @param mixed $body_classes
221
+ * @return string
222
+ */
223
+ function body_class( $body_classes ) {
224
+ ob_start();
225
+ if ( is_array( $body_classes ) ) {
226
+ $body_classes = explode( ' ', $body_classes );
227
+ }
228
+ body_class( $body_classes );
229
+ $return = ob_get_contents();
230
+ ob_end_clean();
231
+ return $return;
232
+ }
233
+
234
+ /**
235
+ *
236
+ *
237
+ * @param string $date
238
+ * @param string $format (optional)
239
+ * @return string
240
+ */
241
+ function intl_date( $date, $format = null ) {
242
+ if ( $format === null ) {
243
+ $format = get_option( 'date_format' );
244
+ }
245
+
246
+ if ( $date instanceof DateTime ) {
247
+ $timestamp = $date->getTimestamp();
248
+ } else {
249
+ $timestamp = strtotime( $date );
250
+ }
251
+
252
+ return date_i18n( $format, $timestamp );
253
+ }
254
+
255
+ //debug
256
+
257
+ /**
258
+ *
259
+ *
260
+ * @param mixed $obj
261
+ * @param bool $methods
262
+ * @return string
263
+ */
264
+ function object_docs( $obj, $methods = true ) {
265
+ $class = get_class( $obj );
266
+ $properties = (array)$obj;
267
+ if ( $methods ) {
268
+ /** @var array $methods */
269
+ $methods = $obj->get_method_values();
270
+ }
271
+ $rets = array_merge( $properties, $methods );
272
+ ksort( $rets );
273
+ $str = print_r( $rets, true );
274
+ $str = str_replace( 'Array', $class . ' Object', $str );
275
+ return $str;
276
+ }
277
+
278
+ /**
279
+ * @param int|string $from
280
+ * @param int|string $to
281
+ * @param string $format_past
282
+ * @param string $format_future
283
+ * @return string
284
+ */
285
+ function time_ago( $from, $to = null, $format_past = '%s ago', $format_future = '%s from now' ) {
286
+ $to = $to === null ? time() : $to;
287
+ $to = is_int( $to ) ? $to : strtotime( $to );
288
+ $from = is_int( $from ) ? $from : strtotime( $from );
289
+
290
+ if ( $from < $to ) {
291
+ return sprintf( $format_past, human_time_diff( $from, $to ) );
292
+ } else {
293
+ return sprintf( $format_future, human_time_diff( $to, $from ) );
294
+ }
295
+ }
296
 
297
  }
lib/timber-url-helper.php CHANGED
@@ -2,259 +2,307 @@
2
 
3
  class TimberURLHelper {
4
 
5
- /**
6
- * @return string
7
- */
8
- public static function get_current_url() {
9
- $pageURL = "http://";
10
- if (isset($_SERVER['HTTPS']) && $_SERVER["HTTPS"] == "on") {
11
- $pageURL = "https://";;
12
- }
13
- if ($_SERVER["SERVER_PORT"] != "80") {
14
- $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
15
- } else {
16
- $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
17
- }
18
- return $pageURL;
19
- }
 
 
20
 
21
- /**
22
- * @param string $url
23
- * @return bool
24
- */
25
- public static function is_url($url) {
26
- if (!is_string($url)) {
27
- return false;
28
- }
29
- $url = strtolower($url);
30
- if (strstr($url, '://')) {
31
- return true;
32
- }
33
- return false;
34
- }
 
 
35
 
36
- /**
37
- * @return string
38
- */
39
- public static function get_path_base() {
40
- $struc = get_option('permalink_structure');
41
- $struc = explode('/', $struc);
42
- $p = '/';
43
- foreach ($struc as $s) {
44
- if (!strstr($s, '%') && strlen($s)) {
45
- $p .= $s . '/';
46
- }
47
- }
48
- return $p;
49
- }
 
 
50
 
51
- /**
52
- * @param string $url
53
- * @param bool $force
54
- * @return string
55
- */
56
- public static function get_rel_url($url, $force = false) {
57
- $url_info = parse_url($url);
58
- if (isset($url_info['host']) && $url_info['host'] != $_SERVER['HTTP_HOST'] && !$force) {
59
- return $url;
60
- }
61
- $link = '';
62
- if (isset($url_info['path'])){
63
- $link = $url_info['path'];
64
- }
65
- if (isset($url_info['query']) && strlen($url_info['query'])) {
66
- $link .= '?' . $url_info['query'];
67
- }
68
- if (isset($url_info['fragment']) && strlen($url_info['fragment'])) {
69
- $link .= '#' . $url_info['fragment'];
70
- }
71
- $link = TimberURLHelper::remove_double_slashes($link);
72
- return $link;
73
- }
 
 
74
 
75
- /**
76
- * @param string $url
77
- * @return bool
78
- */
79
- public static function is_local($url) {
80
- if (strstr($url, $_SERVER['HTTP_HOST'])) {
81
- return true;
82
- }
83
- return false;
84
- }
 
 
85
 
86
- /**
87
- * @param string $src
88
- * @return string
89
- */
90
- public static function get_full_path($src) {
91
- $root = ABSPATH;
92
- $old_root_path = $root . $src;
93
- $old_root_path = str_replace('//', '/', $old_root_path);
94
- return $old_root_path;
95
- }
 
 
96
 
97
- /**
98
- * Takes a url and figures out its place based in the file system based on path
99
- * NOTE: Not fool-proof, makes a lot of assumptions about the file path
100
- * matching the URL path
101
- * @param string $url
102
- * @return string
103
- */
104
- public static function url_to_file_system($url) {
105
- $url_parts = parse_url($url);
106
- $path = ABSPATH . $url_parts['path'];
107
- $path = str_replace('//', '/', $path);
108
- return $path;
109
- }
 
110
 
111
- public static function file_system_to_url( $fs ) {
112
- $relative_path = self::get_rel_path($fs);
113
- $home = home_url('/'.$relative_path);
114
- return $home;
115
- }
116
 
117
- /**
118
- * @param string $src
119
- * @return string
120
- */
121
- public static function get_rel_path($src) {
122
- if (strstr($src, ABSPATH)) {
123
- return str_replace(ABSPATH, '', $src);
124
- }
125
- //its outside the wordpress directory, alternate setups:
126
- $src = str_replace(WP_CONTENT_DIR, '', $src);
127
- return WP_CONTENT_SUBDIR . $src;
128
- }
 
 
129
 
130
- /**
131
- * @param string $url
132
- * @return string
133
- */
134
- public static function remove_double_slashes($url) {
135
- $url = str_replace('//', '/', $url);
136
- if (strstr($url, 'http:') && !strstr($url, 'http://')) {
137
- $url = str_replace('http:/', 'http://', $url);
138
- }
139
- return $url;
140
- }
 
 
141
 
142
- /**
143
- * @param string $url
144
- * @param string $path
145
- * @return string
146
- */
147
- public static function prepend_to_url($url, $path) {
148
- if (strstr(strtolower($url), 'http')) {
149
- $url_parts = parse_url($url);
150
- $url = $url_parts['scheme'] . '://' . $url_parts['host'] . $path . $url_parts['path'];
151
- if ( isset($url_parts['query']) ) {
152
- $url .= $url_parts['query'];
153
- }
154
- if ( isset($url_parts['fragment']) ) {
155
- $url .= $url_parts['fragment'];
156
- }
157
- } else {
158
- $url = $url . $path;
159
- }
160
- return self::remove_double_slashes($url);
161
- }
 
 
162
 
163
- /**
164
- * @param string $path
165
- * @return string
166
- */
167
- public static function preslashit($path) {
168
- if (strpos($path, '/') != 0) {
169
- $path = '/' . $path;
170
- }
171
- return $path;
172
- }
 
 
173
 
174
- /**
175
- * @return boolean true if $path is an absolute url, false if relative.
176
- */
177
- public static function is_absolute($path) {
178
- return (boolean) (strstr($path, 'http' ));
179
- }
 
 
180
 
181
- /**
182
- * @param string $url
183
- * @return bool true if $path is an external url, false if relative or local.
184
- * true if it's a subdomain (http://cdn.example.org = true)
185
- */
186
- public static function is_external($url) {
187
- $has_http = strstr(strtolower($url), 'http');
188
- $on_domain = strstr($url, $_SERVER['HTTP_HOST']);
189
- if ($has_http && !$on_domain) {
190
- return true;
191
- }
192
- return false;
193
- }
 
 
 
194
 
195
- /**
196
- * Pass links through untrailingslashit unless they are a single /
197
- *
198
- * @param string $link
199
- * @return string
200
- */
201
- public static function remove_trailing_slash($link) {
202
- if ( $link != "/")
203
- $link = untrailingslashit( $link );
204
- return $link;
205
- }
 
 
 
 
206
 
207
- /**
208
- * @param string $url
209
- * @param int $timeout
210
- * @return string|WP_Error
211
- * @deprecated since 0.20.0
212
- */
213
- static function download_url($url, $timeout = 300) {
214
- if (!$url) {
215
- return new WP_Error('http_no_url', __('Invalid URL Provided.'));
216
- }
 
217
 
218
- $tmpfname = wp_tempnam($url);
219
- if (!$tmpfname) {
220
- return new WP_Error('http_no_file', __('Could not create Temporary file.'));
221
- }
 
 
 
 
 
 
 
 
222
 
223
- $response = wp_remote_get($url, array('timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname));
 
 
 
224
 
225
- if (is_wp_error($response)) {
226
- unlink($tmpfname);
227
- return $response;
228
- }
229
- if (200 != wp_remote_retrieve_response_code($response)) {
230
- unlink($tmpfname);
231
- return new WP_Error('http_404', trim(wp_remote_retrieve_response_message($response)));
232
- }
233
- return $tmpfname;
234
- }
235
 
236
- /**
237
- * @param int $i
238
- * @return array
239
- */
240
- public static function get_params($i = false) {
241
- $args = explode('/', trim(strtolower($_SERVER['REQUEST_URI'])));
242
- $newargs = array();
243
- foreach ($args as $arg) {
244
- if (strlen($arg)) {
245
- $newargs[] = $arg;
246
- }
247
- }
248
- if ($i === false){
249
- return $newargs;
250
- }
251
- if ($i < 0){
252
- //count from end
253
- $i = count($newargs) + $i;
254
- }
255
- if (isset($newargs[$i])) {
256
- return $newargs[$i];
257
- }
258
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
  }
2
 
3
  class TimberURLHelper {
4
 
5
+ /**
6
+ *
7
+ *
8
+ * @return string
9
+ */
10
+ public static function get_current_url() {
11
+ $pageURL = "http://";
12
+ if ( isset( $_SERVER['HTTPS'] ) && $_SERVER["HTTPS"] == "on" ) {
13
+ $pageURL = "https://";;
14
+ }
15
+ if ( $_SERVER["SERVER_PORT"] != "80" ) {
16
+ $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
17
+ } else {
18
+ $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
19
+ }
20
+ return $pageURL;
21
+ }
22
 
23
+ /**
24
+ *
25
+ *
26
+ * @param string $url
27
+ * @return bool
28
+ */
29
+ public static function is_url( $url ) {
30
+ if ( !is_string( $url ) ) {
31
+ return false;
32
+ }
33
+ $url = strtolower( $url );
34
+ if ( strstr( $url, '://' ) ) {
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
 
40
+ /**
41
+ *
42
+ *
43
+ * @return string
44
+ */
45
+ public static function get_path_base() {
46
+ $struc = get_option( 'permalink_structure' );
47
+ $struc = explode( '/', $struc );
48
+ $p = '/';
49
+ foreach ( $struc as $s ) {
50
+ if ( !strstr( $s, '%' ) && strlen( $s ) ) {
51
+ $p .= $s . '/';
52
+ }
53
+ }
54
+ return $p;
55
+ }
56
 
57
+ /**
58
+ *
59
+ *
60
+ * @param string $url
61
+ * @param bool $force
62
+ * @return string
63
+ */
64
+ public static function get_rel_url( $url, $force = false ) {
65
+ $url_info = parse_url( $url );
66
+ if ( isset( $url_info['host'] ) && $url_info['host'] != $_SERVER['HTTP_HOST'] && !$force ) {
67
+ return $url;
68
+ }
69
+ $link = '';
70
+ if ( isset( $url_info['path'] ) ) {
71
+ $link = $url_info['path'];
72
+ }
73
+ if ( isset( $url_info['query'] ) && strlen( $url_info['query'] ) ) {
74
+ $link .= '?' . $url_info['query'];
75
+ }
76
+ if ( isset( $url_info['fragment'] ) && strlen( $url_info['fragment'] ) ) {
77
+ $link .= '#' . $url_info['fragment'];
78
+ }
79
+ $link = TimberURLHelper::remove_double_slashes( $link );
80
+ return $link;
81
+ }
82
 
83
+ /**
84
+ *
85
+ *
86
+ * @param string $url
87
+ * @return bool
88
+ */
89
+ public static function is_local( $url ) {
90
+ if ( strstr( $url, $_SERVER['HTTP_HOST'] ) ) {
91
+ return true;
92
+ }
93
+ return false;
94
+ }
95
 
96
+ /**
97
+ *
98
+ *
99
+ * @param string $src
100
+ * @return string
101
+ */
102
+ public static function get_full_path( $src ) {
103
+ $root = ABSPATH;
104
+ $old_root_path = $root . $src;
105
+ $old_root_path = str_replace( '//', '/', $old_root_path );
106
+ return $old_root_path;
107
+ }
108
 
109
+ /**
110
+ * Takes a url and figures out its place based in the file system based on path
111
+ * NOTE: Not fool-proof, makes a lot of assumptions about the file path
112
+ * matching the URL path
113
+ *
114
+ * @param string $url
115
+ * @return string
116
+ */
117
+ public static function url_to_file_system( $url ) {
118
+ $url_parts = parse_url( $url );
119
+ $path = ABSPATH . $url_parts['path'];
120
+ $path = str_replace( '//', '/', $path );
121
+ return $path;
122
+ }
123
 
124
+ public static function file_system_to_url( $fs ) {
125
+ $relative_path = self::get_rel_path( $fs );
126
+ $home = home_url( '/'.$relative_path );
127
+ return $home;
128
+ }
129
 
130
+ /**
131
+ *
132
+ *
133
+ * @param string $src
134
+ * @return string
135
+ */
136
+ public static function get_rel_path( $src ) {
137
+ if ( strstr( $src, ABSPATH ) ) {
138
+ return str_replace( ABSPATH, '', $src );
139
+ }
140
+ //its outside the wordpress directory, alternate setups:
141
+ $src = str_replace( WP_CONTENT_DIR, '', $src );
142
+ return WP_CONTENT_SUBDIR . $src;
143
+ }
144
 
145
+ /**
146
+ *
147
+ *
148
+ * @param string $url
149
+ * @return string
150
+ */
151
+ public static function remove_double_slashes( $url ) {
152
+ $url = str_replace( '//', '/', $url );
153
+ if ( strstr( $url, 'http:' ) && !strstr( $url, 'http://' ) ) {
154
+ $url = str_replace( 'http:/', 'http://', $url );
155
+ }
156
+ return $url;
157
+ }
158
 
159
+ /**
160
+ *
161
+ *
162
+ * @param string $url
163
+ * @param string $path
164
+ * @return string
165
+ */
166
+ public static function prepend_to_url( $url, $path ) {
167
+ if ( strstr( strtolower( $url ), 'http' ) ) {
168
+ $url_parts = parse_url( $url );
169
+ $url = $url_parts['scheme'] . '://' . $url_parts['host'] . $path . $url_parts['path'];
170
+ if ( isset( $url_parts['query'] ) ) {
171
+ $url .= $url_parts['query'];
172
+ }
173
+ if ( isset( $url_parts['fragment'] ) ) {
174
+ $url .= $url_parts['fragment'];
175
+ }
176
+ } else {
177
+ $url = $url . $path;
178
+ }
179
+ return self::remove_double_slashes( $url );
180
+ }
181
 
182
+ /**
183
+ *
184
+ *
185
+ * @param string $path
186
+ * @return string
187
+ */
188
+ public static function preslashit( $path ) {
189
+ if ( strpos( $path, '/' ) != 0 ) {
190
+ $path = '/' . $path;
191
+ }
192
+ return $path;
193
+ }
194
 
195
+ /**
196
+ * This will evaluate wheter a URL is at an aboslute location (like http://example.org/whatever)
197
+ *
198
+ * @return boolean true if $path is an absolute url, false if relative.
199
+ */
200
+ public static function is_absolute( $path ) {
201
+ return (boolean) ( strstr( $path, 'http' ) );
202
+ }
203
 
204
+ /**
205
+ * This function is slightly different from the one below in the case of:
206
+ * an image hosted on the same domain BUT on a different site than the
207
+ * Wordpress install will be reported as external content.
208
+ *
209
+ * @param string $url a URL to evaluate against
210
+ * @return boolean if $url points to an external location returns true
211
+ */
212
+ public static function is_external_content( $url ) {
213
+ // using content_url() instead of site_url or home_url is IMPORTANT
214
+ // otherwise you run into errors with sites that:
215
+ // 1. use WPML plugin
216
+ // 2. or redefine upload directory
217
+ $is_external = TimberURLHelper::is_absolute( $url ) && !strstr( $url, content_url() );
218
+ return $is_external;
219
+ }
220
 
221
+ /**
222
+ *
223
+ *
224
+ * @param string $url
225
+ * @return bool true if $path is an external url, false if relative or local.
226
+ * true if it's a subdomain (http://cdn.example.org = true)
227
+ */
228
+ public static function is_external( $url ) {
229
+ $has_http = strstr( strtolower( $url ), 'http' );
230
+ $on_domain = strstr( $url, $_SERVER['HTTP_HOST'] );
231
+ if ( $has_http && !$on_domain ) {
232
+ return true;
233
+ }
234
+ return false;
235
+ }
236
 
237
+ /**
238
+ * Pass links through untrailingslashit unless they are a single /
239
+ *
240
+ * @param string $link
241
+ * @return string
242
+ */
243
+ public static function remove_trailing_slash( $link ) {
244
+ if ( $link != "/" )
245
+ $link = untrailingslashit( $link );
246
+ return $link;
247
+ }
248
 
249
+ /**
250
+ * Download an external file via a URL
251
+ *
252
+ * @param string $url
253
+ * @param int $timeout
254
+ * @return string|WP_Error the location of the temporay file name or an error
255
+ * @deprecated since 0.20.0
256
+ */
257
+ static function download_url( $url, $timeout = 300 ) {
258
+ if ( !$url ) {
259
+ return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) );
260
+ }
261
 
262
+ $tmpfname = wp_tempnam( $url );
263
+ if ( !$tmpfname ) {
264
+ return new WP_Error( 'http_no_file', __( 'Could not create Temporary file.' ) );
265
+ }
266
 
267
+ $response = wp_remote_get( $url, array( 'timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname ) );
 
 
 
 
 
 
 
 
 
268
 
269
+ if ( is_wp_error( $response ) ) {
270
+ unlink( $tmpfname );
271
+ return $response;
272
+ }
273
+ if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
274
+ unlink( $tmpfname );
275
+ return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
276
+ }
277
+ return $tmpfname;
278
+ }
279
+
280
+ /**
281
+ * Returns the url parameters, for example for url http://example.org/blog/post/news/2014/whatever
282
+ * this will return array('blog', 'post', 'news', '2014', 'whatever');
283
+ * OR if sent an integer like: TimberUrlHelper::get_params(2); this will return 'news';
284
+ *
285
+ * @param int $i the position of the parameter to grab.
286
+ * @return array|string
287
+ */
288
+ public static function get_params( $i = false ) {
289
+ $args = explode( '/', trim( strtolower( $_SERVER['REQUEST_URI'] ) ) );
290
+ $newargs = array();
291
+ foreach ( $args as $arg ) {
292
+ if ( strlen( $arg ) ) {
293
+ $newargs[] = $arg;
294
+ }
295
+ }
296
+ if ( $i === false ) {
297
+ return $newargs;
298
+ }
299
+ if ( $i < 0 ) {
300
+ //count from end
301
+ $i = count( $newargs ) + $i;
302
+ }
303
+ if ( isset( $newargs[$i] ) ) {
304
+ return $newargs[$i];
305
+ }
306
+ }
307
 
308
  }
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.21.3
6
  Tested up to: 4.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.21.3 =
45
  * Fixed issues with static post pages
46
  * Fixed issues with front pages with static pages
2
  Contributors: jarednova
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.7
5
+ Stable tag: 0.21.4
6
  Tested up to: 4.1
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
41
 
42
  == Changelog ==
43
 
44
+ = 0.21.4 =
45
+ * Fixed issue with multisite variables
46
+ * Fixed issue with string conversion on function output
47
+ *
48
+
49
  = 0.21.3 =
50
  * Fixed issues with static post pages
51
  * Fixed issues with front pages with static pages
timber-starter-theme/composer.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "upstatement/timber-starter-theme",
3
  "description": "Starter theme to build a Timber theme",
4
- "type":"wordpress-plugin",
5
  "minimum-stability" : "dev",
6
  "authors": [
7
  {
1
  {
2
  "name": "upstatement/timber-starter-theme",
3
  "description": "Starter theme to build a Timber theme",
4
+ "type":"wordpress-theme",
5
  "minimum-stability" : "dev",
6
  "authors": [
7
  {
timber-starter-theme/single.php CHANGED
@@ -12,7 +12,6 @@
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();
17
 
18
  if ( post_password_required( $post->ID ) ) {
12
  $context = Timber::get_context();
13
  $post = Timber::query_post();
14
  $context['post'] = $post;
 
15
  $context['comment_form'] = TimberHelper::get_comment_form();
16
 
17
  if ( post_password_required( $post->ID ) ) {
timber-starter-theme/{js → static}/site.js RENAMED
File without changes
timber-starter-theme/tests/test-timber-starter-theme.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  class TestTimberStarterTheme extends WP_UnitTestCase {
4
 
5
- function testFunctionsPHP(){
6
  self::_setupStarterTheme();
7
  require_once(get_template_directory().'/functions.php');
8
  $context = Timber::get_context();
@@ -16,8 +16,6 @@
16
  $dest = WP_CONTENT_DIR.'/themes/timber-starter-theme/';
17
  $src = __DIR__.'/../../timber-starter-theme/';
18
  if (is_dir($src)) {
19
- echo 'its a directory';
20
- return;
21
  self::_copyDirectory($src, $dest);
22
  switch_theme('timber-starter-theme');
23
  } else {
2
 
3
  class TestTimberStarterTheme extends WP_UnitTestCase {
4
 
5
+ function testFunctionsPHP() {
6
  self::_setupStarterTheme();
7
  require_once(get_template_directory().'/functions.php');
8
  $context = Timber::get_context();
16
  $dest = WP_CONTENT_DIR.'/themes/timber-starter-theme/';
17
  $src = __DIR__.'/../../timber-starter-theme/';
18
  if (is_dir($src)) {
 
 
19
  self::_copyDirectory($src, $dest);
20
  switch_theme('timber-starter-theme');
21
  } else {
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.21.3
8
  Author URI: http://upstatement.com/
9
  */
10
 
@@ -164,16 +164,6 @@ class Timber {
164
  return TimberPostGetter::get_posts( $query, $PostClass );
165
  }
166
 
167
- /**
168
- * @param array $results
169
- * @param string $PostClass
170
- * @return TimberPostsCollection
171
- * @deprecated since 0.20.0
172
- */
173
- static function handle_post_results( $results, $PostClass = 'TimberPost' ) {
174
- return TimberPostGetter::handle_post_results( $results, $PostClass );
175
- }
176
-
177
  /**
178
  * @param unknown $query
179
  * @return int
@@ -445,6 +435,7 @@ class Timber {
445
  global $wp_query;
446
  global $paged;
447
  global $wp_rewrite;
 
448
  $args['total'] = ceil( $wp_query->found_posts / $wp_query->query_vars['posts_per_page'] );
449
  if ( $wp_rewrite->using_permalinks() ) {
450
  $url = explode( '?', get_pagenum_link( 0 ) );
@@ -467,6 +458,7 @@ class Timber {
467
  } else {
468
  $args = array_merge( $args, $prefs );
469
  }
 
470
  $data['pages'] = TimberHelper::paginate_links( $args );
471
  $next = get_next_posts_page_link( $args['total'] );
472
  if ( $next ) {
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.21.4
8
  Author URI: http://upstatement.com/
9
  */
10
 
164
  return TimberPostGetter::get_posts( $query, $PostClass );
165
  }
166
 
 
 
 
 
 
 
 
 
 
 
167
  /**
168
  * @param unknown $query
169
  * @return int
435
  global $wp_query;
436
  global $paged;
437
  global $wp_rewrite;
438
+ $args = array();
439
  $args['total'] = ceil( $wp_query->found_posts / $wp_query->query_vars['posts_per_page'] );
440
  if ( $wp_rewrite->using_permalinks() ) {
441
  $url = explode( '?', get_pagenum_link( 0 ) );
458
  } else {
459
  $args = array_merge( $args, $prefs );
460
  }
461
+ $data = array();
462
  $data['pages'] = TimberHelper::paginate_links( $args );
463
  $next = get_next_posts_page_link( $args['total'] );
464
  if ( $next ) {
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit0aac21df2a554d21b56a530bb2ccb977::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitefc86d66a4203b5f4a0f0286c9f915b1::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit0aac21df2a554d21b56a530bb2ccb977
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit0aac21df2a554d21b56a530bb2ccb977
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit0aac21df2a554d21b56a530bb2ccb977', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit0aac21df2a554d21b56a530bb2ccb977', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
@@ -44,7 +44,7 @@ class ComposerAutoloaderInit0aac21df2a554d21b56a530bb2ccb977
44
  }
45
  }
46
 
47
- function composerRequire0aac21df2a554d21b56a530bb2ccb977($file)
48
  {
49
  require $file;
50
  }
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitefc86d66a4203b5f4a0f0286c9f915b1
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitefc86d66a4203b5f4a0f0286c9f915b1', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitefc86d66a4203b5f4a0f0286c9f915b1', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
44
  }
45
  }
46
 
47
+ function composerRequireefc86d66a4203b5f4a0f0286c9f915b1($file)
48
  {
49
  require $file;
50
  }
vendor/composer/installed.json CHANGED
@@ -98,23 +98,23 @@
98
  },
99
  {
100
  "name": "twig/twig",
101
- "version": "v1.18.1",
102
- "version_normalized": "1.18.1.0",
103
  "source": {
104
  "type": "git",
105
  "url": "https://github.com/twigphp/Twig.git",
106
- "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f"
107
  },
108
  "dist": {
109
  "type": "zip",
110
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f",
111
- "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f",
112
  "shasum": ""
113
  },
114
  "require": {
115
  "php": ">=5.2.7"
116
  },
117
- "time": "2015-04-19 08:30:27",
118
  "type": "library",
119
  "extra": {
120
  "branch-alias": {
98
  },
99
  {
100
  "name": "twig/twig",
101
+ "version": "v1.18.2",
102
+ "version_normalized": "1.18.2.0",
103
  "source": {
104
  "type": "git",
105
  "url": "https://github.com/twigphp/Twig.git",
106
+ "reference": "e8e6575abf6102af53ec283f7f14b89e304fa602"
107
  },
108
  "dist": {
109
  "type": "zip",
110
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/e8e6575abf6102af53ec283f7f14b89e304fa602",
111
+ "reference": "e8e6575abf6102af53ec283f7f14b89e304fa602",
112
  "shasum": ""
113
  },
114
  "require": {
115
  "php": ">=5.2.7"
116
  },
117
+ "time": "2015-06-06 23:31:24",
118
  "type": "library",
119
  "extra": {
120
  "branch-alias": {
vendor/twig/twig/.travis.yml CHANGED
@@ -8,11 +8,9 @@ php:
8
  - 5.6
9
  - hhvm
10
  - nightly
11
- - hhvm-nightly
12
 
13
  allow_failures:
14
  - php: nightly
15
- - php: hhvm-nightly
16
 
17
  env:
18
  - TWIG_EXT=no
@@ -26,7 +24,5 @@ matrix:
26
  exclude:
27
  - php: hhvm
28
  env: TWIG_EXT=yes
29
- - php: hhvm-nightly
30
- env: TWIG_EXT=yes
31
  - php: nightly
32
  env: TWIG_EXT=yes
8
  - 5.6
9
  - hhvm
10
  - nightly
 
11
 
12
  allow_failures:
13
  - php: nightly
 
14
 
15
  env:
16
  - TWIG_EXT=no
24
  exclude:
25
  - php: hhvm
26
  env: TWIG_EXT=yes
 
 
27
  - php: nightly
28
  env: TWIG_EXT=yes
vendor/twig/twig/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
 
 
 
 
 
1
  * 1.18.1 (2015-04-19)
2
 
3
  * fixed memory leaks in the C extension
1
+ * 1.18.2 (2015-06-06)
2
+
3
+ * fixed template/line guessing in exceptions for nested templates
4
+ * optimized the number of inodes and the size of realpath cache when using the cache
5
+
6
  * 1.18.1 (2015-04-19)
7
 
8
  * fixed memory leaks in the C extension
vendor/twig/twig/doc/api.rst CHANGED
@@ -72,29 +72,43 @@ options as the constructor second argument::
72
 
73
  The following options are available:
74
 
75
- * ``debug``: When set to ``true``, the generated templates have a
 
 
76
  ``__toString()`` method that you can use to display the generated nodes
77
  (default to ``false``).
78
 
79
- * ``charset``: The charset used by the templates (default to ``utf-8``).
 
 
 
 
 
 
 
80
 
81
- * ``base_template_class``: The base template class to use for generated
82
- templates (default to ``Twig_Template``).
83
 
84
- * ``cache``: An absolute path where to store the compiled templates, or
85
  ``false`` to disable caching (which is the default).
86
 
87
- * ``auto_reload``: When developing with Twig, it's useful to recompile the
 
 
88
  template whenever the source code changes. If you don't provide a value for
89
  the ``auto_reload`` option, it will be determined automatically based on the
90
  ``debug`` value.
91
 
92
- * ``strict_variables``: If set to ``false``, Twig will silently ignore invalid
 
 
93
  variables (variables and or attributes/methods that do not exist) and
94
  replace them with a ``null`` value. When set to ``true``, Twig throws an
95
  exception instead (default to ``false``).
96
 
97
- * ``autoescape``: If set to ``true``, HTML auto-escaping will be enabled by
 
 
98
  default for all templates (default to ``true``).
99
 
100
  As of Twig 1.8, you can set the escaping strategy to use (``html``, ``js``,
@@ -110,7 +124,9 @@ The following options are available:
110
  strategy does not incur any overhead at runtime as auto-escaping is done at
111
  compilation time.)
112
 
113
- * ``optimizations``: A flag that indicates which optimizations to apply
 
 
114
  (default to ``-1`` -- all optimizations are enabled; set it to ``0`` to
115
  disable).
116
 
72
 
73
  The following options are available:
74
 
75
+ * ``debug`` *boolean*
76
+
77
+ When set to ``true``, the generated templates have a
78
  ``__toString()`` method that you can use to display the generated nodes
79
  (default to ``false``).
80
 
81
+ * ``charset`` *string (default to ``utf-8``)*
82
+
83
+ The charset used by the templates.
84
+
85
+ * ``base_template_class`` *string (default to ``Twig_Template``)*
86
+
87
+ The base template class to use for generated
88
+ templates.
89
 
90
+ * ``cache`` *string|false*
 
91
 
92
+ An absolute path where to store the compiled templates, or
93
  ``false`` to disable caching (which is the default).
94
 
95
+ * ``auto_reload`` *boolean*
96
+
97
+ When developing with Twig, it's useful to recompile the
98
  template whenever the source code changes. If you don't provide a value for
99
  the ``auto_reload`` option, it will be determined automatically based on the
100
  ``debug`` value.
101
 
102
+ * ``strict_variables`` *boolean*
103
+
104
+ If set to ``false``, Twig will silently ignore invalid
105
  variables (variables and or attributes/methods that do not exist) and
106
  replace them with a ``null`` value. When set to ``true``, Twig throws an
107
  exception instead (default to ``false``).
108
 
109
+ * ``autoescape`` *string|boolean*
110
+
111
+ If set to ``true``, HTML auto-escaping will be enabled by
112
  default for all templates (default to ``true``).
113
 
114
  As of Twig 1.8, you can set the escaping strategy to use (``html``, ``js``,
124
  strategy does not incur any overhead at runtime as auto-escaping is done at
125
  compilation time.)
126
 
127
+ * ``optimizations`` *integer*
128
+
129
+ A flag that indicates which optimizations to apply
130
  (default to ``-1`` -- all optimizations are enabled; set it to ``0`` to
131
  disable).
132
 
vendor/twig/twig/doc/tags/if.rst CHANGED
@@ -37,8 +37,16 @@ You can also use ``not`` to check for values that evaluate to ``false``:
37
  <p>You are not subscribed to our mailing list.</p>
38
  {% endif %}
39
 
40
- For multiple branches ``elseif`` and ``else`` can be used like in PHP. You can use
41
- more complex ``expressions`` there too:
 
 
 
 
 
 
 
 
42
 
43
  .. code-block:: jinja
44
 
37
  <p>You are not subscribed to our mailing list.</p>
38
  {% endif %}
39
 
40
+ For multiple conditions, ``and`` and ``or`` can be used:
41
+
42
+ .. code-block:: jinja
43
+
44
+ {% if temperature > 18 and temperature < 27 %}
45
+ <p>It's a nice day for a walk in the park.</p>
46
+ {% endif %}
47
+
48
+ For multiple branches ``elseif`` and ``else`` can be used like in PHP. You can
49
+ use more complex ``expressions`` there too:
50
 
51
  .. code-block:: jinja
52
 
vendor/twig/twig/doc/tags/spaceless.rst CHANGED
@@ -33,5 +33,5 @@ quirks under some circumstances.
33
  .. tip::
34
 
35
  For more information on whitespace control, read the
36
- :doc:`dedicated<../templates>` section of the documentation and learn how
37
  you can also use the whitespace control modifier on your tags.
33
  .. tip::
34
 
35
  For more information on whitespace control, read the
36
+ :ref:`dedicated section <templates-whitespace-control>` of the documentation and learn how
37
  you can also use the whitespace control modifier on your tags.
vendor/twig/twig/doc/templates.rst CHANGED
@@ -669,6 +669,10 @@ You can combine multiple expressions with the following operators:
669
 
670
  Twig also support bitwise operators (``b-and``, ``b-xor``, and ``b-or``).
671
 
 
 
 
 
672
  Comparisons
673
  ~~~~~~~~~~~
674
 
@@ -801,6 +805,8 @@ inserted into the string:
801
  {{ "foo #{bar} baz" }}
802
  {{ "foo #{1 + 2} baz" }}
803
 
 
 
804
  Whitespace Control
805
  ------------------
806
 
669
 
670
  Twig also support bitwise operators (``b-and``, ``b-xor``, and ``b-or``).
671
 
672
+ .. note::
673
+
674
+ Operators are case sensitive.
675
+
676
  Comparisons
677
  ~~~~~~~~~~~
678
 
805
  {{ "foo #{bar} baz" }}
806
  {{ "foo #{1 + 2} baz" }}
807
 
808
+ .. _templates-whitespace-control:
809
+
810
  Whitespace Control
811
  ------------------
812
 
vendor/twig/twig/ext/twig/php_twig.h CHANGED
@@ -15,7 +15,7 @@
15
  #ifndef PHP_TWIG_H
16
  #define PHP_TWIG_H
17
 
18
- #define PHP_TWIG_VERSION "1.18.1"
19
 
20
  #include "php.h"
21
 
15
  #ifndef PHP_TWIG_H
16
  #define PHP_TWIG_H
17
 
18
+ #define PHP_TWIG_VERSION "1.18.2"
19
 
20
  #include "php.h"
21
 
vendor/twig/twig/ext/twig/twig.c CHANGED
@@ -779,12 +779,18 @@ PHP_FUNCTION(twig_template_get_attributes)
779
  $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object));
780
  } elseif (is_array($object)) {
781
  if (empty($object)) {
782
- $message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem);
783
  } else {
784
- $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
785
  }
786
  } elseif (Twig_Template::ARRAY_CALL === $type) {
787
- $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
 
 
 
 
 
 
788
  } else {
789
  $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
790
  }
@@ -807,12 +813,21 @@ PHP_FUNCTION(twig_template_get_attributes)
807
  } else {
808
  char *type_name = zend_zval_type_name(object);
809
  Z_ADDREF_P(object);
810
- convert_to_string(object);
811
- TWIG_RUNTIME_ERROR(template TSRMLS_CC,
812
- (strcmp("array", type) == 0)
813
- ? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
814
- : "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
815
- item, type_name, Z_STRVAL_P(object));
 
 
 
 
 
 
 
 
 
816
  zval_ptr_dtor(&object);
817
  }
818
  efree(item);
@@ -836,7 +851,14 @@ PHP_FUNCTION(twig_template_get_attributes)
836
  if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
837
  return null;
838
  }
839
- throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
 
 
 
 
 
 
 
840
  }
841
  */
842
  if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
@@ -846,9 +868,15 @@ PHP_FUNCTION(twig_template_get_attributes)
846
 
847
  type_name = zend_zval_type_name(object);
848
  Z_ADDREF_P(object);
849
- convert_to_string_ex(&object);
 
850
 
851
- TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));
 
 
 
 
 
852
 
853
  zval_ptr_dtor(&object);
854
  efree(item);
779
  $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object));
780
  } elseif (is_array($object)) {
781
  if (empty($object)) {
782
+ $message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem);
783
  } else {
784
+ $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
785
  }
786
  } elseif (Twig_Template::ARRAY_CALL === $type) {
787
+ if (null === $object) {
788
+ $message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
789
+ } else {
790
+ $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
791
+ }
792
+ } elseif (null === $object) {
793
+ $message = sprintf('Impossible to access an attribute ("%s") on a null variable', $item);
794
  } else {
795
  $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
796
  }
813
  } else {
814
  char *type_name = zend_zval_type_name(object);
815
  Z_ADDREF_P(object);
816
+ if (Z_TYPE_P(object) == IS_NULL) {
817
+ convert_to_string(object);
818
+ TWIG_RUNTIME_ERROR(template TSRMLS_CC,
819
+ (strcmp("array", type) == 0)
820
+ ? "Impossible to access a key (\"%s\") on a %s variable"
821
+ : "Impossible to access an attribute (\"%s\") on a %s variable",
822
+ item, type_name);
823
+ } else {
824
+ convert_to_string(object);
825
+ TWIG_RUNTIME_ERROR(template TSRMLS_CC,
826
+ (strcmp("array", type) == 0)
827
+ ? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
828
+ : "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
829
+ item, type_name, Z_STRVAL_P(object));
830
+ }
831
  zval_ptr_dtor(&object);
832
  }
833
  efree(item);
851
  if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
852
  return null;
853
  }
854
+
855
+ if (null === $object) {
856
+ $message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item);
857
+ } else {
858
+ $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
859
+ }
860
+
861
+ throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
862
  }
863
  */
864
  if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
868
 
869
  type_name = zend_zval_type_name(object);
870
  Z_ADDREF_P(object);
871
+ if (Z_TYPE_P(object) == IS_NULL) {
872
+ convert_to_string_ex(&object);
873
 
874
+ TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable", item, type_name);
875
+ } else {
876
+ convert_to_string_ex(&object);
877
+
878
+ TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));
879
+ }
880
 
881
  zval_ptr_dtor(&object);
882
  efree(item);
vendor/twig/twig/lib/Twig/Environment.php CHANGED
@@ -16,7 +16,7 @@
16
  */
17
  class Twig_Environment
18
  {
19
- const VERSION = '1.18.1';
20
 
21
  protected $charset;
22
  protected $loader;
@@ -250,7 +250,7 @@ class Twig_Environment
250
 
251
  $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
252
 
253
- return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php';
254
  }
255
 
256
  /**
@@ -351,8 +351,7 @@ class Twig_Environment
351
  *
352
  * This method should not be used as a generic way to load templates.
353
  *
354
- * @param string $name The template name
355
- * @param int $index The index if it is an embedded template
356
  *
357
  * @return Twig_Template A template instance representing the given template name
358
  *
@@ -483,7 +482,7 @@ class Twig_Environment
483
  /**
484
  * Sets the Lexer instance.
485
  *
486
- * @param Twig_LexerInterface A Twig_LexerInterface instance
487
  */
488
  public function setLexer(Twig_LexerInterface $lexer)
489
  {
@@ -522,7 +521,7 @@ class Twig_Environment
522
  /**
523
  * Sets the Parser instance.
524
  *
525
- * @param Twig_ParserInterface A Twig_ParserInterface instance
526
  */
527
  public function setParser(Twig_ParserInterface $parser)
528
  {
@@ -1271,11 +1270,11 @@ class Twig_Environment
1271
  if (false === @mkdir($dir, 0777, true)) {
1272
  clearstatcache(false, $dir);
1273
  if (!is_dir($dir)) {
1274
- throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir));
1275
  }
1276
  }
1277
  } elseif (!is_writable($dir)) {
1278
- throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
1279
  }
1280
 
1281
  $tmpFile = tempnam($dir, basename($file));
16
  */
17
  class Twig_Environment
18
  {
19
+ const VERSION = '1.18.2';
20
 
21
  protected $charset;
22
  protected $loader;
250
 
251
  $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
252
 
253
+ return $this->getCache().'/'.$class[0].'/'.$class[1].'/'.$class.'.php';
254
  }
255
 
256
  /**
351
  *
352
  * This method should not be used as a generic way to load templates.
353
  *
354
+ * @param string $template The template name
 
355
  *
356
  * @return Twig_Template A template instance representing the given template name
357
  *
482
  /**
483
  * Sets the Lexer instance.
484
  *
485
+ * @param Twig_LexerInterface $lexer A Twig_LexerInterface instance
486
  */
487
  public function setLexer(Twig_LexerInterface $lexer)
488
  {
521
  /**
522
  * Sets the Parser instance.
523
  *
524
+ * @param Twig_ParserInterface $parser A Twig_ParserInterface instance
525
  */
526
  public function setParser(Twig_ParserInterface $parser)
527
  {
1270
  if (false === @mkdir($dir, 0777, true)) {
1271
  clearstatcache(false, $dir);
1272
  if (!is_dir($dir)) {
1273
+ throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
1274
  }
1275
  }
1276
  } elseif (!is_writable($dir)) {
1277
+ throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
1278
  }
1279
 
1280
  $tmpFile = tempnam($dir, basename($file));
vendor/twig/twig/lib/Twig/ExpressionParser.php CHANGED
@@ -315,7 +315,7 @@ class Twig_ExpressionParser
315
  {
316
  switch ($name) {
317
  case 'parent':
318
- $args = $this->parseArguments();
319
  if (!count($this->parser->getBlockStack())) {
320
  throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
321
  }
@@ -468,6 +468,10 @@ class Twig_ExpressionParser
468
  *
469
  * @param bool $namedArguments Whether to allow named arguments or not
470
  * @param bool $definition Whether we are parsing arguments for a function definition
 
 
 
 
471
  */
472
  public function parseArguments($namedArguments = false, $definition = false)
473
  {
315
  {
316
  switch ($name) {
317
  case 'parent':
318
+ $this->parseArguments();
319
  if (!count($this->parser->getBlockStack())) {
320
  throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
321
  }
468
  *
469
  * @param bool $namedArguments Whether to allow named arguments or not
470
  * @param bool $definition Whether we are parsing arguments for a function definition
471
+ *
472
+ * @return Twig_Node
473
+ *
474
+ * @throws Twig_Error_Syntax
475
  */
476
  public function parseArguments($namedArguments = false, $definition = false)
477
  {
vendor/twig/twig/lib/Twig/Extension/Core.php CHANGED
@@ -921,7 +921,9 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
921
  /**
922
  * Sorts an array.
923
  *
924
- * @param array $array An array
 
 
925
  */
926
  function twig_sort_filter($array)
927
  {
@@ -952,6 +954,8 @@ function twig_in_filter($value, $compare)
952
  * @param string $strategy The escaping strategy
953
  * @param string $charset The charset
954
  * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
 
 
955
  */
956
  function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
957
  {
@@ -1398,11 +1402,13 @@ function twig_test_iterable($value)
1398
  /**
1399
  * Renders a template.
1400
  *
1401
- * @param string|array $template The template to render or an array of templates to try consecutively
1402
- * @param array $variables The variables to pass to the template
1403
- * @param bool $with_context Whether to pass the current context variables or not
1404
- * @param bool $ignore_missing Whether to ignore missing templates or not
1405
- * @param bool $sandboxed Whether to sandbox the template or not
 
 
1406
  *
1407
  * @return string The rendered template
1408
  */
921
  /**
922
  * Sorts an array.
923
  *
924
+ * @param array $array
925
+ *
926
+ * @return array
927
  */
928
  function twig_sort_filter($array)
929
  {
954
  * @param string $strategy The escaping strategy
955
  * @param string $charset The charset
956
  * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
957
+ *
958
+ * @return string
959
  */
960
  function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
961
  {
1402
  /**
1403
  * Renders a template.
1404
  *
1405
+ * @param Twig_Environment $env
1406
+ * @param array $context
1407
+ * @param string|array $template The template to render or an array of templates to try consecutively
1408
+ * @param array $variables The variables to pass to the template
1409
+ * @param bool $withContext
1410
+ * @param bool $ignoreMissing Whether to ignore missing templates or not
1411
+ * @param bool $sandboxed Whether to sandbox the template or not
1412
  *
1413
  * @return string The rendered template
1414
  */
vendor/twig/twig/lib/Twig/Extension/Escaper.php CHANGED
@@ -104,6 +104,8 @@ class Twig_Extension_Escaper extends Twig_Extension
104
  * Marks a variable as being safe.
105
  *
106
  * @param string $string A PHP variable
 
 
107
  */
108
  function twig_raw_filter($string)
109
  {
104
  * Marks a variable as being safe.
105
  *
106
  * @param string $string A PHP variable
107
+ *
108
+ * @return string
109
  */
110
  function twig_raw_filter($string)
111
  {
vendor/twig/twig/lib/Twig/LoaderInterface.php CHANGED
@@ -42,7 +42,8 @@ interface Twig_LoaderInterface
42
  * Returns true if the template is still fresh.
43
  *
44
  * @param string $name The template name
45
- * @param timestamp $time The last modification time of the cached template
 
46
  *
47
  * @return bool true if the template is fresh, false otherwise
48
  *
42
  * Returns true if the template is still fresh.
43
  *
44
  * @param string $name The template name
45
+ * @param int $time Timestamp of the last modification time of the
46
+ * cached template
47
  *
48
  * @return bool true if the template is fresh, false otherwise
49
  *
vendor/twig/twig/lib/Twig/Node.php CHANGED
@@ -122,7 +122,7 @@ class Twig_Node implements Twig_NodeInterface
122
  /**
123
  * Returns true if the attribute is defined.
124
  *
125
- * @param string The attribute name
126
  *
127
  * @return bool true if the attribute is defined, false otherwise
128
  */
@@ -132,11 +132,11 @@ class Twig_Node implements Twig_NodeInterface
132
  }
133
 
134
  /**
135
- * Gets an attribute.
136
  *
137
- * @param string The attribute name
138
  *
139
- * @return mixed The attribute value
140
  */
141
  public function getAttribute($name)
142
  {
@@ -148,10 +148,10 @@ class Twig_Node implements Twig_NodeInterface
148
  }
149
 
150
  /**
151
- * Sets an attribute.
152
  *
153
- * @param string The attribute name
154
- * @param mixed The attribute value
155
  */
156
  public function setAttribute($name, $value)
157
  {
@@ -159,9 +159,9 @@ class Twig_Node implements Twig_NodeInterface
159
  }
160
 
161
  /**
162
- * Removes an attribute.
163
  *
164
- * @param string The attribute name
165
  */
166
  public function removeAttribute($name)
167
  {
@@ -169,11 +169,11 @@ class Twig_Node implements Twig_NodeInterface
169
  }
170
 
171
  /**
172
- * Returns true if the node with the given identifier exists.
173
  *
174
- * @param string The node name
175
  *
176
- * @return bool true if the node with the given name exists, false otherwise
177
  */
178
  public function hasNode($name)
179
  {
@@ -183,9 +183,9 @@ class Twig_Node implements Twig_NodeInterface
183
  /**
184
  * Gets a node by name.
185
  *
186
- * @param string The node name
187
  *
188
- * @return Twig_Node A Twig_Node instance
189
  */
190
  public function getNode($name)
191
  {
@@ -199,8 +199,8 @@ class Twig_Node implements Twig_NodeInterface
199
  /**
200
  * Sets a node.
201
  *
202
- * @param string The node name
203
- * @param Twig_Node A Twig_Node instance
204
  */
205
  public function setNode($name, $node = null)
206
  {
@@ -210,7 +210,7 @@ class Twig_Node implements Twig_NodeInterface
210
  /**
211
  * Removes a node by name.
212
  *
213
- * @param string The node name
214
  */
215
  public function removeNode($name)
216
  {
122
  /**
123
  * Returns true if the attribute is defined.
124
  *
125
+ * @param string $name The attribute name
126
  *
127
  * @return bool true if the attribute is defined, false otherwise
128
  */
132
  }
133
 
134
  /**
135
+ * Gets an attribute value by name.
136
  *
137
+ * @param string $name
138
  *
139
+ * @return mixed
140
  */
141
  public function getAttribute($name)
142
  {
148
  }
149
 
150
  /**
151
+ * Sets an attribute by name to a value.
152
  *
153
+ * @param string $name
154
+ * @param mixed $value
155
  */
156
  public function setAttribute($name, $value)
157
  {
159
  }
160
 
161
  /**
162
+ * Removes an attribute by name.
163
  *
164
+ * @param string $name
165
  */
166
  public function removeAttribute($name)
167
  {
169
  }
170
 
171
  /**
172
+ * Returns true if the node with the given name exists.
173
  *
174
+ * @param string $name
175
  *
176
+ * @return bool
177
  */
178
  public function hasNode($name)
179
  {
183
  /**
184
  * Gets a node by name.
185
  *
186
+ * @param string $name
187
  *
188
+ * @return Twig_Node
189
  */
190
  public function getNode($name)
191
  {
199
  /**
200
  * Sets a node.
201
  *
202
+ * @param string $name
203
+ * @param Twig_Node $node
204
  */
205
  public function setNode($name, $node = null)
206
  {
210
  /**
211
  * Removes a node by name.
212
  *
213
+ * @param string $name
214
  */
215
  public function removeNode($name)
216
  {
vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php CHANGED
@@ -47,6 +47,8 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
47
  * This is mostly needed when another visitor adds filters (like the escaper one).
48
  *
49
  * @param Twig_Node $node A Node
 
 
50
  */
51
  protected function removeNodeFilter($node)
52
  {
47
  * This is mostly needed when another visitor adds filters (like the escaper one).
48
  *
49
  * @param Twig_Node $node A Node
50
+ *
51
+ * @return Twig_Node
52
  */
53
  protected function removeNodeFilter($node)
54
  {
vendor/twig/twig/lib/Twig/NodeTraverser.php CHANGED
@@ -54,6 +54,8 @@ class Twig_NodeTraverser
54
  * Traverses a node and calls the registered visitors.
55
  *
56
  * @param Twig_NodeInterface $node A Twig_NodeInterface instance
 
 
57
  */
58
  public function traverse(Twig_NodeInterface $node)
59
  {
54
  * Traverses a node and calls the registered visitors.
55
  *
56
  * @param Twig_NodeInterface $node A Twig_NodeInterface instance
57
+ *
58
+ * @return Twig_NodeInterface
59
  */
60
  public function traverse(Twig_NodeInterface $node)
61
  {
vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php CHANGED
@@ -129,6 +129,8 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
129
  *
130
  * @param Twig_NodeInterface $node A Node
131
  * @param Twig_Environment $env The current Twig environment
 
 
132
  */
133
  protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
134
  {
@@ -153,6 +155,8 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
153
  *
154
  * @param Twig_NodeInterface $node A Node
155
  * @param Twig_Environment $env The current Twig environment
 
 
156
  */
157
  protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
158
  {
129
  *
130
  * @param Twig_NodeInterface $node A Node
131
  * @param Twig_Environment $env The current Twig environment
132
+ *
133
+ * @return Twig_NodeInterface
134
  */
135
  protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
136
  {
155
  *
156
  * @param Twig_NodeInterface $node A Node
157
  * @param Twig_Environment $env The current Twig environment
158
+ *
159
+ * @return Twig_NodeInterface
160
  */
161
  protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
162
  {
vendor/twig/twig/lib/Twig/Template.php CHANGED
@@ -58,6 +58,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
58
  * This method is for internal use only and should never be called
59
  * directly.
60
  *
 
 
61
  * @return Twig_TemplateInterface|false The parent template or false if there is no parent
62
  */
63
  public function getParent(array $context)
@@ -73,7 +75,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
73
  return false;
74
  }
75
 
76
- if ($parent instanceof Twig_Template) {
77
  return $this->parents[$parent->getTemplateName()] = $parent;
78
  }
79
 
@@ -247,13 +249,20 @@ abstract class Twig_Template implements Twig_TemplateInterface
247
  return $this->env->resolveTemplate($template);
248
  }
249
 
250
- if ($template instanceof Twig_Template) {
251
  return $template;
252
  }
253
 
254
  return $this->env->loadTemplate($template, $index);
255
  } catch (Twig_Error $e) {
256
- $e->setTemplateFile($templateName ? $templateName : $this->getTemplateName());
 
 
 
 
 
 
 
257
  if (!$line) {
258
  $e->guess();
259
  } else {
@@ -352,7 +361,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
352
  * @param string $item The variable to return from the context
353
  * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not
354
  *
355
- * @return The content of the context variable
356
  *
357
  * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
358
  */
@@ -383,10 +392,10 @@ abstract class Twig_Template implements Twig_TemplateInterface
383
  *
384
  * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
385
  */
386
- protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
387
  {
388
  // array
389
- if (Twig_Template::METHOD_CALL !== $type) {
390
  $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
391
 
392
  if ((is_array($object) && array_key_exists($arrayItem, $object))
@@ -399,7 +408,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
399
  return $object[$arrayItem];
400
  }
401
 
402
- if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) {
403
  if ($isDefinedTest) {
404
  return false;
405
  }
@@ -418,8 +427,14 @@ abstract class Twig_Template implements Twig_TemplateInterface
418
  } else {
419
  $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
420
  }
421
- } elseif (Twig_Template::ARRAY_CALL === $type) {
422
- $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
 
 
 
 
 
 
423
  } else {
424
  $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
425
  }
@@ -437,11 +452,17 @@ abstract class Twig_Template implements Twig_TemplateInterface
437
  return;
438
  }
439
 
440
- throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
 
 
 
 
 
 
441
  }
442
 
443
  // object property
444
- if (Twig_Template::METHOD_CALL !== $type) {
445
  if (isset($object->$item) || array_key_exists((string) $item, $object)) {
446
  if ($isDefinedTest) {
447
  return true;
58
  * This method is for internal use only and should never be called
59
  * directly.
60
  *
61
+ * @param array $context
62
+ *
63
  * @return Twig_TemplateInterface|false The parent template or false if there is no parent
64
  */
65
  public function getParent(array $context)
75
  return false;
76
  }
77
 
78
+ if ($parent instanceof self) {
79
  return $this->parents[$parent->getTemplateName()] = $parent;
80
  }
81
 
249
  return $this->env->resolveTemplate($template);
250
  }
251
 
252
+ if ($template instanceof self) {
253
  return $template;
254
  }
255
 
256
  return $this->env->loadTemplate($template, $index);
257
  } catch (Twig_Error $e) {
258
+ if (!$e->getTemplateFile()) {
259
+ $e->setTemplateFile($templateName ? $templateName : $this->getTemplateName());
260
+ }
261
+
262
+ if ($e->getTemplateLine()) {
263
+ throw $e;
264
+ }
265
+
266
  if (!$line) {
267
  $e->guess();
268
  } else {
361
  * @param string $item The variable to return from the context
362
  * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not
363
  *
364
+ * @return mixed The content of the context variable
365
  *
366
  * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
367
  */
392
  *
393
  * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
394
  */
395
+ protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
396
  {
397
  // array
398
+ if (self::METHOD_CALL !== $type) {
399
  $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
400
 
401
  if ((is_array($object) && array_key_exists($arrayItem, $object))
408
  return $object[$arrayItem];
409
  }
410
 
411
+ if (self::ARRAY_CALL === $type || !is_object($object)) {
412
  if ($isDefinedTest) {
413
  return false;
414
  }
427
  } else {
428
  $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
429
  }
430
+ } elseif (self::ARRAY_CALL === $type) {
431
+ if (null === $object) {
432
+ $message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
433
+ } else {
434
+ $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
435
+ }
436
+ } elseif (null === $object) {
437
+ $message = sprintf('Impossible to access an attribute ("%s") on a null variable', $item);
438
  } else {
439
  $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
440
  }
452
  return;
453
  }
454
 
455
+ if (null === $object) {
456
+ $message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item);
457
+ } else {
458
+ $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
459
+ }
460
+
461
+ throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
462
  }
463
 
464
  // object property
465
+ if (self::METHOD_CALL !== $type) {
466
  if (isset($object->$item) || array_key_exists((string) $item, $object)) {
467
  if ($isDefinedTest) {
468
  return true;
vendor/twig/twig/lib/Twig/TokenParser.php CHANGED
@@ -24,7 +24,7 @@ abstract class Twig_TokenParser implements Twig_TokenParserInterface
24
  /**
25
  * Sets the parser associated with this token parser
26
  *
27
- * @param $parser A Twig_Parser instance
28
  */
29
  public function setParser(Twig_Parser $parser)
30
  {
24
  /**
25
  * Sets the parser associated with this token parser
26
  *
27
+ * @param Twig_Parser $parser A Twig_Parser instance
28
  */
29
  public function setParser(Twig_Parser $parser)
30
  {
vendor/twig/twig/lib/Twig/TokenParser/Block.php CHANGED
@@ -47,7 +47,7 @@ class Twig_TokenParser_Block extends Twig_TokenParser
47
  $value = $token->getValue();
48
 
49
  if ($value != $name) {
50
- throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
51
  }
52
  }
53
  } else {
47
  $value = $token->getValue();
48
 
49
  if ($value != $name) {
50
+ throw new Twig_Error_Syntax(sprintf('Expected endblock for block "%s" (but "%s" given)', $name, $value), $stream->getCurrent()->getLine(), $stream->getFilename());
51
  }
52
  }
53
  } else {
vendor/twig/twig/lib/Twig/TokenParser/Macro.php CHANGED
@@ -42,7 +42,7 @@ class Twig_TokenParser_Macro extends Twig_TokenParser
42
  $value = $token->getValue();
43
 
44
  if ($value != $name) {
45
- throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
46
  }
47
  }
48
  $this->parser->popLocalScope();
42
  $value = $token->getValue();
43
 
44
  if ($value != $name) {
45
+ throw new Twig_Error_Syntax(sprintf('Expected endmacro for macro "%s" (but "%s" given)', $name, $value), $stream->getCurrent()->getLine(), $stream->getFilename());
46
  }
47
  }
48
  $this->parser->popLocalScope();
vendor/twig/twig/lib/Twig/TokenParser/Set.php CHANGED
@@ -48,13 +48,13 @@ class Twig_TokenParser_Set extends Twig_TokenParser
48
  $stream->expect(Twig_Token::BLOCK_END_TYPE);
49
 
50
  if (count($names) !== count($values)) {
51
- throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignments.", $stream->getCurrent()->getLine(), $stream->getFilename());
52
  }
53
  } else {
54
  $capture = true;
55
 
56
  if (count($names) > 1) {
57
- throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $stream->getCurrent()->getLine(), $stream->getFilename());
58
  }
59
 
60
  $stream->expect(Twig_Token::BLOCK_END_TYPE);
48
  $stream->expect(Twig_Token::BLOCK_END_TYPE);
49
 
50
  if (count($names) !== count($values)) {
51
+ throw new Twig_Error_Syntax('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getFilename());
52
  }
53
  } else {
54
  $capture = true;
55
 
56
  if (count($names) > 1) {
57
+ throw new Twig_Error_Syntax('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getFilename());
58
  }
59
 
60
  $stream->expect(Twig_Token::BLOCK_END_TYPE);
vendor/twig/twig/lib/Twig/TokenParserInterface.php CHANGED
@@ -19,7 +19,7 @@ interface Twig_TokenParserInterface
19
  /**
20
  * Sets the parser associated with this token parser
21
  *
22
- * @param $parser A Twig_Parser instance
23
  */
24
  public function setParser(Twig_Parser $parser);
25
 
19
  /**
20
  * Sets the parser associated with this token parser
21
  *
22
+ * @param Twig_Parser $parser A Twig_Parser instance
23
  */
24
  public function setParser(Twig_Parser $parser);
25
 
vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php CHANGED
@@ -56,7 +56,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
56
  // globals can be modified after runtime init
57
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
58
  $twig->addGlobal('foo', 'foo');
59
- $globals = $twig->getGlobals();
60
  $twig->initRuntime();
61
  $twig->addGlobal('foo', 'bar');
62
  $globals = $twig->getGlobals();
@@ -91,7 +91,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
91
  // globals cannot be added after runtime init
92
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
93
  $twig->addGlobal('foo', 'foo');
94
- $globals = $twig->getGlobals();
95
  $twig->initRuntime();
96
  try {
97
  $twig->addGlobal('bar', 'bar');
@@ -103,7 +103,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
103
  // globals cannot be added after extensions init
104
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
105
  $twig->addGlobal('foo', 'foo');
106
- $globals = $twig->getGlobals();
107
  $twig->getFunctions();
108
  try {
109
  $twig->addGlobal('bar', 'bar');
@@ -115,7 +115,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
115
  // globals cannot be added after extensions and runtime init
116
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
117
  $twig->addGlobal('foo', 'foo');
118
- $globals = $twig->getGlobals();
119
  $twig->getFunctions();
120
  $twig->initRuntime();
121
  try {
56
  // globals can be modified after runtime init
57
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
58
  $twig->addGlobal('foo', 'foo');
59
+ $twig->getGlobals();
60
  $twig->initRuntime();
61
  $twig->addGlobal('foo', 'bar');
62
  $globals = $twig->getGlobals();
91
  // globals cannot be added after runtime init
92
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
93
  $twig->addGlobal('foo', 'foo');
94
+ $twig->getGlobals();
95
  $twig->initRuntime();
96
  try {
97
  $twig->addGlobal('bar', 'bar');
103
  // globals cannot be added after extensions init
104
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
105
  $twig->addGlobal('foo', 'foo');
106
+ $twig->getGlobals();
107
  $twig->getFunctions();
108
  try {
109
  $twig->addGlobal('bar', 'bar');
115
  // globals cannot be added after extensions and runtime init
116
  $twig = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
117
  $twig->addGlobal('foo', 'foo');
118
+ $twig->getGlobals();
119
  $twig->getFunctions();
120
  $twig->initRuntime();
121
  try {
vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/syntax_error_in_reused_template.test ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ --TEST--
2
+ Exception for syntax error in reused template
3
+ --TEMPLATE--
4
+ {% use 'foo.twig' %}
5
+ --TEMPLATE(foo.twig)--
6
+ {% block bar %}
7
+ {% do node.data = 5 %}
8
+ {% endblock %}
9
+ --EXCEPTION--
10
+ Twig_Error_Syntax: Unexpected token "operator" of value "=" ("end of statement block" expected) in "foo.twig" at line 3
vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in.test CHANGED
@@ -50,6 +50,7 @@ TRUE
50
  {{ [] in [true, ''] ? 'TRUE' : 'FALSE' }}
51
  {{ [] in [true, []] ? 'TRUE' : 'FALSE' }}
52
 
 
53
  {{ resource in 'foo'~resource ? 'TRUE' : 'FALSE' }}
54
  {{ object in 'stdClass' ? 'TRUE' : 'FALSE' }}
55
  {{ [] in 'Array' ? 'TRUE' : 'FALSE' }}
@@ -73,7 +74,7 @@ TRUE
73
  {{ 5.5 in '125.5' ? 'TRUE' : 'FALSE' }}
74
  {{ '5.5' in 125.5 ? 'TRUE' : 'FALSE' }}
75
  --DATA--
76
- return array('bar' => 'bar', 'foo' => array('bar' => 'bar'), 'dir_object' => new SplFileInfo(dirname(__FILE__)), 'object' => new stdClass(), 'resource' => fopen(dirname(__FILE__), 'r'))
77
  --EXPECT--
78
  TRUE
79
  TRUE
@@ -102,6 +103,7 @@ TRUE
102
  FALSE
103
  TRUE
104
 
 
105
  FALSE
106
  FALSE
107
  FALSE
50
  {{ [] in [true, ''] ? 'TRUE' : 'FALSE' }}
51
  {{ [] in [true, []] ? 'TRUE' : 'FALSE' }}
52
 
53
+ {{ resource ? 'TRUE' : 'FALSE' }}
54
  {{ resource in 'foo'~resource ? 'TRUE' : 'FALSE' }}
55
  {{ object in 'stdClass' ? 'TRUE' : 'FALSE' }}
56
  {{ [] in 'Array' ? 'TRUE' : 'FALSE' }}
74
  {{ 5.5 in '125.5' ? 'TRUE' : 'FALSE' }}
75
  {{ '5.5' in 125.5 ? 'TRUE' : 'FALSE' }}
76
  --DATA--
77
+ return array('bar' => 'bar', 'foo' => array('bar' => 'bar'), 'dir_object' => new SplFileInfo(dirname(__FILE__)), 'object' => new stdClass(), 'resource' => opendir(dirname(__FILE__)))
78
  --EXPECT--
79
  TRUE
80
  TRUE
103
  FALSE
104
  TRUE
105
 
106
+ TRUE
107
  FALSE
108
  FALSE
109
  FALSE
vendor/twig/twig/test/Twig/Tests/LexerTest.php CHANGED
@@ -144,7 +144,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
144
 
145
  $lexer = new Twig_Lexer(new Twig_Environment());
146
  $stream = $lexer->tokenize($template);
147
- $node = $stream->next();
148
  $node = $stream->next();
149
  $this->assertEquals("922337203685477580700", $node->getValue());
150
  }
144
 
145
  $lexer = new Twig_Lexer(new Twig_Environment());
146
  $stream = $lexer->tokenize($template);
147
+ $stream->next();
148
  $node = $stream->next();
149
  $this->assertEquals("922337203685477580700", $node->getValue());
150
  }
vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php CHANGED
@@ -78,8 +78,8 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
78
  ), $loader->getPaths('named'));
79
 
80
  $this->assertEquals(
81
- $basePath.'/named_quater/named_absolute.html',
82
- $loader->getCacheKey('@named/named_absolute.html')
83
  );
84
  $this->assertEquals("path (final)\n", $loader->getSource('index.html'));
85
  $this->assertEquals("path (final)\n", $loader->getSource('@__main__/index.html'));
78
  ), $loader->getPaths('named'));
79
 
80
  $this->assertEquals(
81
+ realpath($basePath.'/named_quater/named_absolute.html'),
82
+ realpath($loader->getCacheKey('@named/named_absolute.html'))
83
  );
84
  $this->assertEquals("path (final)\n", $loader->getSource('index.html'));
85
  $this->assertEquals("path (final)\n", $loader->getSource('@__main__/index.html'));
vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php CHANGED
@@ -130,7 +130,7 @@ class __TwigTemplate_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b785
130
  EOF
131
  , $twig);
132
 
133
- $set = new Twig_Node_Set(false, new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 4))), new Twig_Node(array(new Twig_Node_Expression_Constant("foo", 4))), 4);
134
  $body = new Twig_Node(array($set));
135
  $extends = new Twig_Node_Expression_Conditional(
136
  new Twig_Node_Expression_Constant(true, 2),
130
  EOF
131
  , $twig);
132
 
133
+ $set = new Twig_Node_Set(false, new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 4))), new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 4))), 4);
134
  $body = new Twig_Node(array($set));
135
  $extends = new Twig_Node_Expression_Conditional(
136
  new Twig_Node_Expression_Constant(true, 2),
vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php CHANGED
@@ -13,32 +13,88 @@ abstract class Twig_Tests_Profiler_Dumper_AbstractTest extends PHPUnit_Framework
13
  {
14
  protected function getProfile()
15
  {
16
- $profile = new Twig_Profiler_Profile();
17
- $index = new Twig_Profiler_Profile('index.twig', Twig_Profiler_Profile::TEMPLATE);
18
- $profile->addProfile($index);
19
- $body = new Twig_Profiler_Profile('embedded.twig', Twig_Profiler_Profile::BLOCK, 'body');
20
- $body->leave();
21
- $index->addProfile($body);
22
- $embedded = new Twig_Profiler_Profile('embedded.twig', Twig_Profiler_Profile::TEMPLATE);
23
- $included = new Twig_Profiler_Profile('included.twig', Twig_Profiler_Profile::TEMPLATE);
24
- $embedded->addProfile($included);
25
- $index->addProfile($embedded);
26
- $included->leave();
27
- $embedded->leave();
28
-
29
- $macro = new Twig_Profiler_Profile('index.twig', Twig_Profiler_Profile::MACRO, 'foo');
30
- $macro->leave();
31
- $index->addProfile($macro);
32
-
33
- $embedded = clone $embedded;
34
- $index->addProfile($embedded);
35
- usleep(500);
36
- $embedded->leave();
37
-
38
- usleep(4500);
39
- $index->leave();
40
-
41
- $profile->leave();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
  return $profile;
44
  }
13
  {
14
  protected function getProfile()
15
  {
16
+ $profile = $this->getMockBuilder('Twig_Profiler_Profile')->disableOriginalConstructor()->getMock();
17
+
18
+ $profile->expects($this->any())->method('isRoot')->will($this->returnValue(true));
19
+ $profile->expects($this->any())->method('getName')->will($this->returnValue('main'));
20
+ $profile->expects($this->any())->method('getDuration')->will($this->returnValue(1));
21
+ $profile->expects($this->any())->method('getMemoryUsage')->will($this->returnValue(0));
22
+ $profile->expects($this->any())->method('getPeakMemoryUsage')->will($this->returnValue(0));
23
+
24
+ $subProfiles = array(
25
+ $this->getIndexProfile(
26
+ array(
27
+ $this->getEmbeddedBlockProfile(),
28
+ $this->getEmbeddedTemplateProfile(
29
+ array(
30
+ $this->getIncludedTemplateProfile(),
31
+ )
32
+ ),
33
+ $this->getMacroProfile(),
34
+ $this->getEmbeddedTemplateProfile(
35
+ array(
36
+ $this->getIncludedTemplateProfile(),
37
+ )
38
+ ),
39
+ )
40
+ ),
41
+ );
42
+
43
+ $profile->expects($this->any())->method('getProfiles')->will($this->returnValue($subProfiles));
44
+ $profile->expects($this->any())->method('getIterator')->will($this->returnValue(new ArrayIterator($subProfiles)));
45
+
46
+ return $profile;
47
+ }
48
+
49
+ private function getIndexProfile(array $subProfiles = array())
50
+ {
51
+ return $this->generateProfile('main', 1, true, 'template', 'index.twig', $subProfiles);
52
+ }
53
+
54
+ private function getEmbeddedBlockProfile(array $subProfiles = array())
55
+ {
56
+ return $this->generateProfile('body', 0.0001, false, 'block', 'embedded.twig', $subProfiles);
57
+ }
58
+
59
+ private function getEmbeddedTemplateProfile(array $subProfiles = array())
60
+ {
61
+ return $this->generateProfile('main', 0.0001, true, 'template', 'embedded.twig', $subProfiles);
62
+ }
63
+
64
+ private function getIncludedTemplateProfile(array $subProfiles = array())
65
+ {
66
+ return $this->generateProfile('main', 0.0001, true, 'template', 'included.twig', $subProfiles);
67
+ }
68
+
69
+ private function getMacroProfile(array $subProfiles = array())
70
+ {
71
+ return $this->generateProfile('foo', 0.0001, false, 'macro', 'index.twig', $subProfiles);
72
+ }
73
+
74
+ /**
75
+ * @param string $name
76
+ * @param float $duration
77
+ * @param bool $isTemplate
78
+ * @param string $type
79
+ * @param string $templateName
80
+ * @param array $subProfiles
81
+ *
82
+ * @return Twig_Profiler_Profile
83
+ */
84
+ private function generateProfile($name, $duration, $isTemplate, $type, $templateName, array $subProfiles = array())
85
+ {
86
+ $profile = $this->getMockBuilder('Twig_Profiler_Profile')->disableOriginalConstructor()->getMock();
87
+
88
+ $profile->expects($this->any())->method('isRoot')->will($this->returnValue(false));
89
+ $profile->expects($this->any())->method('getName')->will($this->returnValue($name));
90
+ $profile->expects($this->any())->method('getDuration')->will($this->returnValue($duration));
91
+ $profile->expects($this->any())->method('getMemoryUsage')->will($this->returnValue(0));
92
+ $profile->expects($this->any())->method('getPeakMemoryUsage')->will($this->returnValue(0));
93
+ $profile->expects($this->any())->method('isTemplate')->will($this->returnValue($isTemplate));
94
+ $profile->expects($this->any())->method('getType')->will($this->returnValue($type));
95
+ $profile->expects($this->any())->method('getTemplate')->will($this->returnValue($templateName));
96
+ $profile->expects($this->any())->method('getProfiles')->will($this->returnValue($subProfiles));
97
+ $profile->expects($this->any())->method('getIterator')->will($this->returnValue(new ArrayIterator($subProfiles)));
98
 
99
  return $profile;
100
  }
vendor/twig/twig/test/Twig/Tests/TemplateTest.php CHANGED
@@ -28,6 +28,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
28
 
29
  $context = array(
30
  'string' => 'foo',
 
31
  'empty_array' => array(),
32
  'array' => array('foo' => 'foo'),
33
  'array_access' => new Twig_TemplateArrayAccessObject(),
@@ -47,11 +48,14 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
47
  {
48
  $tests = array(
49
  array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1', false),
 
50
  array('{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1', false),
51
  array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
52
  array('{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
53
  array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1', false),
54
  array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1', false),
 
 
55
  array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1', false),
56
  array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
57
  array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1', false),
@@ -509,7 +513,7 @@ class Twig_TemplateMagicPropertyObjectWithException
509
  {
510
  public function __isset($key)
511
  {
512
- throw new Exception("Hey! Don't try to isset me!");
513
  }
514
  }
515
 
28
 
29
  $context = array(
30
  'string' => 'foo',
31
+ 'null' => null,
32
  'empty_array' => array(),
33
  'array' => array('foo' => 'foo'),
34
  'array_access' => new Twig_TemplateArrayAccessObject(),
48
  {
49
  $tests = array(
50
  array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1', false),
51
+ array('{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1', false),
52
  array('{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1', false),
53
  array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
54
  array('{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
55
  array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1', false),
56
  array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1', false),
57
+ array('{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1', false),
58
+ array('{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1', false),
59
  array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1', false),
60
  array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
61
  array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1', false),
513
  {
514
  public function __isset($key)
515
  {
516
+ throw new Exception('Hey! Don\'t try to isset me!');
517
  }
518
  }
519
 
vendor/twig/twig/test/Twig/Tests/escapingTest.php CHANGED
@@ -226,7 +226,8 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
226
  /**
227
  * Convert a Unicode Codepoint to a literal UTF-8 character.
228
  *
229
- * @param int $codepoint Unicode codepoint in hex notation
 
230
  * @return string UTF-8 literal string
231
  */
232
  protected function codepointToUtf8($codepoint)
226
  /**
227
  * Convert a Unicode Codepoint to a literal UTF-8 character.
228
  *
229
+ * @param int $codepoint Unicode codepoint in hex notation
230
+ *
231
  * @return string UTF-8 literal string
232
  */
233
  protected function codepointToUtf8($codepoint)