Version Description
- Native support for Co-Authors Plus! just use
{{ post.authors }}
939331e282fd54bf3e210645964504304f2b071b - New filter to enable PW propmpt for PW protected posts (
timber/post/content/show_password_form_for_protected
) 0f9b20ec90b34059634c25bc27671875c18f8fcb - New filter for custom loaders (
timber/loader/custom
) (thanks @tnottu!) 9097984a7c3df23068056d7835465e0690338567 - Fixed some updating bugs with 4.6 (thanks @daronspence) 16b8bd71571be71b298e6306abe2cd4b95d8c9e8
- You can now count Query results (thanks Evan Mattson) 141624a0ac18d9dcce62a2a681134009a2b79814
Download this release
Release Info
Developer | jarednova |
Plugin | Timber |
Version | 1.1.4 |
Comparing to | |
See all releases |
Code changes from version 1.1.1 to 1.1.4
- README.md +8 -7
- lib/Admin.php +5 -5
- lib/Core.php +8 -0
- lib/Helper.php +24 -73
- lib/Image/Operation/Resize.php +14 -14
- lib/Integrations.php +17 -9
- lib/Integrations/CoAuthorsPlus.php +30 -0
- lib/Loader.php +16 -111
- lib/LocationManager.php +145 -0
- lib/Pagination.php +172 -0
- lib/Post.php +41 -9
- lib/PostGetter.php +43 -2
- lib/PostType.php +3 -0
- lib/PostsCollection.php +3 -16
- lib/QueryIterator.php +34 -8
- lib/Term.php +1 -1
- lib/TermGetter.php +2 -2
- lib/Timber.php +17 -108
- lib/Twig.php +14 -4
- lib/URLHelper.php +12 -4
- lib/User.php +4 -4
- readme.txt +21 -2
- timber.php +1 -1
- vendor/asm89/twig-cache-extension/README.md +27 -0
- vendor/asm89/twig-cache-extension/composer.json +4 -1
- vendor/asm89/twig-cache-extension/lib/Asm89/Twig/CacheExtension/CacheProvider/PsrCacheAdapter.php +68 -0
- vendor/autoload.php +1 -1
- vendor/composer/autoload_real.php +3 -3
- vendor/composer/installed.json +10 -7
README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<div style="text-align:center">
|
2 |
-
<a href="http://timber.github.io/timber"><img src="http://i.imgur.com/
|
3 |
<div>
|
4 |
By Jared Novack (<a href="https://twitter.com/jarednova">@JaredNova</a>) and <a href="http://upstatement.com">Upstatement</a> (<a href="https://twitter.com/upstatement">@Upstatement</a>)</div>
|
5 |
</div>
|
6 |
|
7 |
[![Build Status](https://img.shields.io/travis/timber/timber/master.svg?style=flat-square)](https://travis-ci.org/timber/timber)
|
8 |
-
[![Coverage Status](https://img.shields.io/codecov/c/github/timber/timber.svg?style=flat-square)](
|
9 |
[![Dependency Status](https://www.versioneye.com/user/projects/574e40e6e298f30048059b9f/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/574e40e6e298f30048059b9f)
|
10 |
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/timber/timber.svg?style=flat-square)](https://scrutinizer-ci.com/g/timber/timber/?branch=master)
|
11 |
[![Latest Stable Version](https://img.shields.io/packagist/v/timber/timber.svg?style=flat-square)](https://packagist.org/packages/timber/timber)
|
@@ -111,11 +111,12 @@ Documentation for Timber classes and functions is [auto generated](https://githu
|
|
111 |
To publish docs:
|
112 |
1. `composer install` if not already run
|
113 |
2. Clone the [timber/slate](https://github.com/timber/slate) repo at the same directory level as Timber
|
114 |
-
3. From the root of the slate directory
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
|
|
119 |
|
120 |
|
121 |
|
1 |
<div style="text-align:center">
|
2 |
+
<a href="http://timber.github.io/timber"><img src="http://i.imgur.com/PbEwvZ9.png" style="display:block; margin:auto; width:100%; max-width:100%"/></a>
|
3 |
<div>
|
4 |
By Jared Novack (<a href="https://twitter.com/jarednova">@JaredNova</a>) and <a href="http://upstatement.com">Upstatement</a> (<a href="https://twitter.com/upstatement">@Upstatement</a>)</div>
|
5 |
</div>
|
6 |
|
7 |
[![Build Status](https://img.shields.io/travis/timber/timber/master.svg?style=flat-square)](https://travis-ci.org/timber/timber)
|
8 |
+
[![Coverage Status](https://img.shields.io/codecov/c/github/timber/timber.svg?style=flat-square)](https://codecov.io/gh/timber/timber)
|
9 |
[![Dependency Status](https://www.versioneye.com/user/projects/574e40e6e298f30048059b9f/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/574e40e6e298f30048059b9f)
|
10 |
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/timber/timber.svg?style=flat-square)](https://scrutinizer-ci.com/g/timber/timber/?branch=master)
|
11 |
[![Latest Stable Version](https://img.shields.io/packagist/v/timber/timber.svg?style=flat-square)](https://packagist.org/packages/timber/timber)
|
111 |
To publish docs:
|
112 |
1. `composer install` if not already run
|
113 |
2. Clone the [timber/slate](https://github.com/timber/slate) repo at the same directory level as Timber
|
114 |
+
3. From the root of the slate directory, run these commands:
|
115 |
+
```bash
|
116 |
+
gem install bundler
|
117 |
+
bundle install
|
118 |
+
sh publish-docs.sh
|
119 |
+
```
|
120 |
|
121 |
|
122 |
|
lib/Admin.php
CHANGED
@@ -48,18 +48,18 @@ class Admin {
|
|
48 |
|
49 |
if ( version_compare("1.0.0", $plugin_data['new_version']) <= 0 ) {
|
50 |
//a version of 1.0.0 or greater is availalbe
|
51 |
-
$m .= '<
|
52 |
|
53 |
-
<
|
54 |
|
55 |
-
$m .= '<
|
56 |
|
57 |
-
$m .= "<
|
58 |
|
59 |
}
|
60 |
|
61 |
if ( version_compare("1.0.0", $plugin_data['Version']) <= 0 ) {
|
62 |
-
$m .= "<
|
63 |
}
|
64 |
|
65 |
// show message
|
48 |
|
49 |
if ( version_compare("1.0.0", $plugin_data['new_version']) <= 0 ) {
|
50 |
//a version of 1.0.0 or greater is availalbe
|
51 |
+
$m .= '<br><b>Warning:</b> Timber 1.0 removed a number of features and methods. Before upgrading please test your theme on a local or staging site to ensure that your theme will work with the newest version.<br>
|
52 |
|
53 |
+
<br><strong>Is your theme in active development?</strong> That is, is someone actively in PHP files writing new code? If you answered "no", then <i>do not upgrade</i>. You will not benefit from Timber 1.0<br>';
|
54 |
|
55 |
+
$m .= '<br>Read the <strong><a href="https://github.com/timber/timber/wiki/1.0-Upgrade-Guide">Upgrade Guide</a></strong> for more information<br>';
|
56 |
|
57 |
+
$m .= "<br>You can also <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>upgrade to version 0.22.6</a></b> if you want to upgrade, but are unsure if you're ready for 1.0<br>";
|
58 |
|
59 |
}
|
60 |
|
61 |
if ( version_compare("1.0.0", $plugin_data['Version']) <= 0 ) {
|
62 |
+
$m .= "<br>Are you seeing errors since upgrading to 1.0? Download <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>Version 0.22.6</a></b> to bring things back to stability.";
|
63 |
}
|
64 |
|
65 |
// show message
|
lib/Core.php
CHANGED
@@ -117,4 +117,12 @@ abstract class Core {
|
|
117 |
$ret['can_edit'] = $this->can_edit();
|
118 |
return $ret;
|
119 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
}
|
117 |
$ret['can_edit'] = $this->can_edit();
|
118 |
return $ret;
|
119 |
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* @param string $field_name
|
123 |
+
* @return mixed
|
124 |
+
*/
|
125 |
+
public function get_field( $field_name ) {
|
126 |
+
return $this->get_meta_field($field_name);
|
127 |
+
}
|
128 |
}
|
lib/Helper.php
CHANGED
@@ -444,6 +444,25 @@ class Helper {
|
|
444 |
return ($i % 2) != 0;
|
445 |
}
|
446 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
/* Links, Forms, Etc. Utilities
|
448 |
======================== */
|
449 |
|
@@ -461,81 +480,13 @@ class Helper {
|
|
461 |
|
462 |
/**
|
463 |
*
|
464 |
-
*
|
465 |
-
* @param
|
466 |
* @return array
|
467 |
*/
|
468 |
-
public static function paginate_links( $args =
|
469 |
-
|
470 |
-
|
471 |
-
'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
|
472 |
-
'total' => 1,
|
473 |
-
'current' => 0,
|
474 |
-
'show_all' => false,
|
475 |
-
'prev_next' => false,
|
476 |
-
'prev_text' => __('« Previous'),
|
477 |
-
'next_text' => __('Next »'),
|
478 |
-
'end_size' => 1,
|
479 |
-
'mid_size' => 2,
|
480 |
-
'type' => 'array',
|
481 |
-
'add_args' => false, // array of query args to add
|
482 |
-
'add_fragment' => ''
|
483 |
-
);
|
484 |
-
$args = wp_parse_args($args, $defaults);
|
485 |
-
// Who knows what else people pass in $args
|
486 |
-
$args['total'] = intval((int) $args['total']);
|
487 |
-
if ( $args['total'] < 2 ) {
|
488 |
-
return array();
|
489 |
-
}
|
490 |
-
$args['current'] = (int) $args['current'];
|
491 |
-
$args['end_size'] = 0 < (int) $args['end_size'] ? (int) $args['end_size'] : 1; // Out of bounds? Make it the default.
|
492 |
-
$args['mid_size'] = 0 <= (int) $args['mid_size'] ? (int) $args['mid_size'] : 2;
|
493 |
-
$args['add_args'] = is_array($args['add_args']) ? $args['add_args'] : false;
|
494 |
-
$page_links = array();
|
495 |
-
$dots = false;
|
496 |
-
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
497 |
-
$n_display = number_format_i18n($n);
|
498 |
-
if ( $n == $args['current'] ) {
|
499 |
-
$page_links[] = array(
|
500 |
-
'class' => 'page-number page-numbers current',
|
501 |
-
'title' => $n_display,
|
502 |
-
'text' => $n_display,
|
503 |
-
'name' => $n_display,
|
504 |
-
'current' => true
|
505 |
-
);
|
506 |
-
$dots = true;
|
507 |
-
} else {
|
508 |
-
if ( $args['show_all'] || ($n <= $args['end_size'] || ($args['current'] && $n >= $args['current'] - $args['mid_size'] && $n <= $args['current'] + $args['mid_size']) || $n > $args['total'] - $args['end_size']) ) {
|
509 |
-
$link = str_replace('%_%', 1 == $n ? '' : $args['format'], $args['base']);
|
510 |
-
$link = str_replace('%#%', $n, $link);
|
511 |
-
$link = trailingslashit($link).ltrim($args['add_fragment'], '/');
|
512 |
-
if ( $args['add_args'] ) {
|
513 |
-
$link = rtrim(add_query_arg($args['add_args'], $link), '/');
|
514 |
-
}
|
515 |
-
$link = str_replace(' ', '+', $link);
|
516 |
-
$link = untrailingslashit($link);
|
517 |
-
$link = esc_url(apply_filters('paginate_links', $link));
|
518 |
-
$link = user_trailingslashit($link);
|
519 |
-
|
520 |
-
$page_links[] = array(
|
521 |
-
'class' => 'page-number page-numbers',
|
522 |
-
'link' => $link,
|
523 |
-
'title' => $n_display,
|
524 |
-
'name' => $n_display,
|
525 |
-
'current' => $args['current'] == $n
|
526 |
-
);
|
527 |
-
$dots = true;
|
528 |
-
} elseif ( $dots && !$args['show_all'] ) {
|
529 |
-
$page_links[] = array(
|
530 |
-
'class' => 'dots',
|
531 |
-
'title' => __('…')
|
532 |
-
);
|
533 |
-
$dots = false;
|
534 |
-
}
|
535 |
-
}
|
536 |
-
}
|
537 |
-
|
538 |
-
return $page_links;
|
539 |
}
|
540 |
|
541 |
/**
|
444 |
return ($i % 2) != 0;
|
445 |
}
|
446 |
|
447 |
+
/**
|
448 |
+
* Plucks the values of a certain key from an array of objects
|
449 |
+
* @param array $array
|
450 |
+
* @param string $key
|
451 |
+
*/
|
452 |
+
public static function pluck( $array, $key ) {
|
453 |
+
$return = array();
|
454 |
+
foreach ( $array as $obj ) {
|
455 |
+
if ( is_object($obj) && method_exists($obj, $key) ) {
|
456 |
+
$return[] = $obj->$key();
|
457 |
+
} elseif ( is_object($obj) && property_exists($obj, $key) ) {
|
458 |
+
$return[] = $obj->$key;
|
459 |
+
} elseif ( isset($obj[$key]) ) {
|
460 |
+
$return[] = $obj[$key];
|
461 |
+
}
|
462 |
+
}
|
463 |
+
return $return;
|
464 |
+
}
|
465 |
+
|
466 |
/* Links, Forms, Etc. Utilities
|
467 |
======================== */
|
468 |
|
480 |
|
481 |
/**
|
482 |
*
|
483 |
+
* @deprecated since 1.1.2
|
484 |
+
* @param array $args
|
485 |
* @return array
|
486 |
*/
|
487 |
+
public static function paginate_links( $args = array() ) {
|
488 |
+
Helper::warn('Helper/paginate_links has been moved to Pagination/paginate_links');
|
489 |
+
return Pagination::paginate_links($args);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
}
|
491 |
|
492 |
/**
|
lib/Image/Operation/Resize.php
CHANGED
@@ -170,20 +170,20 @@ class Resize extends ImageOperation {
|
|
170 |
* @return boolean|null true if everything went fine, false otherwise
|
171 |
*/
|
172 |
public function run( $load_filename, $save_filename ) {
|
173 |
-
$image = wp_get_image_editor(
|
174 |
-
if ( !is_wp_error(
|
175 |
//should be resized by gif resizer
|
176 |
-
if ( ImageHelper::is_animated_gif(
|
177 |
//attempt to resize
|
178 |
//return if successful
|
179 |
//proceed if not
|
180 |
-
$gif = self::run_animated_gif(
|
181 |
if ( $gif ) {
|
182 |
return true;
|
183 |
}
|
184 |
}
|
185 |
|
186 |
-
$crop = self::get_target_sizes(
|
187 |
$image->crop( $crop['x'],
|
188 |
$crop['y'],
|
189 |
$crop['src_w'],
|
@@ -191,24 +191,24 @@ class Resize extends ImageOperation {
|
|
191 |
$crop['target_w'],
|
192 |
$crop['target_h']
|
193 |
);
|
194 |
-
$result = $image->save(
|
195 |
-
if ( is_wp_error(
|
196 |
// @codeCoverageIgnoreStart
|
197 |
-
Helper::error_log(
|
198 |
-
Helper::error_log(
|
199 |
return false;
|
200 |
// @codeCoverageIgnoreEnd
|
201 |
} else {
|
202 |
return true;
|
203 |
}
|
204 |
-
} else if ( isset(
|
205 |
// @codeCoverageIgnoreStart
|
206 |
-
Helper::error_log(
|
207 |
} else {
|
208 |
-
if(!extension_loaded('gd')) {
|
209 |
-
Helper::error_log(
|
210 |
} else {
|
211 |
-
Helper::error_log(
|
212 |
}
|
213 |
// @codeCoverageIgnoreEnd
|
214 |
}
|
170 |
* @return boolean|null true if everything went fine, false otherwise
|
171 |
*/
|
172 |
public function run( $load_filename, $save_filename ) {
|
173 |
+
$image = wp_get_image_editor($load_filename);
|
174 |
+
if ( !is_wp_error($image) ) {
|
175 |
//should be resized by gif resizer
|
176 |
+
if ( ImageHelper::is_animated_gif($load_filename) ) {
|
177 |
//attempt to resize
|
178 |
//return if successful
|
179 |
//proceed if not
|
180 |
+
$gif = self::run_animated_gif($load_filename, $save_filename, $image);
|
181 |
if ( $gif ) {
|
182 |
return true;
|
183 |
}
|
184 |
}
|
185 |
|
186 |
+
$crop = self::get_target_sizes($image);
|
187 |
$image->crop( $crop['x'],
|
188 |
$crop['y'],
|
189 |
$crop['src_w'],
|
191 |
$crop['target_w'],
|
192 |
$crop['target_h']
|
193 |
);
|
194 |
+
$result = $image->save($save_filename);
|
195 |
+
if ( is_wp_error($result) ) {
|
196 |
// @codeCoverageIgnoreStart
|
197 |
+
Helper::error_log('Error resizing image');
|
198 |
+
Helper::error_log($result);
|
199 |
return false;
|
200 |
// @codeCoverageIgnoreEnd
|
201 |
} else {
|
202 |
return true;
|
203 |
}
|
204 |
+
} else if ( isset($image->error_data['error_loading_image']) ) {
|
205 |
// @codeCoverageIgnoreStart
|
206 |
+
Helper::error_log('Error loading '.$image->error_data['error_loading_image']);
|
207 |
} else {
|
208 |
+
if ( !extension_loaded('gd') ) {
|
209 |
+
Helper::error_log('Can not resize image, please installed php-gd');
|
210 |
} else {
|
211 |
+
Helper::error_log($image);
|
212 |
}
|
213 |
// @codeCoverageIgnoreEnd
|
214 |
}
|
lib/Integrations.php
CHANGED
@@ -2,25 +2,33 @@
|
|
2 |
|
3 |
namespace Timber;
|
4 |
|
5 |
-
use Timber\Integrations\ACF;
|
6 |
-
|
7 |
/**
|
8 |
* This is for integrating external plugins into timber
|
9 |
* @package timber
|
10 |
*/
|
11 |
class Integrations {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
-
public
|
14 |
-
add_action(
|
15 |
|
16 |
-
if ( class_exists(
|
17 |
-
\WP_CLI::add_command(
|
18 |
}
|
19 |
}
|
20 |
|
21 |
-
public
|
22 |
-
if ( class_exists(
|
23 |
-
new ACF();
|
|
|
|
|
|
|
24 |
}
|
25 |
}
|
26 |
}
|
2 |
|
3 |
namespace Timber;
|
4 |
|
|
|
|
|
5 |
/**
|
6 |
* This is for integrating external plugins into timber
|
7 |
* @package timber
|
8 |
*/
|
9 |
class Integrations {
|
10 |
+
|
11 |
+
var $acf;
|
12 |
+
var $coauthors_plus;
|
13 |
+
|
14 |
+
public function __construct() {
|
15 |
+
$this->init();
|
16 |
+
}
|
17 |
|
18 |
+
public function init() {
|
19 |
+
add_action('init', array($this, 'maybe_init_integrations'));
|
20 |
|
21 |
+
if ( class_exists('WP_CLI_Command') ) {
|
22 |
+
\WP_CLI::add_command('timber', 'Timber\Integrations\Timber_WP_CLI_Command');
|
23 |
}
|
24 |
}
|
25 |
|
26 |
+
public function maybe_init_integrations() {
|
27 |
+
if ( class_exists('ACF') ) {
|
28 |
+
$this->acf = new Integrations\ACF();
|
29 |
+
}
|
30 |
+
if ( class_exists('CoAuthors_Plus') ) {
|
31 |
+
$this->coauthors_plus = new Integrations\CoAuthorsPlus();
|
32 |
}
|
33 |
}
|
34 |
}
|
lib/Integrations/CoAuthorsPlus.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Timber\Integrations;
|
4 |
+
|
5 |
+
class CoAuthorsPlus {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @codeCoverageIgnore
|
9 |
+
*/
|
10 |
+
public function __construct() {
|
11 |
+
add_filter('timber/post/authors', array($this, 'authors'), 10, 2);
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Filters {{ post.authors }} to return authors stored from Co-Authors Plus
|
16 |
+
* @since 1.1.4
|
17 |
+
* @param array $author
|
18 |
+
* @param Post $post
|
19 |
+
* @return array of User objects
|
20 |
+
*/
|
21 |
+
public function authors( $author, $post ) {
|
22 |
+
$authors = array();
|
23 |
+
$cauthors = get_coauthors($post->ID);
|
24 |
+
foreach ( $cauthors as $author ) {
|
25 |
+
$authors[] = new \Timber\User($author);
|
26 |
+
}
|
27 |
+
return $authors;
|
28 |
+
}
|
29 |
+
|
30 |
+
}
|
lib/Loader.php
CHANGED
@@ -29,16 +29,16 @@ class Loader {
|
|
29 |
* @param bool|string $caller the calling directory or false
|
30 |
*/
|
31 |
public function __construct( $caller = false ) {
|
32 |
-
$this->locations =
|
33 |
$this->cache_mode = apply_filters('timber_cache_mode', $this->cache_mode);
|
34 |
$this->cache_mode = apply_filters('timber/cache/mode', $this->cache_mode);
|
35 |
}
|
36 |
|
37 |
/**
|
38 |
-
* @param string
|
39 |
-
* @param array
|
40 |
-
* @param array|
|
41 |
-
* @param string
|
42 |
* @return bool|string
|
43 |
*/
|
44 |
public function render( $file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT ) {
|
@@ -68,7 +68,7 @@ class Loader {
|
|
68 |
do_action('timber_loader_render_file', $result);
|
69 |
}
|
70 |
$data = apply_filters('timber_loader_render_data', $data);
|
71 |
-
$data = apply_filters(
|
72 |
$output = $twig->render($file, $data);
|
73 |
}
|
74 |
|
@@ -76,7 +76,7 @@ class Loader {
|
|
76 |
$this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode);
|
77 |
}
|
78 |
$output = apply_filters('timber_output', $output);
|
79 |
-
return apply_filters(
|
80 |
}
|
81 |
|
82 |
/**
|
@@ -110,115 +110,20 @@ class Loader {
|
|
110 |
return false;
|
111 |
}
|
112 |
|
113 |
-
/**
|
114 |
-
* @return array
|
115 |
-
*/
|
116 |
-
protected function get_locations_theme() {
|
117 |
-
$theme_locs = array();
|
118 |
-
$theme_dirs = $this->get_locations_theme_dir();
|
119 |
-
$roots = array(get_stylesheet_directory(), get_template_directory());
|
120 |
-
$roots = array_map('realpath', $roots);
|
121 |
-
$roots = array_unique($roots);
|
122 |
-
foreach ( $roots as $root ) {
|
123 |
-
if ( !is_dir($root) ) {
|
124 |
-
continue;
|
125 |
-
}
|
126 |
-
$theme_locs[] = $root;
|
127 |
-
$root = trailingslashit($root);
|
128 |
-
foreach ( $theme_dirs as $dirname ) {
|
129 |
-
$tloc = realpath($root.$dirname);
|
130 |
-
if ( is_dir($tloc) ) {
|
131 |
-
$theme_locs[] = $tloc;
|
132 |
-
}
|
133 |
-
}
|
134 |
-
}
|
135 |
-
|
136 |
-
return $theme_locs;
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* returns an array of the directory inside themes that holds twig files
|
141 |
-
* @return string[] the names of directores, ie: array('templats', 'views');
|
142 |
-
*/
|
143 |
-
protected function get_locations_theme_dir() {
|
144 |
-
if ( is_string(Timber::$dirname) ) {
|
145 |
-
return array(Timber::$dirname);
|
146 |
-
}
|
147 |
-
return Timber::$dirname;
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
*
|
152 |
-
* @return array
|
153 |
-
*/
|
154 |
-
protected function get_locations_user() {
|
155 |
-
$locs = array();
|
156 |
-
if ( isset(Timber::$locations) ) {
|
157 |
-
if ( is_string(Timber::$locations) ) {
|
158 |
-
Timber::$locations = array(Timber::$locations);
|
159 |
-
}
|
160 |
-
foreach ( Timber::$locations as $tloc ) {
|
161 |
-
$tloc = realpath($tloc);
|
162 |
-
if ( is_dir($tloc) ) {
|
163 |
-
$locs[] = $tloc;
|
164 |
-
}
|
165 |
-
}
|
166 |
-
}
|
167 |
-
return $locs;
|
168 |
-
}
|
169 |
|
170 |
/**
|
171 |
-
* @
|
172 |
-
* @return array
|
173 |
-
*/
|
174 |
-
protected function get_locations_caller( $caller = false ) {
|
175 |
-
$locs = array();
|
176 |
-
if ( $caller && is_string($caller) ) {
|
177 |
-
$caller = realpath($caller);
|
178 |
-
if ( is_dir($caller) ) {
|
179 |
-
$locs[] = $caller;
|
180 |
-
}
|
181 |
-
$caller = trailingslashit($caller);
|
182 |
-
foreach ( $this->get_locations_theme_dir() as $dirname ) {
|
183 |
-
$caller_sub = realpath($caller.$dirname);
|
184 |
-
if ( is_dir($caller_sub) ) {
|
185 |
-
$locs[] = $caller_sub;
|
186 |
-
}
|
187 |
-
}
|
188 |
-
}
|
189 |
-
return $locs;
|
190 |
-
}
|
191 |
-
|
192 |
-
/**
|
193 |
-
* @param bool|string $caller the calling directory (or false)
|
194 |
-
* @return array
|
195 |
-
*/
|
196 |
-
public function get_locations( $caller = false ) {
|
197 |
-
//prioirty: user locations, caller (but not theme), child theme, parent theme, caller
|
198 |
-
$locs = array();
|
199 |
-
$locs = array_merge($locs, $this->get_locations_user());
|
200 |
-
$locs = array_merge($locs, $this->get_locations_caller($caller));
|
201 |
-
//remove themes from caller
|
202 |
-
$locs = array_diff($locs, $this->get_locations_theme());
|
203 |
-
$locs = array_merge($locs, $this->get_locations_theme());
|
204 |
-
$locs = array_merge($locs, $this->get_locations_caller($caller));
|
205 |
-
$locs = array_unique($locs);
|
206 |
-
//now make sure theres a trailing slash on everything
|
207 |
-
$locs = array_map('trailingslashit', $locs);
|
208 |
-
$locs = apply_filters('timber_locations', $locs);
|
209 |
-
$locs = apply_filters('timber/locations', $locs);
|
210 |
-
return $locs;
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* @return \Twig_Loader_Filesystem
|
215 |
*/
|
216 |
public function get_loader() {
|
217 |
-
$
|
218 |
-
$
|
219 |
-
|
|
|
|
|
|
|
220 |
}
|
221 |
|
|
|
222 |
/**
|
223 |
* @return \Twig_Environment
|
224 |
*/
|
@@ -356,7 +261,7 @@ class Loader {
|
|
356 |
* @param string $key
|
357 |
* @param string|boolean $value
|
358 |
* @param string $group
|
359 |
-
* @param
|
360 |
* @param string $cache_mode
|
361 |
* @return string|boolean
|
362 |
*/
|
29 |
* @param bool|string $caller the calling directory or false
|
30 |
*/
|
31 |
public function __construct( $caller = false ) {
|
32 |
+
$this->locations = LocationManager::get_locations($caller);
|
33 |
$this->cache_mode = apply_filters('timber_cache_mode', $this->cache_mode);
|
34 |
$this->cache_mode = apply_filters('timber/cache/mode', $this->cache_mode);
|
35 |
}
|
36 |
|
37 |
/**
|
38 |
+
* @param string $file
|
39 |
+
* @param array $data
|
40 |
+
* @param array|boolean $expires (array for options, false for none, integer for # of seconds)
|
41 |
+
* @param string $cache_mode
|
42 |
* @return bool|string
|
43 |
*/
|
44 |
public function render( $file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT ) {
|
68 |
do_action('timber_loader_render_file', $result);
|
69 |
}
|
70 |
$data = apply_filters('timber_loader_render_data', $data);
|
71 |
+
$data = apply_filters('timber/loader/render_data', $data, $file);
|
72 |
$output = $twig->render($file, $data);
|
73 |
}
|
74 |
|
76 |
$this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode);
|
77 |
}
|
78 |
$output = apply_filters('timber_output', $output);
|
79 |
+
return apply_filters('timber/output', $output, $data, $file);
|
80 |
}
|
81 |
|
82 |
/**
|
110 |
return false;
|
111 |
}
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
/**
|
115 |
+
* @return \Twig_Loader_Chain
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
*/
|
117 |
public function get_loader() {
|
118 |
+
$filesystem_paths = array_merge($this->locations, array(ini_get('open_basedir') ? ABSPATH : '/'));
|
119 |
+
$filesystem_paths = apply_filters('timber/loader/paths', $filesystem_paths);
|
120 |
+
$filesystem_loader = array(new \Twig_Loader_Filesystem($filesystem_paths));
|
121 |
+
$custom_loaders = apply_filters('timber/loader/custom', array());
|
122 |
+
$all_loaders = array_merge($custom_loaders, $filesystem_loader);
|
123 |
+
return new \Twig_Loader_Chain($all_loaders);
|
124 |
}
|
125 |
|
126 |
+
|
127 |
/**
|
128 |
* @return \Twig_Environment
|
129 |
*/
|
261 |
* @param string $key
|
262 |
* @param string|boolean $value
|
263 |
* @param string $group
|
264 |
+
* @param integer $expires
|
265 |
* @param string $cache_mode
|
266 |
* @return string|boolean
|
267 |
*/
|
lib/LocationManager.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Timber;
|
4 |
+
|
5 |
+
class LocationManager {
|
6 |
+
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @param bool|string $caller the calling directory (or false)
|
10 |
+
* @return array
|
11 |
+
*/
|
12 |
+
public static function get_locations( $caller = false ) {
|
13 |
+
//prioirty: user locations, caller (but not theme), child theme, parent theme, caller
|
14 |
+
$locs = array();
|
15 |
+
$locs = array_merge($locs, self::get_locations_user());
|
16 |
+
$locs = array_merge($locs, self::get_locations_caller($caller));
|
17 |
+
//remove themes from caller
|
18 |
+
$locs = array_diff($locs, self::get_locations_theme());
|
19 |
+
$locs = array_merge($locs, self::get_locations_theme());
|
20 |
+
$locs = array_merge($locs, self::get_locations_caller($caller));
|
21 |
+
$locs = array_unique($locs);
|
22 |
+
//now make sure theres a trailing slash on everything
|
23 |
+
$locs = array_map('trailingslashit', $locs);
|
24 |
+
$locs = apply_filters('timber_locations', $locs);
|
25 |
+
$locs = apply_filters('timber/locations', $locs);
|
26 |
+
return $locs;
|
27 |
+
}
|
28 |
+
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return array
|
32 |
+
*/
|
33 |
+
protected static function get_locations_theme() {
|
34 |
+
$theme_locs = array();
|
35 |
+
$theme_dirs = LocationManager::get_locations_theme_dir();
|
36 |
+
$roots = array(get_stylesheet_directory(), get_template_directory());
|
37 |
+
$roots = array_map('realpath', $roots);
|
38 |
+
$roots = array_unique($roots);
|
39 |
+
foreach ( $roots as $root ) {
|
40 |
+
if ( !is_dir($root) ) {
|
41 |
+
continue;
|
42 |
+
}
|
43 |
+
$theme_locs[] = $root;
|
44 |
+
$root = trailingslashit($root);
|
45 |
+
foreach ( $theme_dirs as $dirname ) {
|
46 |
+
$tloc = realpath($root.$dirname);
|
47 |
+
if ( is_dir($tloc) ) {
|
48 |
+
$theme_locs[] = $tloc;
|
49 |
+
}
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
return $theme_locs;
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get calling script file.
|
59 |
+
* @api
|
60 |
+
* @param int $offset
|
61 |
+
* @return string|null
|
62 |
+
*/
|
63 |
+
public static function get_calling_script_file( $offset = 0 ) {
|
64 |
+
$callers = array();
|
65 |
+
$backtrace = debug_backtrace();
|
66 |
+
foreach ( $backtrace as $trace ) {
|
67 |
+
if ( array_key_exists('file', $trace) && $trace['file'] != __FILE__ ) {
|
68 |
+
$callers[] = $trace['file'];
|
69 |
+
}
|
70 |
+
}
|
71 |
+
$callers = array_unique($callers);
|
72 |
+
$callers = array_values($callers);
|
73 |
+
return $callers[$offset];
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Get calling script dir.
|
78 |
+
* @api
|
79 |
+
* @return string
|
80 |
+
*/
|
81 |
+
public static function get_calling_script_dir( $offset = 0 ) {
|
82 |
+
$caller = self::get_calling_script_file($offset);
|
83 |
+
if ( !is_null($caller) ) {
|
84 |
+
$pathinfo = pathinfo($caller);
|
85 |
+
$dir = $pathinfo['dirname'];
|
86 |
+
return $dir;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* returns an array of the directory inside themes that holds twig files
|
92 |
+
* @return string[] the names of directores, ie: array('templats', 'views');
|
93 |
+
*/
|
94 |
+
public static function get_locations_theme_dir() {
|
95 |
+
if ( is_string(Timber::$dirname) ) {
|
96 |
+
return array(Timber::$dirname);
|
97 |
+
}
|
98 |
+
return Timber::$dirname;
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
/**
|
103 |
+
*
|
104 |
+
* @return array
|
105 |
+
*/
|
106 |
+
protected static function get_locations_user() {
|
107 |
+
$locs = array();
|
108 |
+
if ( isset(Timber::$locations) ) {
|
109 |
+
if ( is_string(Timber::$locations) ) {
|
110 |
+
Timber::$locations = array(Timber::$locations);
|
111 |
+
}
|
112 |
+
foreach ( Timber::$locations as $tloc ) {
|
113 |
+
$tloc = realpath($tloc);
|
114 |
+
if ( is_dir($tloc) ) {
|
115 |
+
$locs[] = $tloc;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
}
|
119 |
+
return $locs;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* @param bool|string $caller the calling directory
|
124 |
+
* @return array
|
125 |
+
*/
|
126 |
+
protected static function get_locations_caller( $caller = false ) {
|
127 |
+
$locs = array();
|
128 |
+
if ( $caller && is_string($caller) ) {
|
129 |
+
$caller = realpath($caller);
|
130 |
+
if ( is_dir($caller) ) {
|
131 |
+
$locs[] = $caller;
|
132 |
+
}
|
133 |
+
$caller = trailingslashit($caller);
|
134 |
+
foreach ( LocationManager::get_locations_theme_dir() as $dirname ) {
|
135 |
+
$caller_sub = realpath($caller.$dirname);
|
136 |
+
if ( is_dir($caller_sub) ) {
|
137 |
+
$locs[] = $caller_sub;
|
138 |
+
}
|
139 |
+
}
|
140 |
+
}
|
141 |
+
return $locs;
|
142 |
+
}
|
143 |
+
|
144 |
+
|
145 |
+
}
|
lib/Pagination.php
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace Timber;
|
4 |
+
|
5 |
+
class Pagination {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Get pagination.
|
9 |
+
* @api
|
10 |
+
* @param array $prefs
|
11 |
+
* @return array mixed
|
12 |
+
*/
|
13 |
+
public static function get_pagination( $prefs ) {
|
14 |
+
global $wp_query;
|
15 |
+
global $paged;
|
16 |
+
global $wp_rewrite;
|
17 |
+
$args = array();
|
18 |
+
$args['total'] = ceil($wp_query->found_posts / $wp_query->query_vars['posts_per_page']);
|
19 |
+
if ( $wp_rewrite->using_permalinks() ) {
|
20 |
+
$url = explode('?', get_pagenum_link(0));
|
21 |
+
if ( isset($url[1]) ) {
|
22 |
+
parse_str($url[1], $query);
|
23 |
+
$args['add_args'] = $query;
|
24 |
+
}
|
25 |
+
$args['format'] = $wp_rewrite->pagination_base.'/%#%';
|
26 |
+
$args['base'] = trailingslashit($url[0]).'%_%';
|
27 |
+
} else {
|
28 |
+
$big = 999999999;
|
29 |
+
$args['base'] = str_replace($big, '%#%', esc_url(get_pagenum_link($big)));
|
30 |
+
}
|
31 |
+
$args['type'] = 'array';
|
32 |
+
$args['current'] = max(1, get_query_var('paged'));
|
33 |
+
$args['mid_size'] = max(9 - $args['current'], 3);
|
34 |
+
if ( is_int($prefs) ) {
|
35 |
+
$args['mid_size'] = $prefs - 2;
|
36 |
+
} else {
|
37 |
+
$args = array_merge($args, $prefs);
|
38 |
+
}
|
39 |
+
$data = array();
|
40 |
+
$data['current'] = $args['current'];
|
41 |
+
$data['total'] = $args['total'];
|
42 |
+
$data['pages'] = Pagination::paginate_links($args);
|
43 |
+
|
44 |
+
if ( $data['total'] <= count($data['pages']) ) {
|
45 |
+
// decrement current so that it matches up with the 0 based index used by the pages array
|
46 |
+
$current = $data['current'] - 1;
|
47 |
+
} else {
|
48 |
+
// $data['current'] can't be used b/c there are more than 10 pages and we are condensing with dots
|
49 |
+
foreach ( $data['pages'] as $key => $page ) {
|
50 |
+
if ( !empty($page['current']) ) {
|
51 |
+
$current = $key;
|
52 |
+
break;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
// set next and prev using pages array generated by paginate links
|
58 |
+
if ( isset($current) && isset($data['pages'][$current + 1]) ) {
|
59 |
+
$data['next'] = array('link' => user_trailingslashit($data['pages'][$current + 1]['link']), 'class' => 'page-numbers next');
|
60 |
+
if ( Pagination::is_search_query($data['next']['link']) ) {
|
61 |
+
$data['next']['link'] = untrailingslashit($data['next']['link']);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
if ( isset($current) && isset($data['pages'][$current - 1]) ) {
|
65 |
+
$data['prev'] = array('link' => user_trailingslashit($data['pages'][$current - 1]['link']), 'class' => 'page-numbers prev');
|
66 |
+
if ( Pagination::is_search_query($data['prev']['link']) ) {
|
67 |
+
$data['prev']['link'] = untrailingslashit($data['prev']['link']);
|
68 |
+
}
|
69 |
+
}
|
70 |
+
if ( $paged < 2 ) {
|
71 |
+
$data['prev'] = '';
|
72 |
+
}
|
73 |
+
if ( $data['total'] === (double) 0 ) {
|
74 |
+
$data['next'] = '';
|
75 |
+
}
|
76 |
+
return $data;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Checks to see whether the given URL has a search query in it (s=*)
|
81 |
+
* @param string $url
|
82 |
+
* @return boolean
|
83 |
+
*/
|
84 |
+
public static function is_search_query( $url ) {
|
85 |
+
if ( strpos($url, 's=') !== false ) {
|
86 |
+
return true;
|
87 |
+
}
|
88 |
+
return false;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
*
|
93 |
+
*
|
94 |
+
* @param array $args
|
95 |
+
* @return array
|
96 |
+
*/
|
97 |
+
public static function paginate_links( $args = array() ) {
|
98 |
+
$defaults = array(
|
99 |
+
'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
|
100 |
+
'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
|
101 |
+
'total' => 1,
|
102 |
+
'current' => 0,
|
103 |
+
'show_all' => false,
|
104 |
+
'prev_next' => false,
|
105 |
+
'prev_text' => __('« Previous'),
|
106 |
+
'next_text' => __('Next »'),
|
107 |
+
'end_size' => 1,
|
108 |
+
'mid_size' => 2,
|
109 |
+
'type' => 'array',
|
110 |
+
'add_args' => false, // array of query args to add
|
111 |
+
'add_fragment' => ''
|
112 |
+
);
|
113 |
+
$args = wp_parse_args($args, $defaults);
|
114 |
+
// Who knows what else people pass in $args
|
115 |
+
$args['total'] = intval((int) $args['total']);
|
116 |
+
if ( $args['total'] < 2 ) {
|
117 |
+
return array();
|
118 |
+
}
|
119 |
+
$args['current'] = (int) $args['current'];
|
120 |
+
$args['end_size'] = 0 < (int) $args['end_size'] ? (int) $args['end_size'] : 1; // Out of bounds? Make it the default.
|
121 |
+
$args['mid_size'] = 0 <= (int) $args['mid_size'] ? (int) $args['mid_size'] : 2;
|
122 |
+
$args['add_args'] = is_array($args['add_args']) ? $args['add_args'] : false;
|
123 |
+
$page_links = array();
|
124 |
+
$dots = false;
|
125 |
+
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
126 |
+
$n_display = number_format_i18n($n);
|
127 |
+
if ( $n == $args['current'] ) {
|
128 |
+
$page_links[] = array(
|
129 |
+
'class' => 'page-number page-numbers current',
|
130 |
+
'title' => $n_display,
|
131 |
+
'text' => $n_display,
|
132 |
+
'name' => $n_display,
|
133 |
+
'current' => true
|
134 |
+
);
|
135 |
+
$dots = true;
|
136 |
+
} else {
|
137 |
+
if ( $args['show_all'] || ($n <= $args['end_size'] || ($args['current'] && $n >= $args['current'] - $args['mid_size'] && $n <= $args['current'] + $args['mid_size']) || $n > $args['total'] - $args['end_size']) ) {
|
138 |
+
$link = str_replace('%_%', 1 == $n ? '' : $args['format'], $args['base']);
|
139 |
+
$link = str_replace('%#%', $n, $link);
|
140 |
+
$link = trailingslashit($link).ltrim($args['add_fragment'], '/');
|
141 |
+
if ( $args['add_args'] ) {
|
142 |
+
$link = rtrim(add_query_arg($args['add_args'], $link), '/');
|
143 |
+
}
|
144 |
+
$link = str_replace(' ', '+', $link);
|
145 |
+
$link = untrailingslashit($link);
|
146 |
+
$link = esc_url(apply_filters('paginate_links', $link));
|
147 |
+
$link = user_trailingslashit($link);
|
148 |
+
if ( self::is_search_query($link) ) {
|
149 |
+
$link = untrailingslashit($link);
|
150 |
+
}
|
151 |
+
$page_links[] = array(
|
152 |
+
'class' => 'page-number page-numbers',
|
153 |
+
'link' => $link,
|
154 |
+
'title' => $n_display,
|
155 |
+
'name' => $n_display,
|
156 |
+
'current' => $args['current'] == $n
|
157 |
+
);
|
158 |
+
$dots = true;
|
159 |
+
} elseif ( $dots && !$args['show_all'] ) {
|
160 |
+
$page_links[] = array(
|
161 |
+
'class' => 'dots',
|
162 |
+
'title' => __('…')
|
163 |
+
);
|
164 |
+
$dots = false;
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
return $page_links;
|
170 |
+
}
|
171 |
+
|
172 |
+
}
|
lib/Post.php
CHANGED
@@ -389,9 +389,10 @@ class Post extends Core implements CoreInterface {
|
|
389 |
*/
|
390 |
public function get_preview( $len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '…' ) {
|
391 |
$text = '';
|
|
|
392 |
$trimmed = false;
|
393 |
$last_p_tag = null;
|
394 |
-
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
395 |
if ( $force ) {
|
396 |
$text = Helper::trim_words($this->post_excerpt, $len, false);
|
397 |
$trimmed = true;
|
@@ -436,10 +437,11 @@ class Post extends Core implements CoreInterface {
|
|
436 |
}
|
437 |
$read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
|
438 |
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
439 |
-
$
|
440 |
} elseif ( $readmore ) {
|
441 |
-
$
|
442 |
}
|
|
|
443 |
if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
|
444 |
$text .= '</p>';
|
445 |
}
|
@@ -649,7 +651,7 @@ class Post extends Core implements CoreInterface {
|
|
649 |
* @return boolean
|
650 |
*/
|
651 |
public function has_field( $field_name ) {
|
652 |
-
return (!$this->get_field(
|
653 |
}
|
654 |
|
655 |
|
@@ -753,7 +755,13 @@ class Post extends Core implements CoreInterface {
|
|
753 |
* @return User|null A User object if found, false if not
|
754 |
*/
|
755 |
public function author() {
|
756 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
757 |
}
|
758 |
|
759 |
/**
|
@@ -769,7 +777,7 @@ class Post extends Core implements CoreInterface {
|
|
769 |
*/
|
770 |
public function modified_author() {
|
771 |
$user_id = get_post_meta($this->ID, '_edit_last', true);
|
772 |
-
return ($user_id ? new User($user_id) : $this->
|
773 |
}
|
774 |
|
775 |
/**
|
@@ -906,6 +914,20 @@ class Post extends Core implements CoreInterface {
|
|
906 |
return $timber_comments;
|
907 |
}
|
908 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
909 |
/**
|
910 |
* Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
|
911 |
* @api
|
@@ -920,6 +942,9 @@ class Post extends Core implements CoreInterface {
|
|
920 |
* @return string
|
921 |
*/
|
922 |
public function content( $page = 0, $len = -1 ) {
|
|
|
|
|
|
|
923 |
if ( $len == -1 && $page == 0 && $this->_content ) {
|
924 |
return $this->_content;
|
925 |
}
|
@@ -1040,6 +1065,15 @@ class Post extends Core implements CoreInterface {
|
|
1040 |
public function format() {
|
1041 |
return get_post_format($this->ID);
|
1042 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1043 |
|
1044 |
/**
|
1045 |
* get the permalink for a post object
|
@@ -1504,9 +1538,7 @@ class Post extends Core implements CoreInterface {
|
|
1504 |
* @return User|null
|
1505 |
*/
|
1506 |
public function get_author() {
|
1507 |
-
|
1508 |
-
return new User($this->post_author);
|
1509 |
-
}
|
1510 |
}
|
1511 |
|
1512 |
/**
|
389 |
*/
|
390 |
public function get_preview( $len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '…' ) {
|
391 |
$text = '';
|
392 |
+
$link = '';
|
393 |
$trimmed = false;
|
394 |
$last_p_tag = null;
|
395 |
+
if ( isset($this->post_excerpt) && strlen(trim($this->post_excerpt)) ) {
|
396 |
if ( $force ) {
|
397 |
$text = Helper::trim_words($this->post_excerpt, $len, false);
|
398 |
$trimmed = true;
|
437 |
}
|
438 |
$read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
|
439 |
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
440 |
+
$link = ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore_matches[1]).'</a>';
|
441 |
} elseif ( $readmore ) {
|
442 |
+
$link = ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore).'</a>';
|
443 |
}
|
444 |
+
$text .= apply_filters('timber/post/get_preview/read_more_link', $link);
|
445 |
if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
|
446 |
$text .= '</p>';
|
447 |
}
|
651 |
* @return boolean
|
652 |
*/
|
653 |
public function has_field( $field_name ) {
|
654 |
+
return (!$this->get_field($field_name)) ? false : true;
|
655 |
}
|
656 |
|
657 |
|
755 |
* @return User|null A User object if found, false if not
|
756 |
*/
|
757 |
public function author() {
|
758 |
+
if ( isset($this->post_author) ) {
|
759 |
+
return new User($this->post_author);
|
760 |
+
}
|
761 |
+
}
|
762 |
+
|
763 |
+
public function authors() {
|
764 |
+
return apply_filters('timber/post/authors', array($this->author()), $this);
|
765 |
}
|
766 |
|
767 |
/**
|
777 |
*/
|
778 |
public function modified_author() {
|
779 |
$user_id = get_post_meta($this->ID, '_edit_last', true);
|
780 |
+
return ($user_id ? new User($user_id) : $this->author());
|
781 |
}
|
782 |
|
783 |
/**
|
914 |
return $timber_comments;
|
915 |
}
|
916 |
|
917 |
+
/**
|
918 |
+
* If the Password form is to be shown, show it!
|
919 |
+
* @return string|void
|
920 |
+
*/
|
921 |
+
protected function maybe_show_password_form(){
|
922 |
+
if ( $this->password_required() ) {
|
923 |
+
$show_pw = false;
|
924 |
+
$show_pw = apply_filters('timber/post/content/show_password_form_for_protected', $show_pw);
|
925 |
+
if ($show_pw) {
|
926 |
+
return apply_filters('timber/post/content/password_form', get_the_password_form($this->ID), $this);
|
927 |
+
}
|
928 |
+
}
|
929 |
+
}
|
930 |
+
|
931 |
/**
|
932 |
* Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
|
933 |
* @api
|
942 |
* @return string
|
943 |
*/
|
944 |
public function content( $page = 0, $len = -1 ) {
|
945 |
+
if ( $form = $this->maybe_show_password_form() ) {
|
946 |
+
return $form;
|
947 |
+
}
|
948 |
if ( $len == -1 && $page == 0 && $this->_content ) {
|
949 |
return $this->_content;
|
950 |
}
|
1065 |
public function format() {
|
1066 |
return get_post_format($this->ID);
|
1067 |
}
|
1068 |
+
|
1069 |
+
/**
|
1070 |
+
* whether post requires password and correct password has been provided
|
1071 |
+
* @api
|
1072 |
+
* @return boolean
|
1073 |
+
*/
|
1074 |
+
public function password_required() {
|
1075 |
+
return post_password_required($this->ID);
|
1076 |
+
}
|
1077 |
|
1078 |
/**
|
1079 |
* get the permalink for a post object
|
1538 |
* @return User|null
|
1539 |
*/
|
1540 |
public function get_author() {
|
1541 |
+
return $this->author();
|
|
|
|
|
1542 |
}
|
1543 |
|
1544 |
/**
|
lib/PostGetter.php
CHANGED
@@ -9,10 +9,22 @@ class PostGetter {
|
|
9 |
|
10 |
/**
|
11 |
* @param mixed $query
|
12 |
-
* @param string $PostClass
|
13 |
* @return array|bool|null
|
14 |
*/
|
15 |
public static function get_post( $query = false, $PostClass = '\Timber\Post' ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
$posts = self::get_posts($query, $PostClass);
|
17 |
if ( $post = reset($posts) ) {
|
18 |
return $post;
|
@@ -33,7 +45,7 @@ class PostGetter {
|
|
33 |
|
34 |
/**
|
35 |
* @param mixed $query
|
36 |
-
* @param string $PostClass
|
37 |
* @return array|bool|null
|
38 |
*/
|
39 |
public static function query_posts( $query = false, $PostClass = '\Timber\Post' ) {
|
@@ -84,6 +96,35 @@ class PostGetter {
|
|
84 |
return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
|
85 |
}
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
/**
|
88 |
* @param string|array $arg
|
89 |
* @return boolean
|
9 |
|
10 |
/**
|
11 |
* @param mixed $query
|
12 |
+
* @param string|array $PostClass
|
13 |
* @return array|bool|null
|
14 |
*/
|
15 |
public static function get_post( $query = false, $PostClass = '\Timber\Post' ) {
|
16 |
+
// if a post id is passed, grab the post directly
|
17 |
+
if ( is_numeric($query) ) {
|
18 |
+
$post_type = get_post_type($query);
|
19 |
+
$PostClass = PostGetter::get_post_class($post_type, $PostClass);
|
20 |
+
$post = new $PostClass($query);
|
21 |
+
// get the latest revision if we're dealing with a preview
|
22 |
+
$posts = PostsCollection::maybe_set_preview(array($post));
|
23 |
+
if ( $post = reset($posts) ) {
|
24 |
+
return $post;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
$posts = self::get_posts($query, $PostClass);
|
29 |
if ( $post = reset($posts) ) {
|
30 |
return $post;
|
45 |
|
46 |
/**
|
47 |
* @param mixed $query
|
48 |
+
* @param string|array $PostClass
|
49 |
* @return array|bool|null
|
50 |
*/
|
51 |
public static function query_posts( $query = false, $PostClass = '\Timber\Post' ) {
|
96 |
return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
|
97 |
}
|
98 |
|
99 |
+
/**
|
100 |
+
* @param string $post_type
|
101 |
+
* @param string|array $post_class
|
102 |
+
*
|
103 |
+
* @return string
|
104 |
+
*/
|
105 |
+
public static function get_post_class( $post_type, $post_class = '\Timber\Post' ) {
|
106 |
+
$post_class = apply_filters( 'Timber\PostClassMap', $post_class );
|
107 |
+
$post_class_use = '\Timber\Post';
|
108 |
+
|
109 |
+
if ( is_array($post_class) ) {
|
110 |
+
if ( isset( $post_class[$post_type]) ) {
|
111 |
+
$post_class_use = $post_class[$post_type];
|
112 |
+
} else {
|
113 |
+
Helper::error_log($post_type . ' not found in ' . print_r($post_class, true));
|
114 |
+
}
|
115 |
+
} elseif ( is_string($post_class) ) {
|
116 |
+
$post_class_use = $post_class;
|
117 |
+
} else {
|
118 |
+
Helper::error_log('Unexpeted value for PostClass: ' . print_r( $post_class, true));
|
119 |
+
}
|
120 |
+
|
121 |
+
if ( !class_exists( $post_class_use ) || !( is_subclass_of($post_class_use, '\Timber\Post') || is_a($post_class_use, '\Timber\Post', true) ) ) {
|
122 |
+
Helper::error_log('Class ' . $post_class_use . ' either does not exist or implement \Timber\Post');
|
123 |
+
}
|
124 |
+
|
125 |
+
return $post_class_use;
|
126 |
+
}
|
127 |
+
|
128 |
/**
|
129 |
* @param string|array $arg
|
130 |
* @return boolean
|
lib/PostType.php
CHANGED
@@ -8,6 +8,9 @@ namespace Timber;
|
|
8 |
*/
|
9 |
class PostType {
|
10 |
|
|
|
|
|
|
|
11 |
public function __construct( $post_type ) {
|
12 |
$this->slug = $post_type;
|
13 |
$this->init($post_type);
|
8 |
*/
|
9 |
class PostType {
|
10 |
|
11 |
+
/**
|
12 |
+
* @param string $post_type
|
13 |
+
*/
|
14 |
public function __construct( $post_type ) {
|
15 |
$this->slug = $post_type;
|
16 |
$this->init($post_type);
|
lib/PostsCollection.php
CHANGED
@@ -18,22 +18,9 @@ class PostsCollection extends \ArrayObject {
|
|
18 |
$posts = array();
|
19 |
}
|
20 |
foreach ( $posts as $post_object ) {
|
21 |
-
$
|
22 |
-
|
23 |
-
|
24 |
-
$post_class_use = '\Timber\Post';
|
25 |
-
|
26 |
-
if ( isset($post_class[$post_type]) ) {
|
27 |
-
$post_class_use = $post_class[$post_type];
|
28 |
-
|
29 |
-
} else {
|
30 |
-
if ( is_array($post_class) ) {
|
31 |
-
Helper::error_log($post_type.' of '.$post_object->ID.' not found in '.print_r($post_class, true));
|
32 |
-
} else {
|
33 |
-
Helper::error_log($post_type.' not found in '.$post_class);
|
34 |
-
}
|
35 |
-
}
|
36 |
-
}
|
37 |
// Don't create yet another object if $post_object is already of the right type
|
38 |
if ( is_a($post_object, $post_class_use) ) {
|
39 |
$post = $post_object;
|
18 |
$posts = array();
|
19 |
}
|
20 |
foreach ( $posts as $post_object ) {
|
21 |
+
$post_type = get_post_type($post_object);
|
22 |
+
$post_class_use = PostGetter::get_post_class($post_type, $post_class);
|
23 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
// Don't create yet another object if $post_object is already of the right type
|
25 |
if ( is_a($post_object, $post_class_use) ) {
|
26 |
$post = $post_object;
|
lib/QueryIterator.php
CHANGED
@@ -10,7 +10,7 @@ if ( !defined('ABSPATH') ) {
|
|
10 |
exit;
|
11 |
}
|
12 |
|
13 |
-
class QueryIterator implements \Iterator {
|
14 |
|
15 |
/**
|
16 |
*
|
@@ -22,13 +22,14 @@ class QueryIterator implements \Iterator {
|
|
22 |
|
23 |
public function __construct( $query = false, $posts_class = 'Timber\Post' ) {
|
24 |
add_action('pre_get_posts', array($this, 'fix_number_posts_wp_quirk'));
|
25 |
-
|
|
|
26 |
$this->_posts_class = $posts_class;
|
|
|
27 |
|
28 |
if ( is_a($query, 'WP_Query') ) {
|
29 |
// We got a full-fledged WP Query, look no further!
|
30 |
$the_query = $query;
|
31 |
-
|
32 |
} elseif ( false === $query ) {
|
33 |
// If query is explicitly set to false, use the main loop
|
34 |
global $wp_query;
|
@@ -38,11 +39,9 @@ class QueryIterator implements \Iterator {
|
|
38 |
} elseif ( Helper::is_array_assoc($query) || (is_string($query) && strstr($query, '=')) ) {
|
39 |
// We have a regularly formed WP query string or array to use
|
40 |
$the_query = new \WP_Query($query);
|
41 |
-
|
42 |
} elseif ( is_numeric($query) || is_string($query) ) {
|
43 |
// We have what could be a post name or post ID to pull out
|
44 |
$the_query = self::get_query_from_string($query);
|
45 |
-
|
46 |
} elseif ( is_array($query) && count($query) && (is_integer($query[0]) || is_string($query[0])) ) {
|
47 |
// We have a list of pids (post IDs) to extract from
|
48 |
$the_query = self::get_query_from_array_of_ids($query);
|
@@ -52,7 +51,6 @@ class QueryIterator implements \Iterator {
|
|
52 |
} else {
|
53 |
Helper::error_log('I have failed you! in '.basename(__FILE__).'::'.__LINE__);
|
54 |
Helper::error_log($query);
|
55 |
-
|
56 |
// We have failed hard, at least let get something.
|
57 |
$the_query = new \WP_Query();
|
58 |
}
|
@@ -62,7 +60,7 @@ class QueryIterator implements \Iterator {
|
|
62 |
}
|
63 |
|
64 |
public function post_count() {
|
65 |
-
|
66 |
}
|
67 |
|
68 |
public function get_posts( $return_collection = false ) {
|
@@ -76,8 +74,9 @@ class QueryIterator implements \Iterator {
|
|
76 |
// GET POSTS
|
77 |
//
|
78 |
public static function get_query_from_array_of_ids( $query = array() ) {
|
79 |
-
if ( !is_array($query) || !count($query) )
|
80 |
return null;
|
|
|
81 |
|
82 |
return new \WP_Query(array(
|
83 |
'post_type'=> 'any',
|
@@ -150,6 +149,16 @@ class QueryIterator implements \Iterator {
|
|
150 |
return $query;
|
151 |
}
|
152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
/**
|
154 |
* this will test for whether a custom page to display posts is active, and if so, set the query to the default
|
155 |
* @param WP_Query $query the original query recived from WordPress
|
@@ -164,4 +173,21 @@ class QueryIterator implements \Iterator {
|
|
164 |
return $query;
|
165 |
}
|
166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
}
|
10 |
exit;
|
11 |
}
|
12 |
|
13 |
+
class QueryIterator implements \Iterator, \Countable {
|
14 |
|
15 |
/**
|
16 |
*
|
22 |
|
23 |
public function __construct( $query = false, $posts_class = 'Timber\Post' ) {
|
24 |
add_action('pre_get_posts', array($this, 'fix_number_posts_wp_quirk'));
|
25 |
+
add_action('pre_get_posts', array($this, 'fix_cat_wp_quirk'));
|
26 |
+
if ( $posts_class ) {
|
27 |
$this->_posts_class = $posts_class;
|
28 |
+
}
|
29 |
|
30 |
if ( is_a($query, 'WP_Query') ) {
|
31 |
// We got a full-fledged WP Query, look no further!
|
32 |
$the_query = $query;
|
|
|
33 |
} elseif ( false === $query ) {
|
34 |
// If query is explicitly set to false, use the main loop
|
35 |
global $wp_query;
|
39 |
} elseif ( Helper::is_array_assoc($query) || (is_string($query) && strstr($query, '=')) ) {
|
40 |
// We have a regularly formed WP query string or array to use
|
41 |
$the_query = new \WP_Query($query);
|
|
|
42 |
} elseif ( is_numeric($query) || is_string($query) ) {
|
43 |
// We have what could be a post name or post ID to pull out
|
44 |
$the_query = self::get_query_from_string($query);
|
|
|
45 |
} elseif ( is_array($query) && count($query) && (is_integer($query[0]) || is_string($query[0])) ) {
|
46 |
// We have a list of pids (post IDs) to extract from
|
47 |
$the_query = self::get_query_from_array_of_ids($query);
|
51 |
} else {
|
52 |
Helper::error_log('I have failed you! in '.basename(__FILE__).'::'.__LINE__);
|
53 |
Helper::error_log($query);
|
|
|
54 |
// We have failed hard, at least let get something.
|
55 |
$the_query = new \WP_Query();
|
56 |
}
|
60 |
}
|
61 |
|
62 |
public function post_count() {
|
63 |
+
return $this->_query->post_count;
|
64 |
}
|
65 |
|
66 |
public function get_posts( $return_collection = false ) {
|
74 |
// GET POSTS
|
75 |
//
|
76 |
public static function get_query_from_array_of_ids( $query = array() ) {
|
77 |
+
if ( !is_array($query) || !count($query) ) {
|
78 |
return null;
|
79 |
+
}
|
80 |
|
81 |
return new \WP_Query(array(
|
82 |
'post_type'=> 'any',
|
149 |
return $query;
|
150 |
}
|
151 |
|
152 |
+
//get_posts uses category, WP_Query uses cat. Why? who knows...
|
153 |
+
public static function fix_cat_wp_quirk( $query ) {
|
154 |
+
if ( isset($query->query) && isset($query->query['category'])
|
155 |
+
&& !isset($query->query['cat']) ) {
|
156 |
+
$query->set('cat', $query->query['category']);
|
157 |
+
unset($query->query['category']);
|
158 |
+
}
|
159 |
+
return $query;
|
160 |
+
}
|
161 |
+
|
162 |
/**
|
163 |
* this will test for whether a custom page to display posts is active, and if so, set the query to the default
|
164 |
* @param WP_Query $query the original query recived from WordPress
|
173 |
return $query;
|
174 |
}
|
175 |
|
176 |
+
/**
|
177 |
+
* Count elements of an object.
|
178 |
+
*
|
179 |
+
* Necessary for some Twig `loop` variable properties.
|
180 |
+
* @see http://twig.sensiolabs.org/doc/tags/for.html#the-loop-variable
|
181 |
+
*
|
182 |
+
* @link http://php.net/manual/en/countable.count.php
|
183 |
+
* @return int The custom count as an integer.
|
184 |
+
* </p>
|
185 |
+
* <p>
|
186 |
+
* The return value is cast to an integer.
|
187 |
+
* @since 5.1.0
|
188 |
+
*/
|
189 |
+
public function count()
|
190 |
+
{
|
191 |
+
return $this->post_count();
|
192 |
+
}
|
193 |
}
|
lib/Term.php
CHANGED
@@ -339,7 +339,7 @@ class Term extends Core implements CoreInterface {
|
|
339 |
$prefix = '<p>';
|
340 |
$desc = term_description($this->ID, $this->taxonomy);
|
341 |
if ( substr($desc, 0, strlen($prefix)) == $prefix ) {
|
342 |
-
|
343 |
}
|
344 |
$desc = preg_replace('/'.preg_quote('</p>', '/').'$/', '', $desc);
|
345 |
return trim($desc);
|
339 |
$prefix = '<p>';
|
340 |
$desc = term_description($this->ID, $this->taxonomy);
|
341 |
if ( substr($desc, 0, strlen($prefix)) == $prefix ) {
|
342 |
+
$desc = substr($desc, strlen($prefix));
|
343 |
}
|
344 |
$desc = preg_replace('/'.preg_quote('</p>', '/').'$/', '', $desc);
|
345 |
return trim($desc);
|
lib/TermGetter.php
CHANGED
@@ -11,7 +11,7 @@ class TermGetter {
|
|
11 |
* @param string $taxonomy
|
12 |
* @return Timber\Term|WP_Error|null
|
13 |
*/
|
14 |
-
public static function get_term( $term, $taxonomy, $TermClass = 'Term' ) {
|
15 |
$term = get_term($term, $taxonomy);
|
16 |
return new $TermClass($term->term_id, $term->taxonomy);
|
17 |
}
|
@@ -22,7 +22,7 @@ class TermGetter {
|
|
22 |
* @param string $TermClass
|
23 |
* @return mixed
|
24 |
*/
|
25 |
-
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'Term' ) {
|
26 |
if ( is_string($maybe_args) && !strstr($maybe_args, '=') ) {
|
27 |
//the user is sending the $TermClass in the second argument
|
28 |
$TermClass = $maybe_args;
|
11 |
* @param string $taxonomy
|
12 |
* @return Timber\Term|WP_Error|null
|
13 |
*/
|
14 |
+
public static function get_term( $term, $taxonomy, $TermClass = '\Timber\Term' ) {
|
15 |
$term = get_term($term, $taxonomy);
|
16 |
return new $TermClass($term->term_id, $term->taxonomy);
|
17 |
}
|
22 |
* @param string $TermClass
|
23 |
* @return mixed
|
24 |
*/
|
25 |
+
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = '\Timber\Term' ) {
|
26 |
if ( is_string($maybe_args) && !strstr($maybe_args, '=') ) {
|
27 |
//the user is sending the $TermClass in the second argument
|
28 |
$TermClass = $maybe_args;
|
lib/Timber.php
CHANGED
@@ -11,6 +11,7 @@ use Timber\TermGetter;
|
|
11 |
use Timber\Site;
|
12 |
use Timber\URLHelper;
|
13 |
use Timber\Helper;
|
|
|
14 |
use Timber\Request;
|
15 |
use Timber\User;
|
16 |
use Timber\Loader;
|
@@ -34,7 +35,7 @@ use Timber\Loader;
|
|
34 |
*/
|
35 |
class Timber {
|
36 |
|
37 |
-
public static $version = '1.
|
38 |
public static $locations;
|
39 |
public static $dirname = 'views';
|
40 |
public static $twig_cache = false;
|
@@ -55,7 +56,7 @@ class Timber {
|
|
55 |
$this->test_compatibility();
|
56 |
$this->backwards_compatibility();
|
57 |
$this->init_constants();
|
58 |
-
$this
|
59 |
}
|
60 |
}
|
61 |
|
@@ -102,12 +103,12 @@ class Timber {
|
|
102 |
/**
|
103 |
* @codeCoverageIgnore
|
104 |
*/
|
105 |
-
protected
|
106 |
if ( class_exists('\WP') && !defined('TIMBER_LOADED') ) {
|
107 |
Twig::init();
|
108 |
ImageHelper::init();
|
109 |
Admin::init();
|
110 |
-
Integrations
|
111 |
define('TIMBER_LOADED', true);
|
112 |
}
|
113 |
}
|
@@ -119,7 +120,7 @@ class Timber {
|
|
119 |
* Get post.
|
120 |
* @api
|
121 |
* @param mixed $query
|
122 |
-
* @param string $PostClass
|
123 |
* @return array|bool|null
|
124 |
*/
|
125 |
public static function get_post( $query = false, $PostClass = 'Timber\Post' ) {
|
@@ -224,7 +225,7 @@ class Timber {
|
|
224 |
*/
|
225 |
public static function get_context() {
|
226 |
if ( empty(self::$context_cache) ) {
|
227 |
-
self::$context_cache['http_host'] = '
|
228 |
self::$context_cache['wp_title'] = Helper::get_wp_title();
|
229 |
self::$context_cache['wp_head'] = Helper::function_wrapper('wp_head');
|
230 |
self::$context_cache['wp_footer'] = Helper::function_wrapper('wp_footer');
|
@@ -251,7 +252,7 @@ class Timber {
|
|
251 |
* @api
|
252 |
* @param array $filenames
|
253 |
* @param array $data
|
254 |
-
* @param
|
255 |
* @param string $cache_mode
|
256 |
* @param bool $via_render
|
257 |
* @return bool|string
|
@@ -260,9 +261,11 @@ class Timber {
|
|
260 |
if ( !defined('TIMBER_LOADED') ) {
|
261 |
self::init();
|
262 |
}
|
263 |
-
$caller =
|
264 |
$loader = new Loader($caller);
|
265 |
$file = $loader->choose_template($filenames);
|
|
|
|
|
266 |
$output = '';
|
267 |
if ( is_null($data) ) {
|
268 |
$data = array();
|
@@ -321,9 +324,9 @@ class Timber {
|
|
321 |
* @api
|
322 |
* @param array $filenames
|
323 |
* @param array $data
|
324 |
-
* @param
|
325 |
* @param string $cache_mode
|
326 |
-
* @return
|
327 |
*/
|
328 |
public static function render( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
|
329 |
$output = self::fetch($filenames, $data, $expires, $cache_mode);
|
@@ -370,9 +373,8 @@ class Timber {
|
|
370 |
* @return string
|
371 |
*/
|
372 |
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
373 |
-
$caller =
|
374 |
-
$
|
375 |
-
$uris = $loader->get_locations($caller);
|
376 |
ob_start();
|
377 |
$found = false;
|
378 |
foreach ( $uris as $uri ) {
|
@@ -413,83 +415,12 @@ class Timber {
|
|
413 |
* @return array mixed
|
414 |
*/
|
415 |
public static function get_pagination( $prefs = array() ) {
|
416 |
-
|
417 |
-
global $paged;
|
418 |
-
global $wp_rewrite;
|
419 |
-
$args = array();
|
420 |
-
$args['total'] = ceil($wp_query->found_posts / $wp_query->query_vars['posts_per_page']);
|
421 |
-
if ( $wp_rewrite->using_permalinks() ) {
|
422 |
-
$url = explode('?', get_pagenum_link(0));
|
423 |
-
if ( isset($url[1]) ) {
|
424 |
-
parse_str($url[1], $query);
|
425 |
-
$args['add_args'] = $query;
|
426 |
-
}
|
427 |
-
$args['format'] = $wp_rewrite->pagination_base.'/%#%';
|
428 |
-
$args['base'] = trailingslashit($url[0]).'%_%';
|
429 |
-
} else {
|
430 |
-
$big = 999999999;
|
431 |
-
$args['base'] = str_replace($big, '%#%', esc_url(get_pagenum_link($big)));
|
432 |
-
}
|
433 |
-
$args['type'] = 'array';
|
434 |
-
$args['current'] = max(1, get_query_var('paged'));
|
435 |
-
$args['mid_size'] = max(9 - $args['current'], 3);
|
436 |
-
if ( is_int($prefs) ) {
|
437 |
-
$args['mid_size'] = $prefs - 2;
|
438 |
-
} else {
|
439 |
-
$args = array_merge($args, $prefs);
|
440 |
-
}
|
441 |
-
$data = array();
|
442 |
-
$data['current'] = $args['current'];
|
443 |
-
$data['total'] = $args['total'];
|
444 |
-
$data['pages'] = Helper::paginate_links($args);
|
445 |
-
|
446 |
-
if ( $data['total'] <= count($data['pages']) ) {
|
447 |
-
// decrement current so that it matches up with the 0 based index used by the pages array
|
448 |
-
$current = $data['current'] - 1;
|
449 |
-
}
|
450 |
-
// $data['current'] can't be used b/c there are more than 10 pages and we are condensing with dots
|
451 |
-
else {
|
452 |
-
foreach ( $data['pages'] as $key => $page ) {
|
453 |
-
if ( !empty($page['current']) ) {
|
454 |
-
$current = $key;
|
455 |
-
break;
|
456 |
-
}
|
457 |
-
}
|
458 |
-
}
|
459 |
-
|
460 |
-
// set next and prev using pages array generated by paginate links
|
461 |
-
if ( isset($current) && isset($data['pages'][$current + 1]) ) {
|
462 |
-
$data['next'] = array('link' => user_trailingslashit($data['pages'][$current + 1]['link']), 'class' => 'page-numbers next');
|
463 |
-
}
|
464 |
-
if ( isset($current) && isset($data['pages'][$current - 1]) ) {
|
465 |
-
$data['prev'] = array('link' => user_trailingslashit($data['pages'][$current - 1]['link']), 'class' => 'page-numbers prev');
|
466 |
-
}
|
467 |
-
if ( $paged < 2 ) {
|
468 |
-
$data['prev'] = '';
|
469 |
-
}
|
470 |
-
if ( $data['total'] === (double) 0 ) {
|
471 |
-
$data['next'] = '';
|
472 |
-
}
|
473 |
-
return $data;
|
474 |
}
|
475 |
|
476 |
/* Utility
|
477 |
================================ */
|
478 |
|
479 |
-
/**
|
480 |
-
* Get calling script dir.
|
481 |
-
* @api
|
482 |
-
* @return string
|
483 |
-
*/
|
484 |
-
public static function get_calling_script_dir( $offset = 0 ) {
|
485 |
-
$caller = self::get_calling_script_file($offset);
|
486 |
-
if ( !is_null($caller) ) {
|
487 |
-
$pathinfo = pathinfo($caller);
|
488 |
-
$dir = $pathinfo['dirname'];
|
489 |
-
return $dir;
|
490 |
-
}
|
491 |
-
}
|
492 |
-
|
493 |
|
494 |
/**
|
495 |
* Add route.
|
@@ -504,27 +435,5 @@ class Timber {
|
|
504 |
\Routes::map($route, $callback, $args);
|
505 |
}
|
506 |
|
507 |
-
|
508 |
-
* Get calling script file.
|
509 |
-
* @api
|
510 |
-
* @param int $offset
|
511 |
-
* @return string|null
|
512 |
-
* @deprecated since 0.20.0
|
513 |
-
*/
|
514 |
-
public static function get_calling_script_file( $offset = 0 ) {
|
515 |
-
$caller = null;
|
516 |
-
$backtrace = debug_backtrace();
|
517 |
-
$i = 0;
|
518 |
-
foreach ( $backtrace as $trace ) {
|
519 |
-
if ( array_key_exists('file', $trace) && $trace['file'] != __FILE__ ) {
|
520 |
-
$caller = $trace['file'];
|
521 |
-
break;
|
522 |
-
}
|
523 |
-
$i++;
|
524 |
-
}
|
525 |
-
if ( $offset ) {
|
526 |
-
$caller = $backtrace[$i + $offset]['file'];
|
527 |
-
}
|
528 |
-
return $caller;
|
529 |
-
}
|
530 |
}
|
11 |
use Timber\Site;
|
12 |
use Timber\URLHelper;
|
13 |
use Timber\Helper;
|
14 |
+
use Timber\Pagination;
|
15 |
use Timber\Request;
|
16 |
use Timber\User;
|
17 |
use Timber\Loader;
|
35 |
*/
|
36 |
class Timber {
|
37 |
|
38 |
+
public static $version = '1.1.4';
|
39 |
public static $locations;
|
40 |
public static $dirname = 'views';
|
41 |
public static $twig_cache = false;
|
56 |
$this->test_compatibility();
|
57 |
$this->backwards_compatibility();
|
58 |
$this->init_constants();
|
59 |
+
$this->init();
|
60 |
}
|
61 |
}
|
62 |
|
103 |
/**
|
104 |
* @codeCoverageIgnore
|
105 |
*/
|
106 |
+
protected function init() {
|
107 |
if ( class_exists('\WP') && !defined('TIMBER_LOADED') ) {
|
108 |
Twig::init();
|
109 |
ImageHelper::init();
|
110 |
Admin::init();
|
111 |
+
new Integrations();
|
112 |
define('TIMBER_LOADED', true);
|
113 |
}
|
114 |
}
|
120 |
* Get post.
|
121 |
* @api
|
122 |
* @param mixed $query
|
123 |
+
* @param string|array $PostClass
|
124 |
* @return array|bool|null
|
125 |
*/
|
126 |
public static function get_post( $query = false, $PostClass = 'Timber\Post' ) {
|
225 |
*/
|
226 |
public static function get_context() {
|
227 |
if ( empty(self::$context_cache) ) {
|
228 |
+
self::$context_cache['http_host'] = URLHelper::get_scheme().'://'.URLHelper::get_host();
|
229 |
self::$context_cache['wp_title'] = Helper::get_wp_title();
|
230 |
self::$context_cache['wp_head'] = Helper::function_wrapper('wp_head');
|
231 |
self::$context_cache['wp_footer'] = Helper::function_wrapper('wp_footer');
|
252 |
* @api
|
253 |
* @param array $filenames
|
254 |
* @param array $data
|
255 |
+
* @param boolean|integer $expires
|
256 |
* @param string $cache_mode
|
257 |
* @param bool $via_render
|
258 |
* @return bool|string
|
261 |
if ( !defined('TIMBER_LOADED') ) {
|
262 |
self::init();
|
263 |
}
|
264 |
+
$caller = LocationManager::get_calling_script_dir(1);
|
265 |
$loader = new Loader($caller);
|
266 |
$file = $loader->choose_template($filenames);
|
267 |
+
$caller_file = LocationManager::get_calling_script_file(1);
|
268 |
+
apply_filters('timber/calling_php_file', $caller_file);
|
269 |
$output = '';
|
270 |
if ( is_null($data) ) {
|
271 |
$data = array();
|
324 |
* @api
|
325 |
* @param array $filenames
|
326 |
* @param array $data
|
327 |
+
* @param boolean|integer $expires
|
328 |
* @param string $cache_mode
|
329 |
+
* @return boolean|string
|
330 |
*/
|
331 |
public static function render( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
|
332 |
$output = self::fetch($filenames, $data, $expires, $cache_mode);
|
373 |
* @return string
|
374 |
*/
|
375 |
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
376 |
+
$caller = LocationManager::get_calling_script_dir(1);
|
377 |
+
$uris = LocationManager::get_locations($caller);
|
|
|
378 |
ob_start();
|
379 |
$found = false;
|
380 |
foreach ( $uris as $uri ) {
|
415 |
* @return array mixed
|
416 |
*/
|
417 |
public static function get_pagination( $prefs = array() ) {
|
418 |
+
return Pagination::get_pagination($prefs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
419 |
}
|
420 |
|
421 |
/* Utility
|
422 |
================================ */
|
423 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
424 |
|
425 |
/**
|
426 |
* Add route.
|
435 |
\Routes::map($route, $callback, $args);
|
436 |
}
|
437 |
|
438 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
439 |
}
|
lib/Twig.php
CHANGED
@@ -61,6 +61,8 @@ class Twig {
|
|
61 |
$twig->addFilter(new \Twig_SimpleFilter('wpautop', 'wpautop'));
|
62 |
$twig->addFilter(new \Twig_SimpleFilter('list', array($this, 'add_list_separators')));
|
63 |
|
|
|
|
|
64 |
$twig->addFilter(new \Twig_SimpleFilter('relative', function( $link ) {
|
65 |
return URLHelper::get_rel_url($link, true);
|
66 |
} ));
|
@@ -217,12 +219,20 @@ class Twig {
|
|
217 |
*/
|
218 |
public function add_timber_escapers( $twig ) {
|
219 |
|
220 |
-
$twig->getExtension(
|
221 |
return esc_url( $string );
|
222 |
-
}
|
223 |
-
$twig->getExtension(
|
224 |
return wp_kses_post( $string );
|
225 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
|
227 |
return $twig;
|
228 |
|
61 |
$twig->addFilter(new \Twig_SimpleFilter('wpautop', 'wpautop'));
|
62 |
$twig->addFilter(new \Twig_SimpleFilter('list', array($this, 'add_list_separators')));
|
63 |
|
64 |
+
$twig->addFilter(new \Twig_SimpleFilter('pluck', array('Timber\Helper', 'pluck')));
|
65 |
+
|
66 |
$twig->addFilter(new \Twig_SimpleFilter('relative', function( $link ) {
|
67 |
return URLHelper::get_rel_url($link, true);
|
68 |
} ));
|
219 |
*/
|
220 |
public function add_timber_escapers( $twig ) {
|
221 |
|
222 |
+
$twig->getExtension('core')->setEscaper('esc_url', function( \Twig_Environment $env, $string ) {
|
223 |
return esc_url( $string );
|
224 |
+
});
|
225 |
+
$twig->getExtension('core')->setEscaper('wp_kses_post', function( \Twig_Environment $env, $string ) {
|
226 |
return wp_kses_post( $string );
|
227 |
+
});
|
228 |
+
|
229 |
+
$twig->getExtension('core')->setEscaper('esc_html', function( \Twig_Environment $env, $string ) {
|
230 |
+
return esc_html( $string );
|
231 |
+
});
|
232 |
+
|
233 |
+
$twig->getExtension('core')->setEscaper('esc_js', function( \Twig_Environment $env, $string ) {
|
234 |
+
return esc_js( $string );
|
235 |
+
});
|
236 |
|
237 |
return $twig;
|
238 |
|
lib/URLHelper.php
CHANGED
@@ -10,10 +10,7 @@ class URLHelper {
|
|
10 |
* @return string
|
11 |
*/
|
12 |
public static function get_current_url() {
|
13 |
-
$pageURL = "
|
14 |
-
if ( isset($_SERVER['HTTPS']) && $_SERVER["HTTPS"] == "on" ) {
|
15 |
-
$pageURL = "https://"; ;
|
16 |
-
}
|
17 |
if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
|
18 |
$pageURL .= self::get_host().":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
|
19 |
} else {
|
@@ -22,6 +19,17 @@ class URLHelper {
|
|
22 |
return $pageURL;
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
*
|
27 |
*
|
10 |
* @return string
|
11 |
*/
|
12 |
public static function get_current_url() {
|
13 |
+
$pageURL = self::get_scheme()."://";
|
|
|
|
|
|
|
14 |
if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
|
15 |
$pageURL .= self::get_host().":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
|
16 |
} else {
|
19 |
return $pageURL;
|
20 |
}
|
21 |
|
22 |
+
/**
|
23 |
+
*
|
24 |
+
* Get url scheme
|
25 |
+
* @return string
|
26 |
+
*/
|
27 |
+
public static function get_scheme()
|
28 |
+
{
|
29 |
+
return isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
30 |
+
}
|
31 |
+
|
32 |
+
|
33 |
/**
|
34 |
*
|
35 |
*
|
lib/User.php
CHANGED
@@ -10,11 +10,11 @@ use Timber\URLHelper;
|
|
10 |
use Timber\Image;
|
11 |
|
12 |
/**
|
13 |
-
* This is used in Timber to represent users retrived from WordPress. You can call `$my_user = new
|
14 |
* @example
|
15 |
* ```php
|
16 |
-
* $context['current_user'] = new
|
17 |
-
* $context['post'] = new
|
18 |
* Timber::render('single.twig', $context);
|
19 |
* ```
|
20 |
* ```twig
|
@@ -203,7 +203,7 @@ class User extends Core implements CoreInterface {
|
|
203 |
* @return string the human-friendly name of the user (ex: "Buster Bluth")
|
204 |
*/
|
205 |
public function name() {
|
206 |
-
return $this->display_name;
|
207 |
}
|
208 |
|
209 |
/**
|
10 |
use Timber\Image;
|
11 |
|
12 |
/**
|
13 |
+
* This is used in Timber to represent users retrived from WordPress. You can call `$my_user = new Timber\User(123);` directly, or access it through the `{{ post.author }}` method.
|
14 |
* @example
|
15 |
* ```php
|
16 |
+
* $context['current_user'] = new Timber\User();
|
17 |
+
* $context['post'] = new Timber\Post();
|
18 |
* Timber::render('single.twig', $context);
|
19 |
* ```
|
20 |
* ```twig
|
203 |
* @return string the human-friendly name of the user (ex: "Buster Bluth")
|
204 |
*/
|
205 |
public function name() {
|
206 |
+
return apply_filters('timber/user/name', $this->display_name, $this);
|
207 |
}
|
208 |
|
209 |
/**
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: jarednova, connorjburton, lggorman
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
-
Stable tag: 1.1.
|
6 |
-
Tested up to: 4.
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -41,6 +41,25 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
41 |
|
42 |
== Changelog ==
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
= 1.1.1 =
|
45 |
* Fixed 301 redirects for pagination (thanks @xavivars)
|
46 |
* Added new escaping filter options for `|e('wp_kses_post')` and `|e('esc_url')`(thanks @matgargano)
|
2 |
Contributors: jarednova, connorjburton, lggorman
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
+
Stable tag: 1.1.4
|
6 |
+
Tested up to: 4.6
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
41 |
|
42 |
== Changelog ==
|
43 |
|
44 |
+
= 1.1.4 =
|
45 |
+
* Native support for Co-Authors Plus! just use `{{ post.authors }}` 939331e282fd54bf3e210645964504304f2b071b
|
46 |
+
* New filter to enable PW propmpt for PW protected posts (`timber/post/content/show_password_form_for_protected`) 0f9b20ec90b34059634c25bc27671875c18f8fcb
|
47 |
+
* New filter for custom loaders (`timber/loader/custom`) (thanks @tnottu!) 9097984a7c3df23068056d7835465e0690338567
|
48 |
+
* Fixed some updating bugs with 4.6 (thanks @daronspence) 16b8bd71571be71b298e6306abe2cd4b95d8c9e8
|
49 |
+
* You can now count Query results (thanks Evan Mattson) 141624a0ac18d9dcce62a2a681134009a2b79814
|
50 |
+
|
51 |
+
= 1.1.3 =
|
52 |
+
* New escapers! (thanks @matgargano) c7e8ed34da6fcd13bdc9005c04045f3a6b33595b
|
53 |
+
* Fix to how categories work in Timber::get_posts 49f6007db3f829097f82ed41d389dd39053fb84a
|
54 |
+
* Fix to usage of class maps in Timber::get_posts (thanks @vilpersson) b1387e443850aa021a0a70203bc20d238d4b21cb
|
55 |
+
* Added Post::password_required method (thanks @marclarr) 2e685ce3d05c50e879817e51256202e032e77122
|
56 |
+
* You can filter the link markup for Post::get_preview (thanks @LiljebergXYZ) b8100d7f2601b4da40bcc0a873c071b6ecf267f1
|
57 |
+
|
58 |
+
= 1.1.2 =
|
59 |
+
* Fix to how post IDs are retrieved (thanks @lggorman) 798acd90ee603de2d009828127bdeaab503beb10
|
60 |
+
* Fixes to pagination in search (@jarednova) 1d1ab67f124b02d8c60646f7b133abdf68cedc38
|
61 |
+
* Fixes to hooks for Timber Debug Bar (@jarednova) 82a914ec0be5be1011a15c1584c2c8e2999f1c1c
|
62 |
+
|
63 |
= 1.1.1 =
|
64 |
* Fixed 301 redirects for pagination (thanks @xavivars)
|
65 |
* Added new escaping filter options for `|e('wp_kses_post')` and `|e('esc_url')`(thanks @matgargano)
|
timber.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Timber
|
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power Twig templates.
|
5 |
Plugin URI: http://timber.upstatement.com
|
6 |
Author: Jared Novack + Upstatement
|
7 |
-
Version: 1.1.
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
// we look for Composer files first in the plugins dir.
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power Twig templates.
|
5 |
Plugin URI: http://timber.upstatement.com
|
6 |
Author: Jared Novack + Upstatement
|
7 |
+
Version: 1.1.4
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
// we look for Composer files first in the plugins dir.
|
vendor/asm89/twig-cache-extension/README.md
CHANGED
@@ -40,6 +40,33 @@ $cacheExtension = new CacheExtension($cacheStrategy);
|
|
40 |
$twig->addExtension($cacheExtension);
|
41 |
```
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
### Usage
|
44 |
|
45 |
To cache a part of a template in Twig surround the code with a `cache` block.
|
40 |
$twig->addExtension($cacheExtension);
|
41 |
```
|
42 |
|
43 |
+
### Want to use a PSR-6 cache pool?
|
44 |
+
|
45 |
+
Instead of using the default `DoctrineCacheAdapter` the extension also has
|
46 |
+
a `PSR-6` compatible adapter. You need to instantiate one of the cache pool
|
47 |
+
implementations as can be found on: http://php-cache.readthedocs.io/en/latest/
|
48 |
+
|
49 |
+
Example: Making use of the `ApcuCachePool` via the `PsrCacheAdapter`:
|
50 |
+
|
51 |
+
```bash
|
52 |
+
composer require cache/apcu-adapter
|
53 |
+
```
|
54 |
+
|
55 |
+
```php
|
56 |
+
<?php
|
57 |
+
|
58 |
+
use Asm89\Twig\CacheExtension\CacheProvider\PsrCacheAdapter;
|
59 |
+
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
60 |
+
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
61 |
+
use Cache\Adapter\Apcu\ApcuCachePool();
|
62 |
+
|
63 |
+
$cacheProvider = new PsrCacheAdapter(new ApcuCachePool());
|
64 |
+
$cacheStrategy = new LifetimeCacheStrategy($cacheProvider);
|
65 |
+
$cacheExtension = new CacheExtension($cacheStrategy);
|
66 |
+
|
67 |
+
$twig->addExtension($cacheExtension);
|
68 |
+
```
|
69 |
+
|
70 |
### Usage
|
71 |
|
72 |
To cache a part of a template in Twig surround the code with a `cache` block.
|
vendor/asm89/twig-cache-extension/composer.json
CHANGED
@@ -18,6 +18,9 @@
|
|
18 |
"require-dev": {
|
19 |
"doctrine/cache": "~1.0"
|
20 |
},
|
|
|
|
|
|
|
21 |
"autoload": {
|
22 |
"psr-4": {
|
23 |
"": "lib/"
|
@@ -30,7 +33,7 @@
|
|
30 |
},
|
31 |
"extra": {
|
32 |
"branch-alias": {
|
33 |
-
"dev-master": "1.
|
34 |
}
|
35 |
}
|
36 |
}
|
18 |
"require-dev": {
|
19 |
"doctrine/cache": "~1.0"
|
20 |
},
|
21 |
+
"suggest": {
|
22 |
+
"psr/cache-implementation": "To make use of PSR-6 cache implementation via PsrCacheAdapter."
|
23 |
+
},
|
24 |
"autoload": {
|
25 |
"psr-4": {
|
26 |
"": "lib/"
|
33 |
},
|
34 |
"extra": {
|
35 |
"branch-alias": {
|
36 |
+
"dev-master": "1.2-dev"
|
37 |
}
|
38 |
}
|
39 |
}
|
vendor/asm89/twig-cache-extension/lib/Asm89/Twig/CacheExtension/CacheProvider/PsrCacheAdapter.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of twig-cache-extension.
|
5 |
+
*
|
6 |
+
* (c) Alexander <iam.asm89@gmail.com>
|
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 |
+
namespace Asm89\Twig\CacheExtension\CacheProvider;
|
13 |
+
|
14 |
+
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
15 |
+
use Psr\Cache\CacheItemPoolInterface;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Adapter class to make extension interoperable with every PSR-6 adapter.
|
19 |
+
*
|
20 |
+
* @see http://php-cache.readthedocs.io/
|
21 |
+
*
|
22 |
+
* @author Rvanlaak <rvanlaak@gmail.com>
|
23 |
+
*/
|
24 |
+
class PsrCacheAdapter implements CacheProviderInterface
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* @var CacheItemPoolInterface
|
28 |
+
*/
|
29 |
+
private $cache;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param CacheItemPoolInterface $cache
|
33 |
+
*/
|
34 |
+
public function __construct(CacheItemPoolInterface $cache)
|
35 |
+
{
|
36 |
+
$this->cache = $cache;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param string $key
|
41 |
+
* @return mixed|false
|
42 |
+
*/
|
43 |
+
public function fetch($key)
|
44 |
+
{
|
45 |
+
// PSR-6 implementation returns null, CacheProviderInterface expects false
|
46 |
+
$item = $this->cache->getItem($key);
|
47 |
+
if ($item->isHit()) {
|
48 |
+
return $item->get();
|
49 |
+
}
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @param string $key
|
55 |
+
* @param string $value
|
56 |
+
* @param int|\DateInterval $lifetime
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
+
public function save($key, $value, $lifetime = 0)
|
60 |
+
{
|
61 |
+
$item = $this->cache->getItem($key);
|
62 |
+
$item->set($value);
|
63 |
+
$item->expiresAfter($lifetime);
|
64 |
+
|
65 |
+
return $this->cache->save($item);
|
66 |
+
}
|
67 |
+
|
68 |
+
}
|
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 ComposerAutoloaderInit6fd1e70a55055dbbade2a373bb243cbf::getLoader();
|
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 ComposerAutoloaderInit6db8cd96031eb5111a748582779e5b56
|
|
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) {
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit6fd1e70a55055dbbade2a373bb243cbf
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit6fd1e70a55055dbbade2a373bb243cbf', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit6fd1e70a55055dbbade2a373bb243cbf', 'loadClassLoader'));
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
vendor/composer/installed.json
CHANGED
@@ -168,17 +168,17 @@
|
|
168 |
},
|
169 |
{
|
170 |
"name": "asm89/twig-cache-extension",
|
171 |
-
"version": "1.
|
172 |
-
"version_normalized": "1.
|
173 |
"source": {
|
174 |
"type": "git",
|
175 |
"url": "https://github.com/asm89/twig-cache-extension.git",
|
176 |
-
"reference": "
|
177 |
},
|
178 |
"dist": {
|
179 |
"type": "zip",
|
180 |
-
"url": "https://api.github.com/repos/asm89/twig-cache-extension/zipball/
|
181 |
-
"reference": "
|
182 |
"shasum": ""
|
183 |
},
|
184 |
"require": {
|
@@ -188,11 +188,14 @@
|
|
188 |
"require-dev": {
|
189 |
"doctrine/cache": "~1.0"
|
190 |
},
|
191 |
-
"
|
|
|
|
|
|
|
192 |
"type": "library",
|
193 |
"extra": {
|
194 |
"branch-alias": {
|
195 |
-
"dev-master": "1.
|
196 |
}
|
197 |
},
|
198 |
"installation-source": "dist",
|
168 |
},
|
169 |
{
|
170 |
"name": "asm89/twig-cache-extension",
|
171 |
+
"version": "1.3.0",
|
172 |
+
"version_normalized": "1.3.0.0",
|
173 |
"source": {
|
174 |
"type": "git",
|
175 |
"url": "https://github.com/asm89/twig-cache-extension.git",
|
176 |
+
"reference": "37cfee1f06fe8372cbe714d2d9224db276790936"
|
177 |
},
|
178 |
"dist": {
|
179 |
"type": "zip",
|
180 |
+
"url": "https://api.github.com/repos/asm89/twig-cache-extension/zipball/37cfee1f06fe8372cbe714d2d9224db276790936",
|
181 |
+
"reference": "37cfee1f06fe8372cbe714d2d9224db276790936",
|
182 |
"shasum": ""
|
183 |
},
|
184 |
"require": {
|
188 |
"require-dev": {
|
189 |
"doctrine/cache": "~1.0"
|
190 |
},
|
191 |
+
"suggest": {
|
192 |
+
"psr/cache-implementation": "To make use of PSR-6 cache implementation via PsrCacheAdapter."
|
193 |
+
},
|
194 |
+
"time": "2016-06-14 09:16:57",
|
195 |
"type": "library",
|
196 |
"extra": {
|
197 |
"branch-alias": {
|
198 |
+
"dev-master": "1.2-dev"
|
199 |
}
|
200 |
},
|
201 |
"installation-source": "dist",
|