Version Description
- Much much much more inline docs
- Fix to TimberComment::approved()
- HHVM support confirmed (it always worked, but now the tests prove it)
- Fixes to multisite handling of themes
- Fix to comments pagination (thanks @newkind)
Download this release
Release Info
Developer | jarednova |
Plugin | Timber |
Version | 0.21.9 |
Comparing to | |
See all releases |
Code changes from version 0.21.8 to 0.21.9
- README.md +12 -1
- lib/cache/TimberKeyGeneratorInterface.php +3 -2
- lib/timber-archives.php +251 -243
- lib/timber-comment.php +18 -6
- lib/timber-helper.php +26 -23
- lib/timber-image.php +93 -26
- lib/timber-loader.php +1 -0
- lib/timber-menu-item.php +90 -49
- lib/timber-menu.php +72 -6
- lib/timber-post-getter.php +1 -1
- lib/timber-post.php +520 -220
- lib/timber-site.php +31 -8
- lib/timber-term.php +364 -327
- lib/timber-theme.php +115 -54
- lib/timber-twig.php +10 -27
- lib/timber-user.php +13 -2
- readme.txt +10 -3
- timber-starter-theme/search.php +1 -0
- timber.php +3 -2
- vendor/autoload.php +1 -1
- vendor/composer/ClassLoader.php +26 -0
- vendor/composer/LICENSE +21 -0
- vendor/composer/autoload_real.php +4 -4
- vendor/composer/installed.json +7 -7
- vendor/twig/twig/CHANGELOG +19 -0
- vendor/twig/twig/composer.json +1 -1
- vendor/twig/twig/doc/advanced.rst +21 -0
- vendor/twig/twig/doc/deprecated.rst +21 -0
- vendor/twig/twig/doc/filters/batch.rst +6 -0
- vendor/twig/twig/doc/functions/source.rst +11 -0
- vendor/twig/twig/doc/internals.rst +1 -1
- vendor/twig/twig/doc/intro.rst +5 -1
- vendor/twig/twig/doc/tags/macro.rst +3 -0
- vendor/twig/twig/doc/tags/use.rst +1 -1
- vendor/twig/twig/doc/templates.rst +5 -2
- vendor/twig/twig/ext/twig/php_twig.h +1 -1
- vendor/twig/twig/ext/twig/twig.c +33 -5
- vendor/twig/twig/lib/Twig/BaseNodeVisitor.php +62 -0
- vendor/twig/twig/lib/Twig/Environment.php +15 -13
- vendor/twig/twig/lib/Twig/ExpressionParser.php +7 -1
- vendor/twig/twig/lib/Twig/Extension/Core.php +52 -38
- vendor/twig/twig/lib/Twig/Extension/Debug.php +1 -1
- vendor/twig/twig/lib/Twig/Extension/Sandbox.php +1 -1
- vendor/twig/twig/lib/Twig/Filter.php +5 -4
- vendor/twig/twig/lib/Twig/Filter/Function.php +1 -0
- vendor/twig/twig/lib/Twig/Filter/Method.php +1 -0
- vendor/twig/twig/lib/Twig/Filter/Node.php +1 -0
- vendor/twig/twig/lib/Twig/FilterCallableInterface.php +1 -0
- vendor/twig/twig/lib/Twig/FilterInterface.php +1 -0
- vendor/twig/twig/lib/Twig/Function.php +3 -2
- vendor/twig/twig/lib/Twig/Function/Function.php +1 -0
- vendor/twig/twig/lib/Twig/Function/Method.php +1 -0
- vendor/twig/twig/lib/Twig/Function/Node.php +1 -0
- vendor/twig/twig/lib/Twig/FunctionCallableInterface.php +1 -0
- vendor/twig/twig/lib/Twig/FunctionInterface.php +1 -0
- vendor/twig/twig/lib/Twig/Lexer.php +24 -24
- vendor/twig/twig/lib/Twig/LoaderInterface.php +3 -3
- vendor/twig/twig/lib/Twig/Node/CheckSecurity.php +3 -3
- vendor/twig/twig/lib/Twig/Node/Embed.php +2 -2
- vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php +3 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Call.php +39 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Filter.php +3 -0
- vendor/twig/twig/lib/Twig/Node/Expression/Function.php +3 -0
- vendor/twig/twig/lib/Twig/Node/Expression/Name.php +1 -1
- vendor/twig/twig/lib/Twig/Node/Expression/Parent.php +3 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Test.php +3 -0
- vendor/twig/twig/lib/Twig/Node/For.php +1 -1
- vendor/twig/twig/lib/Twig/Node/If.php +1 -1
- vendor/twig/twig/lib/Twig/Node/Import.php +2 -2
- vendor/twig/twig/lib/Twig/Node/Include.php +2 -2
- vendor/twig/twig/lib/Twig/Node/Macro.php +43 -16
- vendor/twig/twig/lib/Twig/Node/Module.php +18 -18
- vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php +5 -15
- vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php +8 -8
- vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php +18 -3
- vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php +5 -15
- vendor/twig/twig/lib/Twig/Parser.php +15 -6
- vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php +1 -1
- vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php +3 -3
- vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php +3 -3
- vendor/twig/twig/lib/Twig/Profiler/Profile.php +1 -1
- vendor/twig/twig/lib/Twig/SimpleFilter.php +12 -6
- vendor/twig/twig/lib/Twig/SimpleFunction.php +10 -4
- vendor/twig/twig/lib/Twig/SimpleTest.php +6 -0
- vendor/twig/twig/lib/Twig/Template.php +38 -3
- vendor/twig/twig/lib/Twig/TemplateInterface.php +2 -2
- vendor/twig/twig/lib/Twig/Test.php +1 -0
- vendor/twig/twig/lib/Twig/Test/Function.php +1 -0
- vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php +12 -4
- vendor/twig/twig/lib/Twig/Test/Method.php +1 -0
- vendor/twig/twig/lib/Twig/Test/Node.php +1 -0
- vendor/twig/twig/lib/Twig/TestCallableInterface.php +1 -0
- vendor/twig/twig/lib/Twig/TestInterface.php +1 -0
- vendor/twig/twig/lib/Twig/Token.php +15 -15
- vendor/twig/twig/lib/Twig/TokenParser.php +1 -1
- vendor/twig/twig/lib/Twig/TokenParser/From.php +4 -0
- vendor/twig/twig/lib/Twig/TokenParserBroker.php +1 -0
- vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php +1 -0
- vendor/twig/twig/lib/Twig/TokenParserInterface.php +1 -1
- vendor/twig/twig/lib/Twig/TokenStream.php +7 -7
- vendor/twig/twig/test/Twig/Tests/CompilerTest.php +1 -1
- vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php +3 -3
- vendor/twig/twig/test/Twig/Tests/ErrorTest.php +1 -1
- vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php +10 -10
- vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php +6 -6
- vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_template_in_child_template.test +15 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_keys.test +10 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_zero_elements.test +10 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling.test +16 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test +13 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs.test +21 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test +8 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from_with_reserved_name.test +9 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/import_with_reserved_nam.test +11 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/reserved_name.test +10 -0
- vendor/twig/twig/test/Twig/Tests/IntegrationTest.php +2 -2
- vendor/twig/twig/test/Twig/Tests/LexerTest.php +2 -2
- vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php +2 -2
- vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php +15 -1
- vendor/twig/twig/test/Twig/Tests/Node/Expression/FilterTest.php +34 -1
- vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php +24 -1
- vendor/twig/twig/test/Twig/Tests/Node/Expression/TestTest.php +26 -0
- vendor/twig/twig/test/Twig/Tests/Node/MacroTest.php +10 -1
- vendor/twig/twig/test/Twig/Tests/ParserTest.php +1 -1
- vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php +3 -3
- vendor/twig/twig/test/Twig/Tests/TemplateTest.php +54 -40
- vendor/twig/twig/test/Twig/Tests/escapingTest.php +100 -100
README.md
CHANGED
@@ -8,6 +8,9 @@ By Jared Novack (<a href="http://twitter.com/jarednova">@JaredNova</a>) and <a h
|
|
8 |
[![Coverage Status](https://coveralls.io/repos/jarednova/timber/badge.svg?branch=master)](https://coveralls.io/r/jarednova/timber?branch=master)
|
9 |
[![Dependency Status](https://www.versioneye.com/user/projects/54e3c717d1ec5734f4000099/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54e3c717d1ec5734f4000099)
|
10 |
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/jarednova/timber/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/jarednova/timber/?branch=master)
|
|
|
|
|
|
|
11 |
|
12 |
### Because WordPress is awesome, but the_loop isn't
|
13 |
Timber helps you create fully-customized WordPress themes faster with more sustainable code. With Timber, you write your HTML using the [Twig Template Engine](http://twig.sensiolabs.org/) separate from your PHP files.
|
@@ -69,10 +72,18 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
69 |
* [**Twig**](https://github.com/fabpot/Twig) The template language used by Timber.
|
70 |
|
71 |
#### Should I use it?
|
72 |
-
It's
|
73 |
|
74 |
#### Contributing
|
75 |
Read the [contributor guidelines](https://github.com/jarednova/timber/wiki#contributing) in the wiki.
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
|
8 |
[![Coverage Status](https://coveralls.io/repos/jarednova/timber/badge.svg?branch=master)](https://coveralls.io/r/jarednova/timber?branch=master)
|
9 |
[![Dependency Status](https://www.versioneye.com/user/projects/54e3c717d1ec5734f4000099/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54e3c717d1ec5734f4000099)
|
10 |
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/jarednova/timber/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/jarednova/timber/?branch=master)
|
11 |
+
[![Latest Stable Version](https://poser.pugx.org/jarednova/timber/v/stable.svg)](https://packagist.org/packages/jarednova/timber)
|
12 |
+
[![WordPress Download Count](https://img.shields.io/wordpress/plugin/dt/timber-library.svg)](https://wordpress.org/plugins/timber-library/)
|
13 |
+
[![HHVM Status](http://hhvm.h4cc.de/badge/jarednova/timber.svg)](http://hhvm.h4cc.de/package/jarednova/timber)
|
14 |
|
15 |
### Because WordPress is awesome, but the_loop isn't
|
16 |
Timber helps you create fully-customized WordPress themes faster with more sustainable code. With Timber, you write your HTML using the [Twig Template Engine](http://twig.sensiolabs.org/) separate from your PHP files.
|
72 |
* [**Twig**](https://github.com/fabpot/Twig) The template language used by Timber.
|
73 |
|
74 |
#### Should I use it?
|
75 |
+
It's MIT-licensed, so please use in personal or commercial work. Just don't re-sell it. While Timber is still in development, it's also in-use on [hundreds of sites](http://jarednova.github.io/timber/#showcase). While much has been stabilized since the first major push back in June 2013, you should expect some breaking changes as development progresses towards a version 1.0.
|
76 |
|
77 |
#### Contributing
|
78 |
Read the [contributor guidelines](https://github.com/jarednova/timber/wiki#contributing) in the wiki.
|
79 |
|
80 |
+
## How To...
|
81 |
+
|
82 |
+
#### Generate documentation
|
83 |
+
```bash
|
84 |
+
$ cd /srv/www/timber
|
85 |
+
$ ./bin/generate-docs.sh
|
86 |
+
```
|
87 |
+
|
88 |
|
89 |
|
lib/cache/TimberKeyGeneratorInterface.php
CHANGED
@@ -2,7 +2,8 @@
|
|
2 |
|
3 |
namespace Timber\Cache;
|
4 |
|
5 |
-
interface TimberKeyGeneratorInterface
|
6 |
-
|
7 |
public function _get_cache_key();
|
|
|
8 |
}
|
2 |
|
3 |
namespace Timber\Cache;
|
4 |
|
5 |
+
interface TimberKeyGeneratorInterface {
|
6 |
+
|
7 |
public function _get_cache_key();
|
8 |
+
|
9 |
}
|
lib/timber-archives.php
CHANGED
@@ -1,266 +1,274 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class TimberArchives extends TimberCore
|
4 |
-
{
|
5 |
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
|
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
|
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
|
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
|
|
123 |
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
|
157 |
-
|
158 |
-
|
159 |
|
160 |
-
|
161 |
-
|
162 |
|
163 |
-
|
164 |
-
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
|
176 |
-
|
177 |
-
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
|
266 |
}
|
1 |
<?php
|
2 |
|
3 |
+
class TimberArchives extends TimberCore {
|
|
|
4 |
|
5 |
+
public $base = '';
|
6 |
+
/**
|
7 |
+
* @api
|
8 |
+
* @var array the items of the archives to iterate through and markup for your page
|
9 |
+
*/
|
10 |
+
public $items;
|
11 |
|
12 |
+
function __construct( $args = null, $base = '' ) {
|
13 |
+
$this->init($args, $base);
|
14 |
+
}
|
15 |
|
16 |
+
/**
|
17 |
+
* @internal
|
18 |
+
* @param array|string $args
|
19 |
+
* @param string $base
|
20 |
+
*/
|
21 |
+
function init( $args = null, $base = '' ) {
|
22 |
+
$this->base = $base;
|
23 |
+
$this->items = $this->get_items($args);
|
24 |
+
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @internal
|
28 |
+
* @param string $url
|
29 |
+
* @param string $text
|
30 |
+
* @return mixed
|
31 |
+
*/
|
32 |
+
protected function get_archives_link( $url, $text ) {
|
33 |
+
$ret = array();
|
34 |
+
$ret['text'] = $ret['title'] = $ret['name'] = wptexturize($text);
|
35 |
+
$ret['url'] = $ret['link'] = esc_url(TimberURLHelper::prepend_to_url($url, $this->base));
|
36 |
+
return $ret;
|
37 |
+
}
|
38 |
|
39 |
+
/**
|
40 |
+
* @internal
|
41 |
+
* @param array|string $args
|
42 |
+
* @param string $last_changed
|
43 |
+
* @param string $join
|
44 |
+
* @param string $where
|
45 |
+
* @param string $order
|
46 |
+
* @param string $limit
|
47 |
+
* @return array
|
48 |
+
*/
|
49 |
+
protected function get_items_yearly( $args, $last_changed, $join, $where, $order, $limit ) {
|
50 |
+
global $wpdb;
|
51 |
+
$output = array();
|
52 |
+
$query = "SELECT YEAR(post_date) AS `year`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date) ORDER BY post_date $order $limit";
|
53 |
+
$key = md5($query);
|
54 |
+
$key = "wp_get_archives:$key:$last_changed";
|
55 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
56 |
+
$results = $wpdb->get_results($query);
|
57 |
+
wp_cache_set($key, $results, 'posts');
|
58 |
+
}
|
59 |
+
if ($results) {
|
60 |
+
foreach ((array)$results as $result) {
|
61 |
+
$url = get_year_link($result->year);
|
62 |
+
$text = sprintf('%d', $result->year);
|
63 |
+
$output[] = $this->get_archives_link($url, $text);
|
64 |
+
}
|
65 |
+
}
|
66 |
+
return $output;
|
67 |
+
}
|
68 |
|
69 |
+
/**
|
70 |
+
* @internal
|
71 |
+
* @param array|string $args
|
72 |
+
* @param string $last_changed
|
73 |
+
* @param string $join
|
74 |
+
* @param string $where
|
75 |
+
* @param string $order
|
76 |
+
* @param int $limit
|
77 |
+
* @param bool $nested
|
78 |
+
* @return array
|
79 |
+
*/
|
80 |
+
protected function get_items_monthly( $args, $last_changed, $join, $where, $order, $limit = 1000, $nested = true ) {
|
81 |
+
global $wpdb, $wp_locale;
|
82 |
+
$output = array();
|
83 |
+
$defaults = array(
|
84 |
+
'show_year' => false,
|
85 |
+
);
|
86 |
+
$r = wp_parse_args($args, $defaults);
|
87 |
|
88 |
+
$show_year = $r['show_year'];
|
89 |
+
//will need to specify which year we're looking for
|
90 |
+
$query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts "
|
91 |
+
. "FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) "
|
92 |
+
. "ORDER BY post_date $order $limit";
|
93 |
+
$key = md5($query);
|
94 |
+
$key = "wp_get_archives:$key:$last_changed";
|
95 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
96 |
+
$results = $wpdb->get_results($query);
|
97 |
+
wp_cache_set($key, $results, 'posts');
|
98 |
+
}
|
99 |
+
if ($results) {
|
100 |
+
foreach ((array)$results as $result) {
|
101 |
+
$url = get_month_link($result->year, $result->month);
|
102 |
+
if ($show_year && !$nested) {
|
103 |
+
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($result->month), $result->year);
|
104 |
+
} else {
|
105 |
+
$text = sprintf(__('%1$s'), $wp_locale->get_month($result->month));
|
106 |
+
}
|
107 |
+
if ($nested) {
|
108 |
+
$output[$result->year][] = $this->get_archives_link($url, $text);
|
109 |
+
} else {
|
110 |
+
$output[] = $this->get_archives_link($url, $text);
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
114 |
+
if ($nested) {
|
115 |
+
$out2 = array();
|
116 |
+
foreach ($output as $year => $months) {
|
117 |
+
$out2[] = array('name' => $year, 'children' => $months);
|
118 |
+
}
|
119 |
+
return $out2;
|
120 |
+
}
|
121 |
+
return $output;
|
122 |
+
}
|
123 |
|
124 |
+
/**
|
125 |
+
* @api
|
126 |
+
* @param array|string $args
|
127 |
+
* @return array|string
|
128 |
+
*/
|
129 |
+
function get_items( $args = null ) {
|
130 |
+
global $wpdb;
|
131 |
|
132 |
+
$defaults = array(
|
133 |
+
'type' => 'monthly-nested',
|
134 |
+
'limit' => '',
|
135 |
+
'show_post_count' => false,
|
136 |
+
'order' => 'DESC',
|
137 |
+
'post_type' => 'post',
|
138 |
+
'show_year' => false,
|
139 |
+
'nested' => false
|
140 |
+
);
|
141 |
|
142 |
+
$args = wp_parse_args($args, $defaults);
|
143 |
+
$post_type = $args['post_type'];
|
144 |
+
$order = $args['order'];
|
145 |
+
$nested = $args['nested'];
|
146 |
+
$type = $args['type'];
|
147 |
+
$limit = '';
|
148 |
+
if ( $type == 'yearlymonthly' || $type == 'yearmonth' ) {
|
149 |
+
$type = 'monthly-nested';
|
150 |
+
}
|
151 |
+
if ( $type == 'monthly-nested' ) {
|
152 |
+
$nested = true;
|
153 |
+
}
|
154 |
|
155 |
+
if ( !empty($args['limit']) ) {
|
156 |
+
$limit = absint($limit);
|
157 |
+
$limit = ' LIMIT ' . $limit;
|
158 |
+
}
|
159 |
|
160 |
+
$order = strtoupper($order);
|
161 |
+
if ( $order !== 'ASC' ) {
|
162 |
+
$order = 'DESC';
|
163 |
+
}
|
164 |
|
165 |
+
// this is what will separate dates on weekly archive links
|
166 |
+
$archive_week_separator = '–';
|
167 |
|
168 |
+
// over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride
|
169 |
+
$archive_date_format_over_ride = 0;
|
170 |
|
171 |
+
// options for daily archive (only if you over-ride the general date format)
|
172 |
+
$archive_day_date_format = 'Y/m/d';
|
173 |
|
174 |
+
// options for weekly archive (only if you over-ride the general date format)
|
175 |
+
$archive_week_start_date_format = 'Y/m/d';
|
176 |
+
$archive_week_end_date_format = 'Y/m/d';
|
177 |
|
178 |
+
if (!$archive_date_format_over_ride) {
|
179 |
+
$archive_day_date_format = get_option('date_format');
|
180 |
+
$archive_week_start_date_format = get_option('date_format');
|
181 |
+
$archive_week_end_date_format = get_option('date_format');
|
182 |
+
}
|
183 |
|
184 |
+
$where = apply_filters('getarchives_where', 'WHERE post_type = "' . $post_type . '" AND post_status = "publish"', $args);
|
185 |
+
$join = apply_filters('getarchives_join', '', $args);
|
186 |
|
187 |
+
$output = array();
|
188 |
+
$last_changed = wp_cache_get('last_changed', 'posts');
|
189 |
+
if (!$last_changed) {
|
190 |
+
$last_changed = microtime();
|
191 |
+
wp_cache_set('last_changed', $last_changed, 'posts');
|
192 |
+
}
|
193 |
+
if ( 'monthly' == $type ) {
|
194 |
+
$output = $this->get_items_monthly($args, $last_changed, $join, $where, $order, $limit, $nested);
|
195 |
+
} elseif ( 'yearly' == $type ) {
|
196 |
+
$output = $this->get_items_yearly($args, $last_changed, $join, $where, $order, $limit);
|
197 |
+
} elseif ( 'monthly-nested' == $type ) {
|
198 |
+
$years = $this->get_items_yearly($args, $last_changed, $join, $where, $order, $limit);
|
199 |
+
foreach ( $years as &$year ) {
|
200 |
+
$args = array('show_year' => false);
|
201 |
+
$year['children'] = $this->get_items_monthly($args, $last_changed, $join, $where, $order, $limit);
|
202 |
+
}
|
203 |
+
$output = $years;
|
204 |
+
} elseif ( 'daily' == $type ) {
|
205 |
+
$query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date), DAYOFMONTH(post_date) ORDER BY post_date $order $limit";
|
206 |
+
$key = md5($query);
|
207 |
+
$key = "wp_get_archives:$key:$last_changed";
|
208 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
209 |
+
$results = $wpdb->get_results($query);
|
210 |
+
$cache = array();
|
211 |
+
$cache[$key] = $results;
|
212 |
+
wp_cache_set($key, $results, 'posts');
|
213 |
+
}
|
214 |
+
if ( $results ) {
|
215 |
+
foreach ( (array)$results as $result ) {
|
216 |
+
$url = get_day_link($result->year, $result->month, $result->dayofmonth);
|
217 |
+
$date = sprintf('%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth);
|
218 |
+
$text = mysql2date($archive_day_date_format, $date);
|
219 |
+
$output[] = $this->get_archives_link($url, $text);
|
220 |
+
}
|
221 |
+
}
|
222 |
+
} elseif ( 'weekly' == $type ) {
|
223 |
+
$week = _wp_mysql_week('`post_date`');
|
224 |
+
$query = "SELECT DISTINCT $week AS `week`, YEAR( `post_date` ) AS `yr`, DATE_FORMAT( `post_date`, '%Y-%m-%d' ) AS `yyyymmdd`, "
|
225 |
+
. "count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
|
226 |
+
$key = md5($query);
|
227 |
+
$key = "wp_get_archives:$key:$last_changed";
|
228 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
229 |
+
$results = $wpdb->get_results($query);
|
230 |
+
wp_cache_set($key, $results, 'posts');
|
231 |
+
}
|
232 |
+
$arc_w_last = '';
|
233 |
+
if ( $results ) {
|
234 |
+
foreach ( (array)$results as $result ) {
|
235 |
+
if ( $result->week != $arc_w_last ) {
|
236 |
+
$arc_year = $result->yr;
|
237 |
+
$arc_w_last = $result->week;
|
238 |
+
$arc_week = get_weekstartend($result->yyyymmdd, get_option('start_of_week'));
|
239 |
+
$arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']);
|
240 |
+
$arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']);
|
241 |
+
$url = sprintf('%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&', '=', $result->week);
|
242 |
+
$text = $arc_week_start . $archive_week_separator . $arc_week_end;
|
243 |
+
$output[] = $this->get_archives_link($url, $text);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
}
|
247 |
+
} elseif ( 'postbypost' == $type || 'alpha' == $type ) {
|
248 |
+
$orderby = 'alpha' == $type ? 'post_title ASC ' : 'post_date DESC ';
|
249 |
+
$query = "SELECT * FROM $wpdb->posts $join $where ORDER BY $orderby $limit";
|
250 |
+
$key = md5($query);
|
251 |
+
$key = "wp_get_archives:$key:$last_changed";
|
252 |
+
if ( !$results = wp_cache_get($key, 'posts') ) {
|
253 |
+
$results = $wpdb->get_results($query);
|
254 |
+
wp_cache_set($key, $results, 'posts');
|
255 |
+
}
|
256 |
+
if ( $results ) {
|
257 |
+
foreach ( (array)$results as $result ) {
|
258 |
+
if ($result->post_date != '0000-00-00 00:00:00') {
|
259 |
+
$url = get_permalink($result);
|
260 |
+
if ($result->post_title) {
|
261 |
+
/** This filter is documented in wp-includes/post-template.php */
|
262 |
+
$text = strip_tags(apply_filters('the_title', $result->post_title, $result->ID));
|
263 |
+
} else {
|
264 |
+
$text = $result->ID;
|
265 |
+
}
|
266 |
+
$output[] = $this->get_archives_link($url, $text);
|
267 |
+
}
|
268 |
+
}
|
269 |
+
}
|
270 |
+
}
|
271 |
+
return $output;
|
272 |
+
}
|
273 |
|
274 |
}
|
lib/timber-comment.php
CHANGED
@@ -30,6 +30,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
30 |
}
|
31 |
|
32 |
/**
|
|
|
33 |
* @param integer $cid
|
34 |
*/
|
35 |
function init($cid) {
|
@@ -45,6 +46,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
45 |
}
|
46 |
|
47 |
/**
|
|
|
48 |
* @return TimberUser
|
49 |
*/
|
50 |
public function author() {
|
@@ -94,24 +96,29 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
94 |
}
|
95 |
|
96 |
/**
|
|
|
97 |
* @return string
|
98 |
*/
|
99 |
public function content() {
|
100 |
-
return $this->comment_content;
|
101 |
}
|
102 |
|
103 |
/**
|
104 |
-
* @
|
|
|
105 |
*/
|
106 |
-
public function
|
107 |
-
return $this->
|
108 |
}
|
109 |
|
110 |
/**
|
|
|
111 |
* @return string
|
112 |
*/
|
113 |
-
public function date() {
|
114 |
-
|
|
|
|
|
115 |
}
|
116 |
|
117 |
/**
|
@@ -123,6 +130,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
123 |
}
|
124 |
|
125 |
/**
|
|
|
126 |
* @return bool
|
127 |
*/
|
128 |
public function is_child() {
|
@@ -166,6 +174,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
166 |
======================= */
|
167 |
|
168 |
/**
|
|
|
169 |
* @return string
|
170 |
*/
|
171 |
protected function avatar_email() {
|
@@ -180,6 +189,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
180 |
}
|
181 |
|
182 |
/**
|
|
|
183 |
* @param string $email_hash
|
184 |
* @return string
|
185 |
*/
|
@@ -197,6 +207,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
197 |
}
|
198 |
|
199 |
/**
|
|
|
200 |
* @todo what if it's relative?
|
201 |
* @param string $default
|
202 |
* @param string $email
|
@@ -233,6 +244,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
233 |
}
|
234 |
|
235 |
/**
|
|
|
236 |
* @param string $default
|
237 |
* @param string $host
|
238 |
* @param string $email_hash
|
30 |
}
|
31 |
|
32 |
/**
|
33 |
+
* @internal
|
34 |
* @param integer $cid
|
35 |
*/
|
36 |
function init($cid) {
|
46 |
}
|
47 |
|
48 |
/**
|
49 |
+
* @api
|
50 |
* @return TimberUser
|
51 |
*/
|
52 |
public function author() {
|
96 |
}
|
97 |
|
98 |
/**
|
99 |
+
* @api
|
100 |
* @return string
|
101 |
*/
|
102 |
public function content() {
|
103 |
+
return apply_filters('get_comment_text ', $this->comment_content);
|
104 |
}
|
105 |
|
106 |
/**
|
107 |
+
* @api
|
108 |
+
* @return boolean
|
109 |
*/
|
110 |
+
public function approved() {
|
111 |
+
return $this->comment_approved;
|
112 |
}
|
113 |
|
114 |
/**
|
115 |
+
* @api
|
116 |
* @return string
|
117 |
*/
|
118 |
+
public function date( $date_format = '' ) {
|
119 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
120 |
+
$the_date = (string)mysql2date($df, $this->comment_date);
|
121 |
+
return apply_filters('get_comment_date ', $the_date, $df);
|
122 |
}
|
123 |
|
124 |
/**
|
130 |
}
|
131 |
|
132 |
/**
|
133 |
+
* @api
|
134 |
* @return bool
|
135 |
*/
|
136 |
public function is_child() {
|
174 |
======================= */
|
175 |
|
176 |
/**
|
177 |
+
* @internal
|
178 |
* @return string
|
179 |
*/
|
180 |
protected function avatar_email() {
|
189 |
}
|
190 |
|
191 |
/**
|
192 |
+
* @internal
|
193 |
* @param string $email_hash
|
194 |
* @return string
|
195 |
*/
|
207 |
}
|
208 |
|
209 |
/**
|
210 |
+
* @internal
|
211 |
* @todo what if it's relative?
|
212 |
* @param string $default
|
213 |
* @param string $email
|
244 |
}
|
245 |
|
246 |
/**
|
247 |
+
* @internal
|
248 |
* @param string $default
|
249 |
* @param string $host
|
250 |
* @param string $email_hash
|
lib/timber-helper.php
CHANGED
@@ -3,12 +3,22 @@
|
|
3 |
class TimberHelper {
|
4 |
|
5 |
/**
|
6 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
*
|
8 |
* @param string $slug Unique identifier for transient
|
9 |
-
* @param callable $callback
|
10 |
* @param int $transient_time (optional) Expiration of transients in seconds
|
11 |
-
* @param int $lock_timeout (optional) How long to lock the transient to prevent race conditions
|
12 |
* @param bool $force (optional) Force callback to be executed when transient is locked
|
13 |
* @return mixed
|
14 |
*/
|
@@ -52,24 +62,27 @@ class TimberHelper {
|
|
52 |
}
|
53 |
|
54 |
/**
|
|
|
55 |
* @param string $slug
|
56 |
* @param integer $lock_timeout
|
57 |
*/
|
58 |
-
|
59 |
set_transient( $slug . '_lock', true, $lock_timeout );
|
60 |
}
|
61 |
|
62 |
/**
|
|
|
63 |
* @param string $slug
|
64 |
*/
|
65 |
-
|
66 |
delete_transient( $slug . '_lock', true );
|
67 |
}
|
68 |
|
69 |
/**
|
|
|
70 |
* @param string $slug
|
71 |
*/
|
72 |
-
|
73 |
return (bool)get_transient( $slug . '_lock' );
|
74 |
}
|
75 |
|
@@ -172,13 +185,13 @@ class TimberHelper {
|
|
172 |
* @param string $allowed_tags
|
173 |
* @return string
|
174 |
*/
|
175 |
-
public static function trim_words( $text, $num_words = 55, $more = null, $allowed_tags = 'p a span b i br' ) {
|
176 |
if ( null === $more ) {
|
177 |
$more = __( '…' );
|
178 |
}
|
179 |
$original_text = $text;
|
180 |
$allowed_tag_string = '';
|
181 |
-
foreach ( explode( ' ', $allowed_tags ) as $tag ) {
|
182 |
$allowed_tag_string .= '<' . $tag . '>';
|
183 |
}
|
184 |
$text = strip_tags( $text, $allowed_tag_string );
|
@@ -299,7 +312,7 @@ class TimberHelper {
|
|
299 |
|
300 |
/**
|
301 |
*
|
302 |
-
*
|
303 |
* @param int $ttid
|
304 |
* @return mixed
|
305 |
*/
|
@@ -462,15 +475,12 @@ class TimberHelper {
|
|
462 |
/* Links, Forms, Etc. Utilities
|
463 |
======================== */
|
464 |
|
465 |
-
/* this $args thing is a fucking mess, fix at some point:
|
466 |
-
|
467 |
-
http://codex.wordpress.org/Function_Reference/comment_form */
|
468 |
-
|
469 |
/**
|
470 |
*
|
471 |
-
*
|
472 |
-
* @
|
473 |
-
* @param
|
|
|
474 |
* @return string
|
475 |
*/
|
476 |
public static function get_comment_form( $post_id = null, $args = array() ) {
|
@@ -579,13 +589,6 @@ class TimberHelper {
|
|
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 |
*/
|
3 |
class TimberHelper {
|
4 |
|
5 |
/**
|
6 |
+
* A utility for a one-stop shop for Transients
|
7 |
+
* @api
|
8 |
+
* @example
|
9 |
+
* ```php
|
10 |
+
* $favorites = Timber::transient('user-'.$uid.'-favorites', function() use ($uid) {
|
11 |
+
* //some expensive query here that's doing something you want to store to a transient
|
12 |
+
* return $favorites;
|
13 |
+
* }, 600);
|
14 |
+
* Timber::context['favorites'] = $favorites;
|
15 |
+
* Timber::render('single.twig', $context);
|
16 |
+
* ```
|
17 |
*
|
18 |
* @param string $slug Unique identifier for transient
|
19 |
+
* @param callable $callback Callback that generates the data that's to be cached
|
20 |
* @param int $transient_time (optional) Expiration of transients in seconds
|
21 |
+
* @param int $lock_timeout (optional) How long (in seconds) to lock the transient to prevent race conditions
|
22 |
* @param bool $force (optional) Force callback to be executed when transient is locked
|
23 |
* @return mixed
|
24 |
*/
|
62 |
}
|
63 |
|
64 |
/**
|
65 |
+
* @internal
|
66 |
* @param string $slug
|
67 |
* @param integer $lock_timeout
|
68 |
*/
|
69 |
+
static function _lock_transient( $slug, $lock_timeout ) {
|
70 |
set_transient( $slug . '_lock', true, $lock_timeout );
|
71 |
}
|
72 |
|
73 |
/**
|
74 |
+
* @internal
|
75 |
* @param string $slug
|
76 |
*/
|
77 |
+
static function _unlock_transient( $slug ) {
|
78 |
delete_transient( $slug . '_lock', true );
|
79 |
}
|
80 |
|
81 |
/**
|
82 |
+
* @internal
|
83 |
* @param string $slug
|
84 |
*/
|
85 |
+
static function _is_transient_locked( $slug ) {
|
86 |
return (bool)get_transient( $slug . '_lock' );
|
87 |
}
|
88 |
|
185 |
* @param string $allowed_tags
|
186 |
* @return string
|
187 |
*/
|
188 |
+
public static function trim_words( $text, $num_words = 55, $more = null, $allowed_tags = 'p a span b i br blockquote' ) {
|
189 |
if ( null === $more ) {
|
190 |
$more = __( '…' );
|
191 |
}
|
192 |
$original_text = $text;
|
193 |
$allowed_tag_string = '';
|
194 |
+
foreach ( explode( ' ', apply_filters( 'timber/trim_words/allowed_tags', $allowed_tags ) ) as $tag ) {
|
195 |
$allowed_tag_string .= '<' . $tag . '>';
|
196 |
}
|
197 |
$text = strip_tags( $text, $allowed_tag_string );
|
312 |
|
313 |
/**
|
314 |
*
|
315 |
+
* @deprecated since 0.21.8
|
316 |
* @param int $ttid
|
317 |
* @return mixed
|
318 |
*/
|
475 |
/* Links, Forms, Etc. Utilities
|
476 |
======================== */
|
477 |
|
|
|
|
|
|
|
|
|
478 |
/**
|
479 |
*
|
480 |
+
* Gets the comment form for use on a single article page
|
481 |
+
* @deprecated since 0.21.8
|
482 |
+
* @param int $post_id which post_id should the form be tied to?
|
483 |
+
* @param array $args this $args thing is a fucking mess, [fix at some point](http://codex.wordpress.org/Function_Reference/comment_form)
|
484 |
* @return string
|
485 |
*/
|
486 |
public static function get_comment_form( $post_id = null, $args = array() ) {
|
589 |
return $page_links;
|
590 |
}
|
591 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
592 |
/**
|
593 |
* @deprecated since 0.18.0
|
594 |
*/
|
lib/timber-image.php
CHANGED
@@ -2,32 +2,44 @@
|
|
2 |
|
3 |
class TimberImage extends TimberPost implements TimberCoreInterface {
|
4 |
|
5 |
-
|
6 |
-
|
7 |
public $abs_url;
|
8 |
-
|
|
|
|
|
9 |
public $object_type = 'image';
|
10 |
-
|
|
|
|
|
11 |
public static $representation = 'image';
|
12 |
-
|
|
|
|
|
|
|
13 |
public $file_loc;
|
14 |
public $file;
|
15 |
public $sizes = array();
|
16 |
-
|
|
|
|
|
17 |
public $caption;
|
18 |
-
|
|
|
|
|
|
|
19 |
|
20 |
/**
|
21 |
* @param int $iid
|
22 |
*/
|
23 |
-
function __construct($iid) {
|
24 |
$this->init($iid);
|
25 |
}
|
26 |
|
27 |
/**
|
28 |
* @return string
|
29 |
*/
|
30 |
-
function __toString() {
|
31 |
if ($this->get_src()) {
|
32 |
return $this->get_src();
|
33 |
}
|
@@ -35,6 +47,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
35 |
}
|
36 |
|
37 |
/**
|
|
|
38 |
* @return mixed
|
39 |
*/
|
40 |
function get_pathinfo() {
|
@@ -57,6 +70,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
57 |
}
|
58 |
|
59 |
/**
|
|
|
60 |
* @param string|null $dim
|
61 |
* @return array|int
|
62 |
*/
|
@@ -74,6 +88,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
74 |
}
|
75 |
|
76 |
/**
|
|
|
77 |
* @return int
|
78 |
*/
|
79 |
function get_width() {
|
@@ -81,6 +96,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
81 |
}
|
82 |
|
83 |
/**
|
|
|
84 |
* @return int
|
85 |
*/
|
86 |
function get_height() {
|
@@ -88,40 +104,45 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
88 |
}
|
89 |
|
90 |
/**
|
|
|
91 |
* @param string $size
|
92 |
* @return bool|string
|
93 |
*/
|
94 |
function get_src( $size = '' ) {
|
95 |
-
if (isset($this->abs_url)) {
|
96 |
return $this->_maybe_secure_url($this->abs_url);
|
97 |
}
|
98 |
|
99 |
-
if ($size && is_string($size) && isset($this->sizes[$size])) {
|
100 |
$image = image_downsize($this->ID, $size);
|
101 |
return $this->_maybe_secure_url(reset($image));
|
102 |
}
|
103 |
|
104 |
-
if (!isset($this->file) && isset($this->_wp_attached_file)) {
|
105 |
$this->file = $this->_wp_attached_file;
|
106 |
}
|
107 |
|
108 |
-
if (!isset($this->file)) {
|
109 |
return false;
|
110 |
}
|
111 |
|
112 |
$dir = self::wp_upload_dir();
|
113 |
-
$base =
|
114 |
|
115 |
$src = trailingslashit($this->_maybe_secure_url($base)) . $this->file;
|
116 |
$src = apply_filters('timber/image/src', $src, $this->ID);
|
117 |
return apply_filters('timber_image_src', $src, $this->ID);
|
118 |
}
|
119 |
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
121 |
if (is_ssl() && strpos($url, 'https') !== 0 && strpos($url, 'http') === 0) {
|
122 |
$url = 'https' . substr($url, strlen('http'));
|
123 |
}
|
124 |
-
|
125 |
return $url;
|
126 |
}
|
127 |
|
@@ -136,6 +157,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
136 |
}
|
137 |
|
138 |
/**
|
|
|
139 |
* @return string
|
140 |
*/
|
141 |
function get_path() {
|
@@ -146,15 +168,38 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
146 |
}
|
147 |
|
148 |
/**
|
149 |
-
* @
|
|
|
150 |
*/
|
151 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
if (!$this->post_parent) {
|
153 |
return false;
|
154 |
}
|
155 |
return new $this->PostClass($this->post_parent);
|
156 |
}
|
157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
function get_alt() {
|
159 |
$alt = trim(strip_tags(get_post_meta($this->ID, '_wp_attachment_image_alt', true)));
|
160 |
return $alt;
|
@@ -162,6 +207,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
162 |
|
163 |
|
164 |
/**
|
|
|
165 |
* @param int $iid
|
166 |
*/
|
167 |
function init( $iid = false ) {
|
@@ -211,7 +257,11 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
211 |
}
|
212 |
}
|
213 |
|
214 |
-
|
|
|
|
|
|
|
|
|
215 |
$image_info = $iid;
|
216 |
if (is_numeric($iid)) {
|
217 |
$image_info = wp_get_attachment_metadata($iid);
|
@@ -237,14 +287,22 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
237 |
return $iid;
|
238 |
}
|
239 |
|
240 |
-
|
|
|
|
|
|
|
|
|
241 |
$this->abs_url = home_url( $relative_path );
|
242 |
$file_path = TimberURLHelper::get_full_path( $relative_path );
|
243 |
$this->file_loc = $file_path;
|
244 |
$this->file = $file_path;
|
245 |
}
|
246 |
|
247 |
-
|
|
|
|
|
|
|
|
|
248 |
$url = TimberURLHelper::file_system_to_url( $file_path );
|
249 |
$this->abs_url = $url;
|
250 |
$this->file_loc = $file_path;
|
@@ -252,9 +310,10 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
252 |
}
|
253 |
|
254 |
/**
|
|
|
255 |
* @param string $url
|
256 |
*/
|
257 |
-
|
258 |
$this->abs_url = $url;
|
259 |
if (TimberURLHelper::is_local($url)) {
|
260 |
$this->file = ABSPATH . TimberURLHelper::get_rel_url($url);
|
@@ -263,7 +322,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
263 |
}
|
264 |
|
265 |
/**
|
266 |
-
* @deprecated
|
267 |
* @return string
|
268 |
*/
|
269 |
function get_url() {
|
@@ -271,16 +330,20 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
271 |
}
|
272 |
|
273 |
/**
|
274 |
-
* @deprecated
|
275 |
* @return string
|
276 |
*/
|
277 |
function url() {
|
278 |
return $this->get_src();
|
279 |
}
|
280 |
|
281 |
-
/* Alias */
|
282 |
-
|
283 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
* @return float
|
285 |
*/
|
286 |
public function aspect() {
|
@@ -290,6 +353,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
290 |
}
|
291 |
|
292 |
/**
|
|
|
293 |
* @return int
|
294 |
*/
|
295 |
public function height() {
|
@@ -297,6 +361,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
297 |
}
|
298 |
|
299 |
/**
|
|
|
300 |
* @param string $size
|
301 |
* @return bool|string
|
302 |
*/
|
@@ -305,6 +370,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
305 |
}
|
306 |
|
307 |
/**
|
|
|
308 |
* @return int
|
309 |
*/
|
310 |
public function width() {
|
@@ -312,6 +378,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
312 |
}
|
313 |
|
314 |
/**
|
|
|
315 |
* @return string alt text stored in WordPress
|
316 |
*/
|
317 |
public function alt() {
|
2 |
|
3 |
class TimberImage extends TimberPost implements TimberCoreInterface {
|
4 |
|
5 |
+
protected $_can_edit;
|
6 |
+
protected $_dimensions;
|
7 |
public $abs_url;
|
8 |
+
/**
|
9 |
+
* @var string $object_type what does this class represent in WordPress terms?
|
10 |
+
*/
|
11 |
public $object_type = 'image';
|
12 |
+
/**
|
13 |
+
* @var string $representation what does this class represent in WordPress terms?
|
14 |
+
*/
|
15 |
public static $representation = 'image';
|
16 |
+
/**
|
17 |
+
* @api
|
18 |
+
* @var string $file_loc the location of the image file in the filesystem (ex: `/var/www/htdocs/wp-content/uploads/2015/08/my-pic.jpg`)
|
19 |
+
*/
|
20 |
public $file_loc;
|
21 |
public $file;
|
22 |
public $sizes = array();
|
23 |
+
/**
|
24 |
+
* @var string $caption the string stored in the WordPress database
|
25 |
+
*/
|
26 |
public $caption;
|
27 |
+
/**
|
28 |
+
* @var $_wp_attached_file the file as stored in the WordPress database
|
29 |
+
*/
|
30 |
+
protected $_wp_attached_file;
|
31 |
|
32 |
/**
|
33 |
* @param int $iid
|
34 |
*/
|
35 |
+
public function __construct($iid) {
|
36 |
$this->init($iid);
|
37 |
}
|
38 |
|
39 |
/**
|
40 |
* @return string
|
41 |
*/
|
42 |
+
public function __toString() {
|
43 |
if ($this->get_src()) {
|
44 |
return $this->get_src();
|
45 |
}
|
47 |
}
|
48 |
|
49 |
/**
|
50 |
+
* @internal
|
51 |
* @return mixed
|
52 |
*/
|
53 |
function get_pathinfo() {
|
70 |
}
|
71 |
|
72 |
/**
|
73 |
+
* @internal
|
74 |
* @param string|null $dim
|
75 |
* @return array|int
|
76 |
*/
|
88 |
}
|
89 |
|
90 |
/**
|
91 |
+
* @internal
|
92 |
* @return int
|
93 |
*/
|
94 |
function get_width() {
|
96 |
}
|
97 |
|
98 |
/**
|
99 |
+
* @internal
|
100 |
* @return int
|
101 |
*/
|
102 |
function get_height() {
|
104 |
}
|
105 |
|
106 |
/**
|
107 |
+
* @internal
|
108 |
* @param string $size
|
109 |
* @return bool|string
|
110 |
*/
|
111 |
function get_src( $size = '' ) {
|
112 |
+
if ( isset($this->abs_url) ) {
|
113 |
return $this->_maybe_secure_url($this->abs_url);
|
114 |
}
|
115 |
|
116 |
+
if ( $size && is_string($size) && isset($this->sizes[$size]) ) {
|
117 |
$image = image_downsize($this->ID, $size);
|
118 |
return $this->_maybe_secure_url(reset($image));
|
119 |
}
|
120 |
|
121 |
+
if ( !isset($this->file) && isset($this->_wp_attached_file) ) {
|
122 |
$this->file = $this->_wp_attached_file;
|
123 |
}
|
124 |
|
125 |
+
if ( !isset($this->file) ) {
|
126 |
return false;
|
127 |
}
|
128 |
|
129 |
$dir = self::wp_upload_dir();
|
130 |
+
$base = $dir['baseurl'];
|
131 |
|
132 |
$src = trailingslashit($this->_maybe_secure_url($base)) . $this->file;
|
133 |
$src = apply_filters('timber/image/src', $src, $this->ID);
|
134 |
return apply_filters('timber_image_src', $src, $this->ID);
|
135 |
}
|
136 |
|
137 |
+
/**
|
138 |
+
* @internal
|
139 |
+
* @param string $url for evaluation
|
140 |
+
* @return string with http/https corrected depending on what's appropriate for server
|
141 |
+
*/
|
142 |
+
protected static function _maybe_secure_url($url) {
|
143 |
if (is_ssl() && strpos($url, 'https') !== 0 && strpos($url, 'http') === 0) {
|
144 |
$url = 'https' . substr($url, strlen('http'));
|
145 |
}
|
|
|
146 |
return $url;
|
147 |
}
|
148 |
|
157 |
}
|
158 |
|
159 |
/**
|
160 |
+
* @internal
|
161 |
* @return string
|
162 |
*/
|
163 |
function get_path() {
|
168 |
}
|
169 |
|
170 |
/**
|
171 |
+
* @api
|
172 |
+
* @return string the /relative/path/to/the/file
|
173 |
*/
|
174 |
+
public function path() {
|
175 |
+
return TimberURLHelper::get_rel_path($this->src());
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* @api
|
180 |
+
* @return bool|TimberPost
|
181 |
+
*/
|
182 |
+
function parent() {
|
183 |
if (!$this->post_parent) {
|
184 |
return false;
|
185 |
}
|
186 |
return new $this->PostClass($this->post_parent);
|
187 |
}
|
188 |
|
189 |
+
/**
|
190 |
+
* @internal
|
191 |
+
* @deprecated 0.21.8
|
192 |
+
* @return bool|TimberPost
|
193 |
+
*/
|
194 |
+
function get_parent() {
|
195 |
+
return $this->parent();
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* @internal
|
200 |
+
* @see TimberImage::alt
|
201 |
+
* @return string
|
202 |
+
*/
|
203 |
function get_alt() {
|
204 |
$alt = trim(strip_tags(get_post_meta($this->ID, '_wp_attachment_image_alt', true)));
|
205 |
return $alt;
|
207 |
|
208 |
|
209 |
/**
|
210 |
+
* @internal
|
211 |
* @param int $iid
|
212 |
*/
|
213 |
function init( $iid = false ) {
|
257 |
}
|
258 |
}
|
259 |
|
260 |
+
/**
|
261 |
+
* @internal
|
262 |
+
* @param int $iid the id number of the image in the WP database
|
263 |
+
*/
|
264 |
+
protected function get_image_info( $iid ) {
|
265 |
$image_info = $iid;
|
266 |
if (is_numeric($iid)) {
|
267 |
$image_info = wp_get_attachment_metadata($iid);
|
287 |
return $iid;
|
288 |
}
|
289 |
|
290 |
+
/**
|
291 |
+
* @internal
|
292 |
+
* @param string $relative_path
|
293 |
+
*/
|
294 |
+
protected function init_with_relative_path( $relative_path ) {
|
295 |
$this->abs_url = home_url( $relative_path );
|
296 |
$file_path = TimberURLHelper::get_full_path( $relative_path );
|
297 |
$this->file_loc = $file_path;
|
298 |
$this->file = $file_path;
|
299 |
}
|
300 |
|
301 |
+
/**
|
302 |
+
* @internal
|
303 |
+
* @param string $file_path
|
304 |
+
*/
|
305 |
+
protected function init_with_file_path( $file_path ) {
|
306 |
$url = TimberURLHelper::file_system_to_url( $file_path );
|
307 |
$this->abs_url = $url;
|
308 |
$this->file_loc = $file_path;
|
310 |
}
|
311 |
|
312 |
/**
|
313 |
+
* @internal
|
314 |
* @param string $url
|
315 |
*/
|
316 |
+
protected function init_with_url($url) {
|
317 |
$this->abs_url = $url;
|
318 |
if (TimberURLHelper::is_local($url)) {
|
319 |
$this->file = ABSPATH . TimberURLHelper::get_rel_url($url);
|
322 |
}
|
323 |
|
324 |
/**
|
325 |
+
* @deprecated use src() instead
|
326 |
* @return string
|
327 |
*/
|
328 |
function get_url() {
|
330 |
}
|
331 |
|
332 |
/**
|
333 |
+
* @deprecated use src() instead
|
334 |
* @return string
|
335 |
*/
|
336 |
function url() {
|
337 |
return $this->get_src();
|
338 |
}
|
339 |
|
|
|
|
|
340 |
/**
|
341 |
+
* @api
|
342 |
+
* @example
|
343 |
+
* ```twig
|
344 |
+
* {% if post.thumbnail.aspect < 1 %}
|
345 |
+
* {# handle vertical image #}
|
346 |
+
* <img
|
347 |
* @return float
|
348 |
*/
|
349 |
public function aspect() {
|
353 |
}
|
354 |
|
355 |
/**
|
356 |
+
* @api
|
357 |
* @return int
|
358 |
*/
|
359 |
public function height() {
|
361 |
}
|
362 |
|
363 |
/**
|
364 |
+
* @api
|
365 |
* @param string $size
|
366 |
* @return bool|string
|
367 |
*/
|
370 |
}
|
371 |
|
372 |
/**
|
373 |
+
* @api
|
374 |
* @return int
|
375 |
*/
|
376 |
public function width() {
|
378 |
}
|
379 |
|
380 |
/**
|
381 |
+
* @api
|
382 |
* @return string alt text stored in WordPress
|
383 |
*/
|
384 |
public function alt() {
|
lib/timber-loader.php
CHANGED
@@ -253,6 +253,7 @@ class TimberLoader {
|
|
253 |
$twig->addExtension($this->_get_cache_extension());
|
254 |
|
255 |
$twig = apply_filters('twig_apply_filters', $twig);
|
|
|
256 |
$twig = apply_filters('timber/loader/twig', $twig);
|
257 |
return $twig;
|
258 |
}
|
253 |
$twig->addExtension($this->_get_cache_extension());
|
254 |
|
255 |
$twig = apply_filters('twig_apply_filters', $twig);
|
256 |
+
$twig = apply_filters('timber/twig/filters', $twig);
|
257 |
$twig = apply_filters('timber/loader/twig', $twig);
|
258 |
return $twig;
|
259 |
}
|
lib/timber-menu-item.php
CHANGED
@@ -17,14 +17,15 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
17 |
protected $_menu_item_object_id;
|
18 |
protected $_menu_item_url;
|
19 |
protected $menu_object;
|
20 |
-
protected $
|
21 |
|
22 |
/**
|
23 |
*
|
24 |
*
|
25 |
* @param array|object $data
|
26 |
*/
|
27 |
-
function __construct( $data ) {
|
|
|
28 |
$this->import( $data );
|
29 |
$this->import_classes( $data );
|
30 |
if ( isset( $this->name ) ) {
|
@@ -35,28 +36,30 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
35 |
$this->menu_object = $data;
|
36 |
}
|
37 |
|
38 |
-
|
|
|
|
|
|
|
39 |
return $this->name();
|
40 |
}
|
41 |
|
42 |
/**
|
43 |
-
*
|
44 |
-
*
|
45 |
-
* @param string $class_name
|
46 |
*/
|
47 |
-
function add_class( $class_name ) {
|
48 |
$this->classes[] = $class_name;
|
49 |
$this->class .= ' ' . $class_name;
|
50 |
}
|
51 |
|
52 |
/**
|
53 |
-
*
|
54 |
-
*
|
55 |
* @return string
|
56 |
*/
|
57 |
-
function name() {
|
58 |
-
if (
|
59 |
-
return $
|
60 |
}
|
61 |
if ( isset( $this->_name ) ) {
|
62 |
return $this->_name;
|
@@ -65,30 +68,43 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
65 |
}
|
66 |
|
67 |
/**
|
68 |
-
*
|
69 |
-
*
|
70 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
*/
|
72 |
-
function slug() {
|
73 |
-
if ( !isset( $this->
|
74 |
-
$this->
|
75 |
}
|
76 |
-
if ( isset( $this->
|
77 |
-
return $this->
|
78 |
}
|
79 |
return $this->post_name;
|
80 |
}
|
81 |
|
82 |
-
|
|
|
|
|
|
|
|
|
83 |
if ( isset( $this->_menu_item_object_id ) ) {
|
84 |
return new $this->PostClass( $this->_menu_item_object_id );
|
85 |
}
|
86 |
}
|
87 |
|
88 |
/**
|
89 |
-
*
|
90 |
-
*
|
91 |
-
* @return string
|
92 |
*/
|
93 |
function get_link() {
|
94 |
if ( !isset( $this->url ) || !$this->url ) {
|
@@ -102,9 +118,9 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
-
*
|
106 |
-
*
|
107 |
-
* @return string
|
108 |
*/
|
109 |
function get_path() {
|
110 |
return TimberURLHelper::get_rel_url( $this->get_link() );
|
@@ -130,18 +146,24 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
130 |
}
|
131 |
}
|
132 |
|
133 |
-
|
|
|
|
|
|
|
|
|
|
|
134 |
if (is_array($this->children)) {
|
135 |
foreach( $this->children as $child ) {
|
136 |
$child->level = $this->level + 1;
|
137 |
$child->update_child_levels();
|
138 |
}
|
|
|
139 |
}
|
140 |
}
|
141 |
|
142 |
/**
|
143 |
* Imports the classes to be used in CSS
|
144 |
-
*
|
145 |
* @param array|object $data
|
146 |
*/
|
147 |
function import_classes( $data ) {
|
@@ -156,7 +178,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
156 |
|
157 |
/**
|
158 |
*
|
159 |
-
*
|
160 |
* @return array|bool
|
161 |
*/
|
162 |
function get_children() {
|
@@ -167,8 +189,12 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
167 |
}
|
168 |
|
169 |
/**
|
170 |
-
*
|
171 |
-
*
|
|
|
|
|
|
|
|
|
172 |
* @return bool
|
173 |
*/
|
174 |
function is_external() {
|
@@ -179,9 +205,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
179 |
}
|
180 |
|
181 |
/**
|
182 |
-
*
|
183 |
-
*
|
184 |
-
* @param unknown $key string lookup key
|
185 |
* @return mixed whatever value is storied in the database
|
186 |
*/
|
187 |
public function meta( $key ) {
|
@@ -196,8 +220,8 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
196 |
/* Aliases */
|
197 |
|
198 |
/**
|
199 |
-
*
|
200 |
-
*
|
201 |
* @return array|bool
|
202 |
*/
|
203 |
public function children() {
|
@@ -205,8 +229,8 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
205 |
}
|
206 |
|
207 |
/**
|
208 |
-
*
|
209 |
-
*
|
210 |
* @return bool
|
211 |
*/
|
212 |
public function external() {
|
@@ -214,8 +238,14 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
214 |
}
|
215 |
|
216 |
/**
|
217 |
-
*
|
218 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
* @return string a full URL like http://mysite.com/thing/
|
220 |
*/
|
221 |
public function link() {
|
@@ -223,8 +253,13 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
223 |
}
|
224 |
|
225 |
/**
|
226 |
-
*
|
227 |
-
*
|
|
|
|
|
|
|
|
|
|
|
228 |
* @see get_path()
|
229 |
* @return string the path of a URL like /foo
|
230 |
*/
|
@@ -233,8 +268,9 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
233 |
}
|
234 |
|
235 |
/**
|
236 |
-
*
|
237 |
-
*
|
|
|
238 |
* @see link()
|
239 |
* @return string a full URL like http://mysite.com/thing/
|
240 |
*/
|
@@ -243,8 +279,8 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
243 |
}
|
244 |
|
245 |
/**
|
246 |
-
*
|
247 |
-
*
|
248 |
* @see link()
|
249 |
* @return string a full URL like http://mysite.com/thing/
|
250 |
*/
|
@@ -253,8 +289,13 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
253 |
}
|
254 |
|
255 |
/**
|
256 |
-
*
|
257 |
-
*
|
|
|
|
|
|
|
|
|
|
|
258 |
* @return string the public label like Foo
|
259 |
*/
|
260 |
public function title() {
|
17 |
protected $_menu_item_object_id;
|
18 |
protected $_menu_item_url;
|
19 |
protected $menu_object;
|
20 |
+
protected $master_object;
|
21 |
|
22 |
/**
|
23 |
*
|
24 |
*
|
25 |
* @param array|object $data
|
26 |
*/
|
27 |
+
public function __construct( $data ) {
|
28 |
+
$data = (object) $data;
|
29 |
$this->import( $data );
|
30 |
$this->import_classes( $data );
|
31 |
if ( isset( $this->name ) ) {
|
36 |
$this->menu_object = $data;
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* @return string the label for the menu item
|
41 |
+
*/
|
42 |
+
public function __toString() {
|
43 |
return $this->name();
|
44 |
}
|
45 |
|
46 |
/**
|
47 |
+
* add a class the menu item should have
|
48 |
+
* @param string $class_name to be added
|
|
|
49 |
*/
|
50 |
+
public function add_class( $class_name ) {
|
51 |
$this->classes[] = $class_name;
|
52 |
$this->class .= ' ' . $class_name;
|
53 |
}
|
54 |
|
55 |
/**
|
56 |
+
* The label for the menu item
|
57 |
+
* @api
|
58 |
* @return string
|
59 |
*/
|
60 |
+
public function name() {
|
61 |
+
if ( $title = $this->title() ) {
|
62 |
+
return $title;
|
63 |
}
|
64 |
if ( isset( $this->_name ) ) {
|
65 |
return $this->_name;
|
68 |
}
|
69 |
|
70 |
/**
|
71 |
+
* The slug for the menu item
|
72 |
+
* @api
|
73 |
+
* @example
|
74 |
+
* ```twig
|
75 |
+
* <ul>
|
76 |
+
* {% for item in menu.items %}
|
77 |
+
* <li class="{{item.slug}}">
|
78 |
+
* <a href="{{item.link}}">{{item.name}}</a>
|
79 |
+
* </li>
|
80 |
+
* {% endfor %}
|
81 |
+
* </ul>
|
82 |
+
* @return string the slug of the menu item kinda-like-this
|
83 |
*/
|
84 |
+
public function slug() {
|
85 |
+
if ( !isset( $this->master_object ) ) {
|
86 |
+
$this->master_object = $this->get_master_object();
|
87 |
}
|
88 |
+
if ( isset( $this->master_object->post_name ) && $this->master_object->post_name ) {
|
89 |
+
return $this->master_object->post_name;
|
90 |
}
|
91 |
return $this->post_name;
|
92 |
}
|
93 |
|
94 |
+
/**
|
95 |
+
* @internal
|
96 |
+
* @return mixed whatever object (Post, Term, etc.) the menu item represents
|
97 |
+
*/
|
98 |
+
protected function get_master_object() {
|
99 |
if ( isset( $this->_menu_item_object_id ) ) {
|
100 |
return new $this->PostClass( $this->_menu_item_object_id );
|
101 |
}
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
+
* @internal
|
106 |
+
* @see TimberMenuItem::link
|
107 |
+
* @return string an absolute URL http://example.org/my-page
|
108 |
*/
|
109 |
function get_link() {
|
110 |
if ( !isset( $this->url ) || !$this->url ) {
|
118 |
}
|
119 |
|
120 |
/**
|
121 |
+
* @internal
|
122 |
+
* @see TimberMenuItem::path()
|
123 |
+
* @return string a relative url /my-page
|
124 |
*/
|
125 |
function get_path() {
|
126 |
return TimberURLHelper::get_rel_url( $this->get_link() );
|
146 |
}
|
147 |
}
|
148 |
|
149 |
+
/**
|
150 |
+
*
|
151 |
+
* @internal
|
152 |
+
* @return bool
|
153 |
+
*/
|
154 |
+
function update_child_levels() {
|
155 |
if (is_array($this->children)) {
|
156 |
foreach( $this->children as $child ) {
|
157 |
$child->level = $this->level + 1;
|
158 |
$child->update_child_levels();
|
159 |
}
|
160 |
+
return true;
|
161 |
}
|
162 |
}
|
163 |
|
164 |
/**
|
165 |
* Imports the classes to be used in CSS
|
166 |
+
* @internal
|
167 |
* @param array|object $data
|
168 |
*/
|
169 |
function import_classes( $data ) {
|
178 |
|
179 |
/**
|
180 |
*
|
181 |
+
* @internal
|
182 |
* @return array|bool
|
183 |
*/
|
184 |
function get_children() {
|
189 |
}
|
190 |
|
191 |
/**
|
192 |
+
* Checks to see if the menu item is an external link so if my site is `example.org`, `google.com/whatever` is an external link. Helpful when creating rules for the target of a link
|
193 |
+
* @api
|
194 |
+
* @example
|
195 |
+
* ```twig
|
196 |
+
* <a href="{{ item.link }}" target="{{ item.is_external ? '_blank' : '_self' }}">
|
197 |
+
* ```
|
198 |
* @return bool
|
199 |
*/
|
200 |
function is_external() {
|
205 |
}
|
206 |
|
207 |
/**
|
208 |
+
* @param string $key lookup key
|
|
|
|
|
209 |
* @return mixed whatever value is storied in the database
|
210 |
*/
|
211 |
public function meta( $key ) {
|
220 |
/* Aliases */
|
221 |
|
222 |
/**
|
223 |
+
* Get the child [TimberMenuItems](#TimberMenuItem)s of a [TimberMenuItem](#TimberMenuItem)
|
224 |
+
* @api
|
225 |
* @return array|bool
|
226 |
*/
|
227 |
public function children() {
|
229 |
}
|
230 |
|
231 |
/**
|
232 |
+
* Checks to see if a link is external, helpful when creating rules for the target of a link
|
233 |
+
* @see TimberMenuItem::is_external
|
234 |
* @return bool
|
235 |
*/
|
236 |
public function external() {
|
238 |
}
|
239 |
|
240 |
/**
|
241 |
+
* Get the full link to a Menu Item
|
242 |
+
* @api
|
243 |
+
* @example
|
244 |
+
* ```twig
|
245 |
+
* {% for item in menu.items %}
|
246 |
+
* <li><a href="{{ item.link }}">{{ item.title }}</a></li>
|
247 |
+
* {% endfor %}
|
248 |
+
* ```
|
249 |
* @return string a full URL like http://mysite.com/thing/
|
250 |
*/
|
251 |
public function link() {
|
253 |
}
|
254 |
|
255 |
/**
|
256 |
+
* Return the relative path of a Menu Item's link
|
257 |
+
* @example
|
258 |
+
* ```twig
|
259 |
+
* {% for item in menu.items %}
|
260 |
+
* <li><a href="{{ item.path }}">{{ item.title }}</a></li>
|
261 |
+
* {% endfor %}
|
262 |
+
* ```
|
263 |
* @see get_path()
|
264 |
* @return string the path of a URL like /foo
|
265 |
*/
|
268 |
}
|
269 |
|
270 |
/**
|
271 |
+
* Gets the link a menu item points at
|
272 |
+
* @internal
|
273 |
+
* @deprecated since 0.21.7 use link instead
|
274 |
* @see link()
|
275 |
* @return string a full URL like http://mysite.com/thing/
|
276 |
*/
|
279 |
}
|
280 |
|
281 |
/**
|
282 |
+
* @internal
|
283 |
+
* @deprecated since 0.21.7, use link instead
|
284 |
* @see link()
|
285 |
* @return string a full URL like http://mysite.com/thing/
|
286 |
*/
|
289 |
}
|
290 |
|
291 |
/**
|
292 |
+
* Gets the public label for the menu item
|
293 |
+
* @example
|
294 |
+
* ```twig
|
295 |
+
* {% for item in menu.items %}
|
296 |
+
* <li><a href="{{ item.link }}">{{ item.title }}</a></li>
|
297 |
+
* {% endfor %}
|
298 |
+
* ```
|
299 |
* @return string the public label like Foo
|
300 |
*/
|
301 |
public function title() {
|
lib/timber-menu.php
CHANGED
@@ -1,19 +1,79 @@
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
class TimberMenu extends TimberCore {
|
4 |
|
5 |
public $MenuItemClass = 'TimberMenuItem';
|
6 |
public $PostClass = 'TimberPost';
|
7 |
|
|
|
|
|
|
|
|
|
8 |
public $items = null;
|
9 |
-
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
public $term_id;
|
|
|
|
|
|
|
|
|
13 |
public $title;
|
14 |
|
15 |
/**
|
16 |
-
* @param int $slug
|
17 |
*/
|
18 |
function __construct($slug = 0) {
|
19 |
$locations = get_nav_menu_locations();
|
@@ -30,11 +90,11 @@ class TimberMenu extends TimberCore {
|
|
30 |
$this->init($menu_id);
|
31 |
} else {
|
32 |
$this->init_as_page_menu();
|
33 |
-
//TimberHelper::error_log("Sorry, the menu you were looking for wasn't found ('" . $slug . "'). Here's what Timber did find:");
|
34 |
}
|
35 |
}
|
36 |
|
37 |
/**
|
|
|
38 |
* @param int $menu_id
|
39 |
*/
|
40 |
protected function init($menu_id) {
|
@@ -53,6 +113,9 @@ class TimberMenu extends TimberCore {
|
|
53 |
}
|
54 |
}
|
55 |
|
|
|
|
|
|
|
56 |
protected function init_as_page_menu() {
|
57 |
$menu = get_pages();
|
58 |
if ($menu) {
|
@@ -68,6 +131,7 @@ class TimberMenu extends TimberCore {
|
|
68 |
}
|
69 |
|
70 |
/**
|
|
|
71 |
* @param string $slug
|
72 |
* @param array $locations
|
73 |
* @return integer
|
@@ -85,6 +149,7 @@ class TimberMenu extends TimberCore {
|
|
85 |
}
|
86 |
|
87 |
/**
|
|
|
88 |
* @param int $slug
|
89 |
* @return int
|
90 |
*/
|
@@ -123,10 +188,11 @@ class TimberMenu extends TimberCore {
|
|
123 |
}
|
124 |
|
125 |
/**
|
|
|
126 |
* @param array $items
|
127 |
* @return array
|
128 |
*/
|
129 |
-
function order_children($items) {
|
130 |
$index = array();
|
131 |
$menu = array();
|
132 |
foreach ($items as $item) {
|
1 |
<?php
|
2 |
|
3 |
+
/**
|
4 |
+
* In Timber, you can use TimberMenu() to make a standard Wordpress menu available to the Twig template as an object you can loop through. And once the menu becomes available to the context, you can get items from it in a way that is a little smoother and more versatile than Wordpress's wp_nav_menu. (You need never again rely on a crazy "Walker Function!"). The first thing to do is to initialize the menu using TimberMenu(). This will make the menu available as an object to work with in the context. (TimberMenu can include a Wordpress menu slug or ID, or it can be sent with no parameter--and guess the right menu.)
|
5 |
+
* @example
|
6 |
+
* ```php
|
7 |
+
* <?php
|
8 |
+
* # functions.php
|
9 |
+
* add_filter('timber/context', 'add_to_context');
|
10 |
+
* function add_to_context($data){
|
11 |
+
* // So here you are adding data to Timber's context object, i.e...
|
12 |
+
* $data['foo'] = 'I am some other typical value set in your functions.php file, unrelated to the menu';
|
13 |
+
* // Now, in similar fashion, you add a Timber menu and send it along to the context.
|
14 |
+
* $data['menu'] = new TimberMenu(); // This is where you can also send a WordPress menu slug or ID
|
15 |
+
* return $data;
|
16 |
+
* }
|
17 |
+
*
|
18 |
+
* # index.php (or any PHP file)
|
19 |
+
* // Since you want a menu object available on every page, I added it to the universal Timber context via the functions.php file. You could also this in each PHP file if you find that too confusing.
|
20 |
+
* $context = Timber::get_context();
|
21 |
+
* $context['posts'] = Timber::get_posts();
|
22 |
+
* Timber::render('index.twig', $context);
|
23 |
+
* ?>
|
24 |
+
* ```
|
25 |
+
*
|
26 |
+
* ```twig
|
27 |
+
* <nav>
|
28 |
+
* <ul class="main-nav">
|
29 |
+
* {% for item in menu.get_items %}
|
30 |
+
* <li class="nav-main-item {{item.classes | join(' ')}}"><a class="nav-main-link" href="{{item.get_link}}">{{item.title}}</a>
|
31 |
+
* {% if item.get_children %}
|
32 |
+
* <ul class="nav-drop">
|
33 |
+
* {% for child in item.get_children %}
|
34 |
+
* <li class="nav-drop-item"><a href="{{child.get_link}}">{{child.title}}</a></li>
|
35 |
+
* {% endfor %}
|
36 |
+
* </ul>
|
37 |
+
* {% endif %}
|
38 |
+
* </li>
|
39 |
+
* {% endfor %}
|
40 |
+
* </ul>
|
41 |
+
* </nav>
|
42 |
+
* ```
|
43 |
+
*/
|
44 |
class TimberMenu extends TimberCore {
|
45 |
|
46 |
public $MenuItemClass = 'TimberMenuItem';
|
47 |
public $PostClass = 'TimberPost';
|
48 |
|
49 |
+
/**
|
50 |
+
* @api
|
51 |
+
* @var TimberMenuItem[]|null $items you need to iterate through
|
52 |
+
*/
|
53 |
public $items = null;
|
54 |
+
/**
|
55 |
+
* @api
|
56 |
+
* @var integer $id the ID# of the menu, corresponding to the wp_terms table
|
57 |
+
*/
|
58 |
+
public $id;
|
59 |
+
public $ID;
|
60 |
+
/**
|
61 |
+
* @api
|
62 |
+
* @var string $name of the menu (ex: `Main Navigation`)
|
63 |
+
*/
|
64 |
+
public $name;
|
65 |
+
/**
|
66 |
+
* @var integer $id the ID# of the menu, corresponding to the wp_terms table
|
67 |
+
*/
|
68 |
public $term_id;
|
69 |
+
/**
|
70 |
+
* @api
|
71 |
+
* @var string $name of the menu (ex: `Main Navigation`)
|
72 |
+
*/
|
73 |
public $title;
|
74 |
|
75 |
/**
|
76 |
+
* @param int|string $slug
|
77 |
*/
|
78 |
function __construct($slug = 0) {
|
79 |
$locations = get_nav_menu_locations();
|
90 |
$this->init($menu_id);
|
91 |
} else {
|
92 |
$this->init_as_page_menu();
|
|
|
93 |
}
|
94 |
}
|
95 |
|
96 |
/**
|
97 |
+
* @internal
|
98 |
* @param int $menu_id
|
99 |
*/
|
100 |
protected function init($menu_id) {
|
113 |
}
|
114 |
}
|
115 |
|
116 |
+
/**
|
117 |
+
* @internal
|
118 |
+
*/
|
119 |
protected function init_as_page_menu() {
|
120 |
$menu = get_pages();
|
121 |
if ($menu) {
|
131 |
}
|
132 |
|
133 |
/**
|
134 |
+
* @internal
|
135 |
* @param string $slug
|
136 |
* @param array $locations
|
137 |
* @return integer
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
+
* @internal
|
153 |
* @param int $slug
|
154 |
* @return int
|
155 |
*/
|
188 |
}
|
189 |
|
190 |
/**
|
191 |
+
* @internal
|
192 |
* @param array $items
|
193 |
* @return array
|
194 |
*/
|
195 |
+
protected function order_children($items) {
|
196 |
$index = array();
|
197 |
$menu = array();
|
198 |
foreach ($items as $item) {
|
lib/timber-post-getter.php
CHANGED
@@ -21,7 +21,7 @@ class TimberPostGetter {
|
|
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 |
}
|
21 |
|
22 |
static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
23 |
$posts = self::query_posts( $query, $PostClass );
|
24 |
+
if ( method_exists($posts, 'current') && $post = $posts->current() ) {
|
25 |
return $post;
|
26 |
}
|
27 |
}
|
lib/timber-post.php
CHANGED
@@ -1,55 +1,171 @@
|
|
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
-
* This is the object you use to access or extend WordPress posts
|
5 |
-
*
|
6 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
*/
|
8 |
-
|
9 |
class TimberPost extends TimberCore implements TimberCoreInterface {
|
10 |
|
|
|
|
|
|
|
11 |
public $ImageClass = 'TimberImage';
|
|
|
|
|
|
|
|
|
12 |
public $PostClass = 'TimberPost';
|
13 |
|
|
|
|
|
|
|
14 |
public $object_type = 'post';
|
|
|
|
|
|
|
|
|
15 |
public static $representation = 'post';
|
16 |
|
17 |
-
|
|
|
|
|
|
|
18 |
protected $_content;
|
|
|
|
|
|
|
|
|
|
|
19 |
protected $_get_terms;
|
|
|
|
|
|
|
|
|
20 |
protected $_permalink;
|
|
|
|
|
|
|
|
|
21 |
protected $_next = array();
|
|
|
|
|
|
|
|
|
22 |
protected $_prev = array();
|
23 |
|
|
|
|
|
|
|
|
|
24 |
public $class;
|
|
|
|
|
|
|
|
|
|
|
25 |
public $display_date;
|
|
|
|
|
|
|
|
|
|
|
26 |
public $id;
|
|
|
|
|
|
|
|
|
27 |
public $ID;
|
|
|
|
|
|
|
|
|
28 |
public $post_author;
|
|
|
|
|
|
|
|
|
29 |
public $post_content;
|
|
|
|
|
|
|
|
|
30 |
public $post_date;
|
|
|
|
|
|
|
|
|
31 |
public $post_excerpt;
|
|
|
|
|
|
|
|
|
32 |
public $post_parent;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
public $post_title;
|
|
|
|
|
|
|
|
|
|
|
34 |
public $post_type;
|
|
|
|
|
|
|
|
|
|
|
35 |
public $slug;
|
36 |
|
37 |
/**
|
38 |
-
*
|
|
|
|
|
|
|
|
|
|
|
39 |
* @param mixed $pid
|
40 |
*/
|
41 |
-
function __construct($pid = null) {
|
42 |
$pid = $this->determine_id( $pid );
|
43 |
$this->init($pid);
|
44 |
}
|
45 |
|
46 |
/**
|
|
|
|
|
47 |
* @param mixed a value to test against
|
48 |
* @return int the numberic id we should be using for this post object
|
49 |
*/
|
50 |
protected function determine_id($pid) {
|
51 |
global $wp_query;
|
52 |
-
if ($pid === null &&
|
53 |
isset($wp_query->queried_object_id)
|
54 |
&& $wp_query->queried_object_id
|
55 |
&& isset($wp_query->queried_object)
|
@@ -57,13 +173,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
57 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
58 |
) {
|
59 |
$pid = $wp_query->queried_object_id;
|
60 |
-
} else if ($pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
|
61 |
//hack for static page as home page
|
62 |
$pid = $wp_query->queried_object_id;
|
63 |
-
} else if ($pid === null) {
|
64 |
$gtid = false;
|
65 |
$maybe_post = get_post();
|
66 |
-
if (isset($maybe_post->ID)){
|
67 |
$gtid = true;
|
68 |
}
|
69 |
if ( $gtid ) {
|
@@ -76,7 +192,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
76 |
}
|
77 |
}
|
78 |
}
|
79 |
-
if ($pid === null && ($pid_from_loop = TimberPostGetter::loop_to_id())) {
|
80 |
$pid = $pid_from_loop;
|
81 |
}
|
82 |
return $pid;
|
@@ -86,20 +202,21 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
86 |
* Outputs the title of the post if you do something like `<h1>{{post}}</h1>`
|
87 |
* @return string
|
88 |
*/
|
89 |
-
function __toString() {
|
90 |
return $this->title();
|
91 |
}
|
92 |
|
93 |
|
94 |
/**
|
95 |
* Initializes a TimberPost
|
|
|
96 |
* @param int|bool $pid
|
97 |
*/
|
98 |
-
function init($pid = false) {
|
99 |
-
if ($pid === false) {
|
100 |
$pid = get_the_ID();
|
101 |
}
|
102 |
-
if (is_numeric($pid)) {
|
103 |
$this->ID = $pid;
|
104 |
}
|
105 |
$post_info = $this->get_info($pid);
|
@@ -113,23 +230,23 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
113 |
|
114 |
/**
|
115 |
* Get the URL that will edit the current post/object
|
116 |
-
*
|
|
|
117 |
* @return bool|string
|
118 |
*/
|
119 |
function get_edit_url() {
|
120 |
-
if ($this->can_edit()) {
|
121 |
return get_edit_post_link($this->ID);
|
122 |
}
|
123 |
}
|
124 |
|
125 |
/**
|
126 |
* updates the post_meta of the current object with the given value
|
127 |
-
*
|
128 |
* @param string $field
|
129 |
* @param mixed $value
|
130 |
*/
|
131 |
-
public function update($field, $value) {
|
132 |
-
if (isset($this->ID)) {
|
133 |
update_post_meta($this->ID, $field, $value);
|
134 |
$this->$field = $value;
|
135 |
}
|
@@ -137,16 +254,17 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
137 |
|
138 |
|
139 |
/**
|
140 |
-
*
|
141 |
-
*
|
|
|
142 |
* @param mixed $pid
|
143 |
* @return WP_Post on success
|
144 |
*/
|
145 |
-
protected function prepare_post_info($pid = 0) {
|
146 |
-
if (is_string($pid) || is_numeric($pid) || (is_object($pid) && !isset($pid->post_title)) || $pid === 0) {
|
147 |
$pid = self::check_post_id($pid);
|
148 |
$post = get_post($pid);
|
149 |
-
if ($post) {
|
150 |
return $post;
|
151 |
} else {
|
152 |
$post = get_page($pid);
|
@@ -159,21 +277,21 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
159 |
|
160 |
|
161 |
/**
|
162 |
-
*
|
163 |
-
*
|
164 |
* @param integer $pid ;
|
|
|
165 |
* @return integer ID number of a post
|
166 |
*/
|
167 |
-
protected function check_post_id($pid) {
|
168 |
-
if (is_numeric($pid) && $pid === 0) {
|
169 |
$pid = get_the_ID();
|
170 |
return $pid;
|
171 |
}
|
172 |
-
if (!is_numeric($pid) && is_string($pid)) {
|
173 |
$pid = self::get_post_id_by_name($pid);
|
174 |
return $pid;
|
175 |
}
|
176 |
-
if (!$pid) {
|
177 |
return null;
|
178 |
}
|
179 |
return $pid;
|
@@ -181,8 +299,8 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
181 |
|
182 |
|
183 |
/**
|
184 |
-
*
|
185 |
-
*
|
186 |
* @param string $post_name
|
187 |
* @return int
|
188 |
*/
|
@@ -200,63 +318,68 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
200 |
* get a preview of your post, if you have an excerpt it will use that,
|
201 |
* otherwise it will pull from the post_content.
|
202 |
* If there's a <!-- more --> tag it will use that to mark where to pull through.
|
|
|
|
|
|
|
203 |
* <p>{{post.get_preview(50)}}</p>
|
204 |
-
*
|
205 |
-
* @param
|
206 |
-
* @param
|
207 |
-
* @param
|
208 |
-
* @
|
|
|
209 |
*/
|
210 |
function get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true) {
|
211 |
$text = '';
|
212 |
$trimmed = false;
|
213 |
-
if (isset($this->post_excerpt) && strlen($this->post_excerpt)) {
|
214 |
-
if ($force) {
|
215 |
$text = TimberHelper::trim_words($this->post_excerpt, $len, false);
|
216 |
$trimmed = true;
|
217 |
} else {
|
218 |
$text = $this->post_excerpt;
|
219 |
}
|
220 |
}
|
221 |
-
if (!strlen($text) &&
|
222 |
-
$pieces = explode(
|
223 |
$text = $pieces[0];
|
224 |
-
if ($force) {
|
225 |
$text = TimberHelper::trim_words($text, $len, false);
|
226 |
$trimmed = true;
|
227 |
}
|
|
|
228 |
}
|
229 |
-
if (!strlen($text)) {
|
230 |
$text = TimberHelper::trim_words($this->get_content(), $len, false);
|
231 |
$trimmed = true;
|
232 |
}
|
233 |
-
if (!strlen(trim($text))) {
|
234 |
return trim($text);
|
235 |
}
|
236 |
-
if ($strip) {
|
237 |
$text = trim(strip_tags($text));
|
238 |
}
|
239 |
-
if (strlen($text)) {
|
240 |
$text = trim($text);
|
241 |
$last = $text[strlen($text) - 1];
|
242 |
-
if ($last != '.' && $trimmed) {
|
243 |
$text .= ' … ';
|
244 |
}
|
245 |
-
if (!$strip) {
|
246 |
$last_p_tag = strrpos($text, '</p>');
|
247 |
-
if ($last_p_tag !== false) {
|
248 |
$text = substr($text, 0, $last_p_tag);
|
249 |
}
|
250 |
-
if ($last != '.' && $trimmed) {
|
251 |
$text .= ' … ';
|
252 |
}
|
253 |
}
|
254 |
-
|
255 |
-
|
256 |
-
|
|
|
257 |
}
|
258 |
-
|
259 |
-
if (!$strip) {
|
260 |
$text .= '</p>';
|
261 |
}
|
262 |
}
|
@@ -265,11 +388,11 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
265 |
|
266 |
/**
|
267 |
* gets the post custom and attaches it to the current object
|
|
|
268 |
* @param bool|int $pid a post ID number
|
269 |
-
* @nodoc
|
270 |
*/
|
271 |
-
function import_custom($pid = false) {
|
272 |
-
if (!$pid) {
|
273 |
$pid = $this->ID;
|
274 |
}
|
275 |
$customs = $this->get_post_custom($pid);
|
@@ -279,17 +402,18 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
279 |
/**
|
280 |
* Used internally to fetch the metadata fields (wp_postmeta table)
|
281 |
* and attach them to our TimberPost object
|
|
|
282 |
* @param int $pid
|
283 |
* @return array
|
284 |
*/
|
285 |
-
protected function get_post_custom($pid) {
|
286 |
apply_filters('timber_post_get_meta_pre', array(), $pid, $this);
|
287 |
$customs = get_post_custom($pid);
|
288 |
-
if (!is_array($customs) || empty($customs)) {
|
289 |
return array();
|
290 |
}
|
291 |
-
foreach ($customs as $key => $value) {
|
292 |
-
if (is_array($value) && count($value) == 1 && isset($value[0])) {
|
293 |
$value = $value[0];
|
294 |
}
|
295 |
$customs[$key] = maybe_unserialize($value);
|
@@ -299,28 +423,26 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
299 |
}
|
300 |
|
301 |
/**
|
302 |
-
*
|
303 |
-
*
|
304 |
-
* <img src="{{post.thumbnail.get_src}}" />
|
305 |
* @return null|TimberImage
|
306 |
*/
|
307 |
function get_thumbnail() {
|
308 |
-
if (function_exists('get_post_thumbnail_id')) {
|
309 |
$tid = get_post_thumbnail_id($this->ID);
|
310 |
-
if ($tid) {
|
311 |
return new $this->ImageClass($tid);
|
312 |
}
|
313 |
}
|
314 |
}
|
315 |
|
316 |
/**
|
317 |
-
*
|
318 |
-
*
|
319 |
-
* <a href="{{post.link}}">Read my post</a>
|
320 |
* @return string
|
321 |
*/
|
322 |
function get_permalink() {
|
323 |
-
if (isset($this->_permalink)) {
|
324 |
return $this->_permalink;
|
325 |
}
|
326 |
$this->_permalink = get_permalink($this->ID);
|
@@ -331,6 +453,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
331 |
* get the permalink for a post object
|
332 |
* In your templates you should use link:
|
333 |
* <a href="{{post.link}}">Read my post</a>
|
|
|
334 |
* @return string
|
335 |
*/
|
336 |
function get_link() {
|
@@ -339,22 +462,23 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
339 |
|
340 |
/**
|
341 |
* Get the next post in WordPress's ordering
|
|
|
342 |
* @param bool $taxonomy
|
343 |
* @return TimberPost|boolean
|
344 |
*/
|
345 |
-
function get_next($taxonomy = false) {
|
346 |
-
if (!isset($this->_next) || !isset($this->_next[$taxonomy])) {
|
347 |
global $post;
|
348 |
$this->_next = array();
|
349 |
$old_global = $post;
|
350 |
$post = $this;
|
351 |
-
if ($taxonomy) {
|
352 |
$adjacent = get_adjacent_post(true, '', false, $taxonomy);
|
353 |
} else {
|
354 |
$adjacent = get_adjacent_post(false, '', false);
|
355 |
}
|
356 |
|
357 |
-
if ($adjacent) {
|
358 |
$this->_next[$taxonomy] = new $this->PostClass($adjacent);
|
359 |
} else {
|
360 |
$this->_next[$taxonomy] = false;
|
@@ -372,22 +496,22 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
372 |
global $post, $page, $numpages, $multipage;
|
373 |
$post = $this;
|
374 |
$ret = array();
|
375 |
-
if ($multipage) {
|
376 |
-
for ($i = 1; $i <= $numpages; $i++) {
|
377 |
$link = self::get_wp_link_page($i);
|
378 |
$data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
|
379 |
-
if ($i == $page) {
|
380 |
$data['current'] = true;
|
381 |
}
|
382 |
$ret['pages'][] = $data;
|
383 |
}
|
384 |
$i = $page - 1;
|
385 |
-
if ($i) {
|
386 |
$link = self::get_wp_link_page($i);
|
387 |
$ret['prev'] = array('link' => $link);
|
388 |
}
|
389 |
$i = $page + 1;
|
390 |
-
if ($i <= $numpages) {
|
391 |
$link = self::get_wp_link_page($i);
|
392 |
$ret['next'] = array('link' => $link);
|
393 |
}
|
@@ -402,7 +526,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
402 |
protected static function get_wp_link_page($i) {
|
403 |
$link = _wp_link_page($i);
|
404 |
$link = new SimpleXMLElement($link . '</a>');
|
405 |
-
if (isset($link['href'])) {
|
406 |
return $link['href'];
|
407 |
}
|
408 |
return '';
|
@@ -412,6 +536,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
412 |
* Get the permalink for a post, but as a relative path
|
413 |
* For example, where {{post.link}} would return "http://example.org/2015/07/04/my-cool-post"
|
414 |
* this will return the relative version: "/2015/07/04/my-cool-post"
|
|
|
415 |
* @return string
|
416 |
*/
|
417 |
function get_path() {
|
@@ -420,11 +545,12 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
420 |
|
421 |
/**
|
422 |
* Get the next post in WordPress's ordering
|
|
|
423 |
* @param bool $taxonomy
|
424 |
* @return TimberPost|boolean
|
425 |
*/
|
426 |
-
function get_prev($taxonomy = false) {
|
427 |
-
if (isset($this->_prev) && isset($this->_prev[$taxonomy])) {
|
428 |
return $this->_prev[$taxonomy];
|
429 |
}
|
430 |
global $post;
|
@@ -432,9 +558,8 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
432 |
$post = $this;
|
433 |
$within_taxonomy = ($taxonomy) ? $taxonomy : 'category';
|
434 |
$adjacent = get_adjacent_post(($taxonomy), '', true, $within_taxonomy);
|
435 |
-
|
436 |
$prev_in_taxonomy = false;
|
437 |
-
if ($adjacent) {
|
438 |
$prev_in_taxonomy = new $this->PostClass($adjacent);
|
439 |
}
|
440 |
$this->_prev[$taxonomy] = $prev_in_taxonomy;
|
@@ -444,10 +569,11 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
444 |
|
445 |
/**
|
446 |
* Get the parent post of the post
|
|
|
447 |
* @return bool|TimberPost
|
448 |
*/
|
449 |
function get_parent() {
|
450 |
-
if (!$this->post_parent) {
|
451 |
return false;
|
452 |
}
|
453 |
return new $this->PostClass($this->post_parent);
|
@@ -455,17 +581,18 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
455 |
|
456 |
/**
|
457 |
* Gets a User object from the author of the post
|
458 |
-
*
|
|
|
459 |
* @return bool|TimberUser
|
460 |
*/
|
461 |
function get_author() {
|
462 |
-
if (isset($this->post_author)) {
|
463 |
return new TimberUser($this->post_author);
|
464 |
}
|
465 |
}
|
466 |
|
467 |
/**
|
468 |
-
*
|
469 |
* @return bool|TimberUser
|
470 |
*/
|
471 |
function get_modified_author() {
|
@@ -475,12 +602,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
475 |
|
476 |
/**
|
477 |
* Used internally by init, etc. to build TimberPost object
|
478 |
-
* @
|
|
|
479 |
* @return null|object|WP_Post
|
480 |
*/
|
481 |
protected function get_info($pid) {
|
482 |
$post = $this->prepare_post_info($pid);
|
483 |
-
if (!isset($post->post_status)) {
|
484 |
return null;
|
485 |
}
|
486 |
$post->status = $post->post_status;
|
@@ -488,64 +616,71 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
488 |
$post->slug = $post->post_name;
|
489 |
$customs = $this->get_post_custom($post->ID);
|
490 |
$post->custom = $customs;
|
491 |
-
$post = (object)array_merge((array)$customs, (array)$post);
|
492 |
return $post;
|
493 |
}
|
494 |
|
495 |
/**
|
496 |
-
*
|
497 |
-
*
|
|
|
498 |
* @param string $use
|
499 |
* @return string
|
500 |
*/
|
501 |
-
function get_display_date($use = 'post_date') {
|
502 |
return date(get_option('date_format'), strtotime($this->$use));
|
503 |
}
|
504 |
|
505 |
/**
|
|
|
|
|
506 |
* @param string $date_format
|
507 |
* @return string
|
508 |
*/
|
509 |
-
function get_date($date_format = '') {
|
510 |
$df = $date_format ? $date_format : get_option('date_format');
|
511 |
$the_date = (string)mysql2date($df, $this->post_date);
|
512 |
-
return apply_filters('get_the_date', $the_date, $
|
513 |
}
|
514 |
|
515 |
/**
|
|
|
516 |
* @param string $date_format
|
517 |
* @return string
|
518 |
*/
|
519 |
-
function get_modified_date($date_format = '') {
|
520 |
$df = $date_format ? $date_format : get_option('date_format');
|
521 |
-
$the_time = $this->get_modified_time($df
|
522 |
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
523 |
}
|
524 |
|
525 |
/**
|
526 |
-
* @
|
|
|
527 |
* @return string
|
528 |
*/
|
529 |
-
function get_modified_time($time_format = '') {
|
530 |
$tf = $time_format ? $time_format : get_option('time_format');
|
531 |
$the_time = get_post_modified_time($tf, false, $this->ID, true);
|
532 |
return apply_filters('get_the_modified_time', $the_time, $time_format);
|
533 |
}
|
534 |
|
535 |
/**
|
536 |
-
* @
|
537 |
-
* @
|
|
|
|
|
538 |
* @return array
|
539 |
*/
|
540 |
-
function get_children($post_type = 'any', $childPostClass = false) {
|
541 |
-
if ($childPostClass === false) {
|
542 |
$childPostClass = $this->PostClass;
|
543 |
}
|
544 |
-
if ($post_type == 'parent') {
|
545 |
$post_type = $this->post_type;
|
546 |
}
|
547 |
$children = get_children('post_parent=' . $this->ID . '&post_type=' . $post_type . '&numberposts=-1&orderby=menu_order title&order=ASC');
|
548 |
-
foreach ($children as &$child) {
|
549 |
$child = new $childPostClass($child->ID);
|
550 |
}
|
551 |
$children = array_values($children);
|
@@ -554,9 +689,8 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
554 |
|
555 |
/**
|
556 |
* Get the comments for a post
|
557 |
-
*
|
558 |
-
*
|
559 |
-
* {% endfor %}
|
560 |
* @param int $ct
|
561 |
* @param string $order
|
562 |
* @param string $type
|
@@ -564,44 +698,52 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
564 |
* @param string $CommentClass
|
565 |
* @return array|mixed
|
566 |
*/
|
|
|
567 |
function get_comments($ct = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment') {
|
|
|
|
|
|
|
|
|
568 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
569 |
-
if ($ct > 0) {
|
570 |
$args['number'] = $ct;
|
571 |
}
|
572 |
-
if ($order == 'wp') {
|
573 |
$args['order'] = get_option('comment_order');
|
574 |
}
|
575 |
|
576 |
-
|
577 |
-
|
|
|
|
|
|
|
|
|
|
|
578 |
|
579 |
foreach($comments as $key => &$comment) {
|
580 |
-
$
|
581 |
-
$
|
582 |
}
|
583 |
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
$tComments = array_values($tComments);
|
594 |
|
595 |
-
|
596 |
-
|
|
|
|
|
597 |
|
598 |
/**
|
599 |
* Get the categories for a post
|
600 |
-
*
|
601 |
-
*
|
602 |
-
* <li>{{category.name}}</li>
|
603 |
-
* {% endfor %}
|
604 |
-
* </ul>
|
605 |
* @return array of TimberTerms
|
606 |
*/
|
607 |
function get_categories() {
|
@@ -609,66 +751,65 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
609 |
}
|
610 |
|
611 |
/**
|
|
|
|
|
612 |
* @return mixed
|
613 |
*/
|
614 |
-
function get_category() {
|
615 |
$cats = $this->get_categories();
|
616 |
-
if (count($cats) && isset($cats[0])) {
|
617 |
return $cats[0];
|
618 |
}
|
619 |
}
|
620 |
|
621 |
-
/** # get terms is good
|
622 |
-
*
|
623 |
-
*/
|
624 |
-
|
625 |
/**
|
|
|
626 |
* @param string $tax
|
627 |
* @param bool $merge
|
628 |
* @param string $TermClass
|
629 |
* @return array
|
630 |
*/
|
631 |
-
function get_terms($tax = '', $merge = true, $TermClass = 'TimberTerm') {
|
632 |
-
if (is_string($merge) && class_exists($merge)){
|
633 |
$TermClass = $merge;
|
634 |
}
|
635 |
-
if (is_string($tax)) {
|
636 |
-
if (isset($this->_get_terms) && isset($this->_get_terms[$tax])) {
|
637 |
return $this->_get_terms[$tax];
|
638 |
}
|
639 |
}
|
640 |
-
if (!strlen($tax) || $tax == 'all' || $tax == 'any') {
|
641 |
$taxs = get_object_taxonomies($this->post_type);
|
642 |
-
} else if (is_array($tax)) {
|
643 |
$taxs = $tax;
|
644 |
} else {
|
645 |
$taxs = array($tax);
|
646 |
}
|
647 |
$ret = array();
|
648 |
-
foreach ($taxs as $tax) {
|
649 |
-
if ($tax == 'tags' || $tax == 'tag') {
|
650 |
$tax = 'post_tag';
|
651 |
-
} else if ($tax == 'categories') {
|
652 |
$tax = 'category';
|
653 |
}
|
654 |
$terms = wp_get_post_terms($this->ID, $tax);
|
655 |
-
if (!is_array($terms) && is_object($terms) && get_class($terms) == 'WP_Error') {
|
656 |
//something is very wrong
|
657 |
TimberHelper::error_log('You have an error retrieving terms on a post in timber-post.php:628');
|
658 |
TimberHelper::error_log('tax = ' . $tax);
|
659 |
TimberHelper::error_log($terms);
|
660 |
} else {
|
661 |
-
foreach ($terms as &$term) {
|
662 |
$term = new $TermClass($term->term_id, $tax);
|
663 |
}
|
664 |
-
if ($merge && is_array($terms)) {
|
665 |
$ret = array_merge($ret, $terms);
|
666 |
-
} else if (count($terms)) {
|
667 |
$ret[$tax] = $terms;
|
668 |
}
|
669 |
}
|
670 |
}
|
671 |
-
if (!isset($this->_get_terms)) {
|
672 |
$this->_get_terms = array();
|
673 |
}
|
674 |
$this->_get_terms[$tax] = $ret;
|
@@ -680,12 +821,12 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
680 |
* @param string $taxonomy
|
681 |
* @return bool
|
682 |
*/
|
683 |
-
function has_term($term_name_or_id, $taxonomy = 'all') {
|
684 |
-
if ($taxonomy == 'all' || $taxonomy == 'any') {
|
685 |
$taxes = get_object_taxonomies($this->post_type, 'names');
|
686 |
$ret = false;
|
687 |
-
foreach ($taxes as $tax) {
|
688 |
-
if (has_term($term_name_or_id, $tax, $this->ID)) {
|
689 |
$ret = true;
|
690 |
break;
|
691 |
}
|
@@ -699,20 +840,21 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
699 |
* @param string $field
|
700 |
* @return TimberImage
|
701 |
*/
|
702 |
-
function get_image($field) {
|
703 |
return new $this->ImageClass($this->$field);
|
704 |
}
|
705 |
|
706 |
/**
|
707 |
-
*
|
708 |
-
*
|
709 |
-
*
|
710 |
-
*
|
711 |
-
*
|
712 |
-
*
|
713 |
-
|
714 |
-
|
715 |
-
|
|
|
716 |
* @return array
|
717 |
*/
|
718 |
function get_tags() {
|
@@ -720,11 +862,15 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
720 |
}
|
721 |
|
722 |
/**
|
723 |
-
*
|
724 |
-
*
|
725 |
-
|
726 |
-
|
727 |
-
|
|
|
|
|
|
|
|
|
728 |
* @return string
|
729 |
*/
|
730 |
function get_title() {
|
@@ -732,32 +878,35 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
732 |
}
|
733 |
|
734 |
/**
|
735 |
-
*
|
736 |
-
*
|
737 |
-
|
738 |
-
|
739 |
-
|
|
|
|
|
|
|
740 |
* @param int $len
|
741 |
* @param int $page
|
742 |
* @return string
|
743 |
*/
|
744 |
-
function get_content($len = 0, $page = 0) {
|
745 |
-
if ($len == 0 && $page == 0 && $this->_content) {
|
746 |
return $this->_content;
|
747 |
}
|
748 |
$content = $this->post_content;
|
749 |
-
if ($len) {
|
750 |
$content = wp_trim_words($content, $len);
|
751 |
}
|
752 |
-
if ($page) {
|
753 |
$contents = explode('<!--nextpage-->', $content);
|
754 |
$page--;
|
755 |
-
if (count($contents) > $page) {
|
756 |
$content = $contents[$page];
|
757 |
}
|
758 |
}
|
759 |
$content = apply_filters('the_content', ($content));
|
760 |
-
if ($len == 0 && $page == 0) {
|
761 |
$this->_content = $content;
|
762 |
}
|
763 |
return $content;
|
@@ -771,6 +920,16 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
771 |
return $this->get_content(0, $page);
|
772 |
}
|
773 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
774 |
* @return mixed
|
775 |
*/
|
776 |
public function get_post_type() {
|
@@ -781,7 +940,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
781 |
* @return int
|
782 |
*/
|
783 |
public function get_comment_count() {
|
784 |
-
if (isset($this->ID)) {
|
785 |
return get_comments_number($this->ID);
|
786 |
} else {
|
787 |
return 0;
|
@@ -792,14 +951,14 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
792 |
* @param string $field_name
|
793 |
* @return mixed
|
794 |
*/
|
795 |
-
public function get_field($field_name) {
|
796 |
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
797 |
-
if ($value === null) {
|
798 |
$value = get_post_meta($this->ID, $field_name);
|
799 |
-
if (is_array($value) && count($value) == 1) {
|
800 |
$value = $value[0];
|
801 |
}
|
802 |
-
if (is_array($value) && count($value) == 0) {
|
803 |
$value = null;
|
804 |
}
|
805 |
}
|
@@ -810,11 +969,12 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
810 |
/**
|
811 |
* @param string $field_name
|
812 |
*/
|
813 |
-
function import_field($field_name) {
|
814 |
$this->$field_name = $this->get_field($field_name);
|
815 |
}
|
816 |
|
817 |
/**
|
|
|
818 |
* @return mixed
|
819 |
*/
|
820 |
function get_format() {
|
@@ -822,16 +982,31 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
822 |
}
|
823 |
|
824 |
/**
|
825 |
-
*
|
826 |
-
* @
|
827 |
-
|
828 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
829 |
global $post;
|
830 |
$old_global_post = $post;
|
831 |
$post = $this;
|
832 |
$class_array = get_post_class($class, $this->ID);
|
833 |
$post = $old_global_post;
|
834 |
-
if (is_array($class_array)){
|
835 |
return implode(' ', $class_array);
|
836 |
}
|
837 |
return $class_array;
|
@@ -866,36 +1041,71 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
866 |
return $ret;
|
867 |
}
|
868 |
|
869 |
-
// Aliases
|
870 |
/**
|
871 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
872 |
*/
|
873 |
public function author() {
|
874 |
return $this->get_author();
|
875 |
}
|
876 |
|
877 |
/**
|
878 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
879 |
*/
|
880 |
public function modified_author() {
|
881 |
return $this->get_modified_author();
|
882 |
}
|
883 |
|
884 |
/**
|
885 |
-
*
|
|
|
|
|
886 |
*/
|
887 |
public function categories() {
|
888 |
return $this->get_terms('category');
|
889 |
}
|
890 |
|
891 |
/**
|
892 |
-
*
|
|
|
|
|
|
|
893 |
*/
|
894 |
public function category() {
|
895 |
return $this->get_category();
|
896 |
}
|
897 |
|
898 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
899 |
* @return array
|
900 |
*/
|
901 |
public function children( $post_type = 'any', $childPostClass = false ) {
|
@@ -903,17 +1113,44 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
903 |
}
|
904 |
|
905 |
/**
|
906 |
-
*
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
913 |
* @param int $page
|
914 |
* @return string
|
915 |
*/
|
916 |
-
public function content($page = 0) {
|
917 |
return $this->get_content(0, $page);
|
918 |
}
|
919 |
|
@@ -925,10 +1162,24 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
925 |
}
|
926 |
|
927 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
928 |
* @param string $date_format
|
929 |
* @return string
|
930 |
*/
|
931 |
-
public function date($date_format = '') {
|
932 |
return $this->get_date($date_format);
|
933 |
}
|
934 |
|
@@ -940,6 +1191,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
940 |
}
|
941 |
|
942 |
/**
|
|
|
943 |
* @return mixed
|
944 |
*/
|
945 |
public function format() {
|
@@ -947,7 +1199,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
947 |
}
|
948 |
|
949 |
/**
|
950 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
951 |
*/
|
952 |
public function link() {
|
953 |
return $this->get_permalink();
|
@@ -957,8 +1215,9 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
957 |
* @param string $field_name
|
958 |
* @return mixed
|
959 |
*/
|
960 |
-
public function meta($field_name = null) {
|
961 |
-
if ($field_name
|
|
|
962 |
$field_name = 'meta';
|
963 |
}
|
964 |
return $this->get_field($field_name);
|
@@ -975,7 +1234,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
975 |
* @param string $date_format
|
976 |
* @return string
|
977 |
*/
|
978 |
-
public function modified_date($date_format = '') {
|
979 |
return $this->get_modified_date($date_format);
|
980 |
}
|
981 |
|
@@ -983,15 +1242,16 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
983 |
* @param string $time_format
|
984 |
* @return string
|
985 |
*/
|
986 |
-
public function modified_time($time_format = '') {
|
987 |
return $this->get_modified_time($time_format);
|
988 |
}
|
989 |
|
990 |
/**
|
|
|
991 |
* @param bool $in_same_cat
|
992 |
* @return mixed
|
993 |
*/
|
994 |
-
public function next($in_same_cat = false) {
|
995 |
return $this->get_next($in_same_cat);
|
996 |
}
|
997 |
|
@@ -1003,6 +1263,12 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
1003 |
}
|
1004 |
|
1005 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
1006 |
* @return bool|TimberPost
|
1007 |
*/
|
1008 |
public function parent() {
|
@@ -1010,6 +1276,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
1010 |
}
|
1011 |
|
1012 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1013 |
* @return string
|
1014 |
*/
|
1015 |
public function path() {
|
@@ -1017,6 +1290,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
1017 |
}
|
1018 |
|
1019 |
/**
|
|
|
1020 |
* @return string
|
1021 |
*/
|
1022 |
public function permalink() {
|
@@ -1024,22 +1298,36 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
1024 |
}
|
1025 |
|
1026 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1027 |
* @param bool $in_same_cat
|
1028 |
* @return mixed
|
1029 |
*/
|
1030 |
-
public function prev($in_same_cat = false) {
|
1031 |
return $this->get_prev($in_same_cat);
|
1032 |
}
|
1033 |
|
1034 |
/**
|
1035 |
-
*
|
|
|
|
|
|
|
|
|
1036 |
* @return array
|
1037 |
*/
|
1038 |
-
public function terms($tax = '') {
|
1039 |
-
return $this->get_terms($tax);
|
1040 |
}
|
1041 |
|
1042 |
/**
|
|
|
|
|
1043 |
* @return array
|
1044 |
*/
|
1045 |
public function tags() {
|
@@ -1047,13 +1335,25 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
1047 |
}
|
1048 |
|
1049 |
/**
|
1050 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
1051 |
*/
|
1052 |
public function thumbnail() {
|
1053 |
return $this->get_thumbnail();
|
1054 |
}
|
1055 |
|
1056 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
1057 |
* @return string
|
1058 |
*/
|
1059 |
public function title() {
|
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
+
* This is the object you use to access or extend WordPress posts. Think of it as Timber's (more accessible) version of WP_Post. This is used throughout Timber to represent posts retrieved from WordPress making them available to Twig templates. See the PHP and Twig examples for an example of what it's like to work with this object in your code.
|
5 |
+
* @example
|
6 |
+
* ```php
|
7 |
+
* <?php
|
8 |
+
* // single.php, see connected twig example
|
9 |
+
* $context = Timber::get_context();
|
10 |
+
* $context['post'] = new TimberPost(); // It's a new TimberPost object, but an existing post from WordPress.
|
11 |
+
* Timber::render('single.twig', $context);
|
12 |
+
* ?>
|
13 |
+
* ```
|
14 |
+
* ```twig
|
15 |
+
* {# single.twig #}
|
16 |
+
* <article>
|
17 |
+
* <h1 class="headline">{{post.post_title}}</h1>
|
18 |
+
* <div class="body">
|
19 |
+
* {{post.content}}
|
20 |
+
* </div>
|
21 |
+
* </article>
|
22 |
+
* ```
|
23 |
+
*
|
24 |
+
* @package Timber
|
25 |
*/
|
|
|
26 |
class TimberPost extends TimberCore implements TimberCoreInterface {
|
27 |
|
28 |
+
/**
|
29 |
+
* @var string $ImageClass the name of the class to handle images by default
|
30 |
+
*/
|
31 |
public $ImageClass = 'TimberImage';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string $PostClass the name of the class to handle posts by default
|
35 |
+
*/
|
36 |
public $PostClass = 'TimberPost';
|
37 |
|
38 |
+
/**
|
39 |
+
* @var string $object_type what does this class represent in WordPress terms?
|
40 |
+
*/
|
41 |
public $object_type = 'post';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @var string $representation what does this class represent in WordPress terms?
|
45 |
+
*/
|
46 |
public static $representation = 'post';
|
47 |
|
48 |
+
/**
|
49 |
+
* @internal
|
50 |
+
* @var string $_content stores the processed content internally
|
51 |
+
*/
|
52 |
protected $_content;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @internal
|
56 |
+
* @var array $_get_terms stores the results of a get_terms method call
|
57 |
+
*/
|
58 |
protected $_get_terms;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @var string $_permalink the returned permalink from WP's get_permalink function
|
62 |
+
*/
|
63 |
protected $_permalink;
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @var array $_next stores the results of the next TimberPost in a set inside an array (in order to manage by-taxonomy)
|
67 |
+
*/
|
68 |
protected $_next = array();
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @var array $_prev stores the results of the previous TimberPost in a set inside an array (in order to manage by-taxonomy)
|
72 |
+
*/
|
73 |
protected $_prev = array();
|
74 |
|
75 |
+
/**
|
76 |
+
* @api
|
77 |
+
* @var string $class stores the CSS classes for the post (ex: "post post-type-book post-123")
|
78 |
+
*/
|
79 |
public $class;
|
80 |
+
|
81 |
+
/**
|
82 |
+
* @deprecated since 0.21.7
|
83 |
+
* @var string $display_date @deprecated stores the display date (ex: "October 6, 1984"),
|
84 |
+
*/
|
85 |
public $display_date;
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @api
|
89 |
+
* @var string $id the numeric WordPress id of a post
|
90 |
+
*/
|
91 |
public $id;
|
92 |
+
|
93 |
+
/**
|
94 |
+
* @var string $ID the numeric WordPress id of a post, capitalized to match WP usage
|
95 |
+
*/
|
96 |
public $ID;
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @var int $post_author the numeric ID of the a post's author corresponding to the wp_user dtable
|
100 |
+
*/
|
101 |
public $post_author;
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @var string $post_content the raw text of a WP post as stored in the database
|
105 |
+
*/
|
106 |
public $post_content;
|
107 |
+
|
108 |
+
/**
|
109 |
+
* @var string $post_date the raw date string as stored in the WP database, ex: 2014-07-05 18:01:39
|
110 |
+
*/
|
111 |
public $post_date;
|
112 |
+
|
113 |
+
/**
|
114 |
+
* @var string $post_exceprt the raw text of a manual post exceprt as stored in the database
|
115 |
+
*/
|
116 |
public $post_excerpt;
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @var int $post_parent the numeric ID of a post's parent post
|
120 |
+
*/
|
121 |
public $post_parent;
|
122 |
+
|
123 |
+
/**
|
124 |
+
* @api
|
125 |
+
* @var string $post_status the status of a post ("draft", "publish", etc.)
|
126 |
+
*/
|
127 |
+
public $post_status;
|
128 |
+
|
129 |
+
/**
|
130 |
+
* @var string $post_title the raw text of a post's title as stored in the database
|
131 |
+
*/
|
132 |
public $post_title;
|
133 |
+
|
134 |
+
/**
|
135 |
+
* @api
|
136 |
+
* @var string $post_type the name of the post type, this is the machine name (so "my_custom_post_type" as opposed to "My Custom Post Type")
|
137 |
+
*/
|
138 |
public $post_type;
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @api
|
142 |
+
* @var string $slug the URL-safe slug, this corresponds to the poorly-named "post_name" in the WP database, ex: "hello-world"
|
143 |
+
*/
|
144 |
public $slug;
|
145 |
|
146 |
/**
|
147 |
+
* If you send the constructor nothing it will try to figure out the current post id based on being inside The_Loop
|
148 |
+
* @example
|
149 |
+
* ```php
|
150 |
+
* $post = new TimberPost();
|
151 |
+
* $other_post = new TimberPost($random_post_id);
|
152 |
+
* ```
|
153 |
* @param mixed $pid
|
154 |
*/
|
155 |
+
public function __construct($pid = null) {
|
156 |
$pid = $this->determine_id( $pid );
|
157 |
$this->init($pid);
|
158 |
}
|
159 |
|
160 |
/**
|
161 |
+
* tries to figure out what post you want to get if not explictly defined (or if it is, allows it to be passed through)
|
162 |
+
* @internal
|
163 |
* @param mixed a value to test against
|
164 |
* @return int the numberic id we should be using for this post object
|
165 |
*/
|
166 |
protected function determine_id($pid) {
|
167 |
global $wp_query;
|
168 |
+
if ( $pid === null &&
|
169 |
isset($wp_query->queried_object_id)
|
170 |
&& $wp_query->queried_object_id
|
171 |
&& isset($wp_query->queried_object)
|
173 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
174 |
) {
|
175 |
$pid = $wp_query->queried_object_id;
|
176 |
+
} else if ( $pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
|
177 |
//hack for static page as home page
|
178 |
$pid = $wp_query->queried_object_id;
|
179 |
+
} else if ( $pid === null ) {
|
180 |
$gtid = false;
|
181 |
$maybe_post = get_post();
|
182 |
+
if ( isset($maybe_post->ID) ){
|
183 |
$gtid = true;
|
184 |
}
|
185 |
if ( $gtid ) {
|
192 |
}
|
193 |
}
|
194 |
}
|
195 |
+
if ( $pid === null && ($pid_from_loop = TimberPostGetter::loop_to_id()) ) {
|
196 |
$pid = $pid_from_loop;
|
197 |
}
|
198 |
return $pid;
|
202 |
* Outputs the title of the post if you do something like `<h1>{{post}}</h1>`
|
203 |
* @return string
|
204 |
*/
|
205 |
+
public function __toString() {
|
206 |
return $this->title();
|
207 |
}
|
208 |
|
209 |
|
210 |
/**
|
211 |
* Initializes a TimberPost
|
212 |
+
* @internal
|
213 |
* @param int|bool $pid
|
214 |
*/
|
215 |
+
protected function init($pid = false) {
|
216 |
+
if ( $pid === false ) {
|
217 |
$pid = get_the_ID();
|
218 |
}
|
219 |
+
if ( is_numeric($pid) ) {
|
220 |
$this->ID = $pid;
|
221 |
}
|
222 |
$post_info = $this->get_info($pid);
|
230 |
|
231 |
/**
|
232 |
* Get the URL that will edit the current post/object
|
233 |
+
* @internal
|
234 |
+
* @see TimberPost::edit_link
|
235 |
* @return bool|string
|
236 |
*/
|
237 |
function get_edit_url() {
|
238 |
+
if ( $this->can_edit() ) {
|
239 |
return get_edit_post_link($this->ID);
|
240 |
}
|
241 |
}
|
242 |
|
243 |
/**
|
244 |
* updates the post_meta of the current object with the given value
|
|
|
245 |
* @param string $field
|
246 |
* @param mixed $value
|
247 |
*/
|
248 |
+
public function update( $field, $value ) {
|
249 |
+
if ( isset($this->ID) ) {
|
250 |
update_post_meta($this->ID, $field, $value);
|
251 |
$this->$field = $value;
|
252 |
}
|
254 |
|
255 |
|
256 |
/**
|
257 |
+
* takes a mix of integer (post ID), string (post slug),
|
258 |
+
* or object to return a WordPress post object from WP's built-in get_post() function
|
259 |
+
* @internal
|
260 |
* @param mixed $pid
|
261 |
* @return WP_Post on success
|
262 |
*/
|
263 |
+
protected function prepare_post_info( $pid = 0 ) {
|
264 |
+
if ( is_string($pid) || is_numeric($pid) || (is_object($pid) && !isset($pid->post_title)) || $pid === 0 ) {
|
265 |
$pid = self::check_post_id($pid);
|
266 |
$post = get_post($pid);
|
267 |
+
if ( $post ) {
|
268 |
return $post;
|
269 |
} else {
|
270 |
$post = get_page($pid);
|
277 |
|
278 |
|
279 |
/**
|
280 |
+
* helps you find the post id regardless of whether you send a string or whatever
|
|
|
281 |
* @param integer $pid ;
|
282 |
+
* @internal
|
283 |
* @return integer ID number of a post
|
284 |
*/
|
285 |
+
protected function check_post_id( $pid ) {
|
286 |
+
if ( is_numeric($pid) && $pid === 0 ) {
|
287 |
$pid = get_the_ID();
|
288 |
return $pid;
|
289 |
}
|
290 |
+
if ( !is_numeric($pid) && is_string($pid) ) {
|
291 |
$pid = self::get_post_id_by_name($pid);
|
292 |
return $pid;
|
293 |
}
|
294 |
+
if ( !$pid ) {
|
295 |
return null;
|
296 |
}
|
297 |
return $pid;
|
299 |
|
300 |
|
301 |
/**
|
302 |
+
* get_post_id_by_name($post_name)
|
303 |
+
* @internal
|
304 |
* @param string $post_name
|
305 |
* @return int
|
306 |
*/
|
318 |
* get a preview of your post, if you have an excerpt it will use that,
|
319 |
* otherwise it will pull from the post_content.
|
320 |
* If there's a <!-- more --> tag it will use that to mark where to pull through.
|
321 |
+
* @api
|
322 |
+
* @example
|
323 |
+
* ```twig
|
324 |
* <p>{{post.get_preview(50)}}</p>
|
325 |
+
* ```
|
326 |
+
* @param int $len The number of words that WP should use to make the tease. (Isn't this better than [this mess](http://wordpress.org/support/topic/changing-the-default-length-of-the_excerpt-1?replies=14)?). If you've set a post_excerpt on a post, we'll use that for the preview text; otherwise the first X words of the post_content
|
327 |
+
* @param bool $force What happens if your custom post excerpt is longer then the length requested? By default (`$force = false`) it will use the full `post_excerpt`. However, you can set this to true to *force* your excerpt to be of the desired length
|
328 |
+
* @param string $readmore The text you want to use on the 'readmore' link
|
329 |
+
* @param bool $strip Strip tags? yes or no. tell me!
|
330 |
+
* @return string of the post preview
|
331 |
*/
|
332 |
function get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true) {
|
333 |
$text = '';
|
334 |
$trimmed = false;
|
335 |
+
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
336 |
+
if ( $force ) {
|
337 |
$text = TimberHelper::trim_words($this->post_excerpt, $len, false);
|
338 |
$trimmed = true;
|
339 |
} else {
|
340 |
$text = $this->post_excerpt;
|
341 |
}
|
342 |
}
|
343 |
+
if ( !strlen($text) && preg_match('/<!--\s?more(.*?)?-->/', $this->post_content, $readmore_matches) ) {
|
344 |
+
$pieces = explode($readmore_matches[0], $this->post_content);
|
345 |
$text = $pieces[0];
|
346 |
+
if ( $force ) {
|
347 |
$text = TimberHelper::trim_words($text, $len, false);
|
348 |
$trimmed = true;
|
349 |
}
|
350 |
+
$text = do_shortcode( $text );
|
351 |
}
|
352 |
+
if ( !strlen($text) ) {
|
353 |
$text = TimberHelper::trim_words($this->get_content(), $len, false);
|
354 |
$trimmed = true;
|
355 |
}
|
356 |
+
if ( !strlen(trim($text)) ) {
|
357 |
return trim($text);
|
358 |
}
|
359 |
+
if ( $strip ) {
|
360 |
$text = trim(strip_tags($text));
|
361 |
}
|
362 |
+
if ( strlen($text) ) {
|
363 |
$text = trim($text);
|
364 |
$last = $text[strlen($text) - 1];
|
365 |
+
if ( $last != '.' && $trimmed ) {
|
366 |
$text .= ' … ';
|
367 |
}
|
368 |
+
if ( !$strip ) {
|
369 |
$last_p_tag = strrpos($text, '</p>');
|
370 |
+
if ( $last_p_tag !== false ) {
|
371 |
$text = substr($text, 0, $last_p_tag);
|
372 |
}
|
373 |
+
if ( $last != '.' && $trimmed ) {
|
374 |
$text .= ' … ';
|
375 |
}
|
376 |
}
|
377 |
+
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
378 |
+
$text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . trim($readmore_matches[1]) . '</a>';
|
379 |
+
} elseif ( $readmore ) {
|
380 |
+
$text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . trim($readmore) . '</a>';
|
381 |
}
|
382 |
+
if ( !$strip ) {
|
|
|
383 |
$text .= '</p>';
|
384 |
}
|
385 |
}
|
388 |
|
389 |
/**
|
390 |
* gets the post custom and attaches it to the current object
|
391 |
+
* @internal
|
392 |
* @param bool|int $pid a post ID number
|
|
|
393 |
*/
|
394 |
+
function import_custom( $pid = false ) {
|
395 |
+
if ( !$pid ) {
|
396 |
$pid = $this->ID;
|
397 |
}
|
398 |
$customs = $this->get_post_custom($pid);
|
402 |
/**
|
403 |
* Used internally to fetch the metadata fields (wp_postmeta table)
|
404 |
* and attach them to our TimberPost object
|
405 |
+
* @internal
|
406 |
* @param int $pid
|
407 |
* @return array
|
408 |
*/
|
409 |
+
protected function get_post_custom( $pid ) {
|
410 |
apply_filters('timber_post_get_meta_pre', array(), $pid, $this);
|
411 |
$customs = get_post_custom($pid);
|
412 |
+
if ( !is_array($customs) || empty($customs) ) {
|
413 |
return array();
|
414 |
}
|
415 |
+
foreach ( $customs as $key => $value ) {
|
416 |
+
if ( is_array($value) && count($value) == 1 && isset($value[0]) ) {
|
417 |
$value = $value[0];
|
418 |
}
|
419 |
$customs[$key] = maybe_unserialize($value);
|
423 |
}
|
424 |
|
425 |
/**
|
426 |
+
* @internal
|
427 |
+
* @see TimberPost::thumbnail
|
|
|
428 |
* @return null|TimberImage
|
429 |
*/
|
430 |
function get_thumbnail() {
|
431 |
+
if ( function_exists('get_post_thumbnail_id') ) {
|
432 |
$tid = get_post_thumbnail_id($this->ID);
|
433 |
+
if ( $tid ) {
|
434 |
return new $this->ImageClass($tid);
|
435 |
}
|
436 |
}
|
437 |
}
|
438 |
|
439 |
/**
|
440 |
+
* @internal
|
441 |
+
* @see TimberPost::link
|
|
|
442 |
* @return string
|
443 |
*/
|
444 |
function get_permalink() {
|
445 |
+
if ( isset($this->_permalink) ) {
|
446 |
return $this->_permalink;
|
447 |
}
|
448 |
$this->_permalink = get_permalink($this->ID);
|
453 |
* get the permalink for a post object
|
454 |
* In your templates you should use link:
|
455 |
* <a href="{{post.link}}">Read my post</a>
|
456 |
+
* @internal
|
457 |
* @return string
|
458 |
*/
|
459 |
function get_link() {
|
462 |
|
463 |
/**
|
464 |
* Get the next post in WordPress's ordering
|
465 |
+
* @internal
|
466 |
* @param bool $taxonomy
|
467 |
* @return TimberPost|boolean
|
468 |
*/
|
469 |
+
function get_next( $taxonomy = false ) {
|
470 |
+
if ( !isset($this->_next) || !isset($this->_next[$taxonomy]) ) {
|
471 |
global $post;
|
472 |
$this->_next = array();
|
473 |
$old_global = $post;
|
474 |
$post = $this;
|
475 |
+
if ( $taxonomy ) {
|
476 |
$adjacent = get_adjacent_post(true, '', false, $taxonomy);
|
477 |
} else {
|
478 |
$adjacent = get_adjacent_post(false, '', false);
|
479 |
}
|
480 |
|
481 |
+
if ( $adjacent ) {
|
482 |
$this->_next[$taxonomy] = new $this->PostClass($adjacent);
|
483 |
} else {
|
484 |
$this->_next[$taxonomy] = false;
|
496 |
global $post, $page, $numpages, $multipage;
|
497 |
$post = $this;
|
498 |
$ret = array();
|
499 |
+
if ( $multipage ) {
|
500 |
+
for ( $i = 1; $i <= $numpages; $i++ ) {
|
501 |
$link = self::get_wp_link_page($i);
|
502 |
$data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
|
503 |
+
if ( $i == $page ) {
|
504 |
$data['current'] = true;
|
505 |
}
|
506 |
$ret['pages'][] = $data;
|
507 |
}
|
508 |
$i = $page - 1;
|
509 |
+
if ( $i ) {
|
510 |
$link = self::get_wp_link_page($i);
|
511 |
$ret['prev'] = array('link' => $link);
|
512 |
}
|
513 |
$i = $page + 1;
|
514 |
+
if ( $i <= $numpages ) {
|
515 |
$link = self::get_wp_link_page($i);
|
516 |
$ret['next'] = array('link' => $link);
|
517 |
}
|
526 |
protected static function get_wp_link_page($i) {
|
527 |
$link = _wp_link_page($i);
|
528 |
$link = new SimpleXMLElement($link . '</a>');
|
529 |
+
if ( isset($link['href']) ) {
|
530 |
return $link['href'];
|
531 |
}
|
532 |
return '';
|
536 |
* Get the permalink for a post, but as a relative path
|
537 |
* For example, where {{post.link}} would return "http://example.org/2015/07/04/my-cool-post"
|
538 |
* this will return the relative version: "/2015/07/04/my-cool-post"
|
539 |
+
* @internal
|
540 |
* @return string
|
541 |
*/
|
542 |
function get_path() {
|
545 |
|
546 |
/**
|
547 |
* Get the next post in WordPress's ordering
|
548 |
+
* @internal
|
549 |
* @param bool $taxonomy
|
550 |
* @return TimberPost|boolean
|
551 |
*/
|
552 |
+
function get_prev( $taxonomy = false ) {
|
553 |
+
if ( isset($this->_prev) && isset($this->_prev[$taxonomy]) ) {
|
554 |
return $this->_prev[$taxonomy];
|
555 |
}
|
556 |
global $post;
|
558 |
$post = $this;
|
559 |
$within_taxonomy = ($taxonomy) ? $taxonomy : 'category';
|
560 |
$adjacent = get_adjacent_post(($taxonomy), '', true, $within_taxonomy);
|
|
|
561 |
$prev_in_taxonomy = false;
|
562 |
+
if ( $adjacent ) {
|
563 |
$prev_in_taxonomy = new $this->PostClass($adjacent);
|
564 |
}
|
565 |
$this->_prev[$taxonomy] = $prev_in_taxonomy;
|
569 |
|
570 |
/**
|
571 |
* Get the parent post of the post
|
572 |
+
* @internal
|
573 |
* @return bool|TimberPost
|
574 |
*/
|
575 |
function get_parent() {
|
576 |
+
if ( !$this->post_parent ) {
|
577 |
return false;
|
578 |
}
|
579 |
return new $this->PostClass($this->post_parent);
|
581 |
|
582 |
/**
|
583 |
* Gets a User object from the author of the post
|
584 |
+
* @internal
|
585 |
+
* @see TimberPost::author
|
586 |
* @return bool|TimberUser
|
587 |
*/
|
588 |
function get_author() {
|
589 |
+
if ( isset($this->post_author) ) {
|
590 |
return new TimberUser($this->post_author);
|
591 |
}
|
592 |
}
|
593 |
|
594 |
/**
|
595 |
+
* @internal
|
596 |
* @return bool|TimberUser
|
597 |
*/
|
598 |
function get_modified_author() {
|
602 |
|
603 |
/**
|
604 |
* Used internally by init, etc. to build TimberPost object
|
605 |
+
* @internal
|
606 |
+
* @param int $pid
|
607 |
* @return null|object|WP_Post
|
608 |
*/
|
609 |
protected function get_info($pid) {
|
610 |
$post = $this->prepare_post_info($pid);
|
611 |
+
if ( !isset($post->post_status) ) {
|
612 |
return null;
|
613 |
}
|
614 |
$post->status = $post->post_status;
|
616 |
$post->slug = $post->post_name;
|
617 |
$customs = $this->get_post_custom($post->ID);
|
618 |
$post->custom = $customs;
|
619 |
+
$post = (object) array_merge((array)$customs, (array)$post);
|
620 |
return $post;
|
621 |
}
|
622 |
|
623 |
/**
|
624 |
+
* Get the human-friendly date that should actually display in a .twig template
|
625 |
+
* @deprecated since 0.20.0
|
626 |
+
* @see TimberPost::date
|
627 |
* @param string $use
|
628 |
* @return string
|
629 |
*/
|
630 |
+
function get_display_date( $use = 'post_date' ) {
|
631 |
return date(get_option('date_format'), strtotime($this->$use));
|
632 |
}
|
633 |
|
634 |
/**
|
635 |
+
* @internal
|
636 |
+
* @see TimberPost::date
|
637 |
* @param string $date_format
|
638 |
* @return string
|
639 |
*/
|
640 |
+
function get_date( $date_format = '' ) {
|
641 |
$df = $date_format ? $date_format : get_option('date_format');
|
642 |
$the_date = (string)mysql2date($df, $this->post_date);
|
643 |
+
return apply_filters('get_the_date', $the_date, $df);
|
644 |
}
|
645 |
|
646 |
/**
|
647 |
+
* @internal
|
648 |
* @param string $date_format
|
649 |
* @return string
|
650 |
*/
|
651 |
+
function get_modified_date( $date_format = '' ) {
|
652 |
$df = $date_format ? $date_format : get_option('date_format');
|
653 |
+
$the_time = $this->get_modified_time($df);
|
654 |
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
655 |
}
|
656 |
|
657 |
/**
|
658 |
+
* @internal
|
659 |
+
* @param string $time_format
|
660 |
* @return string
|
661 |
*/
|
662 |
+
function get_modified_time( $time_format = '' ) {
|
663 |
$tf = $time_format ? $time_format : get_option('time_format');
|
664 |
$the_time = get_post_modified_time($tf, false, $this->ID, true);
|
665 |
return apply_filters('get_the_modified_time', $the_time, $time_format);
|
666 |
}
|
667 |
|
668 |
/**
|
669 |
+
* @internal
|
670 |
+
* @see TimberPost::children
|
671 |
+
* @param string $post_type
|
672 |
+
* @param bool|string $childPostClass
|
673 |
* @return array
|
674 |
*/
|
675 |
+
function get_children( $post_type = 'any', $childPostClass = false ) {
|
676 |
+
if ( $childPostClass === false ) {
|
677 |
$childPostClass = $this->PostClass;
|
678 |
}
|
679 |
+
if ( $post_type == 'parent' ) {
|
680 |
$post_type = $this->post_type;
|
681 |
}
|
682 |
$children = get_children('post_parent=' . $this->ID . '&post_type=' . $post_type . '&numberposts=-1&orderby=menu_order title&order=ASC');
|
683 |
+
foreach ( $children as &$child ) {
|
684 |
$child = new $childPostClass($child->ID);
|
685 |
}
|
686 |
$children = array_values($children);
|
689 |
|
690 |
/**
|
691 |
* Get the comments for a post
|
692 |
+
* @internal
|
693 |
+
* @see TimberPost::comments
|
|
|
694 |
* @param int $ct
|
695 |
* @param string $order
|
696 |
* @param string $type
|
698 |
* @param string $CommentClass
|
699 |
* @return array|mixed
|
700 |
*/
|
701 |
+
|
702 |
function get_comments($ct = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment') {
|
703 |
+
|
704 |
+
global $overridden_cpage;
|
705 |
+
$overridden_cpage = false;
|
706 |
+
|
707 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
708 |
+
if ( $ct > 0 ) {
|
709 |
$args['number'] = $ct;
|
710 |
}
|
711 |
+
if ( strtolower($order) == 'wp' || strtolower($order) == 'wordpress' ) {
|
712 |
$args['order'] = get_option('comment_order');
|
713 |
}
|
714 |
|
715 |
+
$comments = get_comments($args);
|
716 |
+
$timber_comments = array();
|
717 |
+
|
718 |
+
if ( '' == get_query_var('cpage') && get_option('page_comments') ) {
|
719 |
+
set_query_var( 'cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1 );
|
720 |
+
$overridden_cpage = true;
|
721 |
+
}
|
722 |
|
723 |
foreach($comments as $key => &$comment) {
|
724 |
+
$timber_comment = new $CommentClass($comment);
|
725 |
+
$timber_comments[$timber_comment->id] = $timber_comment;
|
726 |
}
|
727 |
|
728 |
+
foreach( $timber_comments as $key => $comment ) {
|
729 |
+
if ( $comment->is_child() ) {
|
730 |
+
unset($timber_comments[$comment->id]);
|
731 |
|
732 |
+
if ( isset($timber_comments[$comment->comment_parent]) ) {
|
733 |
+
$timber_comments[$comment->comment_parent]->children[] = $comment;
|
734 |
+
}
|
735 |
+
}
|
736 |
+
}
|
|
|
737 |
|
738 |
+
$timber_comments = array_values($timber_comments);
|
739 |
+
|
740 |
+
return $timber_comments;
|
741 |
+
}
|
742 |
|
743 |
/**
|
744 |
* Get the categories for a post
|
745 |
+
* @internal
|
746 |
+
* @see TimberPost::categories
|
|
|
|
|
|
|
747 |
* @return array of TimberTerms
|
748 |
*/
|
749 |
function get_categories() {
|
751 |
}
|
752 |
|
753 |
/**
|
754 |
+
* @internal
|
755 |
+
* @see TimberPost::category
|
756 |
* @return mixed
|
757 |
*/
|
758 |
+
function get_category( ) {
|
759 |
$cats = $this->get_categories();
|
760 |
+
if ( count($cats) && isset($cats[0]) ) {
|
761 |
return $cats[0];
|
762 |
}
|
763 |
}
|
764 |
|
|
|
|
|
|
|
|
|
765 |
/**
|
766 |
+
* @internal
|
767 |
* @param string $tax
|
768 |
* @param bool $merge
|
769 |
* @param string $TermClass
|
770 |
* @return array
|
771 |
*/
|
772 |
+
function get_terms( $tax = '', $merge = true, $TermClass = 'TimberTerm' ) {
|
773 |
+
if ( is_string($merge) && class_exists($merge) ) {
|
774 |
$TermClass = $merge;
|
775 |
}
|
776 |
+
if ( is_string($tax) ) {
|
777 |
+
if ( isset($this->_get_terms) && isset($this->_get_terms[$tax]) ) {
|
778 |
return $this->_get_terms[$tax];
|
779 |
}
|
780 |
}
|
781 |
+
if ( !strlen($tax) || $tax == 'all' || $tax == 'any' ) {
|
782 |
$taxs = get_object_taxonomies($this->post_type);
|
783 |
+
} else if ( is_array($tax) ) {
|
784 |
$taxs = $tax;
|
785 |
} else {
|
786 |
$taxs = array($tax);
|
787 |
}
|
788 |
$ret = array();
|
789 |
+
foreach ( $taxs as $tax ) {
|
790 |
+
if ( $tax == 'tags' || $tax == 'tag' ) {
|
791 |
$tax = 'post_tag';
|
792 |
+
} else if ( $tax == 'categories' ) {
|
793 |
$tax = 'category';
|
794 |
}
|
795 |
$terms = wp_get_post_terms($this->ID, $tax);
|
796 |
+
if ( !is_array($terms) && is_object($terms) && get_class($terms) == 'WP_Error' ) {
|
797 |
//something is very wrong
|
798 |
TimberHelper::error_log('You have an error retrieving terms on a post in timber-post.php:628');
|
799 |
TimberHelper::error_log('tax = ' . $tax);
|
800 |
TimberHelper::error_log($terms);
|
801 |
} else {
|
802 |
+
foreach ( $terms as &$term ) {
|
803 |
$term = new $TermClass($term->term_id, $tax);
|
804 |
}
|
805 |
+
if ( $merge && is_array($terms) ) {
|
806 |
$ret = array_merge($ret, $terms);
|
807 |
+
} else if ( count($terms) ) {
|
808 |
$ret[$tax] = $terms;
|
809 |
}
|
810 |
}
|
811 |
}
|
812 |
+
if ( !isset($this->_get_terms) ) {
|
813 |
$this->_get_terms = array();
|
814 |
}
|
815 |
$this->_get_terms[$tax] = $ret;
|
821 |
* @param string $taxonomy
|
822 |
* @return bool
|
823 |
*/
|
824 |
+
function has_term( $term_name_or_id, $taxonomy = 'all' ) {
|
825 |
+
if ( $taxonomy == 'all' || $taxonomy == 'any' ) {
|
826 |
$taxes = get_object_taxonomies($this->post_type, 'names');
|
827 |
$ret = false;
|
828 |
+
foreach ( $taxes as $tax ) {
|
829 |
+
if ( has_term($term_name_or_id, $tax, $this->ID) ) {
|
830 |
$ret = true;
|
831 |
break;
|
832 |
}
|
840 |
* @param string $field
|
841 |
* @return TimberImage
|
842 |
*/
|
843 |
+
function get_image( $field ) {
|
844 |
return new $this->ImageClass($this->$field);
|
845 |
}
|
846 |
|
847 |
/**
|
848 |
+
* Gets an array of tags for you to use
|
849 |
+
* @internal
|
850 |
+
* @example
|
851 |
+
* ```twig
|
852 |
+
* <ul class="tags">
|
853 |
+
* {% for tag in post.tags %}
|
854 |
+
* <li>{{tag.name}}</li>
|
855 |
+
* {% endfor %}
|
856 |
+
* </ul>
|
857 |
+
* ```
|
858 |
* @return array
|
859 |
*/
|
860 |
function get_tags() {
|
862 |
}
|
863 |
|
864 |
/**
|
865 |
+
* Outputs the title with filters applied
|
866 |
+
* @internal
|
867 |
+
* @example
|
868 |
+
* ```twig
|
869 |
+
* <h1>{{post.get_title}}</h1>
|
870 |
+
* ```
|
871 |
+
* ```html
|
872 |
+
* <h1>Hello World!</h1>
|
873 |
+
* ```
|
874 |
* @return string
|
875 |
*/
|
876 |
function get_title() {
|
878 |
}
|
879 |
|
880 |
/**
|
881 |
+
* Displays the content of the post with filters, shortcodes and wpautop applied
|
882 |
+
* @example
|
883 |
+
* ```twig
|
884 |
+
* <div class="article-text">{{post.get_content}}</div>
|
885 |
+
* ```
|
886 |
+
* ```html
|
887 |
+
* <div class="article-text"><p>Blah blah blah</p><p>More blah blah blah.</p></div>
|
888 |
+
* ```
|
889 |
* @param int $len
|
890 |
* @param int $page
|
891 |
* @return string
|
892 |
*/
|
893 |
+
function get_content( $len = 0, $page = 0 ) {
|
894 |
+
if ( $len == 0 && $page == 0 && $this->_content ) {
|
895 |
return $this->_content;
|
896 |
}
|
897 |
$content = $this->post_content;
|
898 |
+
if ( $len ) {
|
899 |
$content = wp_trim_words($content, $len);
|
900 |
}
|
901 |
+
if ( $page ) {
|
902 |
$contents = explode('<!--nextpage-->', $content);
|
903 |
$page--;
|
904 |
+
if ( count($contents) > $page ) {
|
905 |
$content = $contents[$page];
|
906 |
}
|
907 |
}
|
908 |
$content = apply_filters('the_content', ($content));
|
909 |
+
if ( $len == 0 && $page == 0 ) {
|
910 |
$this->_content = $content;
|
911 |
}
|
912 |
return $content;
|
920 |
return $this->get_content(0, $page);
|
921 |
}
|
922 |
/**
|
923 |
+
*
|
924 |
+
* Here is my summary
|
925 |
+
* @example
|
926 |
+
* ```twig
|
927 |
+
* This post is from <span>{{ post.get_post_type.labels.plural }}</span>
|
928 |
+
* ```
|
929 |
+
*
|
930 |
+
* ```html
|
931 |
+
* This post is from <span>Recipes</span>
|
932 |
+
* ```
|
933 |
* @return mixed
|
934 |
*/
|
935 |
public function get_post_type() {
|
940 |
* @return int
|
941 |
*/
|
942 |
public function get_comment_count() {
|
943 |
+
if ( isset($this->ID) ) {
|
944 |
return get_comments_number($this->ID);
|
945 |
} else {
|
946 |
return 0;
|
951 |
* @param string $field_name
|
952 |
* @return mixed
|
953 |
*/
|
954 |
+
public function get_field( $field_name ) {
|
955 |
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
956 |
+
if ( $value === null ) {
|
957 |
$value = get_post_meta($this->ID, $field_name);
|
958 |
+
if ( is_array($value) && count($value) == 1 ) {
|
959 |
$value = $value[0];
|
960 |
}
|
961 |
+
if ( is_array($value) && count($value) == 0 ) {
|
962 |
$value = null;
|
963 |
}
|
964 |
}
|
969 |
/**
|
970 |
* @param string $field_name
|
971 |
*/
|
972 |
+
function import_field( $field_name ) {
|
973 |
$this->$field_name = $this->get_field($field_name);
|
974 |
}
|
975 |
|
976 |
/**
|
977 |
+
* @internal
|
978 |
* @return mixed
|
979 |
*/
|
980 |
function get_format() {
|
982 |
}
|
983 |
|
984 |
/**
|
985 |
+
* Get the CSS classes for a post. For usage you should use `{{post.class}}` instead of `{{post.post_class}}`
|
986 |
+
* @internal
|
987 |
+
* @param string $class additional classes you want to add
|
988 |
+
* @see TimberPost::$class
|
989 |
+
* @example
|
990 |
+
* ```twig
|
991 |
+
* <article class="{{ post.class }}">
|
992 |
+
* {# Some stuff here #}
|
993 |
+
* </article>
|
994 |
+
* ```
|
995 |
+
*
|
996 |
+
* ```html
|
997 |
+
* <article class="post-2612 post type-post status-publish format-standard has-post-thumbnail hentry category-data tag-charleston-church-shooting tag-dylann-roof tag-gun-violence tag-hate-crimes tag-national-incident-based-reporting-system">
|
998 |
+
* {# Some stuff here #}
|
999 |
+
* </article>
|
1000 |
+
* ```
|
1001 |
+
* @return string a space-seperated list of classes
|
1002 |
+
*/
|
1003 |
+
public function post_class( $class='' ) {
|
1004 |
global $post;
|
1005 |
$old_global_post = $post;
|
1006 |
$post = $this;
|
1007 |
$class_array = get_post_class($class, $this->ID);
|
1008 |
$post = $old_global_post;
|
1009 |
+
if ( is_array($class_array) ){
|
1010 |
return implode(' ', $class_array);
|
1011 |
}
|
1012 |
return $class_array;
|
1041 |
return $ret;
|
1042 |
}
|
1043 |
|
|
|
1044 |
/**
|
1045 |
+
* Return the author of a post
|
1046 |
+
* @api
|
1047 |
+
* @example
|
1048 |
+
* ```twig
|
1049 |
+
* <h1>{{post.title}}</h1>
|
1050 |
+
* <p class="byline">
|
1051 |
+
* <a href="{{post.author.link}}">{{post.author.name}}</a>
|
1052 |
+
* </p>
|
1053 |
+
* ```
|
1054 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
1055 |
*/
|
1056 |
public function author() {
|
1057 |
return $this->get_author();
|
1058 |
}
|
1059 |
|
1060 |
/**
|
1061 |
+
* Get the author (WordPress user) who last modified the post
|
1062 |
+
* @example
|
1063 |
+
* ```twig
|
1064 |
+
* Last updated by {{ post.modified_author.name }}
|
1065 |
+
* ```
|
1066 |
+
* ```html
|
1067 |
+
* Last updated by Harper Lee
|
1068 |
+
* ```
|
1069 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
1070 |
*/
|
1071 |
public function modified_author() {
|
1072 |
return $this->get_modified_author();
|
1073 |
}
|
1074 |
|
1075 |
/**
|
1076 |
+
* Get the categoires on a particular post
|
1077 |
+
* @api
|
1078 |
+
* @return array of TimberTerms
|
1079 |
*/
|
1080 |
public function categories() {
|
1081 |
return $this->get_terms('category');
|
1082 |
}
|
1083 |
|
1084 |
/**
|
1085 |
+
* Returns a category attached to a post
|
1086 |
+
* @api
|
1087 |
+
* If mulitpuile categories are set, it will return just the first one
|
1088 |
+
* @return TimberTerm|null
|
1089 |
*/
|
1090 |
public function category() {
|
1091 |
return $this->get_category();
|
1092 |
}
|
1093 |
|
1094 |
/**
|
1095 |
+
* Returns an array of children on the post as TimberPosts
|
1096 |
+
* (or other claass as you define).
|
1097 |
+
* @api
|
1098 |
+
* @example
|
1099 |
+
* ```twig
|
1100 |
+
* {% if post.children %}
|
1101 |
+
* Here are the child pages:
|
1102 |
+
* {% for child in page.children %}
|
1103 |
+
* <a href="{{ child.link }}">{{ child.title }}</a>
|
1104 |
+
* {% endfor %}
|
1105 |
+
* {% endif %}
|
1106 |
+
* ```
|
1107 |
+
* @param string $post_type _optional_ use to find children of a particular post type (attachment vs. page for example). You might want to restrict to certain types of children in case other stuff gets all mucked in there. You can use 'parent' to use the parent's post type
|
1108 |
+
* @param string|bool $childPostClass _optional_ a custom post class (ex: 'MyTimberPost') to return the objects as. By default (false) it will use TimberPost::$post_class value.
|
1109 |
* @return array
|
1110 |
*/
|
1111 |
public function children( $post_type = 'any', $childPostClass = false ) {
|
1113 |
}
|
1114 |
|
1115 |
/**
|
1116 |
+
* Gets the comments on a TimberPost and returns them as an array of [TimberComments](#TimberComment) (or whatever comment class you set).
|
1117 |
+
* @api
|
1118 |
+
* @param int $count Set the number of comments you want to get. `0` is analogous to "all"
|
1119 |
+
* @param string $order use ordering set in WordPress admin, or a different scheme
|
1120 |
+
* @param string $type For when other plugins use the comments table for their own special purposes, might be set to 'liveblog' or other depending on what's stored in yr comments table
|
1121 |
+
* @param string $status Could be 'pending', etc.
|
1122 |
+
* @param string $CommentClass What class to use when returning Comment objects. As you become a Timber pro, you might find yourself extending TimberComment for your site or app (obviously, totally optional)
|
1123 |
+
* @example
|
1124 |
+
* ```twig
|
1125 |
+
* {# single.twig #}
|
1126 |
+
* <h4>Comments:</h4>
|
1127 |
+
* {% for comment in post.comments %}
|
1128 |
+
* <div class="comment-{{comment.ID}} comment-order-{{loop.index}}">
|
1129 |
+
* <p>{{comment.author.name}} said:</p>
|
1130 |
+
* <p>{{comment.content}}</p>
|
1131 |
+
* </div>
|
1132 |
+
* {% endfor %}
|
1133 |
+
* ```
|
1134 |
+
* @return bool|array
|
1135 |
+
*/
|
1136 |
+
public function comments( $count = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment' ) {
|
1137 |
+
return $this->get_comments($count, $order, $type, $status, $CommentClass);
|
1138 |
+
}
|
1139 |
+
|
1140 |
+
/**
|
1141 |
+
* Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
|
1142 |
+
* @api
|
1143 |
+
* @example
|
1144 |
+
* ```twig
|
1145 |
+
* <div class="article">
|
1146 |
+
* <h2>{{post.title}}</h2>
|
1147 |
+
* <div class="content">{{ post.content }}</div>
|
1148 |
+
* </div>
|
1149 |
+
* ```
|
1150 |
* @param int $page
|
1151 |
* @return string
|
1152 |
*/
|
1153 |
+
public function content( $page = 0 ) {
|
1154 |
return $this->get_content(0, $page);
|
1155 |
}
|
1156 |
|
1162 |
}
|
1163 |
|
1164 |
/**
|
1165 |
+
* Get the date to use in your template!
|
1166 |
+
* @api
|
1167 |
+
* @example
|
1168 |
+
* ```twig
|
1169 |
+
* Published on {{ post.date }} // Uses WP's formatting set in Admin
|
1170 |
+
* OR
|
1171 |
+
* Published on {{ post.date | date('F jS') }} // Jan 12th
|
1172 |
+
* ```
|
1173 |
+
*
|
1174 |
+
* ```html
|
1175 |
+
* Published on January 12, 2015
|
1176 |
+
* OR
|
1177 |
+
* Published on Jan 12th
|
1178 |
+
* ```
|
1179 |
* @param string $date_format
|
1180 |
* @return string
|
1181 |
*/
|
1182 |
+
public function date( $date_format = '' ) {
|
1183 |
return $this->get_date($date_format);
|
1184 |
}
|
1185 |
|
1191 |
}
|
1192 |
|
1193 |
/**
|
1194 |
+
* @api
|
1195 |
* @return mixed
|
1196 |
*/
|
1197 |
public function format() {
|
1199 |
}
|
1200 |
|
1201 |
/**
|
1202 |
+
* get the permalink for a post object
|
1203 |
+
* @api
|
1204 |
+
* @example
|
1205 |
+
* ```twig
|
1206 |
+
* <a href="{{post.link}}">Read my post</a>
|
1207 |
+
* ```
|
1208 |
+
* @return string ex: http://example.org/2015/07/my-awesome-post
|
1209 |
*/
|
1210 |
public function link() {
|
1211 |
return $this->get_permalink();
|
1215 |
* @param string $field_name
|
1216 |
* @return mixed
|
1217 |
*/
|
1218 |
+
public function meta( $field_name = null ) {
|
1219 |
+
if ( $field_name === null ) {
|
1220 |
+
//on the off-chance the field is actually named meta
|
1221 |
$field_name = 'meta';
|
1222 |
}
|
1223 |
return $this->get_field($field_name);
|
1234 |
* @param string $date_format
|
1235 |
* @return string
|
1236 |
*/
|
1237 |
+
public function modified_date( $date_format = '' ) {
|
1238 |
return $this->get_modified_date($date_format);
|
1239 |
}
|
1240 |
|
1242 |
* @param string $time_format
|
1243 |
* @return string
|
1244 |
*/
|
1245 |
+
public function modified_time( $time_format = '' ) {
|
1246 |
return $this->get_modified_time($time_format);
|
1247 |
}
|
1248 |
|
1249 |
/**
|
1250 |
+
* @api
|
1251 |
* @param bool $in_same_cat
|
1252 |
* @return mixed
|
1253 |
*/
|
1254 |
+
public function next( $in_same_cat = false ) {
|
1255 |
return $this->get_next($in_same_cat);
|
1256 |
}
|
1257 |
|
1263 |
}
|
1264 |
|
1265 |
/**
|
1266 |
+
* Gets the parent (if one exists) from a post as a TimberPost object (or whatever is set in TimberPost::$PostClass)
|
1267 |
+
* @api
|
1268 |
+
* @example
|
1269 |
+
* ```twig
|
1270 |
+
* Parent page: <a href="{{ post.parent.link }}">{{ post.parent.title }}</a>
|
1271 |
+
* ```
|
1272 |
* @return bool|TimberPost
|
1273 |
*/
|
1274 |
public function parent() {
|
1276 |
}
|
1277 |
|
1278 |
/**
|
1279 |
+
* Gets the relative path of a WP Post, so while link() will return http://example.org/2015/07/my-cool-post
|
1280 |
+
* this will return just /2015/07/my-cool-post
|
1281 |
+
* @api
|
1282 |
+
* @example
|
1283 |
+
* ```twig
|
1284 |
+
* <a href="{{post.path}}">{{post.title}}</a>
|
1285 |
+
* ```
|
1286 |
* @return string
|
1287 |
*/
|
1288 |
public function path() {
|
1290 |
}
|
1291 |
|
1292 |
/**
|
1293 |
+
* @deprecated use link() instead
|
1294 |
* @return string
|
1295 |
*/
|
1296 |
public function permalink() {
|
1298 |
}
|
1299 |
|
1300 |
/**
|
1301 |
+
* Get the previous post in a set
|
1302 |
+
* @api
|
1303 |
+
* @example
|
1304 |
+
* ```twig
|
1305 |
+
* <h4>Prior Entry:</h4>
|
1306 |
+
* <h3>{{post.prev.title}}</h3>
|
1307 |
+
* <p>{{post.prev.get_preview(25)}}</p>
|
1308 |
+
* ```
|
1309 |
* @param bool $in_same_cat
|
1310 |
* @return mixed
|
1311 |
*/
|
1312 |
+
public function prev( $in_same_cat = false ) {
|
1313 |
return $this->get_prev($in_same_cat);
|
1314 |
}
|
1315 |
|
1316 |
/**
|
1317 |
+
* Get the terms associated with the post
|
1318 |
+
* This goes across all taxonomies by default
|
1319 |
+
* @api
|
1320 |
+
* @param string $tax What taxonomy to pull from, defaults to all of them. You can use custom ones, or built-in WordPress taxonomies (category, tag). Timber plays nice and figures out that tag/tags/post_tag are all the same (and categories/category), for custom taxonomies you're on your own.
|
1321 |
+
* @param bool $merge Should the resulting array be one big one (true)? Or should it be an array of sub-arrays for each taxonomy (false)?
|
1322 |
* @return array
|
1323 |
*/
|
1324 |
+
public function terms( $tax = '', $merge = true ) {
|
1325 |
+
return $this->get_terms($tax, $merge);
|
1326 |
}
|
1327 |
|
1328 |
/**
|
1329 |
+
* Gets the tags on a post, uses WP's post_tag taxonomy
|
1330 |
+
* @api
|
1331 |
* @return array
|
1332 |
*/
|
1333 |
public function tags() {
|
1335 |
}
|
1336 |
|
1337 |
/**
|
1338 |
+
* get the featured image as a TimberImage
|
1339 |
+
* @api
|
1340 |
+
* @example
|
1341 |
+
* ```twig
|
1342 |
+
* <img src="{{post.thumbnail.src}}" />
|
1343 |
+
* ```
|
1344 |
+
* @return TimberImage|null of your thumbnail
|
1345 |
*/
|
1346 |
public function thumbnail() {
|
1347 |
return $this->get_thumbnail();
|
1348 |
}
|
1349 |
|
1350 |
/**
|
1351 |
+
* Returns the processed title to be used in templates. This returns the title of the post after WP's filters have run. This is analogous to `the_title()` in standard WP template tags.
|
1352 |
+
* @api
|
1353 |
+
* @example
|
1354 |
+
* ```twig
|
1355 |
+
* <h1>{{ post.title }}</h1>
|
1356 |
+
* ```
|
1357 |
* @return string
|
1358 |
*/
|
1359 |
public function title() {
|
lib/timber-site.php
CHANGED
@@ -4,16 +4,36 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
4 |
|
5 |
public $admin_email;
|
6 |
public $blogname;
|
|
|
|
|
|
|
|
|
7 |
public $charset;
|
|
|
|
|
|
|
|
|
8 |
public $description;
|
9 |
public $id;
|
10 |
public $language;
|
11 |
public $language_attributes;
|
|
|
|
|
|
|
|
|
12 |
public $multisite;
|
13 |
public $name;
|
14 |
public $pingback_url;
|
15 |
public $siteurl;
|
|
|
|
|
|
|
|
|
16 |
public $theme;
|
|
|
|
|
|
|
|
|
17 |
public $title;
|
18 |
public $url;
|
19 |
|
@@ -31,8 +51,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
31 |
}
|
32 |
|
33 |
/**
|
34 |
-
*
|
35 |
-
*
|
36 |
* @param string|int $site_name_or_id
|
37 |
*/
|
38 |
protected function init_with_multisite( $site_name_or_id ) {
|
@@ -46,10 +65,10 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
46 |
$info = get_blog_details( $site_name_or_id );
|
47 |
$this->import( $info );
|
48 |
$this->ID = $info->blog_id;
|
|
|
49 |
$this->name = $this->blogname;
|
50 |
$this->title = $this->blogname;
|
51 |
-
$this->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' );
|
@@ -61,6 +80,9 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
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' );
|
@@ -94,7 +116,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
94 |
|
95 |
/**
|
96 |
*
|
97 |
-
*
|
98 |
* @return string
|
99 |
*/
|
100 |
function get_link() {
|
@@ -103,7 +125,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
103 |
|
104 |
/**
|
105 |
*
|
106 |
-
*
|
107 |
* @return string
|
108 |
*/
|
109 |
function get_url() {
|
@@ -112,7 +134,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
112 |
|
113 |
/**
|
114 |
*
|
115 |
-
*
|
116 |
* @return string
|
117 |
*/
|
118 |
public function link() {
|
@@ -144,7 +166,8 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
144 |
|
145 |
/**
|
146 |
*
|
147 |
-
*
|
|
|
148 |
* @return string
|
149 |
*/
|
150 |
function url() {
|
4 |
|
5 |
public $admin_email;
|
6 |
public $blogname;
|
7 |
+
/**
|
8 |
+
* @api
|
9 |
+
* @var string
|
10 |
+
*/
|
11 |
public $charset;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @var string
|
15 |
+
*/
|
16 |
public $description;
|
17 |
public $id;
|
18 |
public $language;
|
19 |
public $language_attributes;
|
20 |
+
/**
|
21 |
+
* @api
|
22 |
+
* @var bool
|
23 |
+
*/
|
24 |
public $multisite;
|
25 |
public $name;
|
26 |
public $pingback_url;
|
27 |
public $siteurl;
|
28 |
+
/**
|
29 |
+
* @api
|
30 |
+
* @var [TimberTheme](#TimberTheme)
|
31 |
+
*/
|
32 |
public $theme;
|
33 |
+
/**
|
34 |
+
* @api
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
public $title;
|
38 |
public $url;
|
39 |
|
51 |
}
|
52 |
|
53 |
/**
|
54 |
+
* @internal
|
|
|
55 |
* @param string|int $site_name_or_id
|
56 |
*/
|
57 |
protected function init_with_multisite( $site_name_or_id ) {
|
65 |
$info = get_blog_details( $site_name_or_id );
|
66 |
$this->import( $info );
|
67 |
$this->ID = $info->blog_id;
|
68 |
+
$this->id = $this->ID;
|
69 |
$this->name = $this->blogname;
|
70 |
$this->title = $this->blogname;
|
71 |
+
$this->url = $this->siteurl;
|
|
|
72 |
$theme_slug = get_blog_option( $info->blog_id, 'stylesheet' );
|
73 |
$this->theme = new TimberTheme( $theme_slug );
|
74 |
$this->language = get_bloginfo( 'language' );
|
80 |
$this->admin_email = get_blog_option( $info->blog_id, 'admin_email' );
|
81 |
}
|
82 |
|
83 |
+
/**
|
84 |
+
* @internal
|
85 |
+
*/
|
86 |
protected function init() {
|
87 |
$this->admin_email = get_bloginfo( 'admin_email' );
|
88 |
$this->name = get_bloginfo( 'name' );
|
116 |
|
117 |
/**
|
118 |
*
|
119 |
+
* @internal
|
120 |
* @return string
|
121 |
*/
|
122 |
function get_link() {
|
125 |
|
126 |
/**
|
127 |
*
|
128 |
+
* @internal
|
129 |
* @return string
|
130 |
*/
|
131 |
function get_url() {
|
134 |
|
135 |
/**
|
136 |
*
|
137 |
+
* @api
|
138 |
* @return string
|
139 |
*/
|
140 |
public function link() {
|
166 |
|
167 |
/**
|
168 |
*
|
169 |
+
* @api
|
170 |
+
* @see TimberSite::link
|
171 |
* @return string
|
172 |
*/
|
173 |
function url() {
|
lib/timber-term.php
CHANGED
@@ -2,332 +2,369 @@
|
|
2 |
|
3 |
class TimberTerm extends TimberCore implements TimberCoreInterface {
|
4 |
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
|
333 |
}
|
2 |
|
3 |
class TimberTerm extends TimberCore implements TimberCoreInterface {
|
4 |
|
5 |
+
public $PostClass = 'TimberPost';
|
6 |
+
public $TermClass = 'TimberTerm';
|
7 |
+
|
8 |
+
public $object_type = 'term';
|
9 |
+
public static $representation = 'term';
|
10 |
+
|
11 |
+
public $_children;
|
12 |
+
/**
|
13 |
+
* @api
|
14 |
+
* @var string the human-friendly name of the term (ex: French Cuisine)
|
15 |
+
*/
|
16 |
+
public $name;
|
17 |
+
/**
|
18 |
+
* @api
|
19 |
+
* @var strng the WordPress taxonomy slug (ex: `post_tag` or `actors`)
|
20 |
+
*/
|
21 |
+
public $taxonomy;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param int $tid
|
25 |
+
* @param string $tax
|
26 |
+
*/
|
27 |
+
public function __construct( $tid = null, $tax = '' ) {
|
28 |
+
if ($tid === null) {
|
29 |
+
$tid = $this->get_term_from_query();
|
30 |
+
}
|
31 |
+
if (strlen($tax)) {
|
32 |
+
$this->taxonomy = $tax;
|
33 |
+
}
|
34 |
+
$this->init($tid);
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @return string
|
39 |
+
*/
|
40 |
+
public function __toString() {
|
41 |
+
return $this->name;
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
|
46 |
+
/* Setup
|
47 |
+
===================== */
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @internal
|
51 |
+
* @return integer
|
52 |
+
*/
|
53 |
+
protected function get_term_from_query() {
|
54 |
+
global $wp_query;
|
55 |
+
if ( isset($wp_query->queried_object) ) {
|
56 |
+
$qo = $wp_query->queried_object;
|
57 |
+
return $qo->term_id;
|
58 |
+
}
|
59 |
+
if ( isset($wp_query->tax_query->queries[0]['terms'][0]) ) {
|
60 |
+
return $wp_query->tax_query->queries[0]['terms'][0];
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @internal
|
66 |
+
* @param int $tid
|
67 |
+
*/
|
68 |
+
protected function init( $tid ) {
|
69 |
+
$term = $this->get_term($tid);
|
70 |
+
if ( isset($term->id) ) {
|
71 |
+
$term->ID = $term->id;
|
72 |
+
} else if ( isset($term->term_id) ) {
|
73 |
+
$term->ID = $term->term_id;
|
74 |
+
} else if ( is_string($tid) ) {
|
75 |
+
//echo 'bad call using '.$tid;
|
76 |
+
//TimberHelper::error_log(debug_backtrace());
|
77 |
+
}
|
78 |
+
if ( isset($term->ID) ){
|
79 |
+
$term->id = $term->ID;
|
80 |
+
$this->import($term);
|
81 |
+
if ( isset($term->term_id) ) {
|
82 |
+
$custom = $this->get_term_meta($term->term_id);
|
83 |
+
$this->import($custom);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @internal
|
90 |
+
* @param int $tid
|
91 |
+
* @return array
|
92 |
+
*/
|
93 |
+
protected function get_term_meta($tid) {
|
94 |
+
$customs = array();
|
95 |
+
$customs = apply_filters('timber_term_get_meta', $customs, $tid, $this);
|
96 |
+
return apply_filters('timber/term/meta', $customs, $tid, $this);
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @internal
|
101 |
+
* @param int $tid
|
102 |
+
* @return mixed
|
103 |
+
*/
|
104 |
+
protected function get_term( $tid ) {
|
105 |
+
if ( is_object($tid) || is_array($tid) ) {
|
106 |
+
return $tid;
|
107 |
+
}
|
108 |
+
$tid = self::get_tid($tid);
|
109 |
+
|
110 |
+
if ( isset($this->taxonomy) && strlen($this->taxonomy) ) {
|
111 |
+
return get_term($tid, $this->taxonomy);
|
112 |
+
} else {
|
113 |
+
global $wpdb;
|
114 |
+
$query = $wpdb->prepare("SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d LIMIT 1", $tid);
|
115 |
+
$tax = $wpdb->get_var($query);
|
116 |
+
if (isset($tax) && strlen($tax)) {
|
117 |
+
return get_term($tid, $tax);
|
118 |
+
}
|
119 |
+
}
|
120 |
+
return null;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* @internal
|
125 |
+
* @param int $tid
|
126 |
+
* @return int
|
127 |
+
*/
|
128 |
+
protected function get_tid( $tid ) {
|
129 |
+
global $wpdb;
|
130 |
+
if ( is_numeric($tid) ) {
|
131 |
+
return $tid;
|
132 |
+
}
|
133 |
+
if ( gettype($tid) == 'object' ) {
|
134 |
+
$tid = $tid->term_id;
|
135 |
+
}
|
136 |
+
if ( is_numeric($tid) ) {
|
137 |
+
$query = $wpdb->prepare("SELECT * FROM $wpdb->terms WHERE term_id = %d", $tid);
|
138 |
+
} else {
|
139 |
+
$query = $wpdb->prepare("SELECT * FROM $wpdb->terms WHERE slug = %s", $tid);
|
140 |
+
}
|
141 |
+
$result = $wpdb->get_row($query);
|
142 |
+
if ( isset($result->term_id) ) {
|
143 |
+
$result->ID = $result->term_id;
|
144 |
+
$result->id = $result->term_id;
|
145 |
+
return $result->ID;
|
146 |
+
}
|
147 |
+
return 0;
|
148 |
+
}
|
149 |
+
|
150 |
+
/* Public methods
|
151 |
+
===================== */
|
152 |
+
|
153 |
+
/**
|
154 |
+
* @internal
|
155 |
+
* @return string
|
156 |
+
*/
|
157 |
+
public function get_edit_url() {
|
158 |
+
return get_edit_term_link($this->ID, $this->taxonomy);
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* @internal
|
163 |
+
* @param string $field_name
|
164 |
+
* @return string
|
165 |
+
*/
|
166 |
+
public function get_meta_field( $field_name ) {
|
167 |
+
if (!isset($this->$field_name)) {
|
168 |
+
$field_value = '';
|
169 |
+
$field_value = apply_filters('timber_term_get_meta_field', $field_value, $this->ID, $field_name, $this);
|
170 |
+
$field_value = apply_filters('timber/term/meta/field', $field_value, $this->ID, $field_name, $this);
|
171 |
+
$this->$field_name = $field_value;
|
172 |
+
}
|
173 |
+
return $this->$field_name;
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* @internal
|
178 |
+
* @return string
|
179 |
+
*/
|
180 |
+
public function get_path() {
|
181 |
+
$link = $this->get_link();
|
182 |
+
$rel = TimberURLHelper::get_rel_url($link, true);
|
183 |
+
$rel = apply_filters('timber_term_path', $rel, $this);
|
184 |
+
return apply_filters('timber/term/path', $rel, $this);
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* @internal
|
189 |
+
* @return string
|
190 |
+
*/
|
191 |
+
public function get_link() {
|
192 |
+
$link = get_term_link($this);
|
193 |
+
$link = apply_filters('timber_term_link', $link, $this);
|
194 |
+
return apply_filters('timber/term/link', $link, $this);
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* @param int $numberposts
|
199 |
+
* @param string $post_type
|
200 |
+
* @param string $PostClass
|
201 |
+
* @return array|bool|null
|
202 |
+
*/
|
203 |
+
public function get_posts( $numberposts = 10, $post_type = 'any', $PostClass = '' ) {
|
204 |
+
if (!strlen($PostClass)) {
|
205 |
+
$PostClass = $this->PostClass;
|
206 |
+
}
|
207 |
+
$default_tax_query = array(array(
|
208 |
+
'field' => 'id',
|
209 |
+
'terms' => $this->ID,
|
210 |
+
'taxonomy' => $this->taxonomy,
|
211 |
+
));
|
212 |
+
if ( is_string($numberposts) && strstr($numberposts, '=') ) {
|
213 |
+
$args = $numberposts;
|
214 |
+
$new_args = array();
|
215 |
+
parse_str($args, $new_args);
|
216 |
+
$args = $new_args;
|
217 |
+
$args['tax_query'] = $default_tax_query;
|
218 |
+
if (!isset($args['post_type'])) {
|
219 |
+
$args['post_type'] = 'any';
|
220 |
+
}
|
221 |
+
if (class_exists($post_type)) {
|
222 |
+
$PostClass = $post_type;
|
223 |
+
}
|
224 |
+
} else if ( is_array($numberposts) ) {
|
225 |
+
//they sent us an array already baked
|
226 |
+
$args = $numberposts;
|
227 |
+
if ( !isset($args['tax_query']) ) {
|
228 |
+
$args['tax_query'] = $default_tax_query;
|
229 |
+
}
|
230 |
+
if ( class_exists($post_type) ) {
|
231 |
+
$PostClass = $post_type;
|
232 |
+
}
|
233 |
+
if ( !isset($args['post_type']) ) {
|
234 |
+
$args['post_type'] = 'any';
|
235 |
+
}
|
236 |
+
} else {
|
237 |
+
$args = array(
|
238 |
+
'numberposts' => $numberposts,
|
239 |
+
'tax_query' => $default_tax_query,
|
240 |
+
'post_type' => $post_type
|
241 |
+
);
|
242 |
+
}
|
243 |
+
return Timber::get_posts($args, $PostClass);
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* @internal
|
248 |
+
* @return array
|
249 |
+
*/
|
250 |
+
public function get_children() {
|
251 |
+
if ( !isset($this->_children) ) {
|
252 |
+
$children = get_term_children($this->ID, $this->taxonomy);
|
253 |
+
foreach ($children as &$child) {
|
254 |
+
$child = new TimberTerm($child);
|
255 |
+
}
|
256 |
+
$this->_children = $children;
|
257 |
+
}
|
258 |
+
return $this->_children;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
*
|
263 |
+
*
|
264 |
+
* @param string $key
|
265 |
+
* @param mixed $value
|
266 |
+
*/
|
267 |
+
function update( $key, $value ) {
|
268 |
+
$value = apply_filters( 'timber_term_set_meta', $value, $key, $this->ID, $this );
|
269 |
+
$this->$key = $value;
|
270 |
+
}
|
271 |
+
|
272 |
+
/* Alias
|
273 |
+
====================== */
|
274 |
+
|
275 |
+
/**
|
276 |
+
* @api
|
277 |
+
* @return array
|
278 |
+
*/
|
279 |
+
public function children() {
|
280 |
+
return $this->get_children();
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* @api
|
285 |
+
* @return string
|
286 |
+
*/
|
287 |
+
public function edit_link() {
|
288 |
+
return $this->get_edit_url();
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* @internal
|
293 |
+
* @deprecated 0.21.8 use TimberTerm::link() instead
|
294 |
+
* @return string
|
295 |
+
*/
|
296 |
+
public function get_url() {
|
297 |
+
return $this->get_link();
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* @api
|
302 |
+
* @return string
|
303 |
+
*/
|
304 |
+
public function link() {
|
305 |
+
return $this->get_link();
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* @api
|
310 |
+
* @param string $field_name
|
311 |
+
* @return string
|
312 |
+
*/
|
313 |
+
public function meta( $field_name ) {
|
314 |
+
return $this->get_meta_field($field_name);
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* @api
|
319 |
+
* @return string
|
320 |
+
*/
|
321 |
+
public function path() {
|
322 |
+
return $this->get_path();
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* @api
|
327 |
+
* @param int $numberposts_or_args
|
328 |
+
* @param string $post_type_or_class
|
329 |
+
* @param string $post_class
|
330 |
+
* @example
|
331 |
+
* ```twig
|
332 |
+
* <h4>Recent posts in {{term.name}}</h4>
|
333 |
+
* <ul>
|
334 |
+
* {% for post in term.posts(3, 'post') %}
|
335 |
+
* <li><a href="{{post.link}}">{{post.title}}</a></li>
|
336 |
+
* {% endfor %}
|
337 |
+
* </ul>
|
338 |
+
* ```
|
339 |
+
* @return array|bool|null
|
340 |
+
*/
|
341 |
+
public function posts( $numberposts_or_args = 10, $post_type_or_class = 'any', $post_class = '' ) {
|
342 |
+
return $this->get_posts($numberposts_or_args, $post_type_or_class, $post_class);
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* @api
|
347 |
+
* @return string
|
348 |
+
*/
|
349 |
+
public function title() {
|
350 |
+
return $this->name;
|
351 |
+
}
|
352 |
+
|
353 |
+
/**
|
354 |
+
* @deprecated since 0.21.9
|
355 |
+
* @return string
|
356 |
+
*/
|
357 |
+
public function url() {
|
358 |
+
return $this->get_url();
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* @deprecated
|
363 |
+
* @param int $i
|
364 |
+
* @return string
|
365 |
+
*/
|
366 |
+
function get_page( $i ) {
|
367 |
+
return $this->get_path() . '/page/' . $i;
|
368 |
+
}
|
369 |
|
370 |
}
|
lib/timber-theme.php
CHANGED
@@ -1,58 +1,119 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
}
|
1 |
<?php
|
2 |
|
3 |
+
/**
|
4 |
+
* Need to display info about your theme? Well you've come to the right place. By default info on the current theme comes for free with what's fetched by `Timber::get_context()` in which case you can access it your theme like so:
|
5 |
+
* @example
|
6 |
+
* ```php
|
7 |
+
* <?php
|
8 |
+
* $context = Timber::get_context();
|
9 |
+
* Timber::render('index.twig', $context);
|
10 |
+
* ?>
|
11 |
+
* ```
|
12 |
+
* ```twig
|
13 |
+
* <script src="{{theme.link}}/static/js/all.js"></script>
|
14 |
+
* ```
|
15 |
+
* ```html
|
16 |
+
* <script src="http://example.org/wp-content/themes/my-theme/static/js/all.js"></script>
|
17 |
+
* ```
|
18 |
+
* @package Timber
|
19 |
+
*/
|
20 |
+
class TimberTheme extends TimberCore {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @api
|
24 |
+
* @var string the absolute path to the theme (ex: `http://example.org/wp-content/themes/my-timber-theme`)
|
25 |
+
*/
|
26 |
+
public $link;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @api
|
30 |
+
* @var string the human-friendly name of the theme (ex: `My Timber Starter Theme`)
|
31 |
+
*/
|
32 |
+
public $name;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @api
|
36 |
+
* @var string the relative path to the theme (ex: `/wp-content/themes/my-timber-theme`)
|
37 |
+
*/
|
38 |
+
public $path;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @api
|
42 |
+
* @var TimberTheme|bool the TimberTheme object for the parent theme (if it exists), false otherwise
|
43 |
+
*/
|
44 |
+
public $parent = false;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @api
|
48 |
+
* @var string the slug of the parent theme (ex: `_s`)
|
49 |
+
*/
|
50 |
+
public $parent_slug;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @api
|
54 |
+
* @var string the slug of the theme (ex: `my-super-theme`)
|
55 |
+
*/
|
56 |
+
public $slug;
|
57 |
+
public $uri;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Constructs a new TimberTheme object. NOTE the TimberTheme object of the current theme comes in the default `Timber::get_context()` call. You can access this in your twig template via `{{site.theme}}.
|
61 |
+
* @param string $slug
|
62 |
+
* @example
|
63 |
+
* ```php
|
64 |
+
* <?php
|
65 |
+
* $theme = new TimberTheme("my-theme");
|
66 |
+
* $context['theme_stuff'] = $theme;
|
67 |
+
* Timber::render('single.')
|
68 |
+
* ?>
|
69 |
+
* ```
|
70 |
+
* ```twig
|
71 |
+
* We are currently using the {{ theme_stuff.name }} theme.
|
72 |
+
* ```
|
73 |
+
* ```html
|
74 |
+
* We are currently using the My Theme theme.
|
75 |
+
* ```
|
76 |
+
*/
|
77 |
+
function __construct($slug = null) {
|
78 |
+
$this->init($slug);
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* @internal
|
83 |
+
* @param string $slug
|
84 |
+
*/
|
85 |
+
protected function init($slug = null) {
|
86 |
+
$data = wp_get_theme($slug);
|
87 |
+
$this->name = $data->get('Name');
|
88 |
+
$ss = $data->get_stylesheet();
|
89 |
+
$this->slug = $ss;
|
90 |
+
$this->path = WP_CONTENT_SUBDIR . str_replace(WP_CONTENT_DIR, '', get_stylesheet_directory());
|
91 |
+
$this->uri = get_stylesheet_directory_uri();
|
92 |
+
$this->link = $this->uri;
|
93 |
+
$this->parent_slug = $data->get('Template');
|
94 |
+
if (!$this->parent_slug) {
|
95 |
+
$this->path = WP_CONTENT_SUBDIR . str_replace(WP_CONTENT_DIR, '', get_template_directory());
|
96 |
+
$this->uri = get_template_directory_uri();
|
97 |
+
}
|
98 |
+
if ($this->parent_slug && $this->parent_slug != $this->slug) {
|
99 |
+
$this->parent = new TimberTheme($this->parent_slug);
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @param string $name
|
105 |
+
* @param bool $default
|
106 |
+
* @return string
|
107 |
+
*/
|
108 |
+
public function theme_mod($name, $default = false) {
|
109 |
+
return get_theme_mod($name, $default);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @return array
|
114 |
+
*/
|
115 |
+
public function theme_mods() {
|
116 |
+
return get_theme_mods();
|
117 |
+
}
|
118 |
|
119 |
}
|
lib/timber-twig.php
CHANGED
@@ -12,8 +12,8 @@ class TimberTwig {
|
|
12 |
}
|
13 |
|
14 |
function __construct() {
|
15 |
-
add_action( '
|
16 |
-
add_action( '
|
17 |
}
|
18 |
|
19 |
/**
|
@@ -28,6 +28,9 @@ class TimberTwig {
|
|
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 |
|
@@ -58,7 +61,6 @@ class TimberTwig {
|
|
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' ) ) );
|
@@ -94,6 +96,8 @@ class TimberTwig {
|
|
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 ) ) {
|
@@ -177,9 +181,9 @@ class TimberTwig {
|
|
177 |
$twig->addFunction( '__', new Twig_SimpleFunction( '__', function ( $text, $domain = 'default' ) {
|
178 |
return __( $text, $domain );
|
179 |
} ) );
|
180 |
-
|
181 |
$twig = apply_filters( 'get_twig', $twig );
|
182 |
-
|
183 |
return $twig;
|
184 |
}
|
185 |
|
@@ -197,26 +201,6 @@ class TimberTwig {
|
|
197 |
return $arr;
|
198 |
}
|
199 |
|
200 |
-
/**
|
201 |
-
*
|
202 |
-
*
|
203 |
-
* @param mixed $arr
|
204 |
-
* @param string $glue
|
205 |
-
* @return string
|
206 |
-
*/
|
207 |
-
function to_string( $arr, $glue = ' ' ) {
|
208 |
-
if ( is_string( $arr ) ) {
|
209 |
-
return $arr;
|
210 |
-
}
|
211 |
-
if ( is_array( $arr ) && count( $arr ) == 1 ) {
|
212 |
-
return $arr[0];
|
213 |
-
}
|
214 |
-
if ( is_array( $arr ) ) {
|
215 |
-
return implode( $glue, $arr );
|
216 |
-
}
|
217 |
-
return null;
|
218 |
-
}
|
219 |
-
|
220 |
/**
|
221 |
*
|
222 |
*
|
@@ -253,9 +237,8 @@ class TimberTwig {
|
|
253 |
}
|
254 |
|
255 |
/**
|
256 |
-
*
|
257 |
-
*
|
258 |
* @param mixed $body_classes
|
|
|
259 |
* @return string
|
260 |
*/
|
261 |
function body_class( $body_classes ) {
|
12 |
}
|
13 |
|
14 |
function __construct() {
|
15 |
+
add_action( 'timber/twig/filters', array( $this, 'add_timber_filters_deprecated' ) );
|
16 |
+
add_action( 'timber/twig/filters', array( $this, 'add_timber_filters' ) );
|
17 |
}
|
18 |
|
19 |
/**
|
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 |
+
$twig->addFilter( new Twig_SimpleFilter( 'string', function($arr, $glue = ' '){
|
32 |
+
return twig_join_filter($arr, $glue);
|
33 |
+
} ) );
|
34 |
return $twig;
|
35 |
}
|
36 |
|
61 |
/* other filters */
|
62 |
$twig->addFilter( new Twig_SimpleFilter( 'stripshortcodes', 'strip_shortcodes' ) );
|
63 |
$twig->addFilter( new Twig_SimpleFilter( 'array', array( $this, 'to_array' ) ) );
|
|
|
64 |
$twig->addFilter( new Twig_SimpleFilter( 'excerpt', 'wp_trim_words' ) );
|
65 |
$twig->addFilter( new Twig_SimpleFilter( 'function', array( $this, 'exec_function' ) ) );
|
66 |
$twig->addFilter( new Twig_SimpleFilter( 'pretags', array( $this, 'twig_pretags' ) ) );
|
96 |
$twig->addFunction( new Twig_SimpleFunction( 'function', array( &$this, 'exec_function' ) ) );
|
97 |
$twig->addFunction( new Twig_SimpleFunction( 'fn', array( &$this, 'exec_function' ) ) );
|
98 |
|
99 |
+
$twig->addFunction( new Twig_SimpleFunction( 'shortcode', 'do_shortcode' ) );
|
100 |
+
|
101 |
/* TimberObjects */
|
102 |
$twig->addFunction( new Twig_SimpleFunction( 'TimberPost', function ( $pid, $PostClass = 'TimberPost' ) {
|
103 |
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
181 |
$twig->addFunction( '__', new Twig_SimpleFunction( '__', function ( $text, $domain = 'default' ) {
|
182 |
return __( $text, $domain );
|
183 |
} ) );
|
184 |
+
/* get_twig is deprecated, use timber/twig */
|
185 |
$twig = apply_filters( 'get_twig', $twig );
|
186 |
+
$twig = apply_filters( 'timber/twig', $twig );
|
187 |
return $twig;
|
188 |
}
|
189 |
|
201 |
return $arr;
|
202 |
}
|
203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
/**
|
205 |
*
|
206 |
*
|
237 |
}
|
238 |
|
239 |
/**
|
|
|
|
|
240 |
* @param mixed $body_classes
|
241 |
+
* @deprecated 0.20.7
|
242 |
* @return string
|
243 |
*/
|
244 |
function body_class( $body_classes ) {
|
lib/timber-user.php
CHANGED
@@ -35,6 +35,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
35 |
}
|
36 |
|
37 |
/**
|
|
|
38 |
* @param string $field_name
|
39 |
* @return null
|
40 |
*/
|
@@ -43,6 +44,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
43 |
}
|
44 |
|
45 |
/**
|
|
|
46 |
* @param string $field
|
47 |
* @param mixed $value
|
48 |
*/
|
@@ -54,6 +56,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
54 |
}
|
55 |
|
56 |
/**
|
|
|
57 |
* @return string
|
58 |
*/
|
59 |
public function get_link() {
|
@@ -64,9 +67,10 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
64 |
}
|
65 |
|
66 |
/**
|
|
|
67 |
* @param int|bool $uid
|
68 |
*/
|
69 |
-
function init($uid = false) {
|
70 |
if ( $uid === false ) {
|
71 |
$uid = get_current_user_id();
|
72 |
}
|
@@ -137,13 +141,15 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
137 |
}
|
138 |
|
139 |
/**
|
140 |
-
* @
|
|
|
141 |
*/
|
142 |
function name() {
|
143 |
return $this->display_name;
|
144 |
}
|
145 |
|
146 |
/**
|
|
|
147 |
* @return string
|
148 |
*/
|
149 |
function get_permalink() {
|
@@ -151,6 +157,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
151 |
}
|
152 |
|
153 |
/**
|
|
|
154 |
* @return string
|
155 |
*/
|
156 |
function permalink() {
|
@@ -158,6 +165,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
158 |
}
|
159 |
|
160 |
/**
|
|
|
161 |
* @return string ex: /author/lincoln
|
162 |
*/
|
163 |
function get_path() {
|
@@ -173,6 +181,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
173 |
}
|
174 |
|
175 |
/**
|
|
|
176 |
* @return string
|
177 |
*/
|
178 |
function path() {
|
@@ -180,6 +189,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
180 |
}
|
181 |
|
182 |
/**
|
|
|
183 |
* @return string
|
184 |
*/
|
185 |
function slug() {
|
@@ -187,6 +197,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
187 |
}
|
188 |
|
189 |
/**
|
|
|
190 |
* @return string
|
191 |
*/
|
192 |
function link() {
|
35 |
}
|
36 |
|
37 |
/**
|
38 |
+
* @internal
|
39 |
* @param string $field_name
|
40 |
* @return null
|
41 |
*/
|
44 |
}
|
45 |
|
46 |
/**
|
47 |
+
* @internal
|
48 |
* @param string $field
|
49 |
* @param mixed $value
|
50 |
*/
|
56 |
}
|
57 |
|
58 |
/**
|
59 |
+
* @internal
|
60 |
* @return string
|
61 |
*/
|
62 |
public function get_link() {
|
67 |
}
|
68 |
|
69 |
/**
|
70 |
+
* @internal
|
71 |
* @param int|bool $uid
|
72 |
*/
|
73 |
+
protected function init($uid = false) {
|
74 |
if ( $uid === false ) {
|
75 |
$uid = get_current_user_id();
|
76 |
}
|
141 |
}
|
142 |
|
143 |
/**
|
144 |
+
* @api
|
145 |
+
* @return string the human-friendly name of the user (ex: "Buster Bluth")
|
146 |
*/
|
147 |
function name() {
|
148 |
return $this->display_name;
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
+
* @deprecated 0.21.8
|
153 |
* @return string
|
154 |
*/
|
155 |
function get_permalink() {
|
157 |
}
|
158 |
|
159 |
/**
|
160 |
+
* @deprecated 0.21.8
|
161 |
* @return string
|
162 |
*/
|
163 |
function permalink() {
|
165 |
}
|
166 |
|
167 |
/**
|
168 |
+
* @internal
|
169 |
* @return string ex: /author/lincoln
|
170 |
*/
|
171 |
function get_path() {
|
181 |
}
|
182 |
|
183 |
/**
|
184 |
+
* @api
|
185 |
* @return string
|
186 |
*/
|
187 |
function path() {
|
189 |
}
|
190 |
|
191 |
/**
|
192 |
+
* @api
|
193 |
* @return string
|
194 |
*/
|
195 |
function slug() {
|
197 |
}
|
198 |
|
199 |
/**
|
200 |
+
* @api
|
201 |
* @return string
|
202 |
*/
|
203 |
function link() {
|
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.
|
6 |
Tested up to: 4.2.3
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
@@ -34,13 +34,20 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
34 |
|
35 |
#### Want to read more?
|
36 |
* [Timber on GitHub](http://github.com/jarednova/timber/)
|
37 |
-
* [Timber Overview on Tidy Repo](http://
|
38 |
-
* ["
|
39 |
|
40 |
|
41 |
|
42 |
== Changelog ==
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
= 0.21.8 =
|
45 |
* Fixes to things in docs
|
46 |
* Added ID to timber/image/src filter (thanks @aaronhippie)
|
2 |
Contributors: jarednova
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
+
Stable tag: 0.21.9
|
6 |
Tested up to: 4.2.3
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
34 |
|
35 |
#### Want to read more?
|
36 |
* [Timber on GitHub](http://github.com/jarednova/timber/)
|
37 |
+
* [Timber Overview on Tidy Repo](http://tidyrepo.com/timber/)
|
38 |
+
* ["Timber and Twig Reignited My Love for WordPress" on CSS-Tricks](https://css-tricks.com/timber-and-twig-reignited-my-love-for-wordpress/)
|
39 |
|
40 |
|
41 |
|
42 |
== Changelog ==
|
43 |
|
44 |
+
= 0.21.9 =
|
45 |
+
* Much much much more inline docs
|
46 |
+
* Fix to TimberComment::approved()
|
47 |
+
* HHVM support confirmed (it always worked, but now the tests prove it)
|
48 |
+
* Fixes to multisite handling of themes
|
49 |
+
* Fix to comments pagination (thanks @newkind)
|
50 |
+
|
51 |
= 0.21.8 =
|
52 |
* Fixes to things in docs
|
53 |
* Added ID to timber/image/src filter (thanks @aaronhippie)
|
timber-starter-theme/search.php
CHANGED
@@ -15,4 +15,5 @@ $context = Timber::get_context();
|
|
15 |
$context['title'] = 'Search results for '. get_search_query();
|
16 |
$context['posts'] = Timber::get_posts();
|
17 |
|
|
|
18 |
Timber::render( $templates, $context );
|
15 |
$context['title'] = 'Search results for '. get_search_query();
|
16 |
$context['posts'] = Timber::get_posts();
|
17 |
|
18 |
+
|
19 |
Timber::render( $templates, $context );
|
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.
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
|
@@ -208,7 +208,7 @@ class Timber {
|
|
208 |
public static function get_sites( $blog_ids = false ) {
|
209 |
if ( !is_array( $blog_ids ) ) {
|
210 |
global $wpdb;
|
211 |
-
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
|
212 |
}
|
213 |
$return = array();
|
214 |
foreach ( $blog_ids as $blog_id ) {
|
@@ -296,6 +296,7 @@ class Timber {
|
|
296 |
$dummy_loader->get_twig();
|
297 |
$loader = new Twig_Loader_String();
|
298 |
$twig = new Twig_Environment( $loader );
|
|
|
299 |
$twig = apply_filters( 'twig_apply_filters', $twig );
|
300 |
return $twig->render( $string, $data );
|
301 |
}
|
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.9
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
|
208 |
public static function get_sites( $blog_ids = false ) {
|
209 |
if ( !is_array( $blog_ids ) ) {
|
210 |
global $wpdb;
|
211 |
+
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id ASC" );
|
212 |
}
|
213 |
$return = array();
|
214 |
foreach ( $blog_ids as $blog_id ) {
|
296 |
$dummy_loader->get_twig();
|
297 |
$loader = new Twig_Loader_String();
|
298 |
$twig = new Twig_Environment( $loader );
|
299 |
+
$twig = apply_filters( 'timber/twig/filters', $twig );
|
300 |
$twig = apply_filters( 'twig_apply_filters', $twig );
|
301 |
return $twig->render( $string, $data );
|
302 |
}
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit0998bd60918fc7cd5fbb070663b46709::getLoader();
|
vendor/composer/ClassLoader.php
CHANGED
@@ -54,6 +54,8 @@ class ClassLoader
|
|
54 |
private $useIncludePath = false;
|
55 |
private $classMap = array();
|
56 |
|
|
|
|
|
57 |
public function getPrefixes()
|
58 |
{
|
59 |
if (!empty($this->prefixesPsr0)) {
|
@@ -248,6 +250,27 @@ class ClassLoader
|
|
248 |
return $this->useIncludePath;
|
249 |
}
|
250 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
/**
|
252 |
* Registers this instance as an autoloader.
|
253 |
*
|
@@ -299,6 +322,9 @@ class ClassLoader
|
|
299 |
if (isset($this->classMap[$class])) {
|
300 |
return $this->classMap[$class];
|
301 |
}
|
|
|
|
|
|
|
302 |
|
303 |
$file = $this->findFileWithExtension($class, '.php');
|
304 |
|
54 |
private $useIncludePath = false;
|
55 |
private $classMap = array();
|
56 |
|
57 |
+
private $classMapAuthoritative = false;
|
58 |
+
|
59 |
public function getPrefixes()
|
60 |
{
|
61 |
if (!empty($this->prefixesPsr0)) {
|
250 |
return $this->useIncludePath;
|
251 |
}
|
252 |
|
253 |
+
/**
|
254 |
+
* Turns off searching the prefix and fallback directories for classes
|
255 |
+
* that have not been registered with the class map.
|
256 |
+
*
|
257 |
+
* @param bool $classMapAuthoritative
|
258 |
+
*/
|
259 |
+
public function setClassMapAuthoritative($classMapAuthoritative)
|
260 |
+
{
|
261 |
+
$this->classMapAuthoritative = $classMapAuthoritative;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Should class lookup fail if not found in the current class map?
|
266 |
+
*
|
267 |
+
* @return bool
|
268 |
+
*/
|
269 |
+
public function isClassMapAuthoritative()
|
270 |
+
{
|
271 |
+
return $this->classMapAuthoritative;
|
272 |
+
}
|
273 |
+
|
274 |
/**
|
275 |
* Registers this instance as an autoloader.
|
276 |
*
|
322 |
if (isset($this->classMap[$class])) {
|
323 |
return $this->classMap[$class];
|
324 |
}
|
325 |
+
if ($this->classMapAuthoritative) {
|
326 |
+
return false;
|
327 |
+
}
|
328 |
|
329 |
$file = $this->findFileWithExtension($class, '.php');
|
330 |
|
vendor/composer/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
Copyright (c) 2015 Nils Adermann, Jordi Boggiano
|
3 |
+
|
4 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
+
of this software and associated documentation files (the "Software"), to deal
|
6 |
+
in the Software without restriction, including without limitation the rights
|
7 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
+
to do so, subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all
|
12 |
+
copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
+
THE SOFTWARE.
|
21 |
+
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit5f4dd105040c53136ae075426ca9493e
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
@@ -44,7 +44,7 @@ class ComposerAutoloaderInit5f4dd105040c53136ae075426ca9493e
|
|
44 |
}
|
45 |
}
|
46 |
|
47 |
-
function
|
48 |
{
|
49 |
require $file;
|
50 |
}
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit0998bd60918fc7cd5fbb070663b46709
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit0998bd60918fc7cd5fbb070663b46709', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit0998bd60918fc7cd5fbb070663b46709', 'loadClassLoader'));
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
44 |
}
|
45 |
}
|
46 |
|
47 |
+
function composerRequire0998bd60918fc7cd5fbb070663b46709($file)
|
48 |
{
|
49 |
require $file;
|
50 |
}
|
vendor/composer/installed.json
CHANGED
@@ -98,27 +98,27 @@
|
|
98 |
},
|
99 |
{
|
100 |
"name": "twig/twig",
|
101 |
-
"version": "v1.
|
102 |
-
"version_normalized": "1.
|
103 |
"source": {
|
104 |
"type": "git",
|
105 |
"url": "https://github.com/twigphp/Twig.git",
|
106 |
-
"reference": "
|
107 |
},
|
108 |
"dist": {
|
109 |
"type": "zip",
|
110 |
-
"url": "https://api.github.com/repos/twigphp/Twig/zipball/
|
111 |
-
"reference": "
|
112 |
"shasum": ""
|
113 |
},
|
114 |
"require": {
|
115 |
"php": ">=5.2.7"
|
116 |
},
|
117 |
-
"time": "2015-
|
118 |
"type": "library",
|
119 |
"extra": {
|
120 |
"branch-alias": {
|
121 |
-
"dev-master": "1.
|
122 |
}
|
123 |
},
|
124 |
"installation-source": "dist",
|
98 |
},
|
99 |
{
|
100 |
"name": "twig/twig",
|
101 |
+
"version": "v1.20.0",
|
102 |
+
"version_normalized": "1.20.0.0",
|
103 |
"source": {
|
104 |
"type": "git",
|
105 |
"url": "https://github.com/twigphp/Twig.git",
|
106 |
+
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844"
|
107 |
},
|
108 |
"dist": {
|
109 |
"type": "zip",
|
110 |
+
"url": "https://api.github.com/repos/twigphp/Twig/zipball/1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
|
111 |
+
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
|
112 |
"shasum": ""
|
113 |
},
|
114 |
"require": {
|
115 |
"php": ">=5.2.7"
|
116 |
},
|
117 |
+
"time": "2015-08-12 15:56:39",
|
118 |
"type": "library",
|
119 |
"extra": {
|
120 |
"branch-alias": {
|
121 |
+
"dev-master": "1.20-dev"
|
122 |
}
|
123 |
},
|
124 |
"installation-source": "dist",
|
vendor/twig/twig/CHANGELOG
CHANGED
@@ -1,3 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
* 1.18.2 (2015-06-06)
|
2 |
|
3 |
* fixed template/line guessing in exceptions for nested templates
|
1 |
+
* 1.20.0 (2015-08-12)
|
2 |
+
|
3 |
+
* forbid access to the Twig environment from templates and internal parts of Twig_Template
|
4 |
+
* fixed limited RCEs when in sandbox mode
|
5 |
+
* deprecated Twig_Template::getEnvironment()
|
6 |
+
* deprecated the _self variable for usage outside of the from and import tags
|
7 |
+
* added Twig_BaseNodeVisitor to ease the compatibility of node visitors
|
8 |
+
between 1.x and 2.x
|
9 |
+
|
10 |
+
* 1.19.0 (2015-07-31)
|
11 |
+
|
12 |
+
* fixed wrong error message when including an undefined template in a child template
|
13 |
+
* added support for variadic filters, functions, and tests
|
14 |
+
* added support for extra positional arguments in macros
|
15 |
+
* added ignore_missing flag to the source function
|
16 |
+
* fixed batch filter with zero items
|
17 |
+
* deprecated Twig_Environment::clearTemplateCache()
|
18 |
+
* fixed sandbox disabling when using the include function
|
19 |
+
|
20 |
* 1.18.2 (2015-06-06)
|
21 |
|
22 |
* fixed template/line guessing in exceptions for nested templates
|
vendor/twig/twig/composer.json
CHANGED
@@ -36,7 +36,7 @@
|
|
36 |
},
|
37 |
"extra": {
|
38 |
"branch-alias": {
|
39 |
-
"dev-master": "1.
|
40 |
}
|
41 |
}
|
42 |
}
|
36 |
},
|
37 |
"extra": {
|
38 |
"branch-alias": {
|
39 |
+
"dev-master": "1.20-dev"
|
40 |
}
|
41 |
}
|
42 |
}
|
vendor/twig/twig/doc/advanced.rst
CHANGED
@@ -224,6 +224,23 @@ through your filter::
|
|
224 |
|
225 |
$filter = new Twig_SimpleFilter('somefilter', 'somefilter', array('pre_escape' => 'html', 'is_safe' => array('html')));
|
226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
Dynamic Filters
|
228 |
~~~~~~~~~~~~~~~
|
229 |
|
@@ -331,6 +348,10 @@ The ``node`` sub-node will contain an expression of ``my_value``. Node-based
|
|
331 |
tests also have access to the ``arguments`` node. This node will contain the
|
332 |
various other arguments that have been provided to your test.
|
333 |
|
|
|
|
|
|
|
|
|
334 |
Tags
|
335 |
----
|
336 |
|
224 |
|
225 |
$filter = new Twig_SimpleFilter('somefilter', 'somefilter', array('pre_escape' => 'html', 'is_safe' => array('html')));
|
226 |
|
227 |
+
Variadic Filters
|
228 |
+
~~~~~~~~~~~~~~~~
|
229 |
+
|
230 |
+
.. versionadded:: 1.19
|
231 |
+
Support for variadic filters was added in Twig 1.19.
|
232 |
+
|
233 |
+
When a filter should accept an arbitrary number of arguments, set the
|
234 |
+
``is_variadic`` option to ``true``; Twig will pass the extra arguments as the
|
235 |
+
last argument to the filter call as an array::
|
236 |
+
|
237 |
+
$filter = new Twig_SimpleFilter('thumbnail', function ($file, array $options = array()) {
|
238 |
+
// ...
|
239 |
+
}, array('is_variadic' => true));
|
240 |
+
|
241 |
+
Be warned that named arguments passed to a variadic filter cannot be checked
|
242 |
+
for validity as they will automatically end up in the option array.
|
243 |
+
|
244 |
Dynamic Filters
|
245 |
~~~~~~~~~~~~~~~
|
246 |
|
348 |
tests also have access to the ``arguments`` node. This node will contain the
|
349 |
various other arguments that have been provided to your test.
|
350 |
|
351 |
+
If you want to pass a variable number of positional or named arguments to the
|
352 |
+
test, set the ``is_variadic`` option to ``true``. Tests also support dynamic
|
353 |
+
name feature as filters and functions.
|
354 |
+
|
355 |
Tags
|
356 |
----
|
357 |
|
vendor/twig/twig/doc/deprecated.rst
CHANGED
@@ -107,9 +107,30 @@ Loaders
|
|
107 |
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
|
108 |
2.0.
|
109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
Globals
|
111 |
-------
|
112 |
|
113 |
* As of Twig 2.x, the ability to register a global variable after the runtime
|
114 |
or the extensions have been initialized is not possible anymore (but
|
115 |
changing the value of an already registered global is possible).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
|
108 |
2.0.
|
109 |
|
110 |
+
Node Visitors
|
111 |
+
-------------
|
112 |
+
|
113 |
+
* Because of the removal of ``Twig_NodeInterface`` in 2.0, you need to extend
|
114 |
+
``Twig_BaseNodeVistor`` instead of implementing ``Twig_NodeVisitorInterface``
|
115 |
+
directly to make your node visitors compatible with both Twig 1.x and 2.x.
|
116 |
+
|
117 |
Globals
|
118 |
-------
|
119 |
|
120 |
* As of Twig 2.x, the ability to register a global variable after the runtime
|
121 |
or the extensions have been initialized is not possible anymore (but
|
122 |
changing the value of an already registered global is possible).
|
123 |
+
|
124 |
+
* As of Twig 1.x, the ``_self`` global variable is deprecated except for usage
|
125 |
+
in the ``from`` and the ``import`` tags. In Twig 2.0, ``_self`` is not
|
126 |
+
exposed anymore but still usable in the ``from`` and the ``import`` tags.
|
127 |
+
|
128 |
+
Miscellaneous
|
129 |
+
-------------
|
130 |
+
|
131 |
+
* As of Twig 1.x, ``Twig_Environment::clearTemplateCache()`` is deprecated and
|
132 |
+
will be removed in 2.0.
|
133 |
+
|
134 |
+
* As of Twig 1.x, ``Twig_Template::getEnvironment()`` and
|
135 |
+
``Twig_TemplateInterface::getEnvironment()`` are deprecated and will be
|
136 |
+
removed in 2.0.
|
vendor/twig/twig/doc/filters/batch.rst
CHANGED
@@ -43,3 +43,9 @@ The above example will be rendered as:
|
|
43 |
<td>No item</td>
|
44 |
</tr>
|
45 |
</table>
|
|
|
|
|
|
|
|
|
|
|
|
43 |
<td>No item</td>
|
44 |
</tr>
|
45 |
</table>
|
46 |
+
|
47 |
+
Arguments
|
48 |
+
---------
|
49 |
+
|
50 |
+
* ``size``: The size of the batch; fractional numbers will be rounded up
|
51 |
+
* ``fill``: Used to fill in missing items
|
vendor/twig/twig/doc/functions/source.rst
CHANGED
@@ -4,6 +4,9 @@
|
|
4 |
.. versionadded:: 1.15
|
5 |
The ``source`` function was added in Twig 1.15.
|
6 |
|
|
|
|
|
|
|
7 |
The ``source`` function returns the content of a template without rendering it:
|
8 |
|
9 |
.. code-block:: jinja
|
@@ -11,6 +14,13 @@ The ``source`` function returns the content of a template without rendering it:
|
|
11 |
{{ source('template.html') }}
|
12 |
{{ source(some_var) }}
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
The function uses the same template loaders as the ones used to include
|
15 |
templates. So, if you are using the filesystem loader, the templates are looked
|
16 |
for in the paths defined by it.
|
@@ -19,3 +29,4 @@ Arguments
|
|
19 |
---------
|
20 |
|
21 |
* ``name``: The name of the template to read
|
|
4 |
.. versionadded:: 1.15
|
5 |
The ``source`` function was added in Twig 1.15.
|
6 |
|
7 |
+
.. versionadded:: 1.18.3
|
8 |
+
The ``ignore_missing`` flag was added in Twig 1.18.3.
|
9 |
+
|
10 |
The ``source`` function returns the content of a template without rendering it:
|
11 |
|
12 |
.. code-block:: jinja
|
14 |
{{ source('template.html') }}
|
15 |
{{ source(some_var) }}
|
16 |
|
17 |
+
When you set the ``ignore_missing`` flag, Twig will return an empty string if
|
18 |
+
the template does not exist:
|
19 |
+
|
20 |
+
.. code-block:: jinja
|
21 |
+
|
22 |
+
{{ source('template.html', ignore_missing = true) }}
|
23 |
+
|
24 |
The function uses the same template loaders as the ones used to include
|
25 |
templates. So, if you are using the filesystem loader, the templates are looked
|
26 |
for in the paths defined by it.
|
29 |
---------
|
30 |
|
31 |
* ``name``: The name of the template to read
|
32 |
+
* ``ignore_missing``: Whether to ignore missing templates or not
|
vendor/twig/twig/doc/internals.rst
CHANGED
@@ -124,7 +124,7 @@ using)::
|
|
124 |
{
|
125 |
// line 1
|
126 |
echo "Hello ";
|
127 |
-
echo twig_escape_filter($this->env,
|
128 |
}
|
129 |
|
130 |
// some more code
|
124 |
{
|
125 |
// line 1
|
126 |
echo "Hello ";
|
127 |
+
echo twig_escape_filter($this->env, isset($context["name"]) ? $context["name"] : null), "html", null, true);
|
128 |
}
|
129 |
|
130 |
// some more code
|
vendor/twig/twig/doc/intro.rst
CHANGED
@@ -21,10 +21,14 @@ The key-features are...
|
|
21 |
* *Flexible*: Twig is powered by a flexible lexer and parser. This allows the
|
22 |
developer to define its own custom tags and filters, and create its own DSL.
|
23 |
|
|
|
|
|
|
|
|
|
24 |
Prerequisites
|
25 |
-------------
|
26 |
|
27 |
-
Twig needs at least **PHP 5.2.
|
28 |
|
29 |
Installation
|
30 |
------------
|
21 |
* *Flexible*: Twig is powered by a flexible lexer and parser. This allows the
|
22 |
developer to define its own custom tags and filters, and create its own DSL.
|
23 |
|
24 |
+
Twig is used by many Open-Source projects like Symfony, Drupal8, eZPublish,
|
25 |
+
phpBB, Piwik, OroCRM, and many frameworks have support for it as well like
|
26 |
+
Slim, Yii, Laravel, Codeigniter, and Kohana, just to name a few.
|
27 |
+
|
28 |
Prerequisites
|
29 |
-------------
|
30 |
|
31 |
+
Twig needs at least **PHP 5.2.7** to run.
|
32 |
|
33 |
Installation
|
34 |
------------
|
vendor/twig/twig/doc/tags/macro.rst
CHANGED
@@ -20,6 +20,9 @@ Macros differs from native PHP functions in a few ways:
|
|
20 |
|
21 |
* Arguments of a macro are always optional.
|
22 |
|
|
|
|
|
|
|
23 |
But as with PHP functions, macros don't have access to the current template
|
24 |
variables.
|
25 |
|
20 |
|
21 |
* Arguments of a macro are always optional.
|
22 |
|
23 |
+
* If extra positional arguments are passed to a macro, they end up in the
|
24 |
+
special ``varargs`` variable as a list of values.
|
25 |
+
|
26 |
But as with PHP functions, macros don't have access to the current template
|
27 |
variables.
|
28 |
|
vendor/twig/twig/doc/tags/use.rst
CHANGED
@@ -74,7 +74,7 @@ is ignored. To avoid name conflicts, you can rename imported blocks:
|
|
74 |
|
75 |
{% extends "base.html" %}
|
76 |
|
77 |
-
{% use "blocks.html" with sidebar as base_sidebar %}
|
78 |
|
79 |
{% block sidebar %}{% endblock %}
|
80 |
{% block title %}{% endblock %}
|
74 |
|
75 |
{% extends "base.html" %}
|
76 |
|
77 |
+
{% use "blocks.html" with sidebar as base_sidebar, title as base_title %}
|
78 |
|
79 |
{% block sidebar %}{% endblock %}
|
80 |
{% block title %}{% endblock %}
|
vendor/twig/twig/doc/templates.rst
CHANGED
@@ -93,7 +93,7 @@ access the variable attribute:
|
|
93 |
don't put the braces around them.
|
94 |
|
95 |
If a variable or attribute does not exist, you will receive a ``null`` value
|
96 |
-
when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables``
|
97 |
is set, Twig will throw an error (see :ref:`environment options<environment_options>`).
|
98 |
|
99 |
.. sidebar:: Implementation
|
@@ -124,7 +124,7 @@ Global Variables
|
|
124 |
|
125 |
The following variables are always available in templates:
|
126 |
|
127 |
-
* ``_self``: references the current template;
|
128 |
* ``_context``: references the current context;
|
129 |
* ``_charset``: references the current charset.
|
130 |
|
@@ -541,6 +541,9 @@ macro call:
|
|
541 |
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
542 |
{% endmacro %}
|
543 |
|
|
|
|
|
|
|
544 |
.. _twig-expressions:
|
545 |
|
546 |
Expressions
|
93 |
don't put the braces around them.
|
94 |
|
95 |
If a variable or attribute does not exist, you will receive a ``null`` value
|
96 |
+
when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables``
|
97 |
is set, Twig will throw an error (see :ref:`environment options<environment_options>`).
|
98 |
|
99 |
.. sidebar:: Implementation
|
124 |
|
125 |
The following variables are always available in templates:
|
126 |
|
127 |
+
* ``_self``: references the current template (deprecated since Twig 1.20);
|
128 |
* ``_context``: references the current context;
|
129 |
* ``_charset``: references the current charset.
|
130 |
|
541 |
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
542 |
{% endmacro %}
|
543 |
|
544 |
+
If extra positional arguments are passed to a macro call, they end up in the
|
545 |
+
special ``varargs`` variable as a list of values.
|
546 |
+
|
547 |
.. _twig-expressions:
|
548 |
|
549 |
Expressions
|
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.
|
19 |
|
20 |
#include "php.h"
|
21 |
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
+
#define PHP_TWIG_VERSION "1.20.0"
|
19 |
|
20 |
#include "php.h"
|
21 |
|
vendor/twig/twig/ext/twig/twig.c
CHANGED
@@ -55,7 +55,7 @@ ZEND_BEGIN_ARG_INFO_EX(twig_template_get_attribute_args, ZEND_SEND_BY_VAL, ZEND_
|
|
55 |
ZEND_END_ARG_INFO()
|
56 |
|
57 |
#ifndef PHP_FE_END
|
58 |
-
#define PHP_FE_END { NULL, NULL, NULL
|
59 |
#endif
|
60 |
|
61 |
static const zend_function_entry twig_functions[] = {
|
@@ -609,6 +609,7 @@ static char *TWIG_GET_CLASS_NAME(zval *object TSRMLS_DC)
|
|
609 |
|
610 |
static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
611 |
{
|
|
|
612 |
zval *retval;
|
613 |
char *item;
|
614 |
size_t item_len;
|
@@ -619,12 +620,23 @@ static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, v
|
|
619 |
return 0;
|
620 |
}
|
621 |
|
|
|
622 |
retval = va_arg(args, zval*);
|
623 |
|
624 |
item_len = strlen(mptr->common.function_name);
|
625 |
item = estrndup(mptr->common.function_name, item_len);
|
626 |
php_strtolower(item, item_len);
|
627 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
628 |
add_assoc_stringl_ex(retval, item, item_len+1, item, item_len, 0);
|
629 |
|
630 |
return 0;
|
@@ -670,7 +682,7 @@ static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name
|
|
670 |
array_init(class_methods);
|
671 |
array_init(class_properties);
|
672 |
// add all methods to self::cache[$class]['methods']
|
673 |
-
zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class,
|
674 |
zend_hash_apply_with_arguments(&class_ce->properties_info APPLY_TSRMLS_CC, twig_add_property_to_class, 2, &class_ce, class_properties);
|
675 |
|
676 |
add_assoc_zval(class_info, "methods", class_methods);
|
@@ -898,7 +910,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
898 |
|
899 |
/*
|
900 |
// object property
|
901 |
-
if (Twig_Template::METHOD_CALL !== $type) {
|
902 |
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
903 |
if ($isDefinedTest) {
|
904 |
return true;
|
@@ -912,7 +924,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
912 |
}
|
913 |
}
|
914 |
*/
|
915 |
-
if (strcmp("method", type) != 0) {
|
916 |
zval *tmp_properties, *tmp_item;
|
917 |
|
918 |
tmp_properties = TWIG_GET_ARRAY_ELEMENT(tmp_class, "properties", strlen("properties") TSRMLS_CC);
|
@@ -939,7 +951,23 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
939 |
/*
|
940 |
// object method
|
941 |
if (!isset(self::$cache[$class]['methods'])) {
|
942 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
943 |
}
|
944 |
|
945 |
$call = false;
|
55 |
ZEND_END_ARG_INFO()
|
56 |
|
57 |
#ifndef PHP_FE_END
|
58 |
+
#define PHP_FE_END { NULL, NULL, NULL}
|
59 |
#endif
|
60 |
|
61 |
static const zend_function_entry twig_functions[] = {
|
609 |
|
610 |
static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
611 |
{
|
612 |
+
zend_class_entry *ce;
|
613 |
zval *retval;
|
614 |
char *item;
|
615 |
size_t item_len;
|
620 |
return 0;
|
621 |
}
|
622 |
|
623 |
+
ce = *va_arg(args, zend_class_entry**);
|
624 |
retval = va_arg(args, zval*);
|
625 |
|
626 |
item_len = strlen(mptr->common.function_name);
|
627 |
item = estrndup(mptr->common.function_name, item_len);
|
628 |
php_strtolower(item, item_len);
|
629 |
|
630 |
+
if (strcmp("getenvironment", item) == 0) {
|
631 |
+
zend_class_entry **twig_template_ce;
|
632 |
+
if (zend_lookup_class("Twig_Template", strlen("Twig_Template"), &twig_template_ce TSRMLS_CC) == FAILURE) {
|
633 |
+
return 0;
|
634 |
+
}
|
635 |
+
if (instanceof_function(ce, *twig_template_ce TSRMLS_CC)) {
|
636 |
+
return 0;
|
637 |
+
}
|
638 |
+
}
|
639 |
+
|
640 |
add_assoc_stringl_ex(retval, item, item_len+1, item, item_len, 0);
|
641 |
|
642 |
return 0;
|
682 |
array_init(class_methods);
|
683 |
array_init(class_properties);
|
684 |
// add all methods to self::cache[$class]['methods']
|
685 |
+
zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class, 2, &class_ce, class_methods);
|
686 |
zend_hash_apply_with_arguments(&class_ce->properties_info APPLY_TSRMLS_CC, twig_add_property_to_class, 2, &class_ce, class_properties);
|
687 |
|
688 |
add_assoc_zval(class_info, "methods", class_methods);
|
910 |
|
911 |
/*
|
912 |
// object property
|
913 |
+
if (Twig_Template::METHOD_CALL !== $type && !$object instanceof Twig_Template) {
|
914 |
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
915 |
if ($isDefinedTest) {
|
916 |
return true;
|
924 |
}
|
925 |
}
|
926 |
*/
|
927 |
+
if (strcmp("method", type) != 0 && !TWIG_INSTANCE_OF_USERLAND(object, "Twig_Template" TSRMLS_CC)) {
|
928 |
zval *tmp_properties, *tmp_item;
|
929 |
|
930 |
tmp_properties = TWIG_GET_ARRAY_ELEMENT(tmp_class, "properties", strlen("properties") TSRMLS_CC);
|
951 |
/*
|
952 |
// object method
|
953 |
if (!isset(self::$cache[$class]['methods'])) {
|
954 |
+
if ($object instanceof self) {
|
955 |
+
$ref = new ReflectionClass($class);
|
956 |
+
$methods = array();
|
957 |
+
|
958 |
+
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
959 |
+
$methodName = strtolower($refMethod->name);
|
960 |
+
|
961 |
+
// Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
|
962 |
+
if ('getenvironment' !== $methodName) {
|
963 |
+
$methods[$methodName] = true;
|
964 |
+
}
|
965 |
+
}
|
966 |
+
|
967 |
+
self::$cache[$class]['methods'] = $methods;
|
968 |
+
} else {
|
969 |
+
self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
|
970 |
+
}
|
971 |
}
|
972 |
|
973 |
$call = false;
|
vendor/twig/twig/lib/Twig/BaseNodeVisitor.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) Fabien Potencier
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Twig_BaseNodeVisitor can be used to make node visitors compatible with Twig 1.x and 2.x.
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*/
|
17 |
+
abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* {@inheritdoc}
|
21 |
+
*/
|
22 |
+
final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
23 |
+
{
|
24 |
+
if (!$node instanceof Twig_Node) {
|
25 |
+
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
|
26 |
+
}
|
27 |
+
|
28 |
+
return $this->doEnterNode($node, $env);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* {@inheritdoc}
|
33 |
+
*/
|
34 |
+
final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
35 |
+
{
|
36 |
+
if (!$node instanceof Twig_Node) {
|
37 |
+
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
|
38 |
+
}
|
39 |
+
|
40 |
+
return $this->doLeaveNode($node, $env);
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Called before child nodes are visited.
|
45 |
+
*
|
46 |
+
* @param Twig_Node $node The node to visit
|
47 |
+
* @param Twig_Environment $env The Twig environment instance
|
48 |
+
*
|
49 |
+
* @return Twig_Node The modified node
|
50 |
+
*/
|
51 |
+
abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env);
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Called after child nodes are visited.
|
55 |
+
*
|
56 |
+
* @param Twig_Node $node The node to visit
|
57 |
+
* @param Twig_Environment $env The Twig environment instance
|
58 |
+
*
|
59 |
+
* @return Twig_Node|false The modified node or false if the node must be removed
|
60 |
+
*/
|
61 |
+
abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env);
|
62 |
+
}
|
vendor/twig/twig/lib/Twig/Environment.php
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
-
const VERSION = '1.
|
20 |
|
21 |
protected $charset;
|
22 |
protected $loader;
|
@@ -89,21 +89,21 @@ class Twig_Environment
|
|
89 |
}
|
90 |
|
91 |
$options = array_merge(array(
|
92 |
-
'debug'
|
93 |
-
'charset'
|
94 |
'base_template_class' => 'Twig_Template',
|
95 |
-
'strict_variables'
|
96 |
-
'autoescape'
|
97 |
-
'cache'
|
98 |
-
'auto_reload'
|
99 |
-
'optimizations'
|
100 |
), $options);
|
101 |
|
102 |
-
$this->debug
|
103 |
-
$this->charset
|
104 |
-
$this->baseTemplateClass
|
105 |
-
$this->autoReload
|
106 |
-
$this->strictVariables
|
107 |
$this->runtimeInitialized = false;
|
108 |
$this->setCache($options['cache']);
|
109 |
$this->functionCallbacks = array();
|
@@ -443,6 +443,8 @@ class Twig_Environment
|
|
443 |
|
444 |
/**
|
445 |
* Clears the internal template cache.
|
|
|
|
|
446 |
*/
|
447 |
public function clearTemplateCache()
|
448 |
{
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
+
const VERSION = '1.20.0';
|
20 |
|
21 |
protected $charset;
|
22 |
protected $loader;
|
89 |
}
|
90 |
|
91 |
$options = array_merge(array(
|
92 |
+
'debug' => false,
|
93 |
+
'charset' => 'UTF-8',
|
94 |
'base_template_class' => 'Twig_Template',
|
95 |
+
'strict_variables' => false,
|
96 |
+
'autoescape' => 'html',
|
97 |
+
'cache' => false,
|
98 |
+
'auto_reload' => null,
|
99 |
+
'optimizations' => -1,
|
100 |
), $options);
|
101 |
|
102 |
+
$this->debug = (bool) $options['debug'];
|
103 |
+
$this->charset = strtoupper($options['charset']);
|
104 |
+
$this->baseTemplateClass = $options['base_template_class'];
|
105 |
+
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
|
106 |
+
$this->strictVariables = (bool) $options['strict_variables'];
|
107 |
$this->runtimeInitialized = false;
|
108 |
$this->setCache($options['cache']);
|
109 |
$this->functionCallbacks = array();
|
443 |
|
444 |
/**
|
445 |
* Clears the internal template cache.
|
446 |
+
*
|
447 |
+
* @deprecated since 1.18.3 (to be removed in 2.0)
|
448 |
*/
|
449 |
public function clearTemplateCache()
|
450 |
{
|
vendor/twig/twig/lib/Twig/ExpressionParser.php
CHANGED
@@ -387,7 +387,13 @@ class Twig_ExpressionParser
|
|
387 |
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
388 |
}
|
389 |
|
390 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
$node->setAttribute('safe', true);
|
392 |
|
393 |
return $node;
|
387 |
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
388 |
}
|
389 |
|
390 |
+
$name = $arg->getAttribute('value');
|
391 |
+
|
392 |
+
if ($this->parser->isReservedMacroName($name)) {
|
393 |
+
throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword', $name), $token->getLine(), $this->parser->getFilename());
|
394 |
+
}
|
395 |
+
|
396 |
+
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno);
|
397 |
$node->setAttribute('safe', true);
|
398 |
|
399 |
return $node;
|
vendor/twig/twig/lib/Twig/Extension/Core.php
CHANGED
@@ -255,37 +255,37 @@ class Twig_Extension_Core extends Twig_Extension
|
|
255 |
return array(
|
256 |
array(
|
257 |
'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
|
258 |
-
'-'
|
259 |
-
'+'
|
260 |
),
|
261 |
array(
|
262 |
-
'or'
|
263 |
-
'and'
|
264 |
-
'b-or'
|
265 |
-
'b-xor'
|
266 |
-
'b-and'
|
267 |
-
'=='
|
268 |
-
'!='
|
269 |
-
'<'
|
270 |
-
'>'
|
271 |
-
'>='
|
272 |
-
'<='
|
273 |
-
'not in'
|
274 |
-
'in'
|
275 |
-
'matches'
|
276 |
'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
277 |
-
'ends with'
|
278 |
-
'..'
|
279 |
-
'+'
|
280 |
-
'-'
|
281 |
-
'~'
|
282 |
-
'*'
|
283 |
-
'/'
|
284 |
-
'//'
|
285 |
-
'%'
|
286 |
-
'is'
|
287 |
-
'is not'
|
288 |
-
'**'
|
289 |
),
|
290 |
);
|
291 |
}
|
@@ -382,7 +382,7 @@ function twig_cycle($values, $position)
|
|
382 |
* Returns a random value depending on the supplied parameter type:
|
383 |
* - a random item from a Traversable or array
|
384 |
* - a random character from a string
|
385 |
-
* - a random integer between 0 and the integer parameter
|
386 |
*
|
387 |
* @param Twig_Environment $env A Twig_Environment instance
|
388 |
* @param Traversable|array|int|string $values The values to pick a random item from
|
@@ -466,7 +466,7 @@ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $
|
|
466 |
}
|
467 |
|
468 |
/**
|
469 |
-
* Returns a new date object modified
|
470 |
*
|
471 |
* <pre>
|
472 |
* {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
|
@@ -1190,7 +1190,7 @@ function _twig_escape_html_attr_callback($matches)
|
|
1190 |
$chr = $matches[0];
|
1191 |
$ord = ord($chr);
|
1192 |
|
1193 |
-
|
1194 |
* The following replaces characters undefined in HTML with the
|
1195 |
* hex entity for the Unicode replacement character.
|
1196 |
*/
|
@@ -1198,7 +1198,7 @@ function _twig_escape_html_attr_callback($matches)
|
|
1198 |
return '�';
|
1199 |
}
|
1200 |
|
1201 |
-
|
1202 |
* Check if the current character to escape has a name entity we should
|
1203 |
* replace it with while grabbing the hex value of the character.
|
1204 |
*/
|
@@ -1214,7 +1214,7 @@ function _twig_escape_html_attr_callback($matches)
|
|
1214 |
return sprintf('&%s;', $entityMap[$int]);
|
1215 |
}
|
1216 |
|
1217 |
-
|
1218 |
* Per OWASP recommendations, we'll use hex entities for any other
|
1219 |
* characters where a named entity does not exist.
|
1220 |
*/
|
@@ -1427,10 +1427,15 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|
1427 |
}
|
1428 |
}
|
1429 |
|
|
|
1430 |
try {
|
1431 |
-
|
1432 |
} catch (Twig_Error_Loader $e) {
|
1433 |
if (!$ignoreMissing) {
|
|
|
|
|
|
|
|
|
1434 |
throw $e;
|
1435 |
}
|
1436 |
}
|
@@ -1438,18 +1443,27 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|
1438 |
if ($isSandboxed && !$alreadySandboxed) {
|
1439 |
$sandbox->disableSandbox();
|
1440 |
}
|
|
|
|
|
1441 |
}
|
1442 |
|
1443 |
/**
|
1444 |
* Returns a template content without rendering it.
|
1445 |
*
|
1446 |
-
* @param string $name
|
|
|
1447 |
*
|
1448 |
* @return string The template source
|
1449 |
*/
|
1450 |
-
function twig_source(Twig_Environment $env, $name)
|
1451 |
{
|
1452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1453 |
}
|
1454 |
|
1455 |
/**
|
@@ -1488,7 +1502,7 @@ function twig_array_batch($items, $size, $fill = null)
|
|
1488 |
|
1489 |
$result = array_chunk($items, $size, true);
|
1490 |
|
1491 |
-
if (null !== $fill) {
|
1492 |
$last = count($result) - 1;
|
1493 |
if ($fillCount = $size - count($result[$last])) {
|
1494 |
$result[$last] = array_merge(
|
255 |
return array(
|
256 |
array(
|
257 |
'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
|
258 |
+
'-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
|
259 |
+
'+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
|
260 |
),
|
261 |
array(
|
262 |
+
'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
263 |
+
'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
264 |
+
'b-or' => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
265 |
+
'b-xor' => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
266 |
+
'b-and' => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
267 |
+
'==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
268 |
+
'!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
269 |
+
'<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
270 |
+
'>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
271 |
+
'>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
272 |
+
'<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
273 |
+
'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
274 |
+
'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
275 |
+
'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
276 |
'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
277 |
+
'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
278 |
+
'..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
279 |
+
'+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
280 |
+
'-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
281 |
+
'~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
282 |
+
'*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
283 |
+
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
284 |
+
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
285 |
+
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
286 |
+
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
287 |
+
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
288 |
+
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
289 |
),
|
290 |
);
|
291 |
}
|
382 |
* Returns a random value depending on the supplied parameter type:
|
383 |
* - a random item from a Traversable or array
|
384 |
* - a random character from a string
|
385 |
+
* - a random integer between 0 and the integer parameter.
|
386 |
*
|
387 |
* @param Twig_Environment $env A Twig_Environment instance
|
388 |
* @param Traversable|array|int|string $values The values to pick a random item from
|
466 |
}
|
467 |
|
468 |
/**
|
469 |
+
* Returns a new date object modified.
|
470 |
*
|
471 |
* <pre>
|
472 |
* {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
|
1190 |
$chr = $matches[0];
|
1191 |
$ord = ord($chr);
|
1192 |
|
1193 |
+
/*
|
1194 |
* The following replaces characters undefined in HTML with the
|
1195 |
* hex entity for the Unicode replacement character.
|
1196 |
*/
|
1198 |
return '�';
|
1199 |
}
|
1200 |
|
1201 |
+
/*
|
1202 |
* Check if the current character to escape has a name entity we should
|
1203 |
* replace it with while grabbing the hex value of the character.
|
1204 |
*/
|
1214 |
return sprintf('&%s;', $entityMap[$int]);
|
1215 |
}
|
1216 |
|
1217 |
+
/*
|
1218 |
* Per OWASP recommendations, we'll use hex entities for any other
|
1219 |
* characters where a named entity does not exist.
|
1220 |
*/
|
1427 |
}
|
1428 |
}
|
1429 |
|
1430 |
+
$result = null;
|
1431 |
try {
|
1432 |
+
$result = $env->resolveTemplate($template)->render($variables);
|
1433 |
} catch (Twig_Error_Loader $e) {
|
1434 |
if (!$ignoreMissing) {
|
1435 |
+
if ($isSandboxed && !$alreadySandboxed) {
|
1436 |
+
$sandbox->disableSandbox();
|
1437 |
+
}
|
1438 |
+
|
1439 |
throw $e;
|
1440 |
}
|
1441 |
}
|
1443 |
if ($isSandboxed && !$alreadySandboxed) {
|
1444 |
$sandbox->disableSandbox();
|
1445 |
}
|
1446 |
+
|
1447 |
+
return $result;
|
1448 |
}
|
1449 |
|
1450 |
/**
|
1451 |
* Returns a template content without rendering it.
|
1452 |
*
|
1453 |
+
* @param string $name The template name
|
1454 |
+
* @param bool $ignoreMissing Whether to ignore missing templates or not
|
1455 |
*
|
1456 |
* @return string The template source
|
1457 |
*/
|
1458 |
+
function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
|
1459 |
{
|
1460 |
+
try {
|
1461 |
+
return $env->getLoader()->getSource($name);
|
1462 |
+
} catch (Twig_Error_Loader $e) {
|
1463 |
+
if (!$ignoreMissing) {
|
1464 |
+
throw $e;
|
1465 |
+
}
|
1466 |
+
}
|
1467 |
}
|
1468 |
|
1469 |
/**
|
1502 |
|
1503 |
$result = array_chunk($items, $size, true);
|
1504 |
|
1505 |
+
if (null !== $fill && !empty($result)) {
|
1506 |
$last = count($result) - 1;
|
1507 |
if ($fillCount = $size - count($result[$last])) {
|
1508 |
$result[$last] = array_merge(
|
vendor/twig/twig/lib/Twig/Extension/Debug.php
CHANGED
@@ -62,7 +62,7 @@ function twig_var_dump(Twig_Environment $env, $context)
|
|
62 |
|
63 |
var_dump($vars);
|
64 |
} else {
|
65 |
-
for ($i = 2; $i < $count;
|
66 |
var_dump(func_get_arg($i));
|
67 |
}
|
68 |
}
|
62 |
|
63 |
var_dump($vars);
|
64 |
} else {
|
65 |
+
for ($i = 2; $i < $count; ++$i) {
|
66 |
var_dump(func_get_arg($i));
|
67 |
}
|
68 |
}
|
vendor/twig/twig/lib/Twig/Extension/Sandbox.php
CHANGED
@@ -16,7 +16,7 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
|
16 |
|
17 |
public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
|
18 |
{
|
19 |
-
$this->policy
|
20 |
$this->sandboxedGlobally = $sandboxed;
|
21 |
}
|
22 |
|
16 |
|
17 |
public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
|
18 |
{
|
19 |
+
$this->policy = $policy;
|
20 |
$this->sandboxedGlobally = $sandboxed;
|
21 |
}
|
22 |
|
vendor/twig/twig/lib/Twig/Filter.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
@@ -26,10 +27,10 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI
|
|
26 |
{
|
27 |
$this->options = array_merge(array(
|
28 |
'needs_environment' => false,
|
29 |
-
'needs_context'
|
30 |
-
'pre_escape'
|
31 |
-
'preserves_safety'
|
32 |
-
'callable'
|
33 |
), $options);
|
34 |
}
|
35 |
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
27 |
{
|
28 |
$this->options = array_merge(array(
|
29 |
'needs_environment' => false,
|
30 |
+
'needs_context' => false,
|
31 |
+
'pre_escape' => null,
|
32 |
+
'preserves_safety' => null,
|
33 |
+
'callable' => null,
|
34 |
), $options);
|
35 |
}
|
36 |
|
vendor/twig/twig/lib/Twig/Filter/Function.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Filter_Function extends Twig_Filter
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Filter_Function extends Twig_Filter
|
vendor/twig/twig/lib/Twig/Filter/Method.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Filter_Method extends Twig_Filter
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Filter_Method extends Twig_Filter
|
vendor/twig/twig/lib/Twig/Filter/Node.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Filter_Node extends Twig_Filter
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Filter_Node extends Twig_Filter
|
vendor/twig/twig/lib/Twig/FilterCallableInterface.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
interface Twig_FilterCallableInterface
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FilterCallableInterface
|
vendor/twig/twig/lib/Twig/FilterInterface.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
interface Twig_FilterInterface
|
15 |
* Use Twig_SimpleFilter instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FilterInterface
|
vendor/twig/twig/lib/Twig/Function.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
@@ -26,8 +27,8 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCal
|
|
26 |
{
|
27 |
$this->options = array_merge(array(
|
28 |
'needs_environment' => false,
|
29 |
-
'needs_context'
|
30 |
-
'callable'
|
31 |
), $options);
|
32 |
}
|
33 |
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
27 |
{
|
28 |
$this->options = array_merge(array(
|
29 |
'needs_environment' => false,
|
30 |
+
'needs_context' => false,
|
31 |
+
'callable' => null,
|
32 |
), $options);
|
33 |
}
|
34 |
|
vendor/twig/twig/lib/Twig/Function/Function.php
CHANGED
@@ -16,6 +16,7 @@
|
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Function_Function extends Twig_Function
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
19 |
+
*
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
class Twig_Function_Function extends Twig_Function
|
vendor/twig/twig/lib/Twig/Function/Method.php
CHANGED
@@ -16,6 +16,7 @@
|
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Function_Method extends Twig_Function
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
19 |
+
*
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
class Twig_Function_Method extends Twig_Function
|
vendor/twig/twig/lib/Twig/Function/Node.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_Function_Node extends Twig_Function
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
class Twig_Function_Node extends Twig_Function
|
vendor/twig/twig/lib/Twig/FunctionCallableInterface.php
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
interface Twig_FunctionCallableInterface
|
15 |
* Use Twig_SimpleFunction instead.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FunctionCallableInterface
|
vendor/twig/twig/lib/Twig/FunctionInterface.php
CHANGED
@@ -16,6 +16,7 @@
|
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_FunctionInterface
|
16 |
* Use Twig_SimpleFunction instead.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
19 |
+
*
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
interface Twig_FunctionInterface
|
vendor/twig/twig/lib/Twig/Lexer.php
CHANGED
@@ -33,42 +33,42 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
33 |
protected $positions;
|
34 |
protected $currentVarBlockLine;
|
35 |
|
36 |
-
const STATE_DATA
|
37 |
-
const STATE_BLOCK
|
38 |
-
const STATE_VAR
|
39 |
-
const STATE_STRING
|
40 |
-
const STATE_INTERPOLATION
|
41 |
-
|
42 |
-
const REGEX_NAME
|
43 |
-
const REGEX_NUMBER
|
44 |
-
const REGEX_STRING
|
45 |
const REGEX_DQ_STRING_DELIM = '/"/A';
|
46 |
-
const REGEX_DQ_STRING_PART
|
47 |
-
const PUNCTUATION
|
48 |
|
49 |
public function __construct(Twig_Environment $env, array $options = array())
|
50 |
{
|
51 |
$this->env = $env;
|
52 |
|
53 |
$this->options = array_merge(array(
|
54 |
-
'tag_comment'
|
55 |
-
'tag_block'
|
56 |
-
'tag_variable'
|
57 |
'whitespace_trim' => '-',
|
58 |
-
'interpolation'
|
59 |
), $options);
|
60 |
|
61 |
$this->regexes = array(
|
62 |
-
'lex_var'
|
63 |
-
'lex_block'
|
64 |
-
'lex_raw_data'
|
65 |
-
'operator'
|
66 |
-
'lex_comment'
|
67 |
-
'lex_block_raw'
|
68 |
-
'lex_block_line'
|
69 |
-
'lex_tokens_start'
|
70 |
'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
|
71 |
-
'interpolation_end'
|
72 |
);
|
73 |
}
|
74 |
|
33 |
protected $positions;
|
34 |
protected $currentVarBlockLine;
|
35 |
|
36 |
+
const STATE_DATA = 0;
|
37 |
+
const STATE_BLOCK = 1;
|
38 |
+
const STATE_VAR = 2;
|
39 |
+
const STATE_STRING = 3;
|
40 |
+
const STATE_INTERPOLATION = 4;
|
41 |
+
|
42 |
+
const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
|
43 |
+
const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
|
44 |
+
const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
|
45 |
const REGEX_DQ_STRING_DELIM = '/"/A';
|
46 |
+
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
47 |
+
const PUNCTUATION = '()[]{}?:.,|';
|
48 |
|
49 |
public function __construct(Twig_Environment $env, array $options = array())
|
50 |
{
|
51 |
$this->env = $env;
|
52 |
|
53 |
$this->options = array_merge(array(
|
54 |
+
'tag_comment' => array('{#', '#}'),
|
55 |
+
'tag_block' => array('{%', '%}'),
|
56 |
+
'tag_variable' => array('{{', '}}'),
|
57 |
'whitespace_trim' => '-',
|
58 |
+
'interpolation' => array('#{', '}'),
|
59 |
), $options);
|
60 |
|
61 |
$this->regexes = array(
|
62 |
+
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
63 |
+
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
64 |
+
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
65 |
+
'operator' => $this->getOperatorRegex(),
|
66 |
+
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
67 |
+
'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
68 |
+
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
69 |
+
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
70 |
'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
|
71 |
+
'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
|
72 |
);
|
73 |
}
|
74 |
|
vendor/twig/twig/lib/Twig/LoaderInterface.php
CHANGED
@@ -41,9 +41,9 @@ interface Twig_LoaderInterface
|
|
41 |
/**
|
42 |
* Returns true if the template is still fresh.
|
43 |
*
|
44 |
-
* @param string
|
45 |
-
* @param int
|
46 |
-
*
|
47 |
*
|
48 |
* @return bool true if the template is fresh, false otherwise
|
49 |
*
|
41 |
/**
|
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/CheckSecurity.php
CHANGED
@@ -41,9 +41,9 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
41 |
}
|
42 |
|
43 |
$compiler
|
44 |
-
->write(
|
45 |
-
->write(
|
46 |
-
->write(
|
47 |
->write("try {\n")
|
48 |
->indent()
|
49 |
->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
|
41 |
}
|
42 |
|
43 |
$compiler
|
44 |
+
->write('$tags = ')->repr(array_filter($tags))->raw(";\n")
|
45 |
+
->write('$filters = ')->repr(array_filter($filters))->raw(";\n")
|
46 |
+
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
47 |
->write("try {\n")
|
48 |
->indent()
|
49 |
->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
|
vendor/twig/twig/lib/Twig/Node/Embed.php
CHANGED
@@ -28,7 +28,7 @@ class Twig_Node_Embed extends Twig_Node_Include
|
|
28 |
protected function addGetTemplate(Twig_Compiler $compiler)
|
29 |
{
|
30 |
$compiler
|
31 |
-
->write(
|
32 |
->string($this->getAttribute('filename'))
|
33 |
->raw(', ')
|
34 |
->repr($compiler->getFilename())
|
@@ -36,7 +36,7 @@ class Twig_Node_Embed extends Twig_Node_Include
|
|
36 |
->repr($this->getLine())
|
37 |
->raw(', ')
|
38 |
->string($this->getAttribute('index'))
|
39 |
-
->raw(
|
40 |
;
|
41 |
}
|
42 |
}
|
28 |
protected function addGetTemplate(Twig_Compiler $compiler)
|
29 |
{
|
30 |
$compiler
|
31 |
+
->write('$this->loadTemplate(')
|
32 |
->string($this->getAttribute('filename'))
|
33 |
->raw(', ')
|
34 |
->repr($compiler->getFilename())
|
36 |
->repr($this->getLine())
|
37 |
->raw(', ')
|
38 |
->string($this->getAttribute('index'))
|
39 |
+
->raw(')')
|
40 |
;
|
41 |
}
|
42 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php
CHANGED
@@ -36,15 +36,15 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
|
36 |
if ($this->getAttribute('output')) {
|
37 |
$compiler
|
38 |
->addDebugInfo($this)
|
39 |
-
->write(
|
40 |
->subcompile($this->getNode('name'))
|
41 |
->raw(", \$context, \$blocks);\n")
|
42 |
;
|
43 |
} else {
|
44 |
$compiler
|
45 |
-
->raw(
|
46 |
->subcompile($this->getNode('name'))
|
47 |
-
->raw(
|
48 |
;
|
49 |
}
|
50 |
}
|
36 |
if ($this->getAttribute('output')) {
|
37 |
$compiler
|
38 |
->addDebugInfo($this)
|
39 |
+
->write('$this->displayBlock(')
|
40 |
->subcompile($this->getNode('name'))
|
41 |
->raw(", \$context, \$blocks);\n")
|
42 |
;
|
43 |
} else {
|
44 |
$compiler
|
45 |
+
->raw('$this->renderBlock(')
|
46 |
->subcompile($this->getNode('name'))
|
47 |
+
->raw(', $context, $blocks)')
|
48 |
;
|
49 |
}
|
50 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Call.php
CHANGED
@@ -106,12 +106,19 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
106 |
$parameters[$name] = $node;
|
107 |
}
|
108 |
|
109 |
-
|
|
|
110 |
return $parameters;
|
111 |
}
|
112 |
|
113 |
if (!$callable) {
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
}
|
116 |
|
117 |
// manage named arguments
|
@@ -141,6 +148,19 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
141 |
array_shift($definition);
|
142 |
}
|
143 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
|
145 |
$arguments = array();
|
146 |
$names = array();
|
@@ -185,6 +205,23 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
185 |
}
|
186 |
}
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
if (!empty($parameters)) {
|
189 |
$unknownParameter = null;
|
190 |
foreach ($parameters as $parameter) {
|
106 |
$parameters[$name] = $node;
|
107 |
}
|
108 |
|
109 |
+
$isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic');
|
110 |
+
if (!$named && !$isVariadic) {
|
111 |
return $parameters;
|
112 |
}
|
113 |
|
114 |
if (!$callable) {
|
115 |
+
if ($named) {
|
116 |
+
$message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
|
117 |
+
} else {
|
118 |
+
$message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
|
119 |
+
}
|
120 |
+
|
121 |
+
throw new LogicException($message);
|
122 |
}
|
123 |
|
124 |
// manage named arguments
|
148 |
array_shift($definition);
|
149 |
}
|
150 |
}
|
151 |
+
if ($isVariadic) {
|
152 |
+
$argument = end($definition);
|
153 |
+
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
|
154 |
+
array_pop($definition);
|
155 |
+
} else {
|
156 |
+
$callableName = $r->name;
|
157 |
+
if ($r->getDeclaringClass()) {
|
158 |
+
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
159 |
+
}
|
160 |
+
|
161 |
+
throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $callType, $callName));
|
162 |
+
}
|
163 |
+
}
|
164 |
|
165 |
$arguments = array();
|
166 |
$names = array();
|
205 |
}
|
206 |
}
|
207 |
|
208 |
+
if ($isVariadic) {
|
209 |
+
$arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
|
210 |
+
foreach ($parameters as $key => $value) {
|
211 |
+
if (is_int($key)) {
|
212 |
+
$arbitraryArguments->addElement($value);
|
213 |
+
} else {
|
214 |
+
$arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
|
215 |
+
}
|
216 |
+
unset($parameters[$key]);
|
217 |
+
}
|
218 |
+
|
219 |
+
if ($arbitraryArguments->count()) {
|
220 |
+
$arguments = array_merge($arguments, $optionalArguments);
|
221 |
+
$arguments[] = $arbitraryArguments;
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
if (!empty($parameters)) {
|
226 |
$unknownParameter = null;
|
227 |
foreach ($parameters as $parameter) {
|
vendor/twig/twig/lib/Twig/Node/Expression/Filter.php
CHANGED
@@ -30,6 +30,9 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
|
|
30 |
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
|
31 |
$this->setAttribute('callable', $filter->getCallable());
|
32 |
}
|
|
|
|
|
|
|
33 |
|
34 |
$this->compileCallable($compiler);
|
35 |
}
|
30 |
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
|
31 |
$this->setAttribute('callable', $filter->getCallable());
|
32 |
}
|
33 |
+
if ($filter instanceof Twig_SimpleFilter) {
|
34 |
+
$this->setAttribute('is_variadic', $filter->isVariadic());
|
35 |
+
}
|
36 |
|
37 |
$this->compileCallable($compiler);
|
38 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Function.php
CHANGED
@@ -29,6 +29,9 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
|
29 |
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
30 |
$this->setAttribute('callable', $function->getCallable());
|
31 |
}
|
|
|
|
|
|
|
32 |
|
33 |
$this->compileCallable($compiler);
|
34 |
}
|
29 |
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
30 |
$this->setAttribute('callable', $function->getCallable());
|
31 |
}
|
32 |
+
if ($function instanceof Twig_SimpleFunction) {
|
33 |
+
$this->setAttribute('is_variadic', $function->isVariadic());
|
34 |
+
}
|
35 |
|
36 |
$this->compileCallable($compiler);
|
37 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Name.php
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
class Twig_Node_Expression_Name extends Twig_Node_Expression
|
13 |
{
|
14 |
protected $specialVars = array(
|
15 |
-
'_self'
|
16 |
'_context' => '$context',
|
17 |
'_charset' => '$this->env->getCharset()',
|
18 |
);
|
12 |
class Twig_Node_Expression_Name extends Twig_Node_Expression
|
13 |
{
|
14 |
protected $specialVars = array(
|
15 |
+
'_self' => '$this',
|
16 |
'_context' => '$context',
|
17 |
'_charset' => '$this->env->getCharset()',
|
18 |
);
|
vendor/twig/twig/lib/Twig/Node/Expression/Parent.php
CHANGED
@@ -32,15 +32,15 @@ class Twig_Node_Expression_Parent extends Twig_Node_Expression
|
|
32 |
if ($this->getAttribute('output')) {
|
33 |
$compiler
|
34 |
->addDebugInfo($this)
|
35 |
-
->write(
|
36 |
->string($this->getAttribute('name'))
|
37 |
->raw(", \$context, \$blocks);\n")
|
38 |
;
|
39 |
} else {
|
40 |
$compiler
|
41 |
-
->raw(
|
42 |
->string($this->getAttribute('name'))
|
43 |
-
->raw(
|
44 |
;
|
45 |
}
|
46 |
}
|
32 |
if ($this->getAttribute('output')) {
|
33 |
$compiler
|
34 |
->addDebugInfo($this)
|
35 |
+
->write('$this->displayParentBlock(')
|
36 |
->string($this->getAttribute('name'))
|
37 |
->raw(", \$context, \$blocks);\n")
|
38 |
;
|
39 |
} else {
|
40 |
$compiler
|
41 |
+
->raw('$this->renderParentBlock(')
|
42 |
->string($this->getAttribute('name'))
|
43 |
+
->raw(', $context, $blocks)')
|
44 |
;
|
45 |
}
|
46 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Test.php
CHANGED
@@ -26,6 +26,9 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
|
|
26 |
if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
|
27 |
$this->setAttribute('callable', $test->getCallable());
|
28 |
}
|
|
|
|
|
|
|
29 |
|
30 |
$this->compileCallable($compiler);
|
31 |
}
|
26 |
if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
|
27 |
$this->setAttribute('callable', $test->getCallable());
|
28 |
}
|
29 |
+
if ($test instanceof Twig_SimpleTest) {
|
30 |
+
$this->setAttribute('is_variadic', $test->isVariadic());
|
31 |
+
}
|
32 |
|
33 |
$this->compileCallable($compiler);
|
34 |
}
|
vendor/twig/twig/lib/Twig/Node/For.php
CHANGED
@@ -82,7 +82,7 @@ class Twig_Node_For extends Twig_Node
|
|
82 |
$compiler
|
83 |
->write("foreach (\$context['_seq'] as ")
|
84 |
->subcompile($this->getNode('key_target'))
|
85 |
-
->raw(
|
86 |
->subcompile($this->getNode('value_target'))
|
87 |
->raw(") {\n")
|
88 |
->indent()
|
82 |
$compiler
|
83 |
->write("foreach (\$context['_seq'] as ")
|
84 |
->subcompile($this->getNode('key_target'))
|
85 |
+
->raw(' => ')
|
86 |
->subcompile($this->getNode('value_target'))
|
87 |
->raw(") {\n")
|
88 |
->indent()
|
vendor/twig/twig/lib/Twig/Node/If.php
CHANGED
@@ -34,7 +34,7 @@ class Twig_Node_If extends Twig_Node
|
|
34 |
if ($i > 0) {
|
35 |
$compiler
|
36 |
->outdent()
|
37 |
-
->write(
|
38 |
;
|
39 |
} else {
|
40 |
$compiler
|
34 |
if ($i > 0) {
|
35 |
$compiler
|
36 |
->outdent()
|
37 |
+
->write('} elseif (')
|
38 |
;
|
39 |
} else {
|
40 |
$compiler
|
vendor/twig/twig/lib/Twig/Node/Import.php
CHANGED
@@ -36,7 +36,7 @@ class Twig_Node_Import extends Twig_Node
|
|
36 |
;
|
37 |
|
38 |
if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
|
39 |
-
$compiler->raw(
|
40 |
} else {
|
41 |
$compiler
|
42 |
->raw('$this->loadTemplate(')
|
@@ -45,7 +45,7 @@ class Twig_Node_Import extends Twig_Node
|
|
45 |
->repr($compiler->getFilename())
|
46 |
->raw(', ')
|
47 |
->repr($this->getLine())
|
48 |
-
->raw(
|
49 |
;
|
50 |
}
|
51 |
|
36 |
;
|
37 |
|
38 |
if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
|
39 |
+
$compiler->raw('$this');
|
40 |
} else {
|
41 |
$compiler
|
42 |
->raw('$this->loadTemplate(')
|
45 |
->repr($compiler->getFilename())
|
46 |
->raw(', ')
|
47 |
->repr($this->getLine())
|
48 |
+
->raw(')')
|
49 |
;
|
50 |
}
|
51 |
|
vendor/twig/twig/lib/Twig/Node/Include.php
CHANGED
@@ -61,13 +61,13 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|
61 |
protected function addGetTemplate(Twig_Compiler $compiler)
|
62 |
{
|
63 |
$compiler
|
64 |
-
->write(
|
65 |
->subcompile($this->getNode('expr'))
|
66 |
->raw(', ')
|
67 |
->repr($compiler->getFilename())
|
68 |
->raw(', ')
|
69 |
->repr($this->getLine())
|
70 |
-
->raw(
|
71 |
;
|
72 |
}
|
73 |
|
61 |
protected function addGetTemplate(Twig_Compiler $compiler)
|
62 |
{
|
63 |
$compiler
|
64 |
+
->write('$this->loadTemplate(')
|
65 |
->subcompile($this->getNode('expr'))
|
66 |
->raw(', ')
|
67 |
->repr($compiler->getFilename())
|
68 |
->raw(', ')
|
69 |
->repr($this->getLine())
|
70 |
+
->raw(')')
|
71 |
;
|
72 |
}
|
73 |
|
vendor/twig/twig/lib/Twig/Node/Macro.php
CHANGED
@@ -16,8 +16,16 @@
|
|
16 |
*/
|
17 |
class Twig_Node_Macro extends Twig_Node
|
18 |
{
|
|
|
|
|
19 |
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
20 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
|
22 |
}
|
23 |
|
@@ -30,7 +38,7 @@ class Twig_Node_Macro extends Twig_Node
|
|
30 |
{
|
31 |
$compiler
|
32 |
->addDebugInfo($this)
|
33 |
-
->write(sprintf(
|
34 |
;
|
35 |
|
36 |
$count = count($this->getNode('arguments'));
|
@@ -46,36 +54,55 @@ class Twig_Node_Macro extends Twig_Node
|
|
46 |
}
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
$compiler
|
50 |
->raw(")\n")
|
51 |
->write("{\n")
|
52 |
->indent()
|
53 |
;
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
58 |
$compiler
|
59 |
-
->
|
60 |
-
->
|
|
|
|
|
61 |
;
|
|
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
->raw(",\n")
|
69 |
-
;
|
70 |
-
}
|
71 |
|
|
|
|
|
|
|
72 |
$compiler
|
73 |
-
->
|
74 |
-
->
|
|
|
|
|
|
|
75 |
;
|
76 |
}
|
77 |
|
78 |
$compiler
|
|
|
|
|
79 |
->write("\$blocks = array();\n\n")
|
80 |
->write("ob_start();\n")
|
81 |
->write("try {\n")
|
16 |
*/
|
17 |
class Twig_Node_Macro extends Twig_Node
|
18 |
{
|
19 |
+
const VARARGS_NAME = 'varargs';
|
20 |
+
|
21 |
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
22 |
{
|
23 |
+
foreach ($arguments as $argumentName => $argument) {
|
24 |
+
if (self::VARARGS_NAME === $argumentName) {
|
25 |
+
throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getLine());
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
|
30 |
}
|
31 |
|
38 |
{
|
39 |
$compiler
|
40 |
->addDebugInfo($this)
|
41 |
+
->write(sprintf('public function get%s(', $this->getAttribute('name')))
|
42 |
;
|
43 |
|
44 |
$count = count($this->getNode('arguments'));
|
54 |
}
|
55 |
}
|
56 |
|
57 |
+
if (PHP_VERSION_ID >= 50600) {
|
58 |
+
if ($count) {
|
59 |
+
$compiler->raw(', ');
|
60 |
+
}
|
61 |
+
|
62 |
+
$compiler->raw('...$__varargs__');
|
63 |
+
}
|
64 |
+
|
65 |
$compiler
|
66 |
->raw(")\n")
|
67 |
->write("{\n")
|
68 |
->indent()
|
69 |
;
|
70 |
|
71 |
+
$compiler
|
72 |
+
->write("\$context = \$this->env->mergeGlobals(array(\n")
|
73 |
+
->indent()
|
74 |
+
;
|
75 |
+
|
76 |
+
foreach ($this->getNode('arguments') as $name => $default) {
|
77 |
$compiler
|
78 |
+
->addIndentation()
|
79 |
+
->string($name)
|
80 |
+
->raw(' => $__'.$name.'__')
|
81 |
+
->raw(",\n")
|
82 |
;
|
83 |
+
}
|
84 |
|
85 |
+
$compiler
|
86 |
+
->addIndentation()
|
87 |
+
->string(self::VARARGS_NAME)
|
88 |
+
->raw(' => ')
|
89 |
+
;
|
|
|
|
|
|
|
90 |
|
91 |
+
if (PHP_VERSION_ID >= 50600) {
|
92 |
+
$compiler->raw("\$__varargs__,\n");
|
93 |
+
} else {
|
94 |
$compiler
|
95 |
+
->raw('func_num_args() > ')
|
96 |
+
->repr($count)
|
97 |
+
->raw(' ? array_slice(func_get_args(), ')
|
98 |
+
->repr($count)
|
99 |
+
->raw(") : array(),\n")
|
100 |
;
|
101 |
}
|
102 |
|
103 |
$compiler
|
104 |
+
->outdent()
|
105 |
+
->write("));\n\n")
|
106 |
->write("\$blocks = array();\n\n")
|
107 |
->write("ob_start();\n")
|
108 |
->write("try {\n")
|
vendor/twig/twig/lib/Twig/Node/Module.php
CHANGED
@@ -107,20 +107,20 @@ class Twig_Node_Module extends Twig_Node
|
|
107 |
->write("protected function doGetParent(array \$context)\n", "{\n")
|
108 |
->indent()
|
109 |
->addDebugInfo($parent)
|
110 |
-
->write(
|
111 |
;
|
112 |
|
113 |
if ($parent instanceof Twig_Node_Expression_Constant) {
|
114 |
$compiler->subcompile($parent);
|
115 |
} else {
|
116 |
$compiler
|
117 |
-
->raw(
|
118 |
->subcompile($parent)
|
119 |
->raw(', ')
|
120 |
->repr($compiler->getFilename())
|
121 |
->raw(', ')
|
122 |
->repr($this->getNode('parent')->getLine())
|
123 |
-
->raw(
|
124 |
;
|
125 |
}
|
126 |
|
@@ -136,7 +136,7 @@ class Twig_Node_Module extends Twig_Node
|
|
136 |
$compiler
|
137 |
->write("\n\n")
|
138 |
// if the filename contains */, add a blank to avoid a PHP parse error
|
139 |
-
->write(
|
140 |
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
|
141 |
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
|
142 |
->write("{\n")
|
@@ -159,7 +159,7 @@ class Twig_Node_Module extends Twig_Node
|
|
159 |
} elseif ($parent instanceof Twig_Node_Expression_Constant) {
|
160 |
$compiler
|
161 |
->addDebugInfo($parent)
|
162 |
-
->write(
|
163 |
->subcompile($parent)
|
164 |
->raw(', ')
|
165 |
->repr($compiler->getFilename())
|
@@ -189,23 +189,23 @@ class Twig_Node_Module extends Twig_Node
|
|
189 |
|
190 |
foreach ($trait->getNode('targets') as $key => $value) {
|
191 |
$compiler
|
192 |
-
->write(sprintf(
|
193 |
->string($key)
|
194 |
->raw("])) {\n")
|
195 |
->indent()
|
196 |
->write("throw new Twig_Error_Runtime(sprintf('Block ")
|
197 |
->string($key)
|
198 |
-
->raw(
|
199 |
->subcompile($trait->getNode('template'))
|
200 |
->raw(".'));\n")
|
201 |
->outdent()
|
202 |
->write("}\n\n")
|
203 |
|
204 |
-
->write(sprintf(
|
205 |
->subcompile($value)
|
206 |
-
->raw(sprintf(
|
207 |
->string($key)
|
208 |
-
->raw(sprintf(
|
209 |
->string($key)
|
210 |
->raw("]);\n\n")
|
211 |
;
|
@@ -218,9 +218,9 @@ class Twig_Node_Module extends Twig_Node
|
|
218 |
->indent()
|
219 |
;
|
220 |
|
221 |
-
for ($i = 0; $i < $countTraits;
|
222 |
$compiler
|
223 |
-
->write(sprintf(
|
224 |
;
|
225 |
}
|
226 |
|
@@ -285,9 +285,9 @@ class Twig_Node_Module extends Twig_Node
|
|
285 |
if (null !== $parent = $this->getNode('parent')) {
|
286 |
$compiler->addDebugInfo($parent);
|
287 |
if ($parent instanceof Twig_Node_Expression_Constant) {
|
288 |
-
$compiler->write(
|
289 |
} else {
|
290 |
-
$compiler->write(
|
291 |
}
|
292 |
$compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
|
293 |
}
|
@@ -393,7 +393,7 @@ class Twig_Node_Module extends Twig_Node
|
|
393 |
{
|
394 |
if ($node instanceof Twig_Node_Expression_Constant) {
|
395 |
$compiler
|
396 |
-
->write(sprintf(
|
397 |
->subcompile($node)
|
398 |
->raw(', ')
|
399 |
->repr($compiler->getFilename())
|
@@ -403,13 +403,13 @@ class Twig_Node_Module extends Twig_Node
|
|
403 |
;
|
404 |
} else {
|
405 |
$compiler
|
406 |
-
->write(sprintf(
|
407 |
->subcompile($node)
|
408 |
->raw(";\n")
|
409 |
-
->write(sprintf(
|
410 |
->raw(" instanceof Twig_Template) {\n")
|
411 |
->indent()
|
412 |
-
->write(sprintf(
|
413 |
->raw(', ')
|
414 |
->repr($compiler->getFilename())
|
415 |
->raw(', ')
|
107 |
->write("protected function doGetParent(array \$context)\n", "{\n")
|
108 |
->indent()
|
109 |
->addDebugInfo($parent)
|
110 |
+
->write('return ')
|
111 |
;
|
112 |
|
113 |
if ($parent instanceof Twig_Node_Expression_Constant) {
|
114 |
$compiler->subcompile($parent);
|
115 |
} else {
|
116 |
$compiler
|
117 |
+
->raw('$this->loadTemplate(')
|
118 |
->subcompile($parent)
|
119 |
->raw(', ')
|
120 |
->repr($compiler->getFilename())
|
121 |
->raw(', ')
|
122 |
->repr($this->getNode('parent')->getLine())
|
123 |
+
->raw(')')
|
124 |
;
|
125 |
}
|
126 |
|
136 |
$compiler
|
137 |
->write("\n\n")
|
138 |
// if the filename contains */, add a blank to avoid a PHP parse error
|
139 |
+
->write('/* '.str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
|
140 |
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
|
141 |
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
|
142 |
->write("{\n")
|
159 |
} elseif ($parent instanceof Twig_Node_Expression_Constant) {
|
160 |
$compiler
|
161 |
->addDebugInfo($parent)
|
162 |
+
->write('$this->parent = $this->loadTemplate(')
|
163 |
->subcompile($parent)
|
164 |
->raw(', ')
|
165 |
->repr($compiler->getFilename())
|
189 |
|
190 |
foreach ($trait->getNode('targets') as $key => $value) {
|
191 |
$compiler
|
192 |
+
->write(sprintf('if (!isset($_trait_%s_blocks[', $i))
|
193 |
->string($key)
|
194 |
->raw("])) {\n")
|
195 |
->indent()
|
196 |
->write("throw new Twig_Error_Runtime(sprintf('Block ")
|
197 |
->string($key)
|
198 |
+
->raw(' is not defined in trait ')
|
199 |
->subcompile($trait->getNode('template'))
|
200 |
->raw(".'));\n")
|
201 |
->outdent()
|
202 |
->write("}\n\n")
|
203 |
|
204 |
+
->write(sprintf('$_trait_%s_blocks[', $i))
|
205 |
->subcompile($value)
|
206 |
+
->raw(sprintf('] = $_trait_%s_blocks[', $i))
|
207 |
->string($key)
|
208 |
+
->raw(sprintf(']; unset($_trait_%s_blocks[', $i))
|
209 |
->string($key)
|
210 |
->raw("]);\n\n")
|
211 |
;
|
218 |
->indent()
|
219 |
;
|
220 |
|
221 |
+
for ($i = 0; $i < $countTraits; ++$i) {
|
222 |
$compiler
|
223 |
+
->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i))
|
224 |
;
|
225 |
}
|
226 |
|
285 |
if (null !== $parent = $this->getNode('parent')) {
|
286 |
$compiler->addDebugInfo($parent);
|
287 |
if ($parent instanceof Twig_Node_Expression_Constant) {
|
288 |
+
$compiler->write('$this->parent');
|
289 |
} else {
|
290 |
+
$compiler->write('$this->getParent($context)');
|
291 |
}
|
292 |
$compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
|
293 |
}
|
393 |
{
|
394 |
if ($node instanceof Twig_Node_Expression_Constant) {
|
395 |
$compiler
|
396 |
+
->write(sprintf('%s = $this->loadTemplate(', $var))
|
397 |
->subcompile($node)
|
398 |
->raw(', ')
|
399 |
->repr($compiler->getFilename())
|
403 |
;
|
404 |
} else {
|
405 |
$compiler
|
406 |
+
->write(sprintf('%s = ', $var))
|
407 |
->subcompile($node)
|
408 |
->raw(";\n")
|
409 |
+
->write(sprintf('if (!%s', $var))
|
410 |
->raw(" instanceof Twig_Template) {\n")
|
411 |
->indent()
|
412 |
+
->write(sprintf('%s = $this->loadTemplate(%s')
|
413 |
->raw(', ')
|
414 |
->repr($compiler->getFilename())
|
415 |
->raw(', ')
|
vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
-
class Twig_NodeVisitor_Escaper
|
18 |
{
|
19 |
protected $statusStack = array();
|
20 |
protected $blocks = array();
|
@@ -29,14 +29,9 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
-
*
|
33 |
-
*
|
34 |
-
* @param Twig_NodeInterface $node The node to visit
|
35 |
-
* @param Twig_Environment $env The Twig environment instance
|
36 |
-
*
|
37 |
-
* @return Twig_NodeInterface The modified node
|
38 |
*/
|
39 |
-
|
40 |
{
|
41 |
if ($node instanceof Twig_Node_Module) {
|
42 |
if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
|
@@ -55,14 +50,9 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
|
55 |
}
|
56 |
|
57 |
/**
|
58 |
-
*
|
59 |
-
*
|
60 |
-
* @param Twig_NodeInterface $node The node to visit
|
61 |
-
* @param Twig_Environment $env The Twig environment instance
|
62 |
-
*
|
63 |
-
* @return Twig_NodeInterface The modified node
|
64 |
*/
|
65 |
-
|
66 |
{
|
67 |
if ($node instanceof Twig_Node_Module) {
|
68 |
$this->defaultStrategy = false;
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
+
class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
18 |
{
|
19 |
protected $statusStack = array();
|
20 |
protected $blocks = array();
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
+
* {@inheritdoc}
|
|
|
|
|
|
|
|
|
|
|
33 |
*/
|
34 |
+
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
35 |
{
|
36 |
if ($node instanceof Twig_Node_Module) {
|
37 |
if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
|
50 |
}
|
51 |
|
52 |
/**
|
53 |
+
* {@inheritdoc}
|
|
|
|
|
|
|
|
|
|
|
54 |
*/
|
55 |
+
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
56 |
{
|
57 |
if ($node instanceof Twig_Node_Module) {
|
58 |
$this->defaultStrategy = false;
|
vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
CHANGED
@@ -19,13 +19,13 @@
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
-
class Twig_NodeVisitor_Optimizer
|
23 |
{
|
24 |
-
const OPTIMIZE_ALL
|
25 |
-
const OPTIMIZE_NONE
|
26 |
-
const OPTIMIZE_FOR
|
27 |
-
const OPTIMIZE_RAW_FILTER
|
28 |
-
const OPTIMIZE_VAR_ACCESS
|
29 |
|
30 |
protected $loops = array();
|
31 |
protected $loopsTargets = array();
|
@@ -50,7 +50,7 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|
50 |
/**
|
51 |
* {@inheritdoc}
|
52 |
*/
|
53 |
-
|
54 |
{
|
55 |
if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
|
56 |
$this->enterOptimizeFor($node, $env);
|
@@ -76,7 +76,7 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|
76 |
/**
|
77 |
* {@inheritdoc}
|
78 |
*/
|
79 |
-
|
80 |
{
|
81 |
$expression = $node instanceof Twig_Node_Expression;
|
82 |
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
23 |
{
|
24 |
+
const OPTIMIZE_ALL = -1;
|
25 |
+
const OPTIMIZE_NONE = 0;
|
26 |
+
const OPTIMIZE_FOR = 2;
|
27 |
+
const OPTIMIZE_RAW_FILTER = 4;
|
28 |
+
const OPTIMIZE_VAR_ACCESS = 8;
|
29 |
|
30 |
protected $loops = array();
|
31 |
protected $loopsTargets = array();
|
50 |
/**
|
51 |
* {@inheritdoc}
|
52 |
*/
|
53 |
+
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
54 |
{
|
55 |
if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
|
56 |
$this->enterOptimizeFor($node, $env);
|
76 |
/**
|
77 |
* {@inheritdoc}
|
78 |
*/
|
79 |
+
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
80 |
{
|
81 |
$expression = $node instanceof Twig_Node_Expression;
|
82 |
|
vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php
CHANGED
@@ -1,6 +1,15 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
{
|
5 |
protected $data = array();
|
6 |
protected $safeVars = array();
|
@@ -48,12 +57,18 @@ class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
|
|
48 |
);
|
49 |
}
|
50 |
|
51 |
-
|
|
|
|
|
|
|
52 |
{
|
53 |
return $node;
|
54 |
}
|
55 |
|
56 |
-
|
|
|
|
|
|
|
57 |
{
|
58 |
if ($node instanceof Twig_Node_Expression_Constant) {
|
59 |
// constants are marked safe for all
|
1 |
<?php
|
2 |
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) Fabien Potencier
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
13 |
{
|
14 |
protected $data = array();
|
15 |
protected $safeVars = array();
|
57 |
);
|
58 |
}
|
59 |
|
60 |
+
/**
|
61 |
+
* {@inheritdoc}
|
62 |
+
*/
|
63 |
+
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
64 |
{
|
65 |
return $node;
|
66 |
}
|
67 |
|
68 |
+
/**
|
69 |
+
* {@inheritdoc}
|
70 |
+
*/
|
71 |
+
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
72 |
{
|
73 |
if ($node instanceof Twig_Node_Expression_Constant) {
|
74 |
// constants are marked safe for all
|
vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
-
class Twig_NodeVisitor_Sandbox
|
18 |
{
|
19 |
protected $inAModule = false;
|
20 |
protected $tags;
|
@@ -22,14 +22,9 @@ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
|
22 |
protected $functions;
|
23 |
|
24 |
/**
|
25 |
-
*
|
26 |
-
*
|
27 |
-
* @param Twig_NodeInterface $node The node to visit
|
28 |
-
* @param Twig_Environment $env The Twig environment instance
|
29 |
-
*
|
30 |
-
* @return Twig_NodeInterface The modified node
|
31 |
*/
|
32 |
-
|
33 |
{
|
34 |
if ($node instanceof Twig_Node_Module) {
|
35 |
$this->inAModule = true;
|
@@ -64,14 +59,9 @@ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
|
64 |
}
|
65 |
|
66 |
/**
|
67 |
-
*
|
68 |
-
*
|
69 |
-
* @param Twig_NodeInterface $node The node to visit
|
70 |
-
* @param Twig_Environment $env The Twig environment instance
|
71 |
-
*
|
72 |
-
* @return Twig_NodeInterface The modified node
|
73 |
*/
|
74 |
-
|
75 |
{
|
76 |
if ($node instanceof Twig_Node_Module) {
|
77 |
$this->inAModule = false;
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
+
class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor
|
18 |
{
|
19 |
protected $inAModule = false;
|
20 |
protected $tags;
|
22 |
protected $functions;
|
23 |
|
24 |
/**
|
25 |
+
* {@inheritdoc}
|
|
|
|
|
|
|
|
|
|
|
26 |
*/
|
27 |
+
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
28 |
{
|
29 |
if ($node instanceof Twig_Node_Module) {
|
30 |
$this->inAModule = true;
|
59 |
}
|
60 |
|
61 |
/**
|
62 |
+
* {@inheritdoc}
|
|
|
|
|
|
|
|
|
|
|
63 |
*/
|
64 |
+
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
65 |
{
|
66 |
if ($node instanceof Twig_Node_Module) {
|
67 |
$this->inAModule = false;
|
vendor/twig/twig/lib/Twig/Parser.php
CHANGED
@@ -253,20 +253,29 @@ class Twig_Parser implements Twig_ParserInterface
|
|
253 |
}
|
254 |
|
255 |
public function setMacro($name, Twig_Node_Macro $node)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
{
|
257 |
if (null === $this->reservedMacroNames) {
|
258 |
$this->reservedMacroNames = array();
|
259 |
$r = new ReflectionClass($this->env->getBaseTemplateClass());
|
260 |
foreach ($r->getMethods() as $method) {
|
261 |
-
$
|
262 |
-
}
|
263 |
-
}
|
264 |
|
265 |
-
|
266 |
-
|
|
|
|
|
267 |
}
|
268 |
|
269 |
-
$
|
270 |
}
|
271 |
|
272 |
public function addTrait($trait)
|
253 |
}
|
254 |
|
255 |
public function setMacro($name, Twig_Node_Macro $node)
|
256 |
+
{
|
257 |
+
if ($this->isReservedMacroName($name)) {
|
258 |
+
throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine(), $this->getFilename());
|
259 |
+
}
|
260 |
+
|
261 |
+
$this->macros[$name] = $node;
|
262 |
+
}
|
263 |
+
|
264 |
+
public function isReservedMacroName($name)
|
265 |
{
|
266 |
if (null === $this->reservedMacroNames) {
|
267 |
$this->reservedMacroNames = array();
|
268 |
$r = new ReflectionClass($this->env->getBaseTemplateClass());
|
269 |
foreach ($r->getMethods() as $method) {
|
270 |
+
$methodName = strtolower($method->getName());
|
|
|
|
|
271 |
|
272 |
+
if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) {
|
273 |
+
$this->reservedMacroNames[] = substr($methodName, 3);
|
274 |
+
}
|
275 |
+
}
|
276 |
}
|
277 |
|
278 |
+
return in_array(strtolower($name), $this->reservedMacroNames);
|
279 |
}
|
280 |
|
281 |
public function addTrait($trait)
|
vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
*/
|
15 |
class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Text
|
16 |
{
|
17 |
-
static
|
18 |
'block' => '#dfd',
|
19 |
'macro' => '#ddf',
|
20 |
'template' => '#ffd',
|
14 |
*/
|
15 |
class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Text
|
16 |
{
|
17 |
+
private static $colors = array(
|
18 |
'block' => '#dfd',
|
19 |
'macro' => '#ddf',
|
20 |
'template' => '#ffd',
|
vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php
CHANGED
@@ -27,12 +27,12 @@ class Twig_Profiler_Node_EnterProfile extends Twig_Node
|
|
27 |
public function compile(Twig_Compiler $compiler)
|
28 |
{
|
29 |
$compiler
|
30 |
-
->write(sprintf(
|
31 |
->repr($this->getAttribute('extension_name'))
|
32 |
->raw(");\n")
|
33 |
-
->write(sprintf(
|
34 |
->repr($this->getAttribute('type'))
|
35 |
-
->raw(
|
36 |
->repr($this->getAttribute('name'))
|
37 |
->raw("));\n\n")
|
38 |
;
|
27 |
public function compile(Twig_Compiler $compiler)
|
28 |
{
|
29 |
$compiler
|
30 |
+
->write(sprintf('$%s = $this->env->getExtension(', $this->getAttribute('var_name')))
|
31 |
->repr($this->getAttribute('extension_name'))
|
32 |
->raw(");\n")
|
33 |
+
->write(sprintf('$%s->enter($%s = new Twig_Profiler_Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof'))
|
34 |
->repr($this->getAttribute('type'))
|
35 |
+
->raw(', ')
|
36 |
->repr($this->getAttribute('name'))
|
37 |
->raw("));\n\n")
|
38 |
;
|
vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
/**
|
13 |
* @author Fabien Potencier <fabien@symfony.com>
|
14 |
*/
|
15 |
-
class Twig_Profiler_NodeVisitor_Profiler
|
16 |
{
|
17 |
private $extensionName;
|
18 |
|
@@ -24,7 +24,7 @@ class Twig_Profiler_NodeVisitor_Profiler implements Twig_NodeVisitorInterface
|
|
24 |
/**
|
25 |
* {@inheritdoc}
|
26 |
*/
|
27 |
-
|
28 |
{
|
29 |
return $node;
|
30 |
}
|
@@ -32,7 +32,7 @@ class Twig_Profiler_NodeVisitor_Profiler implements Twig_NodeVisitorInterface
|
|
32 |
/**
|
33 |
* {@inheritdoc}
|
34 |
*/
|
35 |
-
|
36 |
{
|
37 |
if ($node instanceof Twig_Node_Module) {
|
38 |
$varName = $this->getVarName();
|
12 |
/**
|
13 |
* @author Fabien Potencier <fabien@symfony.com>
|
14 |
*/
|
15 |
+
class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor
|
16 |
{
|
17 |
private $extensionName;
|
18 |
|
24 |
/**
|
25 |
* {@inheritdoc}
|
26 |
*/
|
27 |
+
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
28 |
{
|
29 |
return $node;
|
30 |
}
|
32 |
/**
|
33 |
* {@inheritdoc}
|
34 |
*/
|
35 |
+
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
36 |
{
|
37 |
if ($node instanceof Twig_Node_Module) {
|
38 |
$varName = $this->getVarName();
|
vendor/twig/twig/lib/Twig/Profiler/Profile.php
CHANGED
@@ -26,7 +26,7 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable
|
|
26 |
private $ends = array();
|
27 |
private $profiles = array();
|
28 |
|
29 |
-
public function __construct($template = 'main', $type =
|
30 |
{
|
31 |
$this->template = $template;
|
32 |
$this->type = $type;
|
26 |
private $ends = array();
|
27 |
private $profiles = array();
|
28 |
|
29 |
+
public function __construct($template = 'main', $type = self::ROOT, $name = 'main')
|
30 |
{
|
31 |
$this->template = $template;
|
32 |
$this->type = $type;
|
vendor/twig/twig/lib/Twig/SimpleFilter.php
CHANGED
@@ -27,12 +27,13 @@ class Twig_SimpleFilter
|
|
27 |
$this->callable = $callable;
|
28 |
$this->options = array_merge(array(
|
29 |
'needs_environment' => false,
|
30 |
-
'needs_context'
|
31 |
-
'
|
32 |
-
'
|
33 |
-
'
|
34 |
-
'
|
35 |
-
'
|
|
|
36 |
), $options);
|
37 |
}
|
38 |
|
@@ -91,4 +92,9 @@ class Twig_SimpleFilter
|
|
91 |
{
|
92 |
return $this->options['pre_escape'];
|
93 |
}
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
27 |
$this->callable = $callable;
|
28 |
$this->options = array_merge(array(
|
29 |
'needs_environment' => false,
|
30 |
+
'needs_context' => false,
|
31 |
+
'is_variadic' => false,
|
32 |
+
'is_safe' => null,
|
33 |
+
'is_safe_callback' => null,
|
34 |
+
'pre_escape' => null,
|
35 |
+
'preserves_safety' => null,
|
36 |
+
'node_class' => 'Twig_Node_Expression_Filter',
|
37 |
), $options);
|
38 |
}
|
39 |
|
92 |
{
|
93 |
return $this->options['pre_escape'];
|
94 |
}
|
95 |
+
|
96 |
+
public function isVariadic()
|
97 |
+
{
|
98 |
+
return $this->options['is_variadic'];
|
99 |
+
}
|
100 |
}
|
vendor/twig/twig/lib/Twig/SimpleFunction.php
CHANGED
@@ -27,10 +27,11 @@ class Twig_SimpleFunction
|
|
27 |
$this->callable = $callable;
|
28 |
$this->options = array_merge(array(
|
29 |
'needs_environment' => false,
|
30 |
-
'needs_context'
|
31 |
-
'
|
32 |
-
'
|
33 |
-
'
|
|
|
34 |
), $options);
|
35 |
}
|
36 |
|
@@ -81,4 +82,9 @@ class Twig_SimpleFunction
|
|
81 |
|
82 |
return array();
|
83 |
}
|
|
|
|
|
|
|
|
|
|
|
84 |
}
|
27 |
$this->callable = $callable;
|
28 |
$this->options = array_merge(array(
|
29 |
'needs_environment' => false,
|
30 |
+
'needs_context' => false,
|
31 |
+
'is_variadic' => false,
|
32 |
+
'is_safe' => null,
|
33 |
+
'is_safe_callback' => null,
|
34 |
+
'node_class' => 'Twig_Node_Expression_Function',
|
35 |
), $options);
|
36 |
}
|
37 |
|
82 |
|
83 |
return array();
|
84 |
}
|
85 |
+
|
86 |
+
public function isVariadic()
|
87 |
+
{
|
88 |
+
return $this->options['is_variadic'];
|
89 |
+
}
|
90 |
}
|
vendor/twig/twig/lib/Twig/SimpleTest.php
CHANGED
@@ -25,6 +25,7 @@ class Twig_SimpleTest
|
|
25 |
$this->name = $name;
|
26 |
$this->callable = $callable;
|
27 |
$this->options = array_merge(array(
|
|
|
28 |
'node_class' => 'Twig_Node_Expression_Test',
|
29 |
), $options);
|
30 |
}
|
@@ -43,4 +44,9 @@ class Twig_SimpleTest
|
|
43 |
{
|
44 |
return $this->options['node_class'];
|
45 |
}
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
25 |
$this->name = $name;
|
26 |
$this->callable = $callable;
|
27 |
$this->options = array_merge(array(
|
28 |
+
'is_variadic' => false,
|
29 |
'node_class' => 'Twig_Node_Expression_Test',
|
30 |
), $options);
|
31 |
}
|
44 |
{
|
45 |
return $this->options['node_class'];
|
46 |
}
|
47 |
+
|
48 |
+
public function isVariadic()
|
49 |
+
{
|
50 |
+
return $this->options['is_variadic'];
|
51 |
+
}
|
52 |
}
|
vendor/twig/twig/lib/Twig/Template.php
CHANGED
@@ -45,10 +45,12 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
45 |
abstract public function getTemplateName();
|
46 |
|
47 |
/**
|
48 |
-
*
|
49 |
*/
|
50 |
public function getEnvironment()
|
51 |
{
|
|
|
|
|
52 |
return $this->env;
|
53 |
}
|
54 |
|
@@ -152,9 +154,25 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
152 |
}
|
153 |
|
154 |
if (null !== $template) {
|
|
|
|
|
|
|
|
|
|
|
155 |
try {
|
156 |
$template->$block($context, $blocks);
|
157 |
} catch (Twig_Error $e) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
throw $e;
|
159 |
} catch (Exception $e) {
|
160 |
throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
|
@@ -462,7 +480,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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;
|
@@ -480,7 +498,24 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
480 |
|
481 |
// object method
|
482 |
if (!isset(self::$cache[$class]['methods'])) {
|
483 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
}
|
485 |
|
486 |
$call = false;
|
45 |
abstract public function getTemplateName();
|
46 |
|
47 |
/**
|
48 |
+
* @deprecated since 1.20 (to be removed in 2.0)
|
49 |
*/
|
50 |
public function getEnvironment()
|
51 |
{
|
52 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.', E_USER_DEPRECATED);
|
53 |
+
|
54 |
return $this->env;
|
55 |
}
|
56 |
|
154 |
}
|
155 |
|
156 |
if (null !== $template) {
|
157 |
+
// avoid RCEs when sandbox is enabled
|
158 |
+
if (!$template instanceof Twig_Template) {
|
159 |
+
throw new \LogicException('A block must be a method on a Twig_Template instance.');
|
160 |
+
}
|
161 |
+
|
162 |
try {
|
163 |
$template->$block($context, $blocks);
|
164 |
} catch (Twig_Error $e) {
|
165 |
+
if (!$e->getTemplateFile()) {
|
166 |
+
$e->setTemplateFile($template->getTemplateName());
|
167 |
+
}
|
168 |
+
|
169 |
+
// this is mostly useful for Twig_Error_Loader exceptions
|
170 |
+
// see Twig_Error_Loader
|
171 |
+
if (false === $e->getTemplateLine()) {
|
172 |
+
$e->setTemplateLine(-1);
|
173 |
+
$e->guess();
|
174 |
+
}
|
175 |
+
|
176 |
throw $e;
|
177 |
} catch (Exception $e) {
|
178 |
throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
|
480 |
}
|
481 |
|
482 |
// object property
|
483 |
+
if (self::METHOD_CALL !== $type && !$object instanceof self) { // Twig_Template does not have public properties, and we don't want to allow access to internal ones
|
484 |
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
485 |
if ($isDefinedTest) {
|
486 |
return true;
|
498 |
|
499 |
// object method
|
500 |
if (!isset(self::$cache[$class]['methods'])) {
|
501 |
+
// get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
|
502 |
+
if ($object instanceof self) {
|
503 |
+
$ref = new ReflectionClass($class);
|
504 |
+
$methods = array();
|
505 |
+
|
506 |
+
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
507 |
+
$methodName = strtolower($refMethod->name);
|
508 |
+
|
509 |
+
// Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
|
510 |
+
if ('getenvironment' !== $methodName) {
|
511 |
+
$methods[$methodName] = true;
|
512 |
+
}
|
513 |
+
}
|
514 |
+
|
515 |
+
self::$cache[$class]['methods'] = $methods;
|
516 |
+
} else {
|
517 |
+
self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
|
518 |
+
}
|
519 |
}
|
520 |
|
521 |
$call = false;
|
vendor/twig/twig/lib/Twig/TemplateInterface.php
CHANGED
@@ -18,8 +18,8 @@
|
|
18 |
*/
|
19 |
interface Twig_TemplateInterface
|
20 |
{
|
21 |
-
const ANY_CALL
|
22 |
-
const ARRAY_CALL
|
23 |
const METHOD_CALL = 'method';
|
24 |
|
25 |
/**
|
18 |
*/
|
19 |
interface Twig_TemplateInterface
|
20 |
{
|
21 |
+
const ANY_CALL = 'any';
|
22 |
+
const ARRAY_CALL = 'array';
|
23 |
const METHOD_CALL = 'method';
|
24 |
|
25 |
/**
|
vendor/twig/twig/lib/Twig/Test.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
|
vendor/twig/twig/lib/Twig/Test/Function.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* Represents a function template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
class Twig_Test_Function extends Twig_Test
|
13 |
* Represents a function template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_Test_Function extends Twig_Test
|
vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
-
* Integration test helper
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
* @author Karma Dordrak <drak@zikula.org>
|
@@ -74,7 +74,7 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
|
74 |
|
75 |
$loader = new Twig_Loader_Array($templates);
|
76 |
|
77 |
-
foreach ($outputs as $match) {
|
78 |
$config = array_merge(array(
|
79 |
'cache' => false,
|
80 |
'strict_variables' => true,
|
@@ -85,6 +85,14 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
|
85 |
$twig->addExtension($extension);
|
86 |
}
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
try {
|
89 |
$template = $twig->loadTemplate('index.twig');
|
90 |
} catch (Exception $e) {
|
@@ -122,14 +130,14 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
|
122 |
}
|
123 |
|
124 |
if (false !== $exception) {
|
125 |
-
list($class
|
126 |
$this->assertThat(null, new PHPUnit_Framework_Constraint_Exception($class));
|
127 |
}
|
128 |
|
129 |
$expected = trim($match[3], "\n ");
|
130 |
|
131 |
if ($expected != $output) {
|
132 |
-
|
133 |
|
134 |
foreach (array_keys($templates) as $name) {
|
135 |
echo "Template: $name\n";
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
+
* Integration test helper.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
* @author Karma Dordrak <drak@zikula.org>
|
74 |
|
75 |
$loader = new Twig_Loader_Array($templates);
|
76 |
|
77 |
+
foreach ($outputs as $i => $match) {
|
78 |
$config = array_merge(array(
|
79 |
'cache' => false,
|
80 |
'strict_variables' => true,
|
85 |
$twig->addExtension($extension);
|
86 |
}
|
87 |
|
88 |
+
// avoid using the same PHP class name for different cases
|
89 |
+
// only for PHP 5.2+
|
90 |
+
if (PHP_VERSION_ID >= 50300) {
|
91 |
+
$p = new ReflectionProperty($twig, 'templateClassPrefix');
|
92 |
+
$p->setAccessible(true);
|
93 |
+
$p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_');
|
94 |
+
}
|
95 |
+
|
96 |
try {
|
97 |
$template = $twig->loadTemplate('index.twig');
|
98 |
} catch (Exception $e) {
|
130 |
}
|
131 |
|
132 |
if (false !== $exception) {
|
133 |
+
list($class) = explode(':', $exception);
|
134 |
$this->assertThat(null, new PHPUnit_Framework_Constraint_Exception($class));
|
135 |
}
|
136 |
|
137 |
$expected = trim($match[3], "\n ");
|
138 |
|
139 |
if ($expected != $output) {
|
140 |
+
printf("Compiled templates that failed on case %d:\n", $i + 1);
|
141 |
|
142 |
foreach (array_keys($templates) as $name) {
|
143 |
echo "Template: $name\n";
|
vendor/twig/twig/lib/Twig/Test/Method.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* Represents a method template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
class Twig_Test_Method extends Twig_Test
|
13 |
* Represents a method template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_Test_Method extends Twig_Test
|
vendor/twig/twig/lib/Twig/Test/Node.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* Represents a template test as a Node.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
class Twig_Test_Node extends Twig_Test
|
13 |
* Represents a template test as a Node.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_Test_Node extends Twig_Test
|
vendor/twig/twig/lib/Twig/TestCallableInterface.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* Represents a callable template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_TestCallableInterface
|
13 |
* Represents a callable template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_TestCallableInterface
|
vendor/twig/twig/lib/Twig/TestInterface.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
16 |
* @deprecated since 1.12 (to be removed in 2.0)
|
17 |
*/
|
18 |
interface Twig_TestInterface
|
13 |
* Represents a template test.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
interface Twig_TestInterface
|
vendor/twig/twig/lib/Twig/Token.php
CHANGED
@@ -21,19 +21,19 @@ class Twig_Token
|
|
21 |
protected $type;
|
22 |
protected $lineno;
|
23 |
|
24 |
-
const EOF_TYPE
|
25 |
-
const TEXT_TYPE
|
26 |
-
const BLOCK_START_TYPE
|
27 |
-
const VAR_START_TYPE
|
28 |
-
const BLOCK_END_TYPE
|
29 |
-
const VAR_END_TYPE
|
30 |
-
const NAME_TYPE
|
31 |
-
const NUMBER_TYPE
|
32 |
-
const STRING_TYPE
|
33 |
-
const OPERATOR_TYPE
|
34 |
-
const PUNCTUATION_TYPE
|
35 |
-
const INTERPOLATION_START_TYPE
|
36 |
-
const INTERPOLATION_END_TYPE
|
37 |
|
38 |
/**
|
39 |
* Constructor.
|
@@ -44,8 +44,8 @@ class Twig_Token
|
|
44 |
*/
|
45 |
public function __construct($type, $value, $lineno)
|
46 |
{
|
47 |
-
$this->type
|
48 |
-
$this->value
|
49 |
$this->lineno = $lineno;
|
50 |
}
|
51 |
|
21 |
protected $type;
|
22 |
protected $lineno;
|
23 |
|
24 |
+
const EOF_TYPE = -1;
|
25 |
+
const TEXT_TYPE = 0;
|
26 |
+
const BLOCK_START_TYPE = 1;
|
27 |
+
const VAR_START_TYPE = 2;
|
28 |
+
const BLOCK_END_TYPE = 3;
|
29 |
+
const VAR_END_TYPE = 4;
|
30 |
+
const NAME_TYPE = 5;
|
31 |
+
const NUMBER_TYPE = 6;
|
32 |
+
const STRING_TYPE = 7;
|
33 |
+
const OPERATOR_TYPE = 8;
|
34 |
+
const PUNCTUATION_TYPE = 9;
|
35 |
+
const INTERPOLATION_START_TYPE = 10;
|
36 |
+
const INTERPOLATION_END_TYPE = 11;
|
37 |
|
38 |
/**
|
39 |
* Constructor.
|
44 |
*/
|
45 |
public function __construct($type, $value, $lineno)
|
46 |
{
|
47 |
+
$this->type = $type;
|
48 |
+
$this->value = $value;
|
49 |
$this->lineno = $lineno;
|
50 |
}
|
51 |
|
vendor/twig/twig/lib/Twig/TokenParser.php
CHANGED
@@ -22,7 +22,7 @@ abstract class Twig_TokenParser implements Twig_TokenParserInterface
|
|
22 |
protected $parser;
|
23 |
|
24 |
/**
|
25 |
-
* Sets the parser associated with this token parser
|
26 |
*
|
27 |
* @param Twig_Parser $parser A Twig_Parser instance
|
28 |
*/
|
22 |
protected $parser;
|
23 |
|
24 |
/**
|
25 |
+
* Sets the parser associated with this token parser.
|
26 |
*
|
27 |
* @param Twig_Parser $parser A Twig_Parser instance
|
28 |
*/
|
vendor/twig/twig/lib/Twig/TokenParser/From.php
CHANGED
@@ -52,6 +52,10 @@ class Twig_TokenParser_From extends Twig_TokenParser
|
|
52 |
$node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
|
53 |
|
54 |
foreach ($targets as $name => $alias) {
|
|
|
|
|
|
|
|
|
55 |
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
56 |
}
|
57 |
|
52 |
$node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
|
53 |
|
54 |
foreach ($targets as $name => $alias) {
|
55 |
+
if ($this->parser->isReservedMacroName($name)) {
|
56 |
+
throw new Twig_Error_Syntax(sprintf('"%s" cannot be an imported macro as it is a reserved keyword', $name), $token->getLine(), $stream->getFilename());
|
57 |
+
}
|
58 |
+
|
59 |
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
60 |
}
|
61 |
|
vendor/twig/twig/lib/Twig/TokenParserBroker.php
CHANGED
@@ -14,6 +14,7 @@
|
|
14 |
* Default implementation of a token parser broker.
|
15 |
*
|
16 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
17 |
* @deprecated since 1.12 (to be removed in 2.0)
|
18 |
*/
|
19 |
class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
14 |
* Default implementation of a token parser broker.
|
15 |
*
|
16 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
17 |
+
*
|
18 |
* @deprecated since 1.12 (to be removed in 2.0)
|
19 |
*/
|
20 |
class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php
CHANGED
@@ -16,6 +16,7 @@
|
|
16 |
* Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
|
|
19 |
* @deprecated since 1.12 (to be removed in 2.0)
|
20 |
*/
|
21 |
interface Twig_TokenParserBrokerInterface
|
16 |
* Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
|
17 |
*
|
18 |
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
19 |
+
*
|
20 |
* @deprecated since 1.12 (to be removed in 2.0)
|
21 |
*/
|
22 |
interface Twig_TokenParserBrokerInterface
|
vendor/twig/twig/lib/Twig/TokenParserInterface.php
CHANGED
@@ -17,7 +17,7 @@
|
|
17 |
interface Twig_TokenParserInterface
|
18 |
{
|
19 |
/**
|
20 |
-
* Sets the parser associated with this token parser
|
21 |
*
|
22 |
* @param Twig_Parser $parser A Twig_Parser instance
|
23 |
*/
|
17 |
interface Twig_TokenParserInterface
|
18 |
{
|
19 |
/**
|
20 |
+
* Sets the parser associated with this token parser.
|
21 |
*
|
22 |
* @param Twig_Parser $parser A Twig_Parser instance
|
23 |
*/
|
vendor/twig/twig/lib/Twig/TokenStream.php
CHANGED
@@ -29,9 +29,9 @@ class Twig_TokenStream
|
|
29 |
*/
|
30 |
public function __construct(array $tokens, $filename = null)
|
31 |
{
|
32 |
-
$this->tokens
|
33 |
-
$this->current
|
34 |
-
$this->filename
|
35 |
}
|
36 |
|
37 |
/**
|
@@ -115,7 +115,7 @@ class Twig_TokenStream
|
|
115 |
}
|
116 |
|
117 |
/**
|
118 |
-
* Tests the current token
|
119 |
*
|
120 |
* @return bool
|
121 |
*/
|
@@ -125,7 +125,7 @@ class Twig_TokenStream
|
|
125 |
}
|
126 |
|
127 |
/**
|
128 |
-
* Checks if end of stream was reached
|
129 |
*
|
130 |
* @return bool
|
131 |
*/
|
@@ -135,7 +135,7 @@ class Twig_TokenStream
|
|
135 |
}
|
136 |
|
137 |
/**
|
138 |
-
* Gets the current token
|
139 |
*
|
140 |
* @return Twig_Token
|
141 |
*/
|
@@ -145,7 +145,7 @@ class Twig_TokenStream
|
|
145 |
}
|
146 |
|
147 |
/**
|
148 |
-
* Gets the filename associated with this stream
|
149 |
*
|
150 |
* @return string
|
151 |
*/
|
29 |
*/
|
30 |
public function __construct(array $tokens, $filename = null)
|
31 |
{
|
32 |
+
$this->tokens = $tokens;
|
33 |
+
$this->current = 0;
|
34 |
+
$this->filename = $filename;
|
35 |
}
|
36 |
|
37 |
/**
|
115 |
}
|
116 |
|
117 |
/**
|
118 |
+
* Tests the current token.
|
119 |
*
|
120 |
* @return bool
|
121 |
*/
|
125 |
}
|
126 |
|
127 |
/**
|
128 |
+
* Checks if end of stream was reached.
|
129 |
*
|
130 |
* @return bool
|
131 |
*/
|
135 |
}
|
136 |
|
137 |
/**
|
138 |
+
* Gets the current token.
|
139 |
*
|
140 |
* @return Twig_Token
|
141 |
*/
|
145 |
}
|
146 |
|
147 |
/**
|
148 |
+
* Gets the filename associated with this stream.
|
149 |
*
|
150 |
* @return string
|
151 |
*/
|
vendor/twig/twig/test/Twig/Tests/CompilerTest.php
CHANGED
@@ -22,7 +22,7 @@ class Twig_Tests_CompilerTest extends PHPUnit_Framework_TestCase
|
|
22 |
|
23 |
$required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
|
24 |
if (false === setlocale(LC_NUMERIC, $required_locales)) {
|
25 |
-
$this->markTestSkipped('Could not set any of required locales: '.implode(
|
26 |
}
|
27 |
|
28 |
$this->assertEquals('1.2', $compiler->repr(1.2)->getSource());
|
22 |
|
23 |
$required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
|
24 |
if (false === setlocale(LC_NUMERIC, $required_locales)) {
|
25 |
+
$this->markTestSkipped('Could not set any of required locales: '.implode(', ', $required_locales));
|
26 |
}
|
27 |
|
28 |
$this->assertEquals('1.2', $compiler->repr(1.2)->getSource());
|
vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
CHANGED
@@ -25,12 +25,12 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
25 |
{
|
26 |
$loader = new Twig_Loader_Array(array(
|
27 |
'html' => '{{ foo }} {{ foo }}',
|
28 |
-
'js'
|
29 |
));
|
30 |
|
31 |
$twig = new Twig_Environment($loader, array(
|
32 |
-
'debug'
|
33 |
-
'cache'
|
34 |
'autoescape' => array($this, 'escapingStrategyCallback'),
|
35 |
));
|
36 |
|
25 |
{
|
26 |
$loader = new Twig_Loader_Array(array(
|
27 |
'html' => '{{ foo }} {{ foo }}',
|
28 |
+
'js' => '{{ bar }} {{ bar }}',
|
29 |
));
|
30 |
|
31 |
$twig = new Twig_Environment($loader, array(
|
32 |
+
'debug' => true,
|
33 |
+
'cache' => false,
|
34 |
'autoescape' => array($this, 'escapingStrategyCallback'),
|
35 |
));
|
36 |
|
vendor/twig/twig/test/Twig/Tests/ErrorTest.php
CHANGED
@@ -99,7 +99,7 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
99 |
// error occurs in an included template
|
100 |
array(
|
101 |
array(
|
102 |
-
'index'
|
103 |
'partial' => '{{ foo.bar }}',
|
104 |
),
|
105 |
'partial', 1,
|
99 |
// error occurs in an included template
|
100 |
array(
|
101 |
array(
|
102 |
+
'index' => "{% include 'partial' %}",
|
103 |
'partial' => '{{ foo.bar }}',
|
104 |
),
|
105 |
'partial', 1,
|
vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php
CHANGED
@@ -18,7 +18,7 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
|
|
18 |
{
|
19 |
$env = new Twig_Environment();
|
20 |
|
21 |
-
for ($i = 0; $i < 100;
|
22 |
$this->assertTrue(in_array(twig_random($env, $value), $expectedInArray, true)); // assertContains() would not consider the type
|
23 |
}
|
24 |
}
|
@@ -26,31 +26,31 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
|
|
26 |
public function getRandomFunctionTestData()
|
27 |
{
|
28 |
return array(
|
29 |
-
array(
|
30 |
array('apple', 'orange', 'citrus'),
|
31 |
array('apple', 'orange', 'citrus'),
|
32 |
),
|
33 |
-
array(
|
34 |
new ArrayObject(array('apple', 'orange', 'citrus')),
|
35 |
array('apple', 'orange', 'citrus'),
|
36 |
),
|
37 |
-
array(
|
38 |
'Ä€é',
|
39 |
array('Ä', '€', 'é'),
|
40 |
),
|
41 |
-
array(
|
42 |
'123',
|
43 |
array('1', '2', '3'),
|
44 |
),
|
45 |
-
array(
|
46 |
5,
|
47 |
range(0, 5, 1),
|
48 |
),
|
49 |
-
array(
|
50 |
5.9,
|
51 |
range(0, 5, 1),
|
52 |
),
|
53 |
-
array(
|
54 |
-2,
|
55 |
array(0, -1, -2),
|
56 |
),
|
@@ -61,7 +61,7 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
|
|
61 |
{
|
62 |
$max = mt_getrandmax();
|
63 |
|
64 |
-
for ($i = 0; $i < 100;
|
65 |
$val = twig_random(new Twig_Environment());
|
66 |
$this->assertTrue(is_int($val) && $val >= 0 && $val <= $max);
|
67 |
}
|
@@ -94,7 +94,7 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
|
|
94 |
$twig->setCharset('ISO-8859-1');
|
95 |
|
96 |
$text = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8');
|
97 |
-
for ($i = 0; $i < 30;
|
98 |
$rand = twig_random($twig, $text);
|
99 |
$this->assertTrue(in_array(twig_convert_encoding($rand, 'UTF-8', 'ISO-8859-1'), array('Ä', 'é'), true));
|
100 |
}
|
18 |
{
|
19 |
$env = new Twig_Environment();
|
20 |
|
21 |
+
for ($i = 0; $i < 100; ++$i) {
|
22 |
$this->assertTrue(in_array(twig_random($env, $value), $expectedInArray, true)); // assertContains() would not consider the type
|
23 |
}
|
24 |
}
|
26 |
public function getRandomFunctionTestData()
|
27 |
{
|
28 |
return array(
|
29 |
+
array(// array
|
30 |
array('apple', 'orange', 'citrus'),
|
31 |
array('apple', 'orange', 'citrus'),
|
32 |
),
|
33 |
+
array(// Traversable
|
34 |
new ArrayObject(array('apple', 'orange', 'citrus')),
|
35 |
array('apple', 'orange', 'citrus'),
|
36 |
),
|
37 |
+
array(// unicode string
|
38 |
'Ä€é',
|
39 |
array('Ä', '€', 'é'),
|
40 |
),
|
41 |
+
array(// numeric but string
|
42 |
'123',
|
43 |
array('1', '2', '3'),
|
44 |
),
|
45 |
+
array(// integer
|
46 |
5,
|
47 |
range(0, 5, 1),
|
48 |
),
|
49 |
+
array(// float
|
50 |
5.9,
|
51 |
range(0, 5, 1),
|
52 |
),
|
53 |
+
array(// negative
|
54 |
-2,
|
55 |
array(0, -1, -2),
|
56 |
),
|
61 |
{
|
62 |
$max = mt_getrandmax();
|
63 |
|
64 |
+
for ($i = 0; $i < 100; ++$i) {
|
65 |
$val = twig_random(new Twig_Environment());
|
66 |
$this->assertTrue(is_int($val) && $val >= 0 && $val <= $max);
|
67 |
}
|
94 |
$twig->setCharset('ISO-8859-1');
|
95 |
|
96 |
$text = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8');
|
97 |
+
for ($i = 0; $i < 30; ++$i) {
|
98 |
$rand = twig_random($twig, $text);
|
99 |
$this->assertTrue(in_array(twig_convert_encoding($rand, 'UTF-8', 'ISO-8859-1'), array('Ä', 'é'), true));
|
100 |
}
|
vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
CHANGED
@@ -17,8 +17,8 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
17 |
{
|
18 |
self::$params = array(
|
19 |
'name' => 'Fabien',
|
20 |
-
'obj'
|
21 |
-
'arr'
|
22 |
);
|
23 |
|
24 |
self::$templates = array(
|
@@ -31,9 +31,9 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
31 |
'1_basic7' => '{{ cycle(["foo","bar"], 1) }}',
|
32 |
'1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}',
|
33 |
'1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}',
|
34 |
-
'1_basic'
|
35 |
'1_layout' => '{% block content %}{% endblock %}',
|
36 |
-
'1_child'
|
37 |
);
|
38 |
}
|
39 |
|
@@ -141,7 +141,7 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
141 |
public function testSandboxLocallySetForAnInclude()
|
142 |
{
|
143 |
self::$templates = array(
|
144 |
-
'2_basic'
|
145 |
'2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
146 |
);
|
147 |
|
@@ -149,7 +149,7 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
149 |
$this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include');
|
150 |
|
151 |
self::$templates = array(
|
152 |
-
'3_basic'
|
153 |
'3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
154 |
);
|
155 |
|
17 |
{
|
18 |
self::$params = array(
|
19 |
'name' => 'Fabien',
|
20 |
+
'obj' => new FooObject(),
|
21 |
+
'arr' => array('obj' => new FooObject()),
|
22 |
);
|
23 |
|
24 |
self::$templates = array(
|
31 |
'1_basic7' => '{{ cycle(["foo","bar"], 1) }}',
|
32 |
'1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}',
|
33 |
'1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}',
|
34 |
+
'1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
35 |
'1_layout' => '{% block content %}{% endblock %}',
|
36 |
+
'1_child' => "{% extends \"1_layout\" %}\n{% block content %}\n{{ \"a\"|json_encode }}\n{% endblock %}",
|
37 |
);
|
38 |
}
|
39 |
|
141 |
public function testSandboxLocallySetForAnInclude()
|
142 |
{
|
143 |
self::$templates = array(
|
144 |
+
'2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}',
|
145 |
'2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
146 |
);
|
147 |
|
149 |
$this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include');
|
150 |
|
151 |
self::$templates = array(
|
152 |
+
'3_basic' => '{{ obj.foo }}{% sandbox %}{% include "3_included" %}{% endsandbox %}{{ obj.foo }}',
|
153 |
'3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
|
154 |
);
|
155 |
|
vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_template_in_child_template.test
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
Exception for an undefined template in a child template
|
3 |
+
--TEMPLATE--
|
4 |
+
{% extends 'base.twig' %}
|
5 |
+
|
6 |
+
{% block sidebar %}
|
7 |
+
{{ include('include.twig') }}
|
8 |
+
{% endblock %}
|
9 |
+
--TEMPLATE(base.twig)--
|
10 |
+
{% block sidebar %}
|
11 |
+
{% endblock %}
|
12 |
+
--DATA--
|
13 |
+
return array()
|
14 |
+
--EXCEPTION--
|
15 |
+
Twig_Error_Loader: Template "include.twig" is not defined in "index.twig" at line 5.
|
vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_keys.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"batch" filter preserves array keys
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ {'foo': 'bar', 'key': 'value'}|batch(4)|first|keys|join(',') }}
|
5 |
+
{{ {'foo': 'bar', 'key': 'value'}|batch(4, 'fill')|first|keys|join(',') }}
|
6 |
+
--DATA--
|
7 |
+
return array()
|
8 |
+
--EXPECT--
|
9 |
+
foo,key
|
10 |
+
foo,key,0,1
|
vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_zero_elements.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"batch" filter with zero elements
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ []|batch(3)|length }}
|
5 |
+
{{ []|batch(3, 'fill')|length }}
|
6 |
+
--DATA--
|
7 |
+
return array()
|
8 |
+
--EXPECT--
|
9 |
+
0
|
10 |
+
0
|
vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling.test
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"include" tag sandboxed
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ include("foo.twig", sandboxed = true) }}
|
5 |
+
{{ include("bar.twig") }}
|
6 |
+
--TEMPLATE(foo.twig)--
|
7 |
+
foo
|
8 |
+
--TEMPLATE(bar.twig)--
|
9 |
+
{{ foo|e }}
|
10 |
+
--DATA--
|
11 |
+
return array('foo' => 'bar<br />')
|
12 |
+
--EXPECT--
|
13 |
+
foo
|
14 |
+
|
15 |
+
|
16 |
+
bar<br />
|
vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"include" tag sandboxed
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ include("unknown.twig", sandboxed = true, ignore_missing = true) }}
|
5 |
+
{{ include("bar.twig") }}
|
6 |
+
--TEMPLATE(bar.twig)--
|
7 |
+
{{ foo|e }}
|
8 |
+
--DATA--
|
9 |
+
return array('foo' => 'bar<br />')
|
10 |
+
--EXPECT--
|
11 |
+
|
12 |
+
|
13 |
+
bar<br />
|
vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs.test
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
macro with arbitrary arguments
|
3 |
+
--TEMPLATE--
|
4 |
+
{% from _self import test1, test2 %}
|
5 |
+
|
6 |
+
{% macro test1(var) %}
|
7 |
+
{{- var }}: {{ varargs|join(", ") }}
|
8 |
+
{% endmacro %}
|
9 |
+
|
10 |
+
{% macro test2() %}
|
11 |
+
{{- varargs|join(", ") }}
|
12 |
+
{% endmacro %}
|
13 |
+
|
14 |
+
{{ test1("foo", "bar", "foobar") }}
|
15 |
+
{{ test2("foo", "bar", "foobar") }}
|
16 |
+
--DATA--
|
17 |
+
return array();
|
18 |
+
--EXPECT--
|
19 |
+
foo: bar, foobar
|
20 |
+
|
21 |
+
foo, bar, foobar
|
vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
macro with varargs argument
|
3 |
+
--TEMPLATE--
|
4 |
+
{% macro test(varargs) %}
|
5 |
+
{% endmacro %}
|
6 |
+
--EXCEPTION--
|
7 |
+
Twig_Error_Syntax: The argument "varargs" in macro "test" cannot be defined because the variable "varargs" is reserved for arbitrary arguments in "index.twig" at line 2
|
8 |
+
|
vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from_with_reserved_name.test
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"from" tag with reserved name
|
3 |
+
--TEMPLATE--
|
4 |
+
{% from 'forms.twig' import templateName %}
|
5 |
+
--TEMPLATE(forms.twig)--
|
6 |
+
--DATA--
|
7 |
+
return array()
|
8 |
+
--EXCEPTION--
|
9 |
+
Twig_Error_Syntax: "templateName" cannot be an imported macro as it is a reserved keyword in "index.twig" at line 2
|
vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/import_with_reserved_nam.test
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"from" tag with reserved name
|
3 |
+
--TEMPLATE--
|
4 |
+
{% import 'forms.twig' as macros %}
|
5 |
+
|
6 |
+
{{ macros.parent() }}
|
7 |
+
--TEMPLATE(forms.twig)--
|
8 |
+
--DATA--
|
9 |
+
return array()
|
10 |
+
--EXCEPTION--
|
11 |
+
Twig_Error_Syntax: "parent" cannot be called as macro as it is a reserved keyword in "index.twig" at line 4
|
vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/reserved_name.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"macro" tag with reserved name
|
3 |
+
--TEMPLATE--
|
4 |
+
{% macro parent(arg1, arg2) %}
|
5 |
+
parent
|
6 |
+
{% endmacro %}
|
7 |
+
--DATA--
|
8 |
+
return array()
|
9 |
+
--EXCEPTION--
|
10 |
+
Twig_Error_Syntax: "parent" cannot be used as a macro name as it is a reserved keyword in "index.twig" at line 2
|
vendor/twig/twig/test/Twig/Tests/IntegrationTest.php
CHANGED
@@ -175,7 +175,7 @@ class TwigTestExtension extends Twig_Extension
|
|
175 |
}
|
176 |
|
177 |
/**
|
178 |
-
* nl2br which also escapes, for testing escaper filters
|
179 |
*/
|
180 |
public function escape_and_nl2br($env, $value, $sep = '<br />')
|
181 |
{
|
@@ -183,7 +183,7 @@ class TwigTestExtension extends Twig_Extension
|
|
183 |
}
|
184 |
|
185 |
/**
|
186 |
-
* nl2br only, for testing filters with pre_escape
|
187 |
*/
|
188 |
public function nl2br($value, $sep = '<br />')
|
189 |
{
|
175 |
}
|
176 |
|
177 |
/**
|
178 |
+
* nl2br which also escapes, for testing escaper filters.
|
179 |
*/
|
180 |
public function escape_and_nl2br($env, $value, $sep = '<br />')
|
181 |
{
|
183 |
}
|
184 |
|
185 |
/**
|
186 |
+
* nl2br only, for testing filters with pre_escape.
|
187 |
*/
|
188 |
public function nl2br($value, $sep = '<br />')
|
189 |
{
|
vendor/twig/twig/test/Twig/Tests/LexerTest.php
CHANGED
@@ -146,14 +146,14 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
146 |
$stream = $lexer->tokenize($template);
|
147 |
$stream->next();
|
148 |
$node = $stream->next();
|
149 |
-
$this->assertEquals(
|
150 |
}
|
151 |
|
152 |
public function testStringWithEscapedDelimiter()
|
153 |
{
|
154 |
$tests = array(
|
155 |
"{{ 'foo \' bar' }}" => 'foo \' bar',
|
156 |
-
'{{ "foo \" bar" }}' =>
|
157 |
);
|
158 |
$lexer = new Twig_Lexer(new Twig_Environment());
|
159 |
foreach ($tests as $template => $expected) {
|
146 |
$stream = $lexer->tokenize($template);
|
147 |
$stream->next();
|
148 |
$node = $stream->next();
|
149 |
+
$this->assertEquals('922337203685477580700', $node->getValue());
|
150 |
}
|
151 |
|
152 |
public function testStringWithEscapedDelimiter()
|
153 |
{
|
154 |
$tests = array(
|
155 |
"{{ 'foo \' bar' }}" => 'foo \' bar',
|
156 |
+
'{{ "foo \" bar" }}' => 'foo " bar',
|
157 |
);
|
158 |
$lexer = new Twig_Lexer(new Twig_Environment());
|
159 |
foreach ($tests as $template => $expected) {
|
vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php
CHANGED
@@ -18,8 +18,8 @@ class Twig_Tests_NativeExtensionTest extends PHPUnit_Framework_TestCase
|
|
18 |
}
|
19 |
|
20 |
$twig = new Twig_Environment(new Twig_Loader_Array(array('index' => '{{ d1.date }}{{ d2.date }}')), array(
|
21 |
-
'debug'
|
22 |
-
'cache'
|
23 |
'autoescape' => false,
|
24 |
));
|
25 |
|
18 |
}
|
19 |
|
20 |
$twig = new Twig_Environment(new Twig_Loader_Array(array('index' => '{{ d1.date }}{{ d2.date }}')), array(
|
21 |
+
'debug' => true,
|
22 |
+
'cache' => false,
|
23 |
'autoescape' => false,
|
24 |
));
|
25 |
|
vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php
CHANGED
@@ -73,7 +73,7 @@ class Twig_Tests_Node_Expression_CallTest extends PHPUnit_Framework_TestCase
|
|
73 |
|
74 |
public function testResolveArgumentsOnlyNecessaryArgumentsForCustomFunction()
|
75 |
{
|
76 |
-
$node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' =>
|
77 |
|
78 |
$this->assertEquals(array('arg1'), $node->getArguments(array($this, 'customFunction'), array('arg1' => 'arg1')));
|
79 |
}
|
@@ -84,6 +84,16 @@ class Twig_Tests_Node_Expression_CallTest extends PHPUnit_Framework_TestCase
|
|
84 |
$this->assertEquals(array('arg1'), $node->getArguments(__CLASS__.'::customStaticFunction', array('arg1' => 'arg1')));
|
85 |
}
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
public static function customStaticFunction($arg1, $arg2 = 'default', $arg3 = array())
|
88 |
{
|
89 |
}
|
@@ -91,6 +101,10 @@ class Twig_Tests_Node_Expression_CallTest extends PHPUnit_Framework_TestCase
|
|
91 |
public function customFunction($arg1, $arg2 = 'default', $arg3 = array())
|
92 |
{
|
93 |
}
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
|
96 |
class Twig_Tests_Node_Expression_Call extends Twig_Node_Expression_Call
|
73 |
|
74 |
public function testResolveArgumentsOnlyNecessaryArgumentsForCustomFunction()
|
75 |
{
|
76 |
+
$node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'custom_function'));
|
77 |
|
78 |
$this->assertEquals(array('arg1'), $node->getArguments(array($this, 'customFunction'), array('arg1' => 'arg1')));
|
79 |
}
|
84 |
$this->assertEquals(array('arg1'), $node->getArguments(__CLASS__.'::customStaticFunction', array('arg1' => 'arg1')));
|
85 |
}
|
86 |
|
87 |
+
/**
|
88 |
+
* @expectedException LogicException
|
89 |
+
* @expectedExceptionMessage The last parameter of "Twig_Tests_Node_Expression_CallTest::customFunctionWithArbitraryArguments" for function "foo" must be an array with default value, eg. "array $arg = array()".
|
90 |
+
*/
|
91 |
+
public function testResolveArgumentsWithMissingParameterForArbitraryArguments()
|
92 |
+
{
|
93 |
+
$node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'foo', 'is_variadic' => true));
|
94 |
+
$node->getArguments(array($this, 'customFunctionWithArbitraryArguments'), array());
|
95 |
+
}
|
96 |
+
|
97 |
public static function customStaticFunction($arg1, $arg2 = 'default', $arg3 = array())
|
98 |
{
|
99 |
}
|
101 |
public function customFunction($arg1, $arg2 = 'default', $arg3 = array())
|
102 |
{
|
103 |
}
|
104 |
+
|
105 |
+
public function customFunctionWithArbitraryArguments()
|
106 |
+
{
|
107 |
+
}
|
108 |
}
|
109 |
|
110 |
class Twig_Tests_Node_Expression_Call extends Twig_Node_Expression_Call
|
vendor/twig/twig/test/Twig/Tests/Node/Expression/FilterTest.php
CHANGED
@@ -25,6 +25,10 @@ class Twig_Tests_Node_Expression_FilterTest extends Twig_Test_NodeTestCase
|
|
25 |
|
26 |
public function getTests()
|
27 |
{
|
|
|
|
|
|
|
|
|
28 |
$tests = array();
|
29 |
|
30 |
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
@@ -41,7 +45,7 @@ class Twig_Tests_Node_Expression_FilterTest extends Twig_Test_NodeTestCase
|
|
41 |
$date = new Twig_Node_Expression_Constant(0, 1);
|
42 |
$node = $this->createFilter($date, 'date', array(
|
43 |
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
44 |
-
'format'
|
45 |
));
|
46 |
$tests[] = array($node, 'twig_date_format_filter($this->env, 0, "d/m/Y H:i:s P", "America/Chicago")');
|
47 |
|
@@ -69,6 +73,31 @@ class Twig_Tests_Node_Expression_FilterTest extends Twig_Test_NodeTestCase
|
|
69 |
$tests[] = array($node, 'call_user_func_array($this->env->getFilter(\'anonymous\')->getCallable(), array("foo"))');
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
return $tests;
|
73 |
}
|
74 |
|
@@ -119,3 +148,7 @@ class Twig_Tests_Node_Expression_FilterTest extends Twig_Test_NodeTestCase
|
|
119 |
return parent::getEnvironment();
|
120 |
}
|
121 |
}
|
|
|
|
|
|
|
|
25 |
|
26 |
public function getTests()
|
27 |
{
|
28 |
+
$environment = new Twig_Environment();
|
29 |
+
$environment->addFilter(new Twig_SimpleFilter('bar', 'bar', array('needs_environment' => true)));
|
30 |
+
$environment->addFilter(new Twig_SimpleFilter('barbar', 'twig_tests_filter_barbar', array('needs_context' => true, 'is_variadic' => true)));
|
31 |
+
|
32 |
$tests = array();
|
33 |
|
34 |
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
45 |
$date = new Twig_Node_Expression_Constant(0, 1);
|
46 |
$node = $this->createFilter($date, 'date', array(
|
47 |
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
48 |
+
'format' => new Twig_Node_Expression_Constant('d/m/Y H:i:s P', 1),
|
49 |
));
|
50 |
$tests[] = array($node, 'twig_date_format_filter($this->env, 0, "d/m/Y H:i:s P", "America/Chicago")');
|
51 |
|
73 |
$tests[] = array($node, 'call_user_func_array($this->env->getFilter(\'anonymous\')->getCallable(), array("foo"))');
|
74 |
}
|
75 |
|
76 |
+
// needs environment
|
77 |
+
$node = $this->createFilter($string, 'bar');
|
78 |
+
$tests[] = array($node, 'bar($this->env, "abc")', $environment);
|
79 |
+
|
80 |
+
$node = $this->createFilter($string, 'bar', array(new Twig_Node_Expression_Constant('bar', 1)));
|
81 |
+
$tests[] = array($node, 'bar($this->env, "abc", "bar")', $environment);
|
82 |
+
|
83 |
+
// arbitrary named arguments
|
84 |
+
$node = $this->createFilter($string, 'barbar');
|
85 |
+
$tests[] = array($node, 'twig_tests_filter_barbar($context, "abc")', $environment);
|
86 |
+
|
87 |
+
$node = $this->createFilter($string, 'barbar', array('foo' => new Twig_Node_Expression_Constant('bar', 1)));
|
88 |
+
$tests[] = array($node, 'twig_tests_filter_barbar($context, "abc", null, null, array("foo" => "bar"))', $environment);
|
89 |
+
|
90 |
+
$node = $this->createFilter($string, 'barbar', array('arg2' => new Twig_Node_Expression_Constant('bar', 1)));
|
91 |
+
$tests[] = array($node, 'twig_tests_filter_barbar($context, "abc", null, "bar")', $environment);
|
92 |
+
|
93 |
+
$node = $this->createFilter($string, 'barbar', array(
|
94 |
+
new Twig_Node_Expression_Constant('1', 1),
|
95 |
+
new Twig_Node_Expression_Constant('2', 1),
|
96 |
+
new Twig_Node_Expression_Constant('3', 1),
|
97 |
+
'foo' => new Twig_Node_Expression_Constant('bar', 1),
|
98 |
+
));
|
99 |
+
$tests[] = array($node, 'twig_tests_filter_barbar($context, "abc", "1", "2", array(0 => "3", "foo" => "bar"))', $environment);
|
100 |
+
|
101 |
return $tests;
|
102 |
}
|
103 |
|
148 |
return parent::getEnvironment();
|
149 |
}
|
150 |
}
|
151 |
+
|
152 |
+
function twig_tests_filter_barbar($context, $string, $arg1 = null, $arg2 = null, array $args = array())
|
153 |
+
{
|
154 |
+
}
|
vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php
CHANGED
@@ -28,6 +28,7 @@ class Twig_Tests_Node_Expression_FunctionTest extends Twig_Test_NodeTestCase
|
|
28 |
$environment->addFunction(new Twig_SimpleFunction('bar', 'bar', array('needs_environment' => true)));
|
29 |
$environment->addFunction(new Twig_SimpleFunction('foofoo', 'foofoo', array('needs_context' => true)));
|
30 |
$environment->addFunction(new Twig_SimpleFunction('foobar', 'foobar', array('needs_environment' => true, 'needs_context' => true)));
|
|
|
31 |
|
32 |
$tests = array();
|
33 |
|
@@ -58,10 +59,28 @@ class Twig_Tests_Node_Expression_FunctionTest extends Twig_Test_NodeTestCase
|
|
58 |
// named arguments
|
59 |
$node = $this->createFunction('date', array(
|
60 |
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
61 |
-
'date'
|
62 |
));
|
63 |
$tests[] = array($node, 'twig_date_converter($this->env, 0, "America/Chicago")');
|
64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
// function as an anonymous function
|
66 |
if (PHP_VERSION_ID >= 50300) {
|
67 |
$node = $this->createFunction('anonymous', array(new Twig_Node_Expression_Constant('foo', 1)));
|
@@ -85,3 +104,7 @@ class Twig_Tests_Node_Expression_FunctionTest extends Twig_Test_NodeTestCase
|
|
85 |
return parent::getEnvironment();
|
86 |
}
|
87 |
}
|
|
|
|
|
|
|
|
28 |
$environment->addFunction(new Twig_SimpleFunction('bar', 'bar', array('needs_environment' => true)));
|
29 |
$environment->addFunction(new Twig_SimpleFunction('foofoo', 'foofoo', array('needs_context' => true)));
|
30 |
$environment->addFunction(new Twig_SimpleFunction('foobar', 'foobar', array('needs_environment' => true, 'needs_context' => true)));
|
31 |
+
$environment->addFunction(new Twig_SimpleFunction('barbar', 'twig_tests_function_barbar', array('is_variadic' => true)));
|
32 |
|
33 |
$tests = array();
|
34 |
|
59 |
// named arguments
|
60 |
$node = $this->createFunction('date', array(
|
61 |
'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1),
|
62 |
+
'date' => new Twig_Node_Expression_Constant(0, 1),
|
63 |
));
|
64 |
$tests[] = array($node, 'twig_date_converter($this->env, 0, "America/Chicago")');
|
65 |
|
66 |
+
// arbitrary named arguments
|
67 |
+
$node = $this->createFunction('barbar');
|
68 |
+
$tests[] = array($node, 'twig_tests_function_barbar()', $environment);
|
69 |
+
|
70 |
+
$node = $this->createFunction('barbar', array('foo' => new Twig_Node_Expression_Constant('bar', 1)));
|
71 |
+
$tests[] = array($node, 'twig_tests_function_barbar(null, null, array("foo" => "bar"))', $environment);
|
72 |
+
|
73 |
+
$node = $this->createFunction('barbar', array('arg2' => new Twig_Node_Expression_Constant('bar', 1)));
|
74 |
+
$tests[] = array($node, 'twig_tests_function_barbar(null, "bar")', $environment);
|
75 |
+
|
76 |
+
$node = $this->createFunction('barbar', array(
|
77 |
+
new Twig_Node_Expression_Constant('1', 1),
|
78 |
+
new Twig_Node_Expression_Constant('2', 1),
|
79 |
+
new Twig_Node_Expression_Constant('3', 1),
|
80 |
+
'foo' => new Twig_Node_Expression_Constant('bar', 1),
|
81 |
+
));
|
82 |
+
$tests[] = array($node, 'twig_tests_function_barbar("1", "2", array(0 => "3", "foo" => "bar"))', $environment);
|
83 |
+
|
84 |
// function as an anonymous function
|
85 |
if (PHP_VERSION_ID >= 50300) {
|
86 |
$node = $this->createFunction('anonymous', array(new Twig_Node_Expression_Constant('foo', 1)));
|
104 |
return parent::getEnvironment();
|
105 |
}
|
106 |
}
|
107 |
+
|
108 |
+
function twig_tests_function_barbar($arg1 = null, $arg2 = null, array $args = array())
|
109 |
+
{
|
110 |
+
}
|
vendor/twig/twig/test/Twig/Tests/Node/Expression/TestTest.php
CHANGED
@@ -25,6 +25,9 @@ class Twig_Tests_Node_Expression_TestTest extends Twig_Test_NodeTestCase
|
|
25 |
|
26 |
public function getTests()
|
27 |
{
|
|
|
|
|
|
|
28 |
$tests = array();
|
29 |
|
30 |
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
@@ -37,6 +40,25 @@ class Twig_Tests_Node_Expression_TestTest extends Twig_Test_NodeTestCase
|
|
37 |
$tests[] = array($node, 'call_user_func_array($this->env->getTest(\'anonymous\')->getCallable(), array("foo", "foo"))');
|
38 |
}
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
return $tests;
|
41 |
}
|
42 |
|
@@ -54,3 +76,7 @@ class Twig_Tests_Node_Expression_TestTest extends Twig_Test_NodeTestCase
|
|
54 |
return parent::getEnvironment();
|
55 |
}
|
56 |
}
|
|
|
|
|
|
|
|
25 |
|
26 |
public function getTests()
|
27 |
{
|
28 |
+
$environment = new Twig_Environment();
|
29 |
+
$environment->addTest(new Twig_SimpleTest('barbar', 'twig_tests_test_barbar', array('is_variadic' => true, 'need_context' => true)));
|
30 |
+
|
31 |
$tests = array();
|
32 |
|
33 |
$expr = new Twig_Node_Expression_Constant('foo', 1);
|
40 |
$tests[] = array($node, 'call_user_func_array($this->env->getTest(\'anonymous\')->getCallable(), array("foo", "foo"))');
|
41 |
}
|
42 |
|
43 |
+
// arbitrary named arguments
|
44 |
+
$string = new Twig_Node_Expression_Constant('abc', 1);
|
45 |
+
$node = $this->createTest($string, 'barbar');
|
46 |
+
$tests[] = array($node, 'twig_tests_test_barbar("abc")', $environment);
|
47 |
+
|
48 |
+
$node = $this->createTest($string, 'barbar', array('foo' => new Twig_Node_Expression_Constant('bar', 1)));
|
49 |
+
$tests[] = array($node, 'twig_tests_test_barbar("abc", null, null, array("foo" => "bar"))', $environment);
|
50 |
+
|
51 |
+
$node = $this->createTest($string, 'barbar', array('arg2' => new Twig_Node_Expression_Constant('bar', 1)));
|
52 |
+
$tests[] = array($node, 'twig_tests_test_barbar("abc", null, "bar")', $environment);
|
53 |
+
|
54 |
+
$node = $this->createTest($string, 'barbar', array(
|
55 |
+
new Twig_Node_Expression_Constant('1', 1),
|
56 |
+
new Twig_Node_Expression_Constant('2', 1),
|
57 |
+
new Twig_Node_Expression_Constant('3', 1),
|
58 |
+
'foo' => new Twig_Node_Expression_Constant('bar', 1),
|
59 |
+
));
|
60 |
+
$tests[] = array($node, 'twig_tests_test_barbar("abc", "1", "2", array(0 => "3", "foo" => "bar"))', $environment);
|
61 |
+
|
62 |
return $tests;
|
63 |
}
|
64 |
|
76 |
return parent::getEnvironment();
|
77 |
}
|
78 |
}
|
79 |
+
|
80 |
+
function twig_tests_test_barbar($string, $arg1 = null, $arg2 = null, array $args = array())
|
81 |
+
{
|
82 |
+
}
|
vendor/twig/twig/test/Twig/Tests/Node/MacroTest.php
CHANGED
@@ -31,14 +31,23 @@ class Twig_Tests_Node_MacroTest extends Twig_Test_NodeTestCase
|
|
31 |
), array(), 1);
|
32 |
$node = new Twig_Node_Macro('foo', $body, $arguments, 1);
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
return array(
|
35 |
array($node, <<<EOF
|
36 |
// line 1
|
37 |
-
public function getfoo(\$__foo__ = null, \$__bar__ = "Foo")
|
38 |
{
|
39 |
\$context = \$this->env->mergeGlobals(array(
|
40 |
"foo" => \$__foo__,
|
41 |
"bar" => \$__bar__,
|
|
|
42 |
));
|
43 |
|
44 |
\$blocks = array();
|
31 |
), array(), 1);
|
32 |
$node = new Twig_Node_Macro('foo', $body, $arguments, 1);
|
33 |
|
34 |
+
if (PHP_VERSION_ID >= 50600) {
|
35 |
+
$declaration = ', ...$__varargs__';
|
36 |
+
$varargs = '$__varargs__';
|
37 |
+
} else {
|
38 |
+
$declaration = '';
|
39 |
+
$varargs = 'func_num_args() > 2 ? array_slice(func_get_args(), 2) : array()';
|
40 |
+
}
|
41 |
+
|
42 |
return array(
|
43 |
array($node, <<<EOF
|
44 |
// line 1
|
45 |
+
public function getfoo(\$__foo__ = null, \$__bar__ = "Foo"$declaration)
|
46 |
{
|
47 |
\$context = \$this->env->mergeGlobals(array(
|
48 |
"foo" => \$__foo__,
|
49 |
"bar" => \$__bar__,
|
50 |
+
"varargs" => $varargs,
|
51 |
));
|
52 |
|
53 |
\$blocks = array();
|
vendor/twig/twig/test/Twig/Tests/ParserTest.php
CHANGED
@@ -16,7 +16,7 @@ class Twig_Tests_ParserTest extends PHPUnit_Framework_TestCase
|
|
16 |
public function testSetMacroThrowsExceptionOnReservedMethods()
|
17 |
{
|
18 |
$parser = $this->getParser();
|
19 |
-
$parser->setMacro('
|
20 |
}
|
21 |
|
22 |
/**
|
16 |
public function testSetMacroThrowsExceptionOnReservedMethods()
|
17 |
{
|
18 |
$parser = $this->getParser();
|
19 |
+
$parser->setMacro('parent', $this->getMock('Twig_Node_Macro', array(), array(), '', null));
|
20 |
}
|
21 |
|
22 |
/**
|
vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php
CHANGED
@@ -73,11 +73,11 @@ abstract class Twig_Tests_Profiler_Dumper_AbstractTest extends PHPUnit_Framework
|
|
73 |
|
74 |
/**
|
75 |
* @param string $name
|
76 |
-
* @param float
|
77 |
-
* @param bool
|
78 |
* @param string $type
|
79 |
* @param string $templateName
|
80 |
-
* @param array
|
81 |
*
|
82 |
* @return Twig_Profiler_Profile
|
83 |
*/
|
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 |
*/
|
vendor/twig/twig/test/Twig/Tests/TemplateTest.php
CHANGED
@@ -10,6 +10,15 @@
|
|
10 |
*/
|
11 |
class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
12 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* @dataProvider getAttributeExceptions
|
15 |
*/
|
@@ -27,13 +36,13 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
27 |
$template = $env->loadTemplate($name);
|
28 |
|
29 |
$context = array(
|
30 |
-
'string'
|
31 |
-
'null'
|
32 |
-
'empty_array'
|
33 |
-
'array'
|
34 |
-
'array_access'
|
35 |
'magic_exception' => new Twig_TemplateMagicPropertyObjectWithException(),
|
36 |
-
'object'
|
37 |
);
|
38 |
|
39 |
try {
|
@@ -60,7 +69,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
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),
|
62 |
array('{{ array_access.a }}', 'Method "a" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
63 |
-
array('{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{
|
64 |
array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.', false),
|
65 |
array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1', false),
|
66 |
);
|
@@ -138,6 +147,11 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
138 |
|
139 |
$this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty'));
|
140 |
$this->assertSame('', $template->getAttribute($template1, 'empty'));
|
|
|
|
|
|
|
|
|
|
|
141 |
}
|
142 |
|
143 |
public function getGetAttributeWithTemplateAsObject()
|
@@ -261,27 +275,27 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
261 |
{
|
262 |
$array = array(
|
263 |
'defined' => 'defined',
|
264 |
-
'zero'
|
265 |
-
'null'
|
266 |
-
'1'
|
267 |
-
'bar'
|
268 |
-
'09'
|
269 |
-
'+4'
|
270 |
);
|
271 |
|
272 |
-
$objectArray
|
273 |
-
$stdObject
|
274 |
$magicPropertyObject = new Twig_TemplateMagicPropertyObject();
|
275 |
-
$propertyObject
|
276 |
-
$propertyObject1
|
277 |
-
$propertyObject2
|
278 |
-
$propertyObject3
|
279 |
-
$methodObject
|
280 |
-
$magicMethodObject
|
281 |
-
|
282 |
-
$anyType
|
283 |
$methodType = Twig_Template::METHOD_CALL;
|
284 |
-
$arrayType
|
285 |
|
286 |
$basicTests = array(
|
287 |
// array(defined, value, property to fetch)
|
@@ -374,7 +388,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
374 |
// tests when input is not an array or object
|
375 |
$tests = array_merge($tests, array(
|
376 |
array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42")'),
|
377 |
-
array(false, null,
|
378 |
array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" does not exist as the array is empty'),
|
379 |
));
|
380 |
|
@@ -456,12 +470,12 @@ class Twig_TemplateArrayAccessObject implements ArrayAccess
|
|
456 |
|
457 |
public $attributes = array(
|
458 |
'defined' => 'defined',
|
459 |
-
'zero'
|
460 |
-
'null'
|
461 |
-
'1'
|
462 |
-
'bar'
|
463 |
-
'09'
|
464 |
-
'+4'
|
465 |
);
|
466 |
|
467 |
public function offsetExists($name)
|
@@ -488,12 +502,12 @@ class Twig_TemplateMagicPropertyObject
|
|
488 |
public $defined = 'defined';
|
489 |
|
490 |
public $attributes = array(
|
491 |
-
'zero'
|
492 |
-
'null'
|
493 |
-
'1'
|
494 |
-
'bar'
|
495 |
-
'09'
|
496 |
-
'+4'
|
497 |
);
|
498 |
|
499 |
protected $protected = 'protected';
|
@@ -520,9 +534,9 @@ class Twig_TemplateMagicPropertyObjectWithException
|
|
520 |
class Twig_TemplatePropertyObject
|
521 |
{
|
522 |
public $defined = 'defined';
|
523 |
-
public $zero
|
524 |
-
public $null
|
525 |
-
public $bar
|
526 |
|
527 |
protected $protected = 'protected';
|
528 |
}
|
10 |
*/
|
11 |
class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
12 |
{
|
13 |
+
/**
|
14 |
+
* @expectedException LogicException
|
15 |
+
*/
|
16 |
+
public function testDisplayBlocksAcceptTemplateOnlyAsBlocks()
|
17 |
+
{
|
18 |
+
$template = $this->getMockForAbstractClass('Twig_Template', array(), '', false);
|
19 |
+
$template->displayBlock('foo', array(), array('foo' => array(new stdClass(), 'foo')));
|
20 |
+
}
|
21 |
+
|
22 |
/**
|
23 |
* @dataProvider getAttributeExceptions
|
24 |
*/
|
36 |
$template = $env->loadTemplate($name);
|
37 |
|
38 |
$context = array(
|
39 |
+
'string' => 'foo',
|
40 |
+
'null' => null,
|
41 |
+
'empty_array' => array(),
|
42 |
+
'array' => array('foo' => 'foo'),
|
43 |
+
'array_access' => new Twig_TemplateArrayAccessObject(),
|
44 |
'magic_exception' => new Twig_TemplateMagicPropertyObjectWithException(),
|
45 |
+
'object' => new stdClass(),
|
46 |
);
|
47 |
|
48 |
try {
|
69 |
array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
|
70 |
array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1', false),
|
71 |
array('{{ array_access.a }}', 'Method "a" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
72 |
+
array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Method "missing_method" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
73 |
array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.', false),
|
74 |
array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1', false),
|
75 |
);
|
147 |
|
148 |
$this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty'));
|
149 |
$this->assertSame('', $template->getAttribute($template1, 'empty'));
|
150 |
+
|
151 |
+
$this->assertFalse($template->getAttribute($template1, 'env', array(), Twig_Template::ANY_CALL, true));
|
152 |
+
$this->assertFalse($template->getAttribute($template1, 'environment', array(), Twig_Template::ANY_CALL, true));
|
153 |
+
$this->assertFalse($template->getAttribute($template1, 'getEnvironment', array(), Twig_Template::METHOD_CALL, true));
|
154 |
+
$this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true));
|
155 |
}
|
156 |
|
157 |
public function getGetAttributeWithTemplateAsObject()
|
275 |
{
|
276 |
$array = array(
|
277 |
'defined' => 'defined',
|
278 |
+
'zero' => 0,
|
279 |
+
'null' => null,
|
280 |
+
'1' => 1,
|
281 |
+
'bar' => true,
|
282 |
+
'09' => '09',
|
283 |
+
'+4' => '+4',
|
284 |
);
|
285 |
|
286 |
+
$objectArray = new Twig_TemplateArrayAccessObject();
|
287 |
+
$stdObject = (object) $array;
|
288 |
$magicPropertyObject = new Twig_TemplateMagicPropertyObject();
|
289 |
+
$propertyObject = new Twig_TemplatePropertyObject();
|
290 |
+
$propertyObject1 = new Twig_TemplatePropertyObjectAndIterator();
|
291 |
+
$propertyObject2 = new Twig_TemplatePropertyObjectAndArrayAccess();
|
292 |
+
$propertyObject3 = new Twig_TemplatePropertyObjectDefinedWithUndefinedValue();
|
293 |
+
$methodObject = new Twig_TemplateMethodObject();
|
294 |
+
$magicMethodObject = new Twig_TemplateMagicMethodObject();
|
295 |
+
|
296 |
+
$anyType = Twig_Template::ANY_CALL;
|
297 |
$methodType = Twig_Template::METHOD_CALL;
|
298 |
+
$arrayType = Twig_Template::ARRAY_CALL;
|
299 |
|
300 |
$basicTests = array(
|
301 |
// array(defined, value, property to fetch)
|
388 |
// tests when input is not an array or object
|
389 |
$tests = array_merge($tests, array(
|
390 |
array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42")'),
|
391 |
+
array(false, null, 'string', 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a string variable ("string")'),
|
392 |
array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" does not exist as the array is empty'),
|
393 |
));
|
394 |
|
470 |
|
471 |
public $attributes = array(
|
472 |
'defined' => 'defined',
|
473 |
+
'zero' => 0,
|
474 |
+
'null' => null,
|
475 |
+
'1' => 1,
|
476 |
+
'bar' => true,
|
477 |
+
'09' => '09',
|
478 |
+
'+4' => '+4',
|
479 |
);
|
480 |
|
481 |
public function offsetExists($name)
|
502 |
public $defined = 'defined';
|
503 |
|
504 |
public $attributes = array(
|
505 |
+
'zero' => 0,
|
506 |
+
'null' => null,
|
507 |
+
'1' => 1,
|
508 |
+
'bar' => true,
|
509 |
+
'09' => '09',
|
510 |
+
'+4' => '+4',
|
511 |
);
|
512 |
|
513 |
protected $protected = 'protected';
|
534 |
class Twig_TemplatePropertyObject
|
535 |
{
|
536 |
public $defined = 'defined';
|
537 |
+
public $zero = 0;
|
538 |
+
public $null = null;
|
539 |
+
public $bar = true;
|
540 |
|
541 |
protected $protected = 'protected';
|
542 |
}
|
vendor/twig/twig/test/Twig/Tests/escapingTest.php
CHANGED
@@ -9,137 +9,137 @@
|
|
9 |
class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
10 |
{
|
11 |
/**
|
12 |
-
* All character encodings supported by htmlspecialchars()
|
13 |
*/
|
14 |
protected $htmlSpecialChars = array(
|
15 |
-
'\''
|
16 |
-
'"'
|
17 |
-
'<'
|
18 |
-
'>'
|
19 |
-
'&'
|
20 |
);
|
21 |
|
22 |
protected $htmlAttrSpecialChars = array(
|
23 |
-
'\''
|
24 |
/* Characters beyond ASCII value 255 to unicode escape */
|
25 |
-
'Ā'
|
26 |
/* Immune chars excluded */
|
27 |
-
','
|
28 |
-
'.'
|
29 |
-
'-'
|
30 |
-
'_'
|
31 |
/* Basic alnums excluded */
|
32 |
-
'a'
|
33 |
-
'A'
|
34 |
-
'z'
|
35 |
-
'Z'
|
36 |
-
'0'
|
37 |
-
'9'
|
38 |
/* Basic control characters and null */
|
39 |
-
"\r"
|
40 |
-
"\n"
|
41 |
-
"\t"
|
42 |
-
"\0"
|
43 |
/* Encode chars as named entities where possible */
|
44 |
-
'<'
|
45 |
-
'>'
|
46 |
-
'&'
|
47 |
-
'"'
|
48 |
/* Encode spaces for quoteless attribute protection */
|
49 |
-
' '
|
50 |
);
|
51 |
|
52 |
protected $jsSpecialChars = array(
|
53 |
/* HTML special chars - escape without exception to hex */
|
54 |
-
'<'
|
55 |
-
'>'
|
56 |
-
'\''
|
57 |
-
'"'
|
58 |
-
'&'
|
59 |
/* Characters beyond ASCII value 255 to unicode escape */
|
60 |
-
'Ā'
|
61 |
/* Immune chars excluded */
|
62 |
-
','
|
63 |
-
'.'
|
64 |
-
'_'
|
65 |
/* Basic alnums excluded */
|
66 |
-
'a'
|
67 |
-
'A'
|
68 |
-
'z'
|
69 |
-
'Z'
|
70 |
-
'0'
|
71 |
-
'9'
|
72 |
/* Basic control characters and null */
|
73 |
-
"\r"
|
74 |
-
"\n"
|
75 |
-
"\t"
|
76 |
-
"\0"
|
77 |
/* Encode spaces for quoteless attribute protection */
|
78 |
-
' '
|
79 |
);
|
80 |
|
81 |
protected $urlSpecialChars = array(
|
82 |
/* HTML special chars - escape without exception to percent encoding */
|
83 |
-
'<'
|
84 |
-
'>'
|
85 |
-
'\''
|
86 |
-
'"'
|
87 |
-
'&'
|
88 |
/* Characters beyond ASCII value 255 to hex sequence */
|
89 |
-
'Ā'
|
90 |
/* Punctuation and unreserved check */
|
91 |
-
','
|
92 |
-
'.'
|
93 |
-
'_'
|
94 |
-
'-'
|
95 |
-
':'
|
96 |
-
';'
|
97 |
-
'!'
|
98 |
/* Basic alnums excluded */
|
99 |
-
'a'
|
100 |
-
'A'
|
101 |
-
'z'
|
102 |
-
'Z'
|
103 |
-
'0'
|
104 |
-
'9'
|
105 |
/* Basic control characters and null */
|
106 |
-
"\r"
|
107 |
-
"\n"
|
108 |
-
"\t"
|
109 |
-
"\0"
|
110 |
/* PHP quirks from the past */
|
111 |
-
' '
|
112 |
-
'~'
|
113 |
-
'+'
|
114 |
);
|
115 |
|
116 |
protected $cssSpecialChars = array(
|
117 |
/* HTML special chars - escape without exception to hex */
|
118 |
-
'<'
|
119 |
-
'>'
|
120 |
-
'\''
|
121 |
-
'"'
|
122 |
-
'&'
|
123 |
/* Characters beyond ASCII value 255 to unicode escape */
|
124 |
-
'Ā'
|
125 |
/* Immune chars excluded */
|
126 |
-
','
|
127 |
-
'.'
|
128 |
-
'_'
|
129 |
/* Basic alnums excluded */
|
130 |
-
'a'
|
131 |
-
'A'
|
132 |
-
'z'
|
133 |
-
'Z'
|
134 |
-
'0'
|
135 |
-
'9'
|
136 |
/* Basic control characters and null */
|
137 |
-
"\r"
|
138 |
-
"\n"
|
139 |
-
"\t"
|
140 |
-
"\0"
|
141 |
/* Encode spaces for quoteless attribute protection */
|
142 |
-
' '
|
143 |
);
|
144 |
|
145 |
protected $env;
|
@@ -205,16 +205,16 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
205 |
}
|
206 |
|
207 |
/**
|
208 |
-
* Range tests to confirm escaped range of characters is within OWASP recommendation
|
209 |
*/
|
210 |
|
211 |
/**
|
212 |
* Only testing the first few 2 ranges on this prot. function as that's all these
|
213 |
-
* other range tests require
|
214 |
*/
|
215 |
public function testUnicodeCodepointConversionToUtf8()
|
216 |
{
|
217 |
-
$expected =
|
218 |
$codepoints = array(0x20, 0x7e, 0x799);
|
219 |
$result = '';
|
220 |
foreach ($codepoints as $value) {
|
@@ -226,7 +226,7 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
226 |
/**
|
227 |
* Convert a Unicode Codepoint to a literal UTF-8 character.
|
228 |
*
|
229 |
-
* @param int
|
230 |
*
|
231 |
* @return string UTF-8 literal string
|
232 |
*/
|
@@ -256,7 +256,7 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
256 |
public function testJavascriptEscapingEscapesOwaspRecommendedRanges()
|
257 |
{
|
258 |
$immune = array(',', '.', '_'); // Exceptions to escaping ranges
|
259 |
-
for ($chr = 0; $chr < 0xFF;
|
260 |
if ($chr >= 0x30 && $chr <= 0x39
|
261 |
|| $chr >= 0x41 && $chr <= 0x5A
|
262 |
|| $chr >= 0x61 && $chr <= 0x7A) {
|
@@ -279,7 +279,7 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
279 |
public function testHtmlAttributeEscapingEscapesOwaspRecommendedRanges()
|
280 |
{
|
281 |
$immune = array(',', '.', '-', '_'); // Exceptions to escaping ranges
|
282 |
-
for ($chr = 0; $chr < 0xFF;
|
283 |
if ($chr >= 0x30 && $chr <= 0x39
|
284 |
|| $chr >= 0x41 && $chr <= 0x5A
|
285 |
|| $chr >= 0x61 && $chr <= 0x7A) {
|
@@ -302,7 +302,7 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
302 |
public function testCssEscapingEscapesOwaspRecommendedRanges()
|
303 |
{
|
304 |
// CSS has no exceptions to escaping ranges
|
305 |
-
for ($chr = 0; $chr < 0xFF;
|
306 |
if ($chr >= 0x30 && $chr <= 0x39
|
307 |
|| $chr >= 0x41 && $chr <= 0x5A
|
308 |
|| $chr >= 0x61 && $chr <= 0x7A) {
|
9 |
class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
10 |
{
|
11 |
/**
|
12 |
+
* All character encodings supported by htmlspecialchars().
|
13 |
*/
|
14 |
protected $htmlSpecialChars = array(
|
15 |
+
'\'' => ''',
|
16 |
+
'"' => '"',
|
17 |
+
'<' => '<',
|
18 |
+
'>' => '>',
|
19 |
+
'&' => '&',
|
20 |
);
|
21 |
|
22 |
protected $htmlAttrSpecialChars = array(
|
23 |
+
'\'' => ''',
|
24 |
/* Characters beyond ASCII value 255 to unicode escape */
|
25 |
+
'Ā' => 'Ā',
|
26 |
/* Immune chars excluded */
|
27 |
+
',' => ',',
|
28 |
+
'.' => '.',
|
29 |
+
'-' => '-',
|
30 |
+
'_' => '_',
|
31 |
/* Basic alnums excluded */
|
32 |
+
'a' => 'a',
|
33 |
+
'A' => 'A',
|
34 |
+
'z' => 'z',
|
35 |
+
'Z' => 'Z',
|
36 |
+
'0' => '0',
|
37 |
+
'9' => '9',
|
38 |
/* Basic control characters and null */
|
39 |
+
"\r" => '
',
|
40 |
+
"\n" => '
',
|
41 |
+
"\t" => '	',
|
42 |
+
"\0" => '�', // should use Unicode replacement char
|
43 |
/* Encode chars as named entities where possible */
|
44 |
+
'<' => '<',
|
45 |
+
'>' => '>',
|
46 |
+
'&' => '&',
|
47 |
+
'"' => '"',
|
48 |
/* Encode spaces for quoteless attribute protection */
|
49 |
+
' ' => ' ',
|
50 |
);
|
51 |
|
52 |
protected $jsSpecialChars = array(
|
53 |
/* HTML special chars - escape without exception to hex */
|
54 |
+
'<' => '\\x3C',
|
55 |
+
'>' => '\\x3E',
|
56 |
+
'\'' => '\\x27',
|
57 |
+
'"' => '\\x22',
|
58 |
+
'&' => '\\x26',
|
59 |
/* Characters beyond ASCII value 255 to unicode escape */
|
60 |
+
'Ā' => '\\u0100',
|
61 |
/* Immune chars excluded */
|
62 |
+
',' => ',',
|
63 |
+
'.' => '.',
|
64 |
+
'_' => '_',
|
65 |
/* Basic alnums excluded */
|
66 |
+
'a' => 'a',
|
67 |
+
'A' => 'A',
|
68 |
+
'z' => 'z',
|
69 |
+
'Z' => 'Z',
|
70 |
+
'0' => '0',
|
71 |
+
'9' => '9',
|
72 |
/* Basic control characters and null */
|
73 |
+
"\r" => '\\x0D',
|
74 |
+
"\n" => '\\x0A',
|
75 |
+
"\t" => '\\x09',
|
76 |
+
"\0" => '\\x00',
|
77 |
/* Encode spaces for quoteless attribute protection */
|
78 |
+
' ' => '\\x20',
|
79 |
);
|
80 |
|
81 |
protected $urlSpecialChars = array(
|
82 |
/* HTML special chars - escape without exception to percent encoding */
|
83 |
+
'<' => '%3C',
|
84 |
+
'>' => '%3E',
|
85 |
+
'\'' => '%27',
|
86 |
+
'"' => '%22',
|
87 |
+
'&' => '%26',
|
88 |
/* Characters beyond ASCII value 255 to hex sequence */
|
89 |
+
'Ā' => '%C4%80',
|
90 |
/* Punctuation and unreserved check */
|
91 |
+
',' => '%2C',
|
92 |
+
'.' => '.',
|
93 |
+
'_' => '_',
|
94 |
+
'-' => '-',
|
95 |
+
':' => '%3A',
|
96 |
+
';' => '%3B',
|
97 |
+
'!' => '%21',
|
98 |
/* Basic alnums excluded */
|
99 |
+
'a' => 'a',
|
100 |
+
'A' => 'A',
|
101 |
+
'z' => 'z',
|
102 |
+
'Z' => 'Z',
|
103 |
+
'0' => '0',
|
104 |
+
'9' => '9',
|
105 |
/* Basic control characters and null */
|
106 |
+
"\r" => '%0D',
|
107 |
+
"\n" => '%0A',
|
108 |
+
"\t" => '%09',
|
109 |
+
"\0" => '%00',
|
110 |
/* PHP quirks from the past */
|
111 |
+
' ' => '%20',
|
112 |
+
'~' => '~',
|
113 |
+
'+' => '%2B',
|
114 |
);
|
115 |
|
116 |
protected $cssSpecialChars = array(
|
117 |
/* HTML special chars - escape without exception to hex */
|
118 |
+
'<' => '\\3C ',
|
119 |
+
'>' => '\\3E ',
|
120 |
+
'\'' => '\\27 ',
|
121 |
+
'"' => '\\22 ',
|
122 |
+
'&' => '\\26 ',
|
123 |
/* Characters beyond ASCII value 255 to unicode escape */
|
124 |
+
'Ā' => '\\100 ',
|
125 |
/* Immune chars excluded */
|
126 |
+
',' => '\\2C ',
|
127 |
+
'.' => '\\2E ',
|
128 |
+
'_' => '\\5F ',
|
129 |
/* Basic alnums excluded */
|
130 |
+
'a' => 'a',
|
131 |
+
'A' => 'A',
|
132 |
+
'z' => 'z',
|
133 |
+
'Z' => 'Z',
|
134 |
+
'0' => '0',
|
135 |
+
'9' => '9',
|
136 |
/* Basic control characters and null */
|
137 |
+
"\r" => '\\D ',
|
138 |
+
"\n" => '\\A ',
|
139 |
+
"\t" => '\\9 ',
|
140 |
+
"\0" => '\\0 ',
|
141 |
/* Encode spaces for quoteless attribute protection */
|
142 |
+
' ' => '\\20 ',
|
143 |
);
|
144 |
|
145 |
protected $env;
|
205 |
}
|
206 |
|
207 |
/**
|
208 |
+
* Range tests to confirm escaped range of characters is within OWASP recommendation.
|
209 |
*/
|
210 |
|
211 |
/**
|
212 |
* Only testing the first few 2 ranges on this prot. function as that's all these
|
213 |
+
* other range tests require.
|
214 |
*/
|
215 |
public function testUnicodeCodepointConversionToUtf8()
|
216 |
{
|
217 |
+
$expected = ' ~ޙ';
|
218 |
$codepoints = array(0x20, 0x7e, 0x799);
|
219 |
$result = '';
|
220 |
foreach ($codepoints as $value) {
|
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 |
*/
|
256 |
public function testJavascriptEscapingEscapesOwaspRecommendedRanges()
|
257 |
{
|
258 |
$immune = array(',', '.', '_'); // Exceptions to escaping ranges
|
259 |
+
for ($chr = 0; $chr < 0xFF; ++$chr) {
|
260 |
if ($chr >= 0x30 && $chr <= 0x39
|
261 |
|| $chr >= 0x41 && $chr <= 0x5A
|
262 |
|| $chr >= 0x61 && $chr <= 0x7A) {
|
279 |
public function testHtmlAttributeEscapingEscapesOwaspRecommendedRanges()
|
280 |
{
|
281 |
$immune = array(',', '.', '-', '_'); // Exceptions to escaping ranges
|
282 |
+
for ($chr = 0; $chr < 0xFF; ++$chr) {
|
283 |
if ($chr >= 0x30 && $chr <= 0x39
|
284 |
|| $chr >= 0x41 && $chr <= 0x5A
|
285 |
|| $chr >= 0x61 && $chr <= 0x7A) {
|
302 |
public function testCssEscapingEscapesOwaspRecommendedRanges()
|
303 |
{
|
304 |
// CSS has no exceptions to escaping ranges
|
305 |
+
for ($chr = 0; $chr < 0xFF; ++$chr) {
|
306 |
if ($chr >= 0x30 && $chr <= 0x39
|
307 |
|| $chr >= 0x41 && $chr <= 0x5A
|
308 |
|| $chr >= 0x61 && $chr <= 0x7A) {
|