Version Description
Download this release
Release Info
Developer | lggorman |
Plugin | Timber |
Version | 0.22.6 |
Comparing to | |
See all releases |
Code changes from version 1.0.2 to 0.22.6
- README.md +21 -29
- init.php +0 -6
- lib/Admin.php +0 -70
- lib/Core.php +0 -118
- lib/FunctionWrapper.php +0 -98
- lib/Image/Operation/Retina.php +0 -80
- lib/Integrations.php +0 -29
- lib/Integrations/ACF.php +0 -60
- lib/Integrations/Command.php +0 -40
- lib/Integrations/Timber_WP_CLI_Command.php +0 -62
- lib/PostGetter.php +0 -131
- lib/PostsCollection.php +0 -100
- lib/QueryIterator.php +0 -162
- lib/Twig.php +0 -324
- lib/{Cache → cache}/KeyGenerator.php +0 -0
- lib/{Cache → cache}/TimberKeyGeneratorInterface.php +0 -0
- lib/{Cache → cache}/WPObjectCacheAdapter.php +6 -6
- lib/{Image/Operation/Letterbox.php → image/timber-image-operation-letterbox.php} +25 -31
- lib/{Image/Operation/Resize.php → image/timber-image-operation-resize.php} +35 -44
- lib/image/timber-image-operation-retina.php +74 -0
- lib/{Image/Operation/ToJpg.php → image/timber-image-operation-tojpg.php} +15 -19
- lib/{Image/Operation.php → image/timber-image-operation.php} +9 -13
- lib/integrations/acf-timber.php +58 -0
- lib/integrations/timber-command.php +36 -0
- lib/integrations/wpcli-timber.php +57 -0
- lib/timber-admin.php +67 -0
- lib/{Archives.php → timber-archives.php} +25 -34
- lib/{Comment.php → timber-comment.php} +49 -56
- lib/{CoreInterface.php → timber-core-interface.php} +1 -3
- lib/timber-core.php +117 -0
- lib/timber-function-wrapper.php +92 -0
- lib/{Helper.php → timber-helper.php} +239 -110
- lib/{ImageHelper.php → timber-image-helper.php} +94 -106
- lib/{Image.php → timber-image.php} +96 -76
- lib/timber-integrations.php +24 -0
- lib/{Loader.php → timber-loader.php} +95 -97
- lib/{MenuItem.php → timber-menu-item.php} +60 -59
- lib/{Menu.php → timber-menu.php} +38 -43
- lib/timber-page.php +9 -0
- lib/timber-post-getter.php +104 -0
- lib/{Post.php → timber-post.php} +681 -782
- lib/timber-posts-collection.php +97 -0
- lib/timber-query-iterator.php +156 -0
- lib/{Request.php → timber-request.php} +1 -8
- lib/timber-routes.php +33 -0
- lib/{Site.php → timber-site.php} +51 -60
- lib/{TermGetter.php → timber-term-getter.php} +17 -22
- lib/{Term.php → timber-term.php} +55 -41
- lib/{Theme.php → timber-theme.php} +8 -14
- lib/timber-twig.php +347 -0
- lib/{URLHelper.php → timber-url-helper.php} +89 -60
- lib/{User.php → timber-user.php} +43 -26
- lib/{Timber.php → timber.php} +138 -142
- readme.txt +12 -40
- timber-starter-theme/single.php +1 -0
- timber-starter-theme/templates/base.twig +1 -1
- timber-starter-theme/templates/single.twig +1 -3
- timber.php +14 -7
- vendor/autoload.php +1 -1
- vendor/composer/autoload_classmap.php +40 -0
- vendor/composer/autoload_files.php +0 -10
- vendor/composer/autoload_psr4.php +0 -1
- vendor/composer/autoload_real.php +3 -17
- vendor/composer/installed.json +6 -6
- vendor/composer/installers/README.md +0 -1
- vendor/composer/installers/src/Composer/Installers/Installer.php +0 -1
- vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +0 -16
- vendor/composer/installers/tests/Composer/Installers/Test/InstallerTest.php +0 -2
README.md
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
<div style="text-align:center">
|
2 |
-
<a href="http://
|
3 |
<div>
|
4 |
-
By Jared Novack (<a href="
|
5 |
</div>
|
6 |
|
7 |
-
[![Build Status](https://img.shields.io/travis/
|
8 |
-
[![Coverage Status](https://img.shields.io/coveralls/
|
9 |
[![Dependency Status](https://img.shields.io/versioneye/d/ruby/rails.svg?style=flat-square)](https://www.versioneye.com/user/projects/54e3c717d1ec5734f4000099)
|
10 |
-
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/
|
11 |
-
[![Latest Stable Version](https://img.shields.io/packagist/v/
|
12 |
[![WordPress Download Count](https://img.shields.io/wordpress/plugin/dt/timber-library.svg?style=flat-square)](https://wordpress.org/plugins/timber-library/)
|
13 |
-
[![HHVM Status](https://img.shields.io/hhvm/
|
14 |
-
[![Join the chat at https://gitter.im/
|
15 |
|
16 |
|
17 |
### Because WordPress is awesome, but the_loop isn't
|
@@ -35,28 +35,23 @@ This is what Timber's `.twig` files look like:
|
|
35 |
Once Timber is installed and activated in your plugin directory, it gives any WordPress theme the ability to take advantage of the power of Twig and other Timber features.
|
36 |
|
37 |
### Looking for docs?
|
38 |
-
* [Timber Documentation](https://github.com/
|
39 |
* [Twig Reference](http://twig.sensiolabs.org/doc/templates.html)
|
40 |
-
* [Video Tutorials](https://github.com/
|
41 |
-
* [Overview / Getting Started Guide](https://github.com/
|
42 |
|
43 |
* * *
|
44 |
|
45 |
### Installation
|
46 |
|
47 |
-
The GitHub version of Timber requires [Composer](https://getcomposer.org/download/). If you'd prefer one-click installation, you should use the [WordPress.org](
|
48 |
|
49 |
```shell
|
50 |
-
composer
|
51 |
```
|
52 |
|
53 |
-
|
54 |
|
55 |
-
```php
|
56 |
-
require_once(__DIR__ . '/vendor/autoload.php');
|
57 |
-
```
|
58 |
-
|
59 |
-
At the top of your `functions.php` file.
|
60 |
* * *
|
61 |
|
62 |
### Mission Statement
|
@@ -72,30 +67,27 @@ Nothing. Timber is meant for you to build a theme on. Like the [Starkers](https:
|
|
72 |
Timber is great for any WordPress developer who cares about writing good, maintainable code. It helps teams of designers and developers working together. At [Upstatement](http://upstatement.com) we made Timber because while our entire team needs to participate in building WordPress sites, not everyone knows the ins-and-outs of the_loop(), codex and PHP (nor should they). With Timber your best WordPress dev can focus on building the .php files with requests from WordPress and pass the data into .twig files. Once there, designers can easily mark-up data and build out a site's look-and-feel.
|
73 |
|
74 |
#### Related Projects
|
75 |
-
* [**Timber Starter Theme**](https://github.com/timber
|
76 |
-
* [**Timber Debug Bar**](https://github.com/
|
77 |
* [**TimberPhoton**](https://github.com/slimndap/TimberPhoton) Plug-in to use JetPack's free Photon image manipulation and CDN with Timber.
|
78 |
-
* [**Timber
|
79 |
-
* [**Timber Sugar**](https://github.com/timber/sugar) A catch-all for goodies to use w Timber.
|
80 |
-
* [**Timmy**](https://github.com/MINDKomm/Timmy) Advanced image manipulation for Timber.
|
81 |
* [**Twig**](https://github.com/fabpot/Twig) The template language used by Timber.
|
82 |
|
83 |
#### Projects that use Timber
|
84 |
* [**Gantry5**](https://wordpress.org/plugins/gantry5/) a framework for theme development
|
85 |
|
86 |
#### Helpful Links
|
87 |
-
* [**CSS Tricks**](https://css-tricks.com/timber-and-twig-reignited-my-love-for-wordpress/) introduction to Timber
|
88 |
-
* [**Twig for Timber Cheatsheet**](http://notlaura.com/the-twig-for-timber-cheatsheet/) by
|
89 |
-
* [**TutsPlus**](http://code.tutsplus.com/articles/kick-start-wordpress-development-with-twig-introduction--cms-24781) A guide to getting started by [@ahmadawais](https://github.com/ahmadawais)
|
90 |
|
91 |
#### Support
|
92 |
Please post on [StackOverflow under the "Timber" tag](http://stackoverflow.com/questions/tagged/timber). Please use GitHub issues only for specific bugs, feature requests and other types of issues.
|
93 |
|
94 |
#### Should I use it?
|
95 |
-
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://
|
96 |
|
97 |
#### Contributing
|
98 |
-
Read the [contributor guidelines](https://github.com/
|
99 |
|
100 |
|
101 |
|
1 |
<div style="text-align:center">
|
2 |
+
<a href="http://jarednova.github.com/timber"><img src="http://i.imgur.com/oM1AHrz.jpg" style="display:block; margin:auto; width:100%; max-width:100%"/></a>
|
3 |
<div>
|
4 |
+
By Jared Novack (<a href="http://twitter.com/jarednova">@JaredNova</a>) and <a href="http://upstatement.com">Upstatement</a> (<a href="http://twitter.com/upstatement">@Upstatement</a>)</div>
|
5 |
</div>
|
6 |
|
7 |
+
[![Build Status](https://img.shields.io/travis/jarednova/timber/master.svg?style=flat-square)](https://travis-ci.org/jarednova/timber)
|
8 |
+
[![Coverage Status](https://img.shields.io/coveralls/jarednova/timber.svg?style=flat-square)](https://coveralls.io/r/jarednova/timber?branch=master)
|
9 |
[![Dependency Status](https://img.shields.io/versioneye/d/ruby/rails.svg?style=flat-square)](https://www.versioneye.com/user/projects/54e3c717d1ec5734f4000099)
|
10 |
+
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/jarednova/timber.svg?style=flat-square)](https://scrutinizer-ci.com/g/jarednova/timber/?branch=master)
|
11 |
+
[![Latest Stable Version](https://img.shields.io/packagist/v/jarednova/timber.svg?style=flat-square)](https://packagist.org/packages/jarednova/timber)
|
12 |
[![WordPress Download Count](https://img.shields.io/wordpress/plugin/dt/timber-library.svg?style=flat-square)](https://wordpress.org/plugins/timber-library/)
|
13 |
+
[![HHVM Status](https://img.shields.io/hhvm/jarednova/timber.svg?style=flat-square)](http://hhvm.h4cc.de/package/jarednova/timber)
|
14 |
+
[![Join the chat at https://gitter.im/jarednova/timber](https://img.shields.io/gitter/room/jarednova/timber.svg?style=flat-square)](https://gitter.im/jarednova/timber?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
15 |
|
16 |
|
17 |
### Because WordPress is awesome, but the_loop isn't
|
35 |
Once Timber is installed and activated in your plugin directory, it gives any WordPress theme the ability to take advantage of the power of Twig and other Timber features.
|
36 |
|
37 |
### Looking for docs?
|
38 |
+
* [Timber Documentation](https://github.com/jarednova/timber/wiki/)
|
39 |
* [Twig Reference](http://twig.sensiolabs.org/doc/templates.html)
|
40 |
+
* [Video Tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)
|
41 |
+
* [Overview / Getting Started Guide](https://github.com/jarednova/timber/wiki/getting-started)
|
42 |
|
43 |
* * *
|
44 |
|
45 |
### Installation
|
46 |
|
47 |
+
The GitHub version of Timber requires [Composer](https://getcomposer.org/download/). If you'd prefer one-click installation, you should use the [WordPress.org](http://wordpress.org/plugins/timber-library/) version.
|
48 |
|
49 |
```shell
|
50 |
+
composer create-project --no-dev jarednova/timber ~/MYSITE/wp-content/plugins/timber
|
51 |
```
|
52 |
|
53 |
+
Once this is complete, activate Timber your WordPress admin. If you're looking for a 'blank' theme to start developing with, download the [timber-starter-theme](https://github.com/upstatement/timber-starter-theme) into your themes directory.
|
54 |
|
|
|
|
|
|
|
|
|
|
|
55 |
* * *
|
56 |
|
57 |
### Mission Statement
|
67 |
Timber is great for any WordPress developer who cares about writing good, maintainable code. It helps teams of designers and developers working together. At [Upstatement](http://upstatement.com) we made Timber because while our entire team needs to participate in building WordPress sites, not everyone knows the ins-and-outs of the_loop(), codex and PHP (nor should they). With Timber your best WordPress dev can focus on building the .php files with requests from WordPress and pass the data into .twig files. Once there, designers can easily mark-up data and build out a site's look-and-feel.
|
68 |
|
69 |
#### Related Projects
|
70 |
+
* [**Timber Starter Theme**](https://github.com/upstatement/timber-starter-theme) The "_s" of Timber to give you an easy start to the most basic theme you can build upon and customize.
|
71 |
+
* [**Timber Debug Bar**](https://github.com/upstatement/debug-bar-timber) Adds a debug bar panel that will show you which template is in-use and the data sent to your twig file.
|
72 |
* [**TimberPhoton**](https://github.com/slimndap/TimberPhoton) Plug-in to use JetPack's free Photon image manipulation and CDN with Timber.
|
73 |
+
* [**Timber Sugar**](https://github.com/Upstatement/timber-sugar) A catch-all for goodies to use w Timber.
|
|
|
|
|
74 |
* [**Twig**](https://github.com/fabpot/Twig) The template language used by Timber.
|
75 |
|
76 |
#### Projects that use Timber
|
77 |
* [**Gantry5**](https://wordpress.org/plugins/gantry5/) a framework for theme development
|
78 |
|
79 |
#### Helpful Links
|
80 |
+
* [**CSS Tricks**](https://css-tricks.com/timber-and-twig-reignited-my-love-for-wordpress/) introduction to Timber
|
81 |
+
* [**Twig for Timber Cheatsheet**](http://notlaura.com/the-twig-for-timber-cheatsheet/) by @laras126
|
|
|
82 |
|
83 |
#### Support
|
84 |
Please post on [StackOverflow under the "Timber" tag](http://stackoverflow.com/questions/tagged/timber). Please use GitHub issues only for specific bugs, feature requests and other types of issues.
|
85 |
|
86 |
#### Should I use it?
|
87 |
+
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.
|
88 |
|
89 |
#### Contributing
|
90 |
+
Read the [contributor guidelines](https://github.com/jarednova/timber/wiki#contributing) in the wiki.
|
91 |
|
92 |
|
93 |
|
init.php
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
use Timber\Timber;
|
4 |
-
|
5 |
-
$timber = new Timber();
|
6 |
-
Timber::$dirname = 'views';
|
|
|
|
|
|
|
|
|
|
|
|
lib/Admin.php
DELETED
@@ -1,70 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
class Admin {
|
6 |
-
|
7 |
-
public static function init() {
|
8 |
-
$filter = add_filter('plugin_row_meta', array( __CLASS__, 'meta_links' ), 10, 2);
|
9 |
-
$action = add_action('in_plugin_update_message-timber-library/timber.php', array( __CLASS__, 'in_plugin_update_message'), 10, 2);
|
10 |
-
$action = add_action('in_plugin_update_message-timber/timber.php', array( __CLASS__, 'in_plugin_update_message'), 10, 2);
|
11 |
-
if ($filter && $action) {
|
12 |
-
return true;
|
13 |
-
}
|
14 |
-
}
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @param array $links
|
18 |
-
* @param string $file
|
19 |
-
* @return array
|
20 |
-
*/
|
21 |
-
public static function meta_links( $links, $file ) {
|
22 |
-
if ( strstr($file, '/timber.php') ) {
|
23 |
-
unset($links[2]);
|
24 |
-
$links[] = '<a href="/wp-admin/plugin-install.php?tab=plugin-information&plugin=timber-library&TB_iframe=true&width=600&height=550" class="thickbox" aria-label="More information about Timber" data-title="Timber">View details</a>';
|
25 |
-
$links[] = '<a href="http://upstatement.com/timber" target="_blank">Homepage</a>';
|
26 |
-
$links[] = '<a href="https://github.com/timber/timber/wiki" target="_blank">Documentation</a>';
|
27 |
-
$links[] = '<a href="https://github.com/timber/timber/wiki/getting-started" target="_blank">Starter Guide</a>';
|
28 |
-
$links[] = '<p><a href="https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip">Site not working on 1.0? Downgrade to version 0.22.6</a></p>';
|
29 |
-
return $links;
|
30 |
-
}
|
31 |
-
return $links;
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* in_plugin_update_message
|
36 |
-
*
|
37 |
-
* Displays an update message for plugin list screens.
|
38 |
-
* Shows only the version updates from the current until the newest version
|
39 |
-
*
|
40 |
-
* @type function
|
41 |
-
* @date 4/22/16
|
42 |
-
*
|
43 |
-
* @param {array} $plugin_data
|
44 |
-
* @param {object} $r
|
45 |
-
*/
|
46 |
-
public static function in_plugin_update_message( $plugin_data, $r ) {
|
47 |
-
$m = '';
|
48 |
-
|
49 |
-
if ( version_compare("1.0.0", $plugin_data->new_version) <= 0 ) {
|
50 |
-
//a version of 1.0.0 or greater is availalbe
|
51 |
-
$m .= '<p><b>Warning:</b> Timber 1.0 removed a number of features and methods. Before upgrading please test your theme on a local or staging site to ensure that your theme will work with the newest version.</p>
|
52 |
-
|
53 |
-
<p><strong>Is your theme in active development?</strong> That is, is someone actively in PHP files writing new code? If you answered "no", then <i>do not upgrade</i>. You will not benefit from Timber 1.0</p>';
|
54 |
-
|
55 |
-
$m .= '<p>Read the <strong><a href="https://github.com/timber/timber/wiki/1.0-Upgrade-Guide">Upgrade Guide</a></strong> for more information</p>';
|
56 |
-
|
57 |
-
$m .= "<p>You can also <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>upgrade to version 0.22.6</a></b> if you want to upgrade, but are unsure if you're ready for 1.0";
|
58 |
-
|
59 |
-
}
|
60 |
-
|
61 |
-
if ( version_compare("1.0.0", $plugin_data->Version) <= 0 ) {
|
62 |
-
$m .= "<p>Are you seeing errors since upgrading to 1.0? Download <b><a href='https://downloads.wordpress.org/plugin/timber-library.0.22.6.zip'>Version 0.22.6</a></b> to bring things back to stability.";
|
63 |
-
}
|
64 |
-
|
65 |
-
// show message
|
66 |
-
echo '<br />'.sprintf($m);
|
67 |
-
|
68 |
-
}
|
69 |
-
|
70 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Core.php
DELETED
@@ -1,118 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
abstract class Core {
|
6 |
-
|
7 |
-
public $id;
|
8 |
-
public $ID;
|
9 |
-
public $object_type;
|
10 |
-
|
11 |
-
/**
|
12 |
-
*
|
13 |
-
* @return boolean
|
14 |
-
*/
|
15 |
-
function __isset( $field ) {
|
16 |
-
if ( isset($this->$field) ) {
|
17 |
-
return $this->$field;
|
18 |
-
}
|
19 |
-
return false;
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* This is helpful for twig to return properties and methods see: https://github.com/fabpot/Twig/issues/2
|
24 |
-
* @return mixed
|
25 |
-
*/
|
26 |
-
function __call( $field, $args ) {
|
27 |
-
return $this->__get($field);
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* This is helpful for twig to return properties and methods see: https://github.com/fabpot/Twig/issues/2
|
32 |
-
*
|
33 |
-
* @return mixed
|
34 |
-
*/
|
35 |
-
function __get( $field ) {
|
36 |
-
if ( property_exists($this, $field) ) {
|
37 |
-
return $this->$field;
|
38 |
-
}
|
39 |
-
if ( method_exists($this, 'meta') && $meta_value = $this->meta($field) ) {
|
40 |
-
return $this->$field = $meta_value;
|
41 |
-
}
|
42 |
-
if ( method_exists($this, $field) ) {
|
43 |
-
return $this->$field = $this->$field();
|
44 |
-
}
|
45 |
-
return $this->$field = false;
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Takes an array or object and adds the properties to the parent object
|
50 |
-
* @example
|
51 |
-
* ```php
|
52 |
-
* $data = array('airplane' => '757-200', 'flight' => '5316');
|
53 |
-
* $post = new TimberPost()
|
54 |
-
* $post->import(data);
|
55 |
-
* echo $post->airplane; //757-200
|
56 |
-
* ```
|
57 |
-
* @param array|object $info an object or array you want to grab data from to attach to the Timber object
|
58 |
-
*/
|
59 |
-
function import( $info, $force = false ) {
|
60 |
-
if ( is_object($info) ) {
|
61 |
-
$info = get_object_vars($info);
|
62 |
-
}
|
63 |
-
if ( is_array($info) ) {
|
64 |
-
foreach ( $info as $key => $value ) {
|
65 |
-
if ( !empty($key) && $force ) {
|
66 |
-
$this->$key = $value;
|
67 |
-
} else if ( !empty($key) && !method_exists($this, $key) ) {
|
68 |
-
$this->$key = $value;
|
69 |
-
}
|
70 |
-
}
|
71 |
-
}
|
72 |
-
}
|
73 |
-
|
74 |
-
|
75 |
-
/**
|
76 |
-
* @ignore
|
77 |
-
* @param string $key
|
78 |
-
* @param mixed $value
|
79 |
-
*/
|
80 |
-
function update( $key, $value ) {
|
81 |
-
update_metadata($this->object_type, $this->ID, $key, $value);
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Can you edit this post/term/user? Well good for you. You're no better than me.
|
86 |
-
* @example
|
87 |
-
* ```twig
|
88 |
-
* {% if post.can_edit %}
|
89 |
-
* <a href="{{ post.edit_link }}">Edit</a>
|
90 |
-
* {% endif %}
|
91 |
-
* ```
|
92 |
-
* ```html
|
93 |
-
* <a href="http://example.org/wp-admin/edit.php?p=242">Edit</a>
|
94 |
-
* ```
|
95 |
-
* @return bool
|
96 |
-
*/
|
97 |
-
function can_edit() {
|
98 |
-
if ( !function_exists('current_user_can') ) {
|
99 |
-
return false;
|
100 |
-
}
|
101 |
-
if ( current_user_can('edit_post', $this->ID) ) {
|
102 |
-
return true;
|
103 |
-
}
|
104 |
-
return false;
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
*
|
109 |
-
*
|
110 |
-
* @return array
|
111 |
-
*/
|
112 |
-
function get_method_values() {
|
113 |
-
$ret = array();
|
114 |
-
$ret['can_edit'] = $this->can_edit();
|
115 |
-
return $ret;
|
116 |
-
}
|
117 |
-
|
118 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/FunctionWrapper.php
DELETED
@@ -1,98 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Helper;
|
6 |
-
|
7 |
-
class FunctionWrapper {
|
8 |
-
|
9 |
-
private $_class;
|
10 |
-
private $_function;
|
11 |
-
private $_args;
|
12 |
-
private $_use_ob;
|
13 |
-
|
14 |
-
public function __toString() {
|
15 |
-
try {
|
16 |
-
return (string) $this->call();
|
17 |
-
} catch ( \Exception $e ) {
|
18 |
-
return 'Caught exception: '.$e->getMessage()."\n";
|
19 |
-
}
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
*
|
24 |
-
*
|
25 |
-
* @param callable $function
|
26 |
-
* @param array $args
|
27 |
-
* @param bool $return_output_buffer
|
28 |
-
*/
|
29 |
-
public function __construct( $function, $args = array(), $return_output_buffer = false ) {
|
30 |
-
if ( is_array($function) ) {
|
31 |
-
if ( (is_string($function[0]) && class_exists($function[0])) || gettype($function[0]) === 'object' ) {
|
32 |
-
$this->_class = $function[0];
|
33 |
-
}
|
34 |
-
|
35 |
-
if ( is_string($function[1]) ) {
|
36 |
-
$this->_function = $function[1];
|
37 |
-
}
|
38 |
-
} else {
|
39 |
-
$this->_function = $function;
|
40 |
-
}
|
41 |
-
|
42 |
-
$this->_args = $args;
|
43 |
-
$this->_use_ob = $return_output_buffer;
|
44 |
-
|
45 |
-
add_filter('get_twig', array(&$this, 'add_to_twig'));
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
*
|
50 |
-
*
|
51 |
-
* @param Twig_Environment $twig
|
52 |
-
* @return Twig_Environment
|
53 |
-
*/
|
54 |
-
public function add_to_twig( $twig ) {
|
55 |
-
$wrapper = $this;
|
56 |
-
|
57 |
-
$twig->addFunction(new \Twig_SimpleFunction($this->_function, function() use ($wrapper) {
|
58 |
-
return call_user_func_array(array($wrapper, 'call'), func_get_args());
|
59 |
-
} ));
|
60 |
-
|
61 |
-
return $twig;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
*
|
66 |
-
*
|
67 |
-
* @return string
|
68 |
-
*/
|
69 |
-
public function call() {
|
70 |
-
$args = $this->_parse_args(func_get_args(), $this->_args);
|
71 |
-
$callable = (isset($this->_class)) ? array($this->_class, $this->_function) : $this->_function;
|
72 |
-
|
73 |
-
if ( $this->_use_ob ) {
|
74 |
-
return Helper::ob_function($callable, $args);
|
75 |
-
} else {
|
76 |
-
return call_user_func_array($callable, $args);
|
77 |
-
}
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
*
|
82 |
-
*
|
83 |
-
* @param array $args
|
84 |
-
* @param array $defaults
|
85 |
-
* @return array
|
86 |
-
*/
|
87 |
-
private function _parse_args( $args, $defaults ) {
|
88 |
-
$_arg = reset($defaults);
|
89 |
-
|
90 |
-
foreach ( $args as $index => $arg ) {
|
91 |
-
$defaults[$index] = is_null($arg) ? $_arg : $arg;
|
92 |
-
$_arg = next($defaults);
|
93 |
-
}
|
94 |
-
|
95 |
-
return $defaults;
|
96 |
-
}
|
97 |
-
|
98 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Image/Operation/Retina.php
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber\Image\Operation;
|
4 |
-
|
5 |
-
use Timber\Helper;
|
6 |
-
use Timber\Image\Operation as ImageOperation;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Contains the class for running image retina-izing operations
|
10 |
-
*/
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Increases image size by a given factor
|
14 |
-
* Arguments:
|
15 |
-
* - factor by which to multiply image dimensions
|
16 |
-
* @property float $factor the factor (ex: 2, 1.5, 1.75) to multiply dimension by
|
17 |
-
*/
|
18 |
-
class Retina extends ImageOperation {
|
19 |
-
|
20 |
-
private $factor;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Construct our operation
|
24 |
-
* @param float $factor to multiply original dimensions by
|
25 |
-
*/
|
26 |
-
function __construct( $factor ) {
|
27 |
-
$this->factor = $factor;
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Generates the final filename based on the source's name and extension
|
32 |
-
*
|
33 |
-
* @param string $src_filename the basename of the file (ex: my-awesome-pic)
|
34 |
-
* @param string $src_extension the extension (ex: .jpg)
|
35 |
-
* @return string the final filename to be used (ex: my-awesome-pic@2x.jpg)
|
36 |
-
*/
|
37 |
-
function filename( $src_filename, $src_extension ) {
|
38 |
-
$newbase = $src_filename.'@'.$this->factor.'x'; // add @2x, @3x, @1.5x, etc.
|
39 |
-
$new_name = $newbase.'.'.$src_extension;
|
40 |
-
return $new_name;
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Performs the actual image manipulation,
|
45 |
-
* including saving the target file.
|
46 |
-
*
|
47 |
-
* @param string $load_filename filepath (not URL) to source file
|
48 |
-
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
49 |
-
* @param string $save_filename filepath (not URL) where result file should be saved
|
50 |
-
* (ex: /src/var/www/wp-content/uploads/my-pic@2x.jpg)
|
51 |
-
* @return bool true if everything went fine, false otherwise
|
52 |
-
*/
|
53 |
-
function run( $load_filename, $save_filename ) {
|
54 |
-
$image = wp_get_image_editor($load_filename);
|
55 |
-
if ( !is_wp_error($image) ) {
|
56 |
-
$current_size = $image->get_size();
|
57 |
-
$src_w = $current_size['width'];
|
58 |
-
$src_h = $current_size['height'];
|
59 |
-
// Get ratios
|
60 |
-
$w = $src_w * $this->factor;
|
61 |
-
$h = $src_h * $this->factor;
|
62 |
-
$image->crop(0, 0, $src_w, $src_h, $w, $h);
|
63 |
-
$result = $image->save($save_filename);
|
64 |
-
if ( is_wp_error($result) ) {
|
65 |
-
// @codeCoverageIgnoreStart
|
66 |
-
Helper::error_log('Error resizing image');
|
67 |
-
Helper::error_log($result);
|
68 |
-
return false;
|
69 |
-
// @codeCoverageIgnoreEnd
|
70 |
-
} else {
|
71 |
-
return true;
|
72 |
-
}
|
73 |
-
} else if ( isset($image->error_data['error_loading_image']) ) {
|
74 |
-
Helper::error_log('Error loading '.$image->error_data['error_loading_image']);
|
75 |
-
} else {
|
76 |
-
Helper::error_log($image);
|
77 |
-
}
|
78 |
-
return false;
|
79 |
-
}
|
80 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Integrations.php
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Integrations\ACF;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* This is for integrating external plugins into timber
|
9 |
-
* @package timber
|
10 |
-
*/
|
11 |
-
class Integrations {
|
12 |
-
|
13 |
-
public static function init() {
|
14 |
-
|
15 |
-
add_action( 'init', array( __CLASS__, 'maybe_init_acftimber' ) );
|
16 |
-
|
17 |
-
if ( class_exists( 'WP_CLI_Command' ) ) {
|
18 |
-
\WP_CLI::add_command( 'timber', 'Timber\Integrations\Timber_WP_CLI_Command' );
|
19 |
-
}
|
20 |
-
}
|
21 |
-
|
22 |
-
public static function maybe_init_acftimber() {
|
23 |
-
|
24 |
-
if ( class_exists( 'ACF' ) ) {
|
25 |
-
new ACF();
|
26 |
-
}
|
27 |
-
|
28 |
-
}
|
29 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Integrations/ACF.php
DELETED
@@ -1,60 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber\Integrations;
|
4 |
-
|
5 |
-
class ACF {
|
6 |
-
|
7 |
-
function __construct() {
|
8 |
-
add_filter('timber_post_get_meta', array($this, 'post_get_meta'), 10, 2);
|
9 |
-
add_filter('timber_post_get_meta_field', array($this, 'post_get_meta_field'), 10, 3);
|
10 |
-
add_filter('timber_term_get_meta', array($this, 'term_get_meta'), 10, 3);
|
11 |
-
add_filter('timber_term_get_meta_field', array($this, 'term_get_meta_field'), 10, 4);
|
12 |
-
add_filter('timber_user_get_meta_field_pre', array($this, 'user_get_meta_field'), 10, 3);
|
13 |
-
add_filter('timber_term_set_meta', array($this, 'term_set_meta'), 10, 4);
|
14 |
-
}
|
15 |
-
|
16 |
-
function post_get_meta( $customs, $post_id ) {
|
17 |
-
return $customs;
|
18 |
-
}
|
19 |
-
|
20 |
-
function post_get_meta_field( $value, $post_id, $field_name ) {
|
21 |
-
return get_field($field_name, $post_id);
|
22 |
-
}
|
23 |
-
|
24 |
-
function term_get_meta_field( $value, $term_id, $field_name, $term ) {
|
25 |
-
$searcher = $term->taxonomy."_".$term->ID;
|
26 |
-
return get_field($field_name, $searcher);
|
27 |
-
}
|
28 |
-
|
29 |
-
function term_set_meta( $value, $field, $term_id, $term ) {
|
30 |
-
$searcher = $term->taxonomy."_".$term->ID;
|
31 |
-
update_field($field, $value, $searcher);
|
32 |
-
return $value;
|
33 |
-
}
|
34 |
-
|
35 |
-
function term_get_meta( $fields, $term_id, $term ) {
|
36 |
-
$searcher = $term->taxonomy."_".$term->ID; // save to a specific category
|
37 |
-
$fds = get_fields($searcher);
|
38 |
-
if ( is_array($fds) ) {
|
39 |
-
foreach ( $fds as $key => $value ) {
|
40 |
-
$key = preg_replace('/_/', '', $key, 1);
|
41 |
-
$key = str_replace($searcher, '', $key);
|
42 |
-
$key = preg_replace('/_/', '', $key, 1);
|
43 |
-
$field = get_field($key, $searcher);
|
44 |
-
$fields[$key] = $field;
|
45 |
-
}
|
46 |
-
$fields = array_merge($fields, $fds);
|
47 |
-
}
|
48 |
-
return $fields;
|
49 |
-
}
|
50 |
-
|
51 |
-
function user_get_meta( $fields, $user_id ) {
|
52 |
-
return $fields;
|
53 |
-
}
|
54 |
-
|
55 |
-
function user_get_meta_field( $value, $uid, $field ) {
|
56 |
-
return get_field($field, 'user_'.$uid);
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Integrations/Command.php
DELETED
@@ -1,40 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber\Integrations;
|
4 |
-
|
5 |
-
use Timber\Loader;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* These are methods that can be executed by WPCLI, other CLI mechanism or other external controllers
|
9 |
-
* @package timber
|
10 |
-
*/
|
11 |
-
class Command {
|
12 |
-
|
13 |
-
public static function clear_cache( $mode = 'all' ) {
|
14 |
-
if ( is_array($mode) ) {
|
15 |
-
$mode = reset($mode);
|
16 |
-
}
|
17 |
-
if ( $mode == 'all' ) {
|
18 |
-
$twig_cache = self::clear_cache_twig();
|
19 |
-
$timber_cache = self::clear_cache_timber();
|
20 |
-
if ( $twig_cache && $timber_cache ) {
|
21 |
-
return true;
|
22 |
-
}
|
23 |
-
} else if ( $mode == 'twig' ) {
|
24 |
-
return self::clear_cache_twig();
|
25 |
-
} else if ( $mode == 'timber' ) {
|
26 |
-
return self::clear_cache_timber();
|
27 |
-
}
|
28 |
-
}
|
29 |
-
|
30 |
-
static function clear_cache_timber() {
|
31 |
-
$loader = new Loader();
|
32 |
-
return $loader->clear_cache_timber();
|
33 |
-
}
|
34 |
-
|
35 |
-
static function clear_cache_twig() {
|
36 |
-
$loader = new Loader();
|
37 |
-
return $loader->clear_cache_twig();
|
38 |
-
}
|
39 |
-
|
40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Integrations/Timber_WP_CLI_Command.php
DELETED
@@ -1,62 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber\Integrations;
|
4 |
-
|
5 |
-
use Timber\Integrations\Command;
|
6 |
-
|
7 |
-
if ( !class_exists('WP_CLI_Command') ) {
|
8 |
-
return;
|
9 |
-
}
|
10 |
-
|
11 |
-
class Timber_WP_CLI_Command extends \WP_CLI_Command {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Clears Timber and Twig's Cache
|
15 |
-
*
|
16 |
-
* ## EXAMPLES
|
17 |
-
*
|
18 |
-
* wp timber clear_cache
|
19 |
-
*
|
20 |
-
*/
|
21 |
-
public function clear_cache( $mode = 'all' ) {
|
22 |
-
Command::clear_cache($mode);
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Clears Twig's Cache
|
27 |
-
*
|
28 |
-
* ## EXAMPLES
|
29 |
-
*
|
30 |
-
* wp timber clear_cache_twig
|
31 |
-
*
|
32 |
-
*/
|
33 |
-
function clear_cache_twig() {
|
34 |
-
$clear = Command::clear_cache_twig();
|
35 |
-
if ( $clear ) {
|
36 |
-
WP_CLI::success('Cleared contents of twig cache');
|
37 |
-
} else {
|
38 |
-
WP_CLI::warning('Failed to clear twig cache');
|
39 |
-
}
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Clears Timber's Cache
|
44 |
-
*
|
45 |
-
* ## EXAMPLES
|
46 |
-
*
|
47 |
-
* wp timber clear_cache_timber
|
48 |
-
*
|
49 |
-
*/
|
50 |
-
function clear_cache_timber() {
|
51 |
-
$clear = Command::clear_cache_timber();
|
52 |
-
$message = 'Failed to clear timber cache';
|
53 |
-
if ( $clear ) {
|
54 |
-
$message = "Cleared contents of Timber's Cache";
|
55 |
-
WP_CLI::success($message);
|
56 |
-
} else {
|
57 |
-
WP_CLI::warning($message);
|
58 |
-
}
|
59 |
-
return $message;
|
60 |
-
}
|
61 |
-
|
62 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/PostGetter.php
DELETED
@@ -1,131 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\PostsCollection;
|
6 |
-
use Timber\QueryIterator;
|
7 |
-
|
8 |
-
class PostGetter {
|
9 |
-
|
10 |
-
/**
|
11 |
-
* @param mixed $query
|
12 |
-
* @param string $PostClass
|
13 |
-
* @return array|bool|null
|
14 |
-
*/
|
15 |
-
static function get_post( $query = false, $PostClass = '\Timber\Post' ) {
|
16 |
-
$posts = self::get_posts($query, $PostClass);
|
17 |
-
if ( $post = reset($posts) ) {
|
18 |
-
return $post;
|
19 |
-
}
|
20 |
-
}
|
21 |
-
|
22 |
-
static function get_posts( $query = false, $PostClass = '\Timber\Post', $return_collection = false ) {
|
23 |
-
$posts = self::query_posts($query, $PostClass);
|
24 |
-
return apply_filters('timber_post_getter_get_posts', $posts->get_posts($return_collection));
|
25 |
-
}
|
26 |
-
|
27 |
-
static function query_post( $query = false, $PostClass = '\Timber\Post' ) {
|
28 |
-
$posts = self::query_posts($query, $PostClass);
|
29 |
-
if ( method_exists($posts, 'current') && $post = $posts->current() ) {
|
30 |
-
return $post;
|
31 |
-
}
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @param mixed $query
|
36 |
-
* @param string $PostClass
|
37 |
-
* @return array|bool|null
|
38 |
-
*/
|
39 |
-
static function query_posts( $query = false, $PostClass = '\Timber\Post' ) {
|
40 |
-
if ( $type = self::get_class_for_use_as_timber_post($query) ) {
|
41 |
-
$PostClass = $type;
|
42 |
-
if ( self::is_post_class_or_class_map($query) ) {
|
43 |
-
$query = false;
|
44 |
-
}
|
45 |
-
}
|
46 |
-
|
47 |
-
if ( is_object($query) && !is_a($query, 'WP_Query') ) {
|
48 |
-
// The only object other than a query is a type of post object
|
49 |
-
$query = array($query);
|
50 |
-
}
|
51 |
-
|
52 |
-
if ( is_array($query) && count($query) && isset($query[0]) && is_object($query[0]) ) {
|
53 |
-
// We have an array of post objects that already have data
|
54 |
-
return new PostsCollection($query, $PostClass);
|
55 |
-
} else {
|
56 |
-
// We have a query (of sorts) to work with
|
57 |
-
$tqi = new QueryIterator($query, $PostClass);
|
58 |
-
return $tqi;
|
59 |
-
}
|
60 |
-
}
|
61 |
-
|
62 |
-
static function get_pids( $query ) {
|
63 |
-
$posts = self::get_posts($query);
|
64 |
-
$pids = array();
|
65 |
-
foreach ( $posts as $post ) {
|
66 |
-
if ( isset($post->ID) ) {
|
67 |
-
$pids[] = $post->ID;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
return $pids;
|
71 |
-
}
|
72 |
-
|
73 |
-
static function loop_to_id() {
|
74 |
-
if ( !self::wp_query_has_posts() ) { return false; }
|
75 |
-
|
76 |
-
global $wp_query;
|
77 |
-
$post_num = property_exists($wp_query, 'current_post')
|
78 |
-
? $wp_query->current_post + 1
|
79 |
-
: 0
|
80 |
-
;
|
81 |
-
|
82 |
-
if ( !isset($wp_query->posts[$post_num]) ) { return false; }
|
83 |
-
|
84 |
-
return $wp_query->posts[$post_num]->ID;
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* @return bool
|
89 |
-
*/
|
90 |
-
static function wp_query_has_posts() {
|
91 |
-
global $wp_query;
|
92 |
-
return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* @param string|array $arg
|
97 |
-
* @return bool
|
98 |
-
*/
|
99 |
-
static function is_post_class_or_class_map( $arg ) {
|
100 |
-
$maybe_type = self::get_class_for_use_as_timber_post($arg);
|
101 |
-
if ( is_array($arg) && isset($arg['post_type']) ) {
|
102 |
-
//the user has passed a true WP_Query-style query array that needs to be used later, so the $arg is not a class map or post class
|
103 |
-
return false;
|
104 |
-
}
|
105 |
-
if ( $maybe_type ) {
|
106 |
-
return true;
|
107 |
-
}
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* @param string|array $arg
|
112 |
-
* @return string|bool if a $type is found; false if not
|
113 |
-
*/
|
114 |
-
static function get_class_for_use_as_timber_post( $arg ) {
|
115 |
-
$type = false;
|
116 |
-
|
117 |
-
if ( is_string($arg) ) {
|
118 |
-
$type = $arg;
|
119 |
-
} else if ( is_array($arg) && isset($arg['post_type']) ) {
|
120 |
-
$type = $arg['post_type'];
|
121 |
-
}
|
122 |
-
|
123 |
-
if ( !$type ) {
|
124 |
-
return false;
|
125 |
-
}
|
126 |
-
|
127 |
-
if ( !is_array($type) && class_exists($type) && is_subclass_of($type, '\Timber\Post') ) {
|
128 |
-
return $type;
|
129 |
-
}
|
130 |
-
}
|
131 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/PostsCollection.php
DELETED
@@ -1,100 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Helper;
|
6 |
-
use Timber\Post;
|
7 |
-
|
8 |
-
// Exit if accessed directly
|
9 |
-
if ( !defined('ABSPATH') )
|
10 |
-
exit;
|
11 |
-
|
12 |
-
class PostsCollection extends \ArrayObject {
|
13 |
-
|
14 |
-
public function __construct( $posts = array(), $post_class = '\Timber\Post' ) {
|
15 |
-
$returned_posts = array();
|
16 |
-
if ( is_null($posts) ) {
|
17 |
-
$posts = array();
|
18 |
-
}
|
19 |
-
foreach ( $posts as $post_object ) {
|
20 |
-
$post_class_use = $post_class;
|
21 |
-
if ( is_array($post_class) ) {
|
22 |
-
$post_type = get_post_type($post_object);
|
23 |
-
$post_class_use = '\Timber\Post';
|
24 |
-
|
25 |
-
if ( isset($post_class[$post_type]) ) {
|
26 |
-
$post_class_use = $post_class[$post_type];
|
27 |
-
|
28 |
-
} else {
|
29 |
-
if ( is_array($post_class) ) {
|
30 |
-
Helper::error_log($post_type.' of '.$post_object->ID.' not found in '.print_r($post_class, true));
|
31 |
-
} else {
|
32 |
-
Helper::error_log($post_type.' not found in '.$post_class);
|
33 |
-
}
|
34 |
-
}
|
35 |
-
}
|
36 |
-
// Don't create yet another object if $post_object is already of the right type
|
37 |
-
if ( is_a($post_object, $post_class_use) ) {
|
38 |
-
$post = $post_object;
|
39 |
-
} else {
|
40 |
-
$post = new $post_class_use($post_object);
|
41 |
-
}
|
42 |
-
|
43 |
-
if ( isset($post->ID) ) {
|
44 |
-
$returned_posts[] = $post;
|
45 |
-
}
|
46 |
-
}
|
47 |
-
|
48 |
-
$returned_posts = self::maybe_set_preview($returned_posts);
|
49 |
-
|
50 |
-
parent::__construct($returned_posts, $flags = 0, 'Timber\PostsIterator');
|
51 |
-
}
|
52 |
-
|
53 |
-
public function get_posts() {
|
54 |
-
return $this->getArrayCopy();
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* @param array $posts
|
59 |
-
* @return array
|
60 |
-
*/
|
61 |
-
static function maybe_set_preview( $posts ) {
|
62 |
-
if ( is_array($posts) && isset($_GET['preview']) && $_GET['preview']
|
63 |
-
&& isset($_GET['preview_id']) && $_GET['preview_id']
|
64 |
-
&& current_user_can('edit_post', $_GET['preview_id']) ) {
|
65 |
-
// No need to check the nonce, that already happened in _show_post_preview on init
|
66 |
-
|
67 |
-
$preview_id = $_GET['preview_id'];
|
68 |
-
foreach ( $posts as &$post ) {
|
69 |
-
if ( is_object($post) && $post->ID == $preview_id ) {
|
70 |
-
// Based on _set_preview( $post ), but adds import_custom
|
71 |
-
$preview = wp_get_post_autosave($preview_id);
|
72 |
-
if ( is_object($preview) ) {
|
73 |
-
|
74 |
-
$preview = sanitize_post($preview);
|
75 |
-
|
76 |
-
$post->post_content = $preview->post_content;
|
77 |
-
$post->post_title = $preview->post_title;
|
78 |
-
$post->post_excerpt = $preview->post_excerpt;
|
79 |
-
$post->import_custom($preview_id);
|
80 |
-
|
81 |
-
add_filter('get_the_terms', '_wp_preview_terms_filter', 10, 3);
|
82 |
-
}
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
}
|
87 |
-
|
88 |
-
return $posts;
|
89 |
-
}
|
90 |
-
|
91 |
-
}
|
92 |
-
|
93 |
-
class PostsIterator extends \ArrayIterator {
|
94 |
-
|
95 |
-
public function current() {
|
96 |
-
global $post;
|
97 |
-
$post = parent::current();
|
98 |
-
return $post;
|
99 |
-
}
|
100 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/QueryIterator.php
DELETED
@@ -1,162 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Helper;
|
6 |
-
use Timber\PostsCollection;
|
7 |
-
|
8 |
-
// Exit if accessed directly
|
9 |
-
if ( !defined('ABSPATH') )
|
10 |
-
exit;
|
11 |
-
|
12 |
-
class QueryIterator implements \Iterator {
|
13 |
-
|
14 |
-
/**
|
15 |
-
*
|
16 |
-
*
|
17 |
-
* @var WP_Query
|
18 |
-
*/
|
19 |
-
private $_query = null;
|
20 |
-
private $_posts_class = 'TimberPost';
|
21 |
-
|
22 |
-
public function __construct( $query = false, $posts_class = 'TimberPost' ) {
|
23 |
-
add_action('pre_get_posts', array($this, 'fix_number_posts_wp_quirk'));
|
24 |
-
if ( $posts_class )
|
25 |
-
$this->_posts_class = $posts_class;
|
26 |
-
|
27 |
-
if ( is_a($query, 'WP_Query') ) {
|
28 |
-
// We got a full-fledged WP Query, look no further!
|
29 |
-
$the_query = $query;
|
30 |
-
|
31 |
-
} elseif ( false === $query ) {
|
32 |
-
// If query is explicitly set to false, use the main loop
|
33 |
-
global $wp_query;
|
34 |
-
$the_query = & $wp_query;
|
35 |
-
//if we're on a custom posts page?
|
36 |
-
$the_query = self::handle_maybe_custom_posts_page($the_query);
|
37 |
-
} elseif ( Helper::is_array_assoc($query) || (is_string($query) && strstr($query, '=')) ) {
|
38 |
-
// We have a regularly formed WP query string or array to use
|
39 |
-
$the_query = new \WP_Query($query);
|
40 |
-
|
41 |
-
} elseif ( is_numeric($query) || is_string($query) ) {
|
42 |
-
// We have what could be a post name or post ID to pull out
|
43 |
-
$the_query = self::get_query_from_string($query);
|
44 |
-
|
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);
|
48 |
-
} elseif ( is_array($query) && empty($query) ) {
|
49 |
-
// it's an empty array
|
50 |
-
$the_query = array();
|
51 |
-
} else {
|
52 |
-
Helper::error_log('I have failed you! in '.basename(__FILE__).'::'.__LINE__);
|
53 |
-
Helper::error_log($query);
|
54 |
-
|
55 |
-
// We have failed hard, at least let get something.
|
56 |
-
$the_query = new \WP_Query();
|
57 |
-
}
|
58 |
-
|
59 |
-
$this->_query = $the_query;
|
60 |
-
|
61 |
-
}
|
62 |
-
|
63 |
-
public function get_posts( $return_collection = false ) {
|
64 |
-
if ( isset($this->_query->posts) ) {
|
65 |
-
$posts = new PostsCollection($this->_query->posts, $this->_posts_class);
|
66 |
-
return ($return_collection) ? $posts : $posts->get_posts();
|
67 |
-
}
|
68 |
-
}
|
69 |
-
|
70 |
-
//
|
71 |
-
// GET POSTS
|
72 |
-
//
|
73 |
-
public static function get_query_from_array_of_ids( $query = array() ) {
|
74 |
-
if ( !is_array($query) || !count($query) )
|
75 |
-
return null;
|
76 |
-
|
77 |
-
return new \WP_Query(array(
|
78 |
-
'post_type'=> 'any',
|
79 |
-
'ignore_sticky_posts' => true,
|
80 |
-
'post__in' => $query,
|
81 |
-
'orderby' => 'post__in',
|
82 |
-
'nopaging' => true
|
83 |
-
));
|
84 |
-
}
|
85 |
-
|
86 |
-
public static function get_query_from_string( $string = '' ) {
|
87 |
-
$post_type = false;
|
88 |
-
|
89 |
-
if ( is_string($string) && strstr($string, '#') ) {
|
90 |
-
//we have a post_type directive here
|
91 |
-
list($post_type, $string) = explode('#', $string);
|
92 |
-
}
|
93 |
-
|
94 |
-
$query = array(
|
95 |
-
'post_type' => ($post_type) ? $post_type : 'any'
|
96 |
-
);
|
97 |
-
|
98 |
-
if ( is_numeric($string) ) {
|
99 |
-
$query['p'] = $string;
|
100 |
-
|
101 |
-
} else {
|
102 |
-
$query['name'] = $string;
|
103 |
-
}
|
104 |
-
|
105 |
-
return new \WP_Query($query);
|
106 |
-
}
|
107 |
-
|
108 |
-
//
|
109 |
-
// Iterator Interface
|
110 |
-
//
|
111 |
-
|
112 |
-
public function valid() {
|
113 |
-
return $this->_query->have_posts();
|
114 |
-
}
|
115 |
-
|
116 |
-
public function current() {
|
117 |
-
global $post;
|
118 |
-
|
119 |
-
$this->_query->the_post();
|
120 |
-
|
121 |
-
// Sets up the global post, but also return the post, for use in Twig template
|
122 |
-
$posts_class = $this->_posts_class;
|
123 |
-
return new $posts_class($post);
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Don't implement next, because current already advances the loop
|
128 |
-
*/
|
129 |
-
final public function next() {}
|
130 |
-
|
131 |
-
public function rewind() {
|
132 |
-
$this->_query->rewind_posts();
|
133 |
-
}
|
134 |
-
|
135 |
-
public function key() {
|
136 |
-
$this->_query->current_post;
|
137 |
-
}
|
138 |
-
|
139 |
-
//get_posts users numberposts
|
140 |
-
static function fix_number_posts_wp_quirk( $query ) {
|
141 |
-
if ( isset($query->query) && isset($query->query['numberposts'])
|
142 |
-
&& !isset($query->query['posts_per_page']) ) {
|
143 |
-
$query->set('posts_per_page', $query->query['numberposts']);
|
144 |
-
}
|
145 |
-
return $query;
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* this will test for whether a custom page to display posts is active, and if so, set the query to the default
|
150 |
-
* @param WP_Query $query the original query recived from WordPress
|
151 |
-
* @return WP_Query
|
152 |
-
*/
|
153 |
-
static function handle_maybe_custom_posts_page( $query ) {
|
154 |
-
if ( $custom_posts_page = get_option('page_for_posts') ) {
|
155 |
-
if ( isset($query->query['p']) && $query->query['p'] == $custom_posts_page ) {
|
156 |
-
return new \WP_Query(array('post_type' => 'post'));
|
157 |
-
}
|
158 |
-
}
|
159 |
-
return $query;
|
160 |
-
}
|
161 |
-
|
162 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Twig.php
DELETED
@@ -1,324 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\URLHelper;
|
6 |
-
use Timber\Helper;
|
7 |
-
|
8 |
-
use Timber\Post;
|
9 |
-
use Timber\Term;
|
10 |
-
use Timber\Image;
|
11 |
-
use Timber\User;
|
12 |
-
|
13 |
-
class Twig {
|
14 |
-
|
15 |
-
public static $dir_name;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @codeCoverageIgnore
|
19 |
-
*/
|
20 |
-
public static function init() {
|
21 |
-
new self();
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @codeCoverageIgnore
|
26 |
-
*/
|
27 |
-
function __construct() {
|
28 |
-
add_action('timber/twig/filters', array($this, 'add_timber_filters'));
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
*
|
33 |
-
*
|
34 |
-
* @param Twig_Environment $twig
|
35 |
-
* @return Twig_Environment
|
36 |
-
*/
|
37 |
-
function add_timber_filters( $twig ) {
|
38 |
-
/* image filters */
|
39 |
-
$twig->addFilter(new \Twig_SimpleFilter('resize', array('TimberImageHelper', 'resize')));
|
40 |
-
$twig->addFilter(new \Twig_SimpleFilter('retina', array('TimberImageHelper', 'retina_resize')));
|
41 |
-
$twig->addFilter(new \Twig_SimpleFilter('letterbox', array('TimberImageHelper', 'letterbox')));
|
42 |
-
$twig->addFilter(new \Twig_SimpleFilter('tojpg', array('TimberImageHelper', 'img_to_jpg')));
|
43 |
-
|
44 |
-
/* debugging filters */
|
45 |
-
$twig->addFilter(new \Twig_SimpleFilter('get_class', 'get_class'));
|
46 |
-
$twig->addFilter(new \Twig_SimpleFilter('get_type', 'get_type'));
|
47 |
-
$twig->addFilter(new \Twig_SimpleFilter('print_r', function( $arr ) {
|
48 |
-
return print_r($arr, true);
|
49 |
-
} ));
|
50 |
-
|
51 |
-
/* other filters */
|
52 |
-
$twig->addFilter(new \Twig_SimpleFilter('stripshortcodes', 'strip_shortcodes'));
|
53 |
-
$twig->addFilter(new \Twig_SimpleFilter('array', array($this, 'to_array')));
|
54 |
-
$twig->addFilter(new \Twig_SimpleFilter('excerpt', 'wp_trim_words'));
|
55 |
-
$twig->addFilter(new \Twig_SimpleFilter('function', array($this, 'exec_function')));
|
56 |
-
$twig->addFilter(new \Twig_SimpleFilter('pretags', array($this, 'twig_pretags')));
|
57 |
-
$twig->addFilter(new \Twig_SimpleFilter('sanitize', 'sanitize_title'));
|
58 |
-
$twig->addFilter(new \Twig_SimpleFilter('shortcodes', 'do_shortcode'));
|
59 |
-
$twig->addFilter(new \Twig_SimpleFilter('time_ago', array($this, 'time_ago')));
|
60 |
-
$twig->addFilter(new \Twig_SimpleFilter('wpautop', 'wpautop'));
|
61 |
-
$twig->addFilter(new \Twig_SimpleFilter('list', array($this, 'add_list_separators')));
|
62 |
-
|
63 |
-
$twig->addFilter(new \Twig_SimpleFilter('relative', function( $link ) {
|
64 |
-
return URLHelper::get_rel_url($link, true);
|
65 |
-
} ));
|
66 |
-
|
67 |
-
$twig->addFilter(new \Twig_SimpleFilter('date', array($this, 'intl_date')));
|
68 |
-
|
69 |
-
$twig->addFilter(new \Twig_SimpleFilter('truncate', function( $text, $len ) {
|
70 |
-
return Helper::trim_words($text, $len);
|
71 |
-
} ));
|
72 |
-
|
73 |
-
/* actions and filters */
|
74 |
-
$twig->addFunction(new \Twig_SimpleFunction('action', function( $context ) {
|
75 |
-
$args = func_get_args();
|
76 |
-
array_shift($args);
|
77 |
-
$args[] = $context;
|
78 |
-
call_user_func_array('do_action', $args);
|
79 |
-
}, array('needs_context' => true)));
|
80 |
-
|
81 |
-
$twig->addFilter(new \Twig_SimpleFilter('apply_filters', function() {
|
82 |
-
$args = func_get_args();
|
83 |
-
$tag = current(array_splice($args, 1, 1));
|
84 |
-
|
85 |
-
return apply_filters_ref_array($tag, $args);
|
86 |
-
} ));
|
87 |
-
$twig->addFunction(new \Twig_SimpleFunction('function', array(&$this, 'exec_function')));
|
88 |
-
$twig->addFunction(new \Twig_SimpleFunction('fn', array(&$this, 'exec_function')));
|
89 |
-
|
90 |
-
$twig->addFunction(new \Twig_SimpleFunction('shortcode', 'do_shortcode'));
|
91 |
-
|
92 |
-
/* TimberObjects */
|
93 |
-
$twig->addFunction(new \Twig_SimpleFunction('TimberPost', function( $pid, $PostClass = 'Timber\Post' ) {
|
94 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
95 |
-
foreach ( $pid as &$p ) {
|
96 |
-
$p = new $PostClass($p);
|
97 |
-
}
|
98 |
-
return $pid;
|
99 |
-
}
|
100 |
-
return new $PostClass($pid);
|
101 |
-
} ));
|
102 |
-
$twig->addFunction(new \Twig_SimpleFunction('TimberImage', function( $pid = false, $ImageClass = 'Timber\Image' ) {
|
103 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
104 |
-
foreach ( $pid as &$p ) {
|
105 |
-
$p = new $ImageClass($p);
|
106 |
-
}
|
107 |
-
return $pid;
|
108 |
-
}
|
109 |
-
return new $ImageClass($pid);
|
110 |
-
} ));
|
111 |
-
|
112 |
-
$twig->addFunction(new \Twig_SimpleFunction('TimberTerm', function( $pid, $TermClass = 'Timber\Term' ) {
|
113 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
114 |
-
foreach ( $pid as &$p ) {
|
115 |
-
$p = new $TermClass($p);
|
116 |
-
}
|
117 |
-
return $pid;
|
118 |
-
}
|
119 |
-
return new $TermClass($pid);
|
120 |
-
} ));
|
121 |
-
$twig->addFunction(new \Twig_SimpleFunction('TimberUser', function( $pid, $UserClass = 'Timber\User' ) {
|
122 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
123 |
-
foreach ( $pid as &$p ) {
|
124 |
-
$p = new $UserClass($p);
|
125 |
-
}
|
126 |
-
return $pid;
|
127 |
-
}
|
128 |
-
return new $UserClass($pid);
|
129 |
-
} ));
|
130 |
-
|
131 |
-
/* TimberObjects Alias */
|
132 |
-
$twig->addFunction(new \Twig_SimpleFunction('Post', function( $pid, $PostClass = 'Timber\Post' ) {
|
133 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
134 |
-
foreach ( $pid as &$p ) {
|
135 |
-
$p = new $PostClass($p);
|
136 |
-
}
|
137 |
-
return $pid;
|
138 |
-
}
|
139 |
-
return new $PostClass($pid);
|
140 |
-
} ));
|
141 |
-
$twig->addFunction(new \Twig_SimpleFunction('Image', function( $pid, $ImageClass = 'Timber\Image' ) {
|
142 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
143 |
-
foreach ( $pid as &$p ) {
|
144 |
-
$p = new $ImageClass($p);
|
145 |
-
}
|
146 |
-
return $pid;
|
147 |
-
}
|
148 |
-
return new $ImageClass($pid);
|
149 |
-
} ));
|
150 |
-
$twig->addFunction(new \Twig_SimpleFunction('Term', function( $pid, $TermClass = 'Timber\Term' ) {
|
151 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
152 |
-
foreach ( $pid as &$p ) {
|
153 |
-
$p = new $TermClass($p);
|
154 |
-
}
|
155 |
-
return $pid;
|
156 |
-
}
|
157 |
-
return new $TermClass($pid);
|
158 |
-
} ));
|
159 |
-
$twig->addFunction(new \Twig_SimpleFunction('User', function( $pid, $UserClass = 'Timber\User' ) {
|
160 |
-
if ( is_array($pid) && !Helper::is_array_assoc($pid) ) {
|
161 |
-
foreach ( $pid as &$p ) {
|
162 |
-
$p = new $UserClass($p);
|
163 |
-
}
|
164 |
-
return $pid;
|
165 |
-
}
|
166 |
-
return new $UserClass($pid);
|
167 |
-
} ));
|
168 |
-
|
169 |
-
/* bloginfo and translate */
|
170 |
-
$twig->addFunction('bloginfo', new \Twig_SimpleFunction('bloginfo', function( $show = '', $filter = 'raw' ) {
|
171 |
-
return get_bloginfo($show, $filter);
|
172 |
-
} ));
|
173 |
-
$twig->addFunction('__', new \Twig_SimpleFunction('__', function( $text, $domain = 'default' ) {
|
174 |
-
return __($text, $domain);
|
175 |
-
} ));
|
176 |
-
$twig->addFunction('translate', new \Twig_SimpleFunction('translate', function( $text, $domain = 'default' ) {
|
177 |
-
return translate($text, $domain);
|
178 |
-
} ));
|
179 |
-
$twig->addFunction('_e', new \Twig_SimpleFunction('_e', function( $text, $domain = 'default' ) {
|
180 |
-
return _e($text, $domain);
|
181 |
-
} ));
|
182 |
-
$twig->addFunction('_n', new \Twig_SimpleFunction('_n', function( $single, $plural, $number, $domain = 'default' ) {
|
183 |
-
return _n($single, $plural, $number, $domain);
|
184 |
-
} ));
|
185 |
-
$twig->addFunction('_x', new \Twig_SimpleFunction('_x', function( $text, $context, $domain = 'default' ) {
|
186 |
-
return _x($text, $context, $domain);
|
187 |
-
} ));
|
188 |
-
$twig->addFunction('_ex', new \Twig_SimpleFunction('_ex', function( $text, $context, $domain = 'default' ) {
|
189 |
-
return _ex($text, $context, $domain);
|
190 |
-
} ));
|
191 |
-
$twig->addFunction('_nx', new \Twig_SimpleFunction('_nx', function( $single, $plural, $number, $context, $domain = 'default' ) {
|
192 |
-
return _nx($single, $plural, $number, $context, $domain);
|
193 |
-
} ));
|
194 |
-
$twig->addFunction('_n_noop', new \Twig_SimpleFunction('_n_noop', function( $singular, $plural, $domain = 'default' ) {
|
195 |
-
return _n_noop($singular, $plural, $domain);
|
196 |
-
} ));
|
197 |
-
$twig->addFunction('_nx_noop', new \Twig_SimpleFunction('_nx_noop', function( $singular, $plural, $context, $domain = 'default' ) {
|
198 |
-
return _nx_noop($singular, $plural, $context, $domain);
|
199 |
-
} ));
|
200 |
-
$twig->addFunction('translate_nooped_plural', new \Twig_SimpleFunction('translate_nooped_plural', function( $nooped_plural, $count, $domain = 'default' ) {
|
201 |
-
return translate_nooped_plural($nooped_plural, $count, $domain);
|
202 |
-
} ));
|
203 |
-
$twig = apply_filters('timber/twig', $twig);
|
204 |
-
/**
|
205 |
-
* get_twig is deprecated, use timber/twig
|
206 |
-
*/
|
207 |
-
$twig = apply_filters('get_twig', $twig);
|
208 |
-
return $twig;
|
209 |
-
}
|
210 |
-
|
211 |
-
/**
|
212 |
-
*
|
213 |
-
*
|
214 |
-
* @param mixed $arr
|
215 |
-
* @return array
|
216 |
-
*/
|
217 |
-
function to_array( $arr ) {
|
218 |
-
if ( is_array($arr) ) {
|
219 |
-
return $arr;
|
220 |
-
}
|
221 |
-
$arr = array($arr);
|
222 |
-
return $arr;
|
223 |
-
}
|
224 |
-
|
225 |
-
/**
|
226 |
-
*
|
227 |
-
*
|
228 |
-
* @param string $function_name
|
229 |
-
* @return mixed
|
230 |
-
*/
|
231 |
-
function exec_function( $function_name ) {
|
232 |
-
$args = func_get_args();
|
233 |
-
array_shift($args);
|
234 |
-
if ( is_string($function_name) ) {
|
235 |
-
$function_name = trim($function_name);
|
236 |
-
}
|
237 |
-
return call_user_func_array($function_name, ($args));
|
238 |
-
}
|
239 |
-
|
240 |
-
/**
|
241 |
-
*
|
242 |
-
*
|
243 |
-
* @param string $content
|
244 |
-
* @return string
|
245 |
-
*/
|
246 |
-
function twig_pretags( $content ) {
|
247 |
-
return preg_replace_callback('|<pre.*>(.*)</pre|isU', array(&$this, 'convert_pre_entities'), $content);
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
*
|
252 |
-
*
|
253 |
-
* @param array $matches
|
254 |
-
* @return string
|
255 |
-
*/
|
256 |
-
function convert_pre_entities( $matches ) {
|
257 |
-
return str_replace($matches[1], htmlentities($matches[1]), $matches[0]);
|
258 |
-
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
*
|
262 |
-
*
|
263 |
-
* @param string $date
|
264 |
-
* @param string $format (optional)
|
265 |
-
* @return string
|
266 |
-
*/
|
267 |
-
function intl_date( $date, $format = null ) {
|
268 |
-
if ( $format === null ) {
|
269 |
-
$format = get_option('date_format');
|
270 |
-
}
|
271 |
-
|
272 |
-
if ( $date instanceof \DateTime ) {
|
273 |
-
$timestamp = $date->getTimestamp() + $date->getOffset();
|
274 |
-
} else if ( is_numeric($date) && strtotime($date) === false ) {
|
275 |
-
$timestamp = intval($date);
|
276 |
-
} else {
|
277 |
-
$timestamp = strtotime($date);
|
278 |
-
}
|
279 |
-
|
280 |
-
return date_i18n($format, $timestamp);
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* @param int|string $from
|
285 |
-
* @param int|string $to
|
286 |
-
* @param string $format_past
|
287 |
-
* @param string $format_future
|
288 |
-
* @return string
|
289 |
-
*/
|
290 |
-
function time_ago( $from, $to = null, $format_past = '%s ago', $format_future = '%s from now' ) {
|
291 |
-
$to = $to === null ? time() : $to;
|
292 |
-
$to = is_int($to) ? $to : strtotime($to);
|
293 |
-
$from = is_int($from) ? $from : strtotime($from);
|
294 |
-
|
295 |
-
if ( $from < $to ) {
|
296 |
-
return sprintf($format_past, human_time_diff($from, $to));
|
297 |
-
} else {
|
298 |
-
return sprintf($format_future, human_time_diff($to, $from));
|
299 |
-
}
|
300 |
-
}
|
301 |
-
|
302 |
-
/**
|
303 |
-
* @param array $arr
|
304 |
-
* @param string $first_delimiter
|
305 |
-
* @param string $second_delimiter
|
306 |
-
* @return string
|
307 |
-
*/
|
308 |
-
function add_list_separators( $arr, $first_delimiter = ',', $second_delimiter = 'and' ) {
|
309 |
-
$length = count($arr);
|
310 |
-
$list = '';
|
311 |
-
foreach ( $arr as $index => $item ) {
|
312 |
-
if ( $index < $length - 2 ) {
|
313 |
-
$delimiter = $first_delimiter.' ';
|
314 |
-
} elseif ( $index == $length - 2 ) {
|
315 |
-
$delimiter = ' '.$second_delimiter.' ';
|
316 |
-
} else {
|
317 |
-
$delimiter = '';
|
318 |
-
}
|
319 |
-
$list = $list.$item.$delimiter;
|
320 |
-
}
|
321 |
-
return $list;
|
322 |
-
}
|
323 |
-
|
324 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/{Cache → cache}/KeyGenerator.php
RENAMED
File without changes
|
lib/{Cache → cache}/TimberKeyGeneratorInterface.php
RENAMED
File without changes
|
lib/{Cache → cache}/WPObjectCacheAdapter.php
RENAMED
@@ -1,7 +1,7 @@
|
|
1 |
<?php namespace Timber\Cache;
|
2 |
|
3 |
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
4 |
-
use
|
5 |
|
6 |
class WPObjectCacheAdapter implements CacheProviderInterface {
|
7 |
|
@@ -12,17 +12,17 @@ class WPObjectCacheAdapter implements CacheProviderInterface {
|
|
12 |
*/
|
13 |
private $timberloader;
|
14 |
|
15 |
-
public function __construct(
|
16 |
$this->cache_group = $cache_group;
|
17 |
$this->timberloader = $timberloader;
|
18 |
}
|
19 |
|
20 |
-
public function fetch(
|
21 |
-
return $this->timberloader->get_cache($key, $this->cache_group,
|
22 |
}
|
23 |
|
24 |
-
public function save(
|
25 |
-
return $this->timberloader->set_cache($key, $value, $this->cache_group, $expire,
|
26 |
}
|
27 |
|
28 |
}
|
1 |
<?php namespace Timber\Cache;
|
2 |
|
3 |
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
4 |
+
use TimberLoader;
|
5 |
|
6 |
class WPObjectCacheAdapter implements CacheProviderInterface {
|
7 |
|
12 |
*/
|
13 |
private $timberloader;
|
14 |
|
15 |
+
public function __construct(TimberLoader $timberloader, $cache_group = 'timber') {
|
16 |
$this->cache_group = $cache_group;
|
17 |
$this->timberloader = $timberloader;
|
18 |
}
|
19 |
|
20 |
+
public function fetch($key) {
|
21 |
+
return $this->timberloader->get_cache($key, $this->cache_group, TimberLoader::CACHE_USE_DEFAULT);
|
22 |
}
|
23 |
|
24 |
+
public function save($key, $value, $expire = 0) {
|
25 |
+
return $this->timberloader->set_cache($key, $value, $this->cache_group, $expire, TimberLoader::CACHE_USE_DEFAULT);
|
26 |
}
|
27 |
|
28 |
}
|
lib/{Image/Operation/Letterbox.php → image/timber-image-operation-letterbox.php}
RENAMED
@@ -1,10 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace Timber\Image\Operation;
|
4 |
-
|
5 |
-
use Timber\Helper;
|
6 |
-
use Timber\Image\Operation as ImageOperation;
|
7 |
-
|
8 |
/*
|
9 |
* Changes image to new size, by shrinking/enlarging then padding with colored bands,
|
10 |
* so that no part of the image is cropped or stretched.
|
@@ -14,7 +8,7 @@ use Timber\Image\Operation as ImageOperation;
|
|
14 |
* - height of new image
|
15 |
* - color of padding
|
16 |
*/
|
17 |
-
class
|
18 |
|
19 |
private $w, $h, $color;
|
20 |
|
@@ -23,7 +17,7 @@ class Letterbox extends ImageOperation {
|
|
23 |
* @param int $h height
|
24 |
* @param string $color hex string, for color of padding bands
|
25 |
*/
|
26 |
-
function __construct(
|
27 |
$this->w = $w;
|
28 |
$this->h = $h;
|
29 |
$this->color = $color;
|
@@ -35,10 +29,10 @@ class Letterbox extends ImageOperation {
|
|
35 |
* @return string the final filename to be used
|
36 |
* (ex: my-awesome-pic-lbox-300x200-FF3366.jpg)
|
37 |
*/
|
38 |
-
public function filename(
|
39 |
-
$color = str_replace('#', '', $this->color);
|
40 |
-
$newbase = $src_filename.'-lbox-'
|
41 |
-
$new_name = $newbase.'.'
|
42 |
return $new_name;
|
43 |
}
|
44 |
|
@@ -52,16 +46,16 @@ class Letterbox extends ImageOperation {
|
|
52 |
* (ex: /src/var/www/wp-content/uploads/my-pic-lbox-300x200-FF3366.jpg)
|
53 |
* @return bool true if everything went fine, false otherwise
|
54 |
*/
|
55 |
-
public function run(
|
56 |
$w = $this->w;
|
57 |
$h = $this->h;
|
58 |
|
59 |
-
$bg = imagecreatetruecolor($w, $h);
|
60 |
-
$c = self::hexrgb($this->color);
|
61 |
-
$bgColor = imagecolorallocate($bg, $c['red'], $c['green'], $c['blue']);
|
62 |
-
imagefill($bg, 0, 0, $bgColor);
|
63 |
-
$image = wp_get_image_editor($load_filename);
|
64 |
-
if ( !is_wp_error($image) ) {
|
65 |
$current_size = $image->get_size();
|
66 |
$quality = $image->get_quality();
|
67 |
$ow = $current_size['width'];
|
@@ -75,38 +69,38 @@ class Letterbox extends ImageOperation {
|
|
75 |
$y = 0;
|
76 |
$x = $w / 2 - $owt / 2;
|
77 |
$oht = $h;
|
78 |
-
$image->crop(0, 0, $ow, $oh, $owt, $oht);
|
79 |
} else {
|
80 |
$w_scale = $w / $ow;
|
81 |
$oht = $oh * $w_scale;
|
82 |
$x = 0;
|
83 |
$y = $h / 2 - $oht / 2;
|
84 |
$owt = $w;
|
85 |
-
$image->crop(0, 0, $ow, $oh, $owt, $oht);
|
86 |
}
|
87 |
-
$result = $image->save($save_filename);
|
88 |
$func = 'imagecreatefromjpeg';
|
89 |
$save_func = 'imagejpeg';
|
90 |
-
$ext = pathinfo($save_filename, PATHINFO_EXTENSION);
|
91 |
if ( $ext == 'gif' ) {
|
92 |
$func = 'imagecreatefromgif';
|
93 |
$save_func = 'imagegif';
|
94 |
} else if ( $ext == 'png' ) {
|
95 |
$func = 'imagecreatefrompng';
|
96 |
$save_func = 'imagepng';
|
97 |
-
if (
|
98 |
-
$quality = $quality
|
99 |
$quality = round(10 - $quality);
|
100 |
}
|
101 |
}
|
102 |
-
$image = $func($save_filename);
|
103 |
-
imagecopy($bg, $image, $x, $y, 0, 0, $owt, $oht);
|
104 |
-
if (
|
105 |
-
return $save_func($bg, $save_filename);
|
106 |
}
|
107 |
-
return $save_func($bg, $save_filename, $quality);
|
108 |
} else {
|
109 |
-
|
110 |
}
|
111 |
return false;
|
112 |
}
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/*
|
3 |
* Changes image to new size, by shrinking/enlarging then padding with colored bands,
|
4 |
* so that no part of the image is cropped or stretched.
|
8 |
* - height of new image
|
9 |
* - color of padding
|
10 |
*/
|
11 |
+
class TimberImageOperationLetterbox extends TimberImageOperation {
|
12 |
|
13 |
private $w, $h, $color;
|
14 |
|
17 |
* @param int $h height
|
18 |
* @param string $color hex string, for color of padding bands
|
19 |
*/
|
20 |
+
function __construct($w, $h, $color) {
|
21 |
$this->w = $w;
|
22 |
$this->h = $h;
|
23 |
$this->color = $color;
|
29 |
* @return string the final filename to be used
|
30 |
* (ex: my-awesome-pic-lbox-300x200-FF3366.jpg)
|
31 |
*/
|
32 |
+
public function filename($src_filename, $src_extension) {
|
33 |
+
$color = str_replace( '#', '', $this->color );
|
34 |
+
$newbase = $src_filename . '-lbox-' . $this->w . 'x' . $this->h . '-' . $color;
|
35 |
+
$new_name = $newbase . '.' . $src_extension;
|
36 |
return $new_name;
|
37 |
}
|
38 |
|
46 |
* (ex: /src/var/www/wp-content/uploads/my-pic-lbox-300x200-FF3366.jpg)
|
47 |
* @return bool true if everything went fine, false otherwise
|
48 |
*/
|
49 |
+
public function run($load_filename, $save_filename) {
|
50 |
$w = $this->w;
|
51 |
$h = $this->h;
|
52 |
|
53 |
+
$bg = imagecreatetruecolor( $w, $h );
|
54 |
+
$c = self::hexrgb( $this->color );
|
55 |
+
$bgColor = imagecolorallocate( $bg, $c['red'], $c['green'], $c['blue'] );
|
56 |
+
imagefill( $bg, 0, 0, $bgColor );
|
57 |
+
$image = wp_get_image_editor( $load_filename );
|
58 |
+
if ( !is_wp_error( $image ) ) {
|
59 |
$current_size = $image->get_size();
|
60 |
$quality = $image->get_quality();
|
61 |
$ow = $current_size['width'];
|
69 |
$y = 0;
|
70 |
$x = $w / 2 - $owt / 2;
|
71 |
$oht = $h;
|
72 |
+
$image->crop( 0, 0, $ow, $oh, $owt, $oht );
|
73 |
} else {
|
74 |
$w_scale = $w / $ow;
|
75 |
$oht = $oh * $w_scale;
|
76 |
$x = 0;
|
77 |
$y = $h / 2 - $oht / 2;
|
78 |
$owt = $w;
|
79 |
+
$image->crop( 0, 0, $ow, $oh, $owt, $oht );
|
80 |
}
|
81 |
+
$result = $image->save( $save_filename );
|
82 |
$func = 'imagecreatefromjpeg';
|
83 |
$save_func = 'imagejpeg';
|
84 |
+
$ext = pathinfo( $save_filename, PATHINFO_EXTENSION );
|
85 |
if ( $ext == 'gif' ) {
|
86 |
$func = 'imagecreatefromgif';
|
87 |
$save_func = 'imagegif';
|
88 |
} else if ( $ext == 'png' ) {
|
89 |
$func = 'imagecreatefrompng';
|
90 |
$save_func = 'imagepng';
|
91 |
+
if ($quality > 9) {
|
92 |
+
$quality = $quality/10;
|
93 |
$quality = round(10 - $quality);
|
94 |
}
|
95 |
}
|
96 |
+
$image = $func( $save_filename );
|
97 |
+
imagecopy( $bg, $image, $x, $y, 0, 0, $owt, $oht );
|
98 |
+
if ($save_func === 'imagegif') {
|
99 |
+
return $save_func( $bg, $save_filename );
|
100 |
}
|
101 |
+
return $save_func( $bg, $save_filename, $quality );
|
102 |
} else {
|
103 |
+
TimberHelper::error_log( $image );
|
104 |
}
|
105 |
return false;
|
106 |
}
|
lib/{Image/Operation/Resize.php → image/timber-image-operation-resize.php}
RENAMED
@@ -1,10 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace Timber\Image\Operation;
|
4 |
-
|
5 |
-
use Timber\Helper;
|
6 |
-
use Timber\Image\Operation as ImageOperation;
|
7 |
-
|
8 |
/**
|
9 |
* Changes image to new size, by shrinking/enlarging
|
10 |
* then cropping to respect new ratio.
|
@@ -14,7 +8,7 @@ use Timber\Image\Operation as ImageOperation;
|
|
14 |
* - height of new image
|
15 |
* - crop method
|
16 |
*/
|
17 |
-
class
|
18 |
|
19 |
private $w, $h, $crop;
|
20 |
|
@@ -23,12 +17,12 @@ class Resize extends ImageOperation {
|
|
23 |
* @param int $h height of new image
|
24 |
* @param string $crop cropping method, one of: 'default', 'center', 'top', 'bottom', 'left', 'right', 'top-center', 'bottom-center'.
|
25 |
*/
|
26 |
-
function __construct(
|
27 |
$this->w = $w;
|
28 |
$this->h = $h;
|
29 |
// Sanitize crop position
|
30 |
-
$allowed_crop_positions = array('default', 'center', 'top', 'bottom', 'left', 'right', 'top-center', 'bottom-center');
|
31 |
-
if ( $crop !== false && !in_array($crop, $allowed_crop_positions) ) {
|
32 |
$crop = $allowed_crop_positions[0];
|
33 |
}
|
34 |
$this->crop = $crop;
|
@@ -39,7 +33,7 @@ class Resize extends ImageOperation {
|
|
39 |
* @param string $src_extension the extension (ex: .jpg)
|
40 |
* @return string the final filename to be used (ex: my-awesome-pic-300x200-c-default.jpg)
|
41 |
*/
|
42 |
-
public function filename(
|
43 |
$w = 0;
|
44 |
$h = 0;
|
45 |
if ( $this->w ) {
|
@@ -48,8 +42,8 @@ class Resize extends ImageOperation {
|
|
48 |
if ( $this->h ) {
|
49 |
$h = $this->h;
|
50 |
}
|
51 |
-
$result = $src_filename.'-'
|
52 |
-
if
|
53 |
$result .= '.'.$src_extension;
|
54 |
}
|
55 |
return $result;
|
@@ -60,7 +54,7 @@ class Resize extends ImageOperation {
|
|
60 |
* @param string $save_filename
|
61 |
*/
|
62 |
protected function run_animated_gif( $load_filename, $save_filename ) {
|
63 |
-
$image = wp_get_image_editor($load_filename);
|
64 |
$current_size = $image->get_size();
|
65 |
$src_w = $current_size['width'];
|
66 |
$src_h = $current_size['height'];
|
@@ -69,10 +63,10 @@ class Resize extends ImageOperation {
|
|
69 |
if ( !class_exists('Imagick') ) {
|
70 |
return false;
|
71 |
}
|
72 |
-
$image = new
|
73 |
$image = $image->coalesceImages();
|
74 |
-
$crop = self::get_target_sizes($load_filename);
|
75 |
-
foreach (
|
76 |
$frame->cropImage($crop['src_w'], $crop['src_h'], $crop['x'], $crop['y']);
|
77 |
$frame->thumbnailImage($w, $h);
|
78 |
$frame->setImagePage($w, $h, 0, 0);
|
@@ -81,11 +75,8 @@ class Resize extends ImageOperation {
|
|
81 |
return $image->writeImages($save_filename, true);
|
82 |
}
|
83 |
|
84 |
-
/**
|
85 |
-
* @param string $load_filename
|
86 |
-
*/
|
87 |
protected function get_target_sizes( $load_filename ) {
|
88 |
-
$image = wp_get_image_editor($load_filename);
|
89 |
$w = $this->w;
|
90 |
$h = $this->h;
|
91 |
$crop = $this->crop;
|
@@ -95,11 +86,11 @@ class Resize extends ImageOperation {
|
|
95 |
$src_h = $current_size['height'];
|
96 |
$src_ratio = $src_w / $src_h;
|
97 |
if ( !$h ) {
|
98 |
-
$h = round($w / $src_ratio);
|
99 |
}
|
100 |
if ( !$w ) {
|
101 |
//the user wants to resize based on constant height
|
102 |
-
$w = round($h * $src_ratio);
|
103 |
}
|
104 |
if ( !$crop ) {
|
105 |
return array(
|
@@ -113,13 +104,13 @@ class Resize extends ImageOperation {
|
|
113 |
$src_wt = $src_h * $dest_ratio;
|
114 |
$src_ht = $src_w / $dest_ratio;
|
115 |
$src_x = $src_w / 2 - $src_wt / 2;
|
116 |
-
$src_y = ($src_h - $src_ht) / 6;
|
117 |
//now specific overrides based on options:
|
118 |
switch ( $crop ) {
|
119 |
case 'center':
|
120 |
// Get source x and y
|
121 |
-
$src_x = round(($src_w - $src_wt) / 2);
|
122 |
-
$src_y = round(($src_h - $src_ht) / 2);
|
123 |
break;
|
124 |
|
125 |
case 'top':
|
@@ -131,11 +122,11 @@ class Resize extends ImageOperation {
|
|
131 |
break;
|
132 |
|
133 |
case 'top-center':
|
134 |
-
$src_y = round(($src_h - $src_ht) / 4);
|
135 |
break;
|
136 |
|
137 |
case 'bottom-center':
|
138 |
-
$src_y = $src_h - $src_ht - round(($src_h - $src_ht) / 4);
|
139 |
break;
|
140 |
|
141 |
case 'left':
|
@@ -147,7 +138,7 @@ class Resize extends ImageOperation {
|
|
147 |
break;
|
148 |
}
|
149 |
// Crop the image
|
150 |
-
return ($dest_ratio > $src_ratio)
|
151 |
? array(
|
152 |
'x' => 0, 'y' => $src_y,
|
153 |
'src_w' => $src_w, 'src_h' => $src_ht,
|
@@ -168,44 +159,44 @@ class Resize extends ImageOperation {
|
|
168 |
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
169 |
* @param string $save_filename filepath (not URL) where result file should be saved
|
170 |
* (ex: /src/var/www/wp-content/uploads/my-pic-300x200-c-default.jpg)
|
171 |
-
* @return
|
172 |
*/
|
173 |
-
public function run(
|
174 |
//should be resized by gif resizer
|
175 |
-
if (
|
176 |
//attempt to resize
|
177 |
//return if successful
|
178 |
//proceed if not
|
179 |
$gif = self::run_animated_gif($load_filename, $save_filename);
|
180 |
-
if (
|
181 |
return true;
|
182 |
}
|
183 |
}
|
184 |
-
$image = wp_get_image_editor($load_filename);
|
185 |
-
if ( !is_wp_error($image) ) {
|
186 |
-
$crop = self::get_target_sizes($load_filename);
|
187 |
-
$image->crop($crop['x'],
|
188 |
$crop['y'],
|
189 |
$crop['src_w'],
|
190 |
$crop['src_h'],
|
191 |
$crop['target_w'],
|
192 |
$crop['target_h']
|
193 |
);
|
194 |
-
$result = $image->save($save_filename);
|
195 |
-
if ( is_wp_error($result) ) {
|
196 |
// @codeCoverageIgnoreStart
|
197 |
-
|
198 |
-
|
199 |
return false;
|
200 |
// @codeCoverageIgnoreEnd
|
201 |
} else {
|
202 |
return true;
|
203 |
}
|
204 |
-
} else if ( isset($image->error_data['error_loading_image']) ) {
|
205 |
// @codeCoverageIgnoreStart
|
206 |
-
|
207 |
} else {
|
208 |
-
|
209 |
// @codeCoverageIgnoreEnd
|
210 |
}
|
211 |
}
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Changes image to new size, by shrinking/enlarging
|
4 |
* then cropping to respect new ratio.
|
8 |
* - height of new image
|
9 |
* - crop method
|
10 |
*/
|
11 |
+
class TimberImageOperationResize extends TimberImageOperation {
|
12 |
|
13 |
private $w, $h, $crop;
|
14 |
|
17 |
* @param int $h height of new image
|
18 |
* @param string $crop cropping method, one of: 'default', 'center', 'top', 'bottom', 'left', 'right', 'top-center', 'bottom-center'.
|
19 |
*/
|
20 |
+
function __construct($w, $h, $crop) {
|
21 |
$this->w = $w;
|
22 |
$this->h = $h;
|
23 |
// Sanitize crop position
|
24 |
+
$allowed_crop_positions = array( 'default', 'center', 'top', 'bottom', 'left', 'right', 'top-center', 'bottom-center' );
|
25 |
+
if ( $crop !== false && !in_array( $crop, $allowed_crop_positions ) ) {
|
26 |
$crop = $allowed_crop_positions[0];
|
27 |
}
|
28 |
$this->crop = $crop;
|
33 |
* @param string $src_extension the extension (ex: .jpg)
|
34 |
* @return string the final filename to be used (ex: my-awesome-pic-300x200-c-default.jpg)
|
35 |
*/
|
36 |
+
public function filename($src_filename, $src_extension) {
|
37 |
$w = 0;
|
38 |
$h = 0;
|
39 |
if ( $this->w ) {
|
42 |
if ( $this->h ) {
|
43 |
$h = $this->h;
|
44 |
}
|
45 |
+
$result = $src_filename . '-' . $w . 'x' . $h . '-c-' . ( $this->crop ? $this->crop : 'f' ); // Crop will be either user named or f (false)
|
46 |
+
if($src_extension) {
|
47 |
$result .= '.'.$src_extension;
|
48 |
}
|
49 |
return $result;
|
54 |
* @param string $save_filename
|
55 |
*/
|
56 |
protected function run_animated_gif( $load_filename, $save_filename ) {
|
57 |
+
$image = wp_get_image_editor( $load_filename );
|
58 |
$current_size = $image->get_size();
|
59 |
$src_w = $current_size['width'];
|
60 |
$src_h = $current_size['height'];
|
63 |
if ( !class_exists('Imagick') ) {
|
64 |
return false;
|
65 |
}
|
66 |
+
$image = new Imagick($load_filename);
|
67 |
$image = $image->coalesceImages();
|
68 |
+
$crop = self::get_target_sizes( $load_filename );
|
69 |
+
foreach ($image as $frame) {
|
70 |
$frame->cropImage($crop['src_w'], $crop['src_h'], $crop['x'], $crop['y']);
|
71 |
$frame->thumbnailImage($w, $h);
|
72 |
$frame->setImagePage($w, $h, 0, 0);
|
75 |
return $image->writeImages($save_filename, true);
|
76 |
}
|
77 |
|
|
|
|
|
|
|
78 |
protected function get_target_sizes( $load_filename ) {
|
79 |
+
$image = wp_get_image_editor( $load_filename );
|
80 |
$w = $this->w;
|
81 |
$h = $this->h;
|
82 |
$crop = $this->crop;
|
86 |
$src_h = $current_size['height'];
|
87 |
$src_ratio = $src_w / $src_h;
|
88 |
if ( !$h ) {
|
89 |
+
$h = round( $w / $src_ratio );
|
90 |
}
|
91 |
if ( !$w ) {
|
92 |
//the user wants to resize based on constant height
|
93 |
+
$w = round( $h * $src_ratio );
|
94 |
}
|
95 |
if ( !$crop ) {
|
96 |
return array(
|
104 |
$src_wt = $src_h * $dest_ratio;
|
105 |
$src_ht = $src_w / $dest_ratio;
|
106 |
$src_x = $src_w / 2 - $src_wt / 2;
|
107 |
+
$src_y = ( $src_h - $src_ht ) / 6;
|
108 |
//now specific overrides based on options:
|
109 |
switch ( $crop ) {
|
110 |
case 'center':
|
111 |
// Get source x and y
|
112 |
+
$src_x = round( ( $src_w - $src_wt ) / 2 );
|
113 |
+
$src_y = round( ( $src_h - $src_ht ) / 2 );
|
114 |
break;
|
115 |
|
116 |
case 'top':
|
122 |
break;
|
123 |
|
124 |
case 'top-center':
|
125 |
+
$src_y = round( ( $src_h - $src_ht ) / 4 );
|
126 |
break;
|
127 |
|
128 |
case 'bottom-center':
|
129 |
+
$src_y = $src_h - $src_ht - round( ( $src_h - $src_ht ) / 4 );
|
130 |
break;
|
131 |
|
132 |
case 'left':
|
138 |
break;
|
139 |
}
|
140 |
// Crop the image
|
141 |
+
return ( $dest_ratio > $src_ratio )
|
142 |
? array(
|
143 |
'x' => 0, 'y' => $src_y,
|
144 |
'src_w' => $src_w, 'src_h' => $src_ht,
|
159 |
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
160 |
* @param string $save_filename filepath (not URL) where result file should be saved
|
161 |
* (ex: /src/var/www/wp-content/uploads/my-pic-300x200-c-default.jpg)
|
162 |
+
* @return bool true if everything went fine, false otherwise
|
163 |
*/
|
164 |
+
public function run($load_filename, $save_filename) {
|
165 |
//should be resized by gif resizer
|
166 |
+
if ( TimberImageHelper::is_animated_gif($load_filename) ) {
|
167 |
//attempt to resize
|
168 |
//return if successful
|
169 |
//proceed if not
|
170 |
$gif = self::run_animated_gif($load_filename, $save_filename);
|
171 |
+
if ($gif) {
|
172 |
return true;
|
173 |
}
|
174 |
}
|
175 |
+
$image = wp_get_image_editor( $load_filename );
|
176 |
+
if ( !is_wp_error( $image ) ) {
|
177 |
+
$crop = self::get_target_sizes( $load_filename );
|
178 |
+
$image->crop( $crop['x'],
|
179 |
$crop['y'],
|
180 |
$crop['src_w'],
|
181 |
$crop['src_h'],
|
182 |
$crop['target_w'],
|
183 |
$crop['target_h']
|
184 |
);
|
185 |
+
$result = $image->save( $save_filename );
|
186 |
+
if ( is_wp_error( $result ) ) {
|
187 |
// @codeCoverageIgnoreStart
|
188 |
+
TimberHelper::error_log( 'Error resizing image' );
|
189 |
+
TimberHelper::error_log( $result );
|
190 |
return false;
|
191 |
// @codeCoverageIgnoreEnd
|
192 |
} else {
|
193 |
return true;
|
194 |
}
|
195 |
+
} else if ( isset( $image->error_data['error_loading_image'] ) ) {
|
196 |
// @codeCoverageIgnoreStart
|
197 |
+
TimberHelper::error_log( 'Error loading ' . $image->error_data['error_loading_image'] );
|
198 |
} else {
|
199 |
+
TimberHelper::error_log( $image );
|
200 |
// @codeCoverageIgnoreEnd
|
201 |
}
|
202 |
}
|
lib/image/timber-image-operation-retina.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Contains the class for running image retina-izing operations
|
4 |
+
*/
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Increases image size by a given factor
|
8 |
+
* Arguments:
|
9 |
+
* - factor by which to multiply image dimensions
|
10 |
+
* @property float $factor the factor (ex: 2, 1.5, 1.75) to multiply dimension by
|
11 |
+
*/
|
12 |
+
class TimberImageOperationRetina extends TimberImageOperation {
|
13 |
+
|
14 |
+
private $factor;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Construct our operation
|
18 |
+
* @param float $factor to multiply original dimensions by
|
19 |
+
*/
|
20 |
+
function __construct($factor) {
|
21 |
+
$this->factor = $factor;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Generates the final filename based on the source's name and extension
|
26 |
+
*
|
27 |
+
* @param string $src_filename the basename of the file (ex: my-awesome-pic)
|
28 |
+
* @param string $src_extension the extension (ex: .jpg)
|
29 |
+
* @return string the final filename to be used (ex: my-awesome-pic@2x.jpg)
|
30 |
+
*/
|
31 |
+
function filename($src_filename, $src_extension) {
|
32 |
+
$newbase = $src_filename . '@' . $this->factor . 'x'; // add @2x, @3x, @1.5x, etc.
|
33 |
+
$new_name = $newbase . '.' . $src_extension;
|
34 |
+
return $new_name;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Performs the actual image manipulation,
|
39 |
+
* including saving the target file.
|
40 |
+
*
|
41 |
+
* @param string $load_filename filepath (not URL) to source file
|
42 |
+
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
43 |
+
* @param string $save_filename filepath (not URL) where result file should be saved
|
44 |
+
* (ex: /src/var/www/wp-content/uploads/my-pic@2x.jpg)
|
45 |
+
* @return bool true if everything went fine, false otherwise
|
46 |
+
*/
|
47 |
+
function run($load_filename, $save_filename){
|
48 |
+
$image = wp_get_image_editor( $load_filename );
|
49 |
+
if ( !is_wp_error( $image ) ) {
|
50 |
+
$current_size = $image->get_size();
|
51 |
+
$src_w = $current_size['width'];
|
52 |
+
$src_h = $current_size['height'];
|
53 |
+
// Get ratios
|
54 |
+
$w = $src_w * $this->factor;
|
55 |
+
$h = $src_h * $this->factor;
|
56 |
+
$image->crop( 0, 0, $src_w, $src_h, $w, $h );
|
57 |
+
$result = $image->save( $save_filename );
|
58 |
+
if ( is_wp_error( $result ) ) {
|
59 |
+
// @codeCoverageIgnoreStart
|
60 |
+
TimberHelper::error_log( 'Error resizing image' );
|
61 |
+
TimberHelper::error_log( $result );
|
62 |
+
return false;
|
63 |
+
// @codeCoverageIgnoreEnd
|
64 |
+
} else {
|
65 |
+
return true;
|
66 |
+
}
|
67 |
+
} else if ( isset( $image->error_data['error_loading_image'] ) ) {
|
68 |
+
TimberHelper::error_log( 'Error loading ' . $image->error_data['error_loading_image'] );
|
69 |
+
} else {
|
70 |
+
TimberHelper::error_log( $image );
|
71 |
+
}
|
72 |
+
return false;
|
73 |
+
}
|
74 |
+
}
|
lib/{Image/Operation/ToJpg.php → image/timber-image-operation-tojpg.php}
RENAMED
@@ -1,22 +1,18 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber\Image\Operation;
|
4 |
-
|
5 |
-
use Timber\Image\Operation as ImageOperation;
|
6 |
-
|
7 |
/**
|
8 |
* Implements converting a PNG file to JPG.
|
9 |
* Argument:
|
10 |
* - color to fill transparent zones
|
11 |
*/
|
12 |
-
class
|
13 |
|
14 |
private $color;
|
15 |
|
16 |
/**
|
17 |
* @param string $color hex string of color to use for transparent zones
|
18 |
*/
|
19 |
-
function __construct(
|
20 |
$this->color = $color;
|
21 |
}
|
22 |
|
@@ -25,8 +21,8 @@ class ToJpg extends ImageOperation {
|
|
25 |
* @param string $src_extension ignored
|
26 |
* @return string the final filename to be used (ex: my-awesome-pic.jpg)
|
27 |
*/
|
28 |
-
function filename(
|
29 |
-
$new_name = $src_filename.'.jpg';
|
30 |
return $new_name;
|
31 |
}
|
32 |
|
@@ -39,15 +35,15 @@ class ToJpg extends ImageOperation {
|
|
39 |
* (ex: /src/var/www/wp-content/uploads/my-pic.png)
|
40 |
* @return bool true if everything went fine, false otherwise
|
41 |
*/
|
42 |
-
function run(
|
43 |
-
$input = self::image_create($load_filename);
|
44 |
-
list($width, $height) = getimagesize($load_filename);
|
45 |
-
$output = imagecreatetruecolor($width, $height);
|
46 |
-
$c = self::hexrgb($this->color);
|
47 |
-
$color = imagecolorallocate($output, $c['red'], $c['green'], $c['blue']);
|
48 |
-
imagefilledrectangle($output, 0, 0, $width, $height, $color);
|
49 |
-
imagecopy($output, $input, 0, 0, 0, 0, $width, $height);
|
50 |
-
imagejpeg($output, $save_filename);
|
51 |
return true;
|
52 |
}
|
53 |
|
@@ -59,7 +55,7 @@ class ToJpg extends ImageOperation {
|
|
59 |
function image_create( $filename, $ext = 'auto' ) {
|
60 |
if ( $ext == 'auto' ) {
|
61 |
$ext = wp_check_filetype($filename);
|
62 |
-
if (
|
63 |
$ext = $ext['ext'];
|
64 |
}
|
65 |
}
|
@@ -73,6 +69,6 @@ class ToJpg extends ImageOperation {
|
|
73 |
if ( $ext == 'jpg' || $ext == 'jpeg' ) {
|
74 |
return imagecreatefromjpeg($filename);
|
75 |
}
|
76 |
-
throw new
|
77 |
}
|
78 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Implements converting a PNG file to JPG.
|
5 |
* Argument:
|
6 |
* - color to fill transparent zones
|
7 |
*/
|
8 |
+
class TimberImageOperationToJpg extends TimberImageOperation {
|
9 |
|
10 |
private $color;
|
11 |
|
12 |
/**
|
13 |
* @param string $color hex string of color to use for transparent zones
|
14 |
*/
|
15 |
+
function __construct($color) {
|
16 |
$this->color = $color;
|
17 |
}
|
18 |
|
21 |
* @param string $src_extension ignored
|
22 |
* @return string the final filename to be used (ex: my-awesome-pic.jpg)
|
23 |
*/
|
24 |
+
function filename($src_filename, $src_extension = 'jpg') {
|
25 |
+
$new_name = $src_filename . '.jpg';
|
26 |
return $new_name;
|
27 |
}
|
28 |
|
35 |
* (ex: /src/var/www/wp-content/uploads/my-pic.png)
|
36 |
* @return bool true if everything went fine, false otherwise
|
37 |
*/
|
38 |
+
function run($load_filename, $save_filename) {
|
39 |
+
$input = self::image_create( $load_filename );
|
40 |
+
list( $width, $height ) = getimagesize( $load_filename );
|
41 |
+
$output = imagecreatetruecolor( $width, $height );
|
42 |
+
$c = self::hexrgb( $this->color );
|
43 |
+
$color = imagecolorallocate( $output, $c['red'], $c['green'], $c['blue'] );
|
44 |
+
imagefilledrectangle( $output, 0, 0, $width, $height, $color );
|
45 |
+
imagecopy( $output, $input, 0, 0, 0, 0, $width, $height );
|
46 |
+
imagejpeg( $output, $save_filename );
|
47 |
return true;
|
48 |
}
|
49 |
|
55 |
function image_create( $filename, $ext = 'auto' ) {
|
56 |
if ( $ext == 'auto' ) {
|
57 |
$ext = wp_check_filetype($filename);
|
58 |
+
if (isset($ext['ext'])) {
|
59 |
$ext = $ext['ext'];
|
60 |
}
|
61 |
}
|
69 |
if ( $ext == 'jpg' || $ext == 'jpeg' ) {
|
70 |
return imagecreatefromjpeg($filename);
|
71 |
}
|
72 |
+
throw new InvalidArgumentException( 'image_create only accepts PNG, GIF and JPGs. File extension was: '.$ext );
|
73 |
}
|
74 |
}
|
lib/{Image/Operation.php → image/timber-image-operation.php}
RENAMED
@@ -1,7 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace Timber\Image;
|
4 |
-
|
5 |
/**
|
6 |
* Each image filter is represented by a subclass of this class,m
|
7 |
* and each filter call is a new instance, with call arguments as properties.
|
@@ -11,9 +8,8 @@ namespace Timber\Image;
|
|
11 |
* - filename
|
12 |
* - run
|
13 |
*/
|
14 |
-
abstract class
|
15 |
/**
|
16 |
-
*
|
17 |
* Builds the result filename, based on source filename and extension
|
18 |
*
|
19 |
* @param string $src_filename source filename (excluding extension and path)
|
@@ -21,7 +17,7 @@ abstract class Operation {
|
|
21 |
* @return string resulting filename (including extension but excluding path)
|
22 |
* ex: my-awesome-file.jpg
|
23 |
*/
|
24 |
-
public abstract function filename(
|
25 |
|
26 |
/**
|
27 |
* Performs the actual image manipulation,
|
@@ -31,7 +27,7 @@ abstract class Operation {
|
|
31 |
* @param string $save_filename filepath (not URL) where result file should be saved
|
32 |
* @return bool true if everything went fine, false otherwise
|
33 |
*/
|
34 |
-
public abstract function run(
|
35 |
|
36 |
/**
|
37 |
* Helper method to convert hex string to rgb array
|
@@ -41,13 +37,13 @@ abstract class Operation {
|
|
41 |
* ex: array('red' => 255, 'green' => 20, 'blue' => 85);
|
42 |
*/
|
43 |
public static function hexrgb( $hexstr ) {
|
44 |
-
if ( !strstr($hexstr, '#') ) {
|
45 |
-
$hexstr = '#'
|
46 |
}
|
47 |
-
if ( strlen($hexstr) == 4 ) {
|
48 |
-
$hexstr = '#'
|
49 |
}
|
50 |
-
$int = hexdec($hexstr);
|
51 |
-
return array("red" => 0xFF & ($int >> 0x10), "green" => 0xFF & ($int >> 0x8), "blue" => 0xFF & $int);
|
52 |
}
|
53 |
}
|
1 |
<?php
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Each image filter is represented by a subclass of this class,m
|
4 |
* and each filter call is a new instance, with call arguments as properties.
|
8 |
* - filename
|
9 |
* - run
|
10 |
*/
|
11 |
+
abstract class TimberImageOperation {
|
12 |
/**
|
|
|
13 |
* Builds the result filename, based on source filename and extension
|
14 |
*
|
15 |
* @param string $src_filename source filename (excluding extension and path)
|
17 |
* @return string resulting filename (including extension but excluding path)
|
18 |
* ex: my-awesome-file.jpg
|
19 |
*/
|
20 |
+
public abstract function filename($src_filename, $src_extension);
|
21 |
|
22 |
/**
|
23 |
* Performs the actual image manipulation,
|
27 |
* @param string $save_filename filepath (not URL) where result file should be saved
|
28 |
* @return bool true if everything went fine, false otherwise
|
29 |
*/
|
30 |
+
public abstract function run($load_filename, $save_filename);
|
31 |
|
32 |
/**
|
33 |
* Helper method to convert hex string to rgb array
|
37 |
* ex: array('red' => 255, 'green' => 20, 'blue' => 85);
|
38 |
*/
|
39 |
public static function hexrgb( $hexstr ) {
|
40 |
+
if ( !strstr( $hexstr, '#' ) ) {
|
41 |
+
$hexstr = '#' . $hexstr;
|
42 |
}
|
43 |
+
if ( strlen( $hexstr ) == 4 ) {
|
44 |
+
$hexstr = '#' . $hexstr[1] . $hexstr[1] . $hexstr[2] . $hexstr[2] . $hexstr[3] . $hexstr[3];
|
45 |
}
|
46 |
+
$int = hexdec( $hexstr );
|
47 |
+
return array( "red" => 0xFF & ( $int >> 0x10 ), "green" => 0xFF & ( $int >> 0x8 ), "blue" => 0xFF & $int );
|
48 |
}
|
49 |
}
|
lib/integrations/acf-timber.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ACFTimber {
|
4 |
+
|
5 |
+
function __construct() {
|
6 |
+
add_filter( 'timber_post_get_meta', array( $this, 'post_get_meta' ), 10, 2 );
|
7 |
+
add_filter( 'timber_post_get_meta_field', array( $this, 'post_get_meta_field' ), 10, 3 );
|
8 |
+
add_filter( 'timber_term_get_meta', array( $this, 'term_get_meta' ), 10, 3 );
|
9 |
+
add_filter( 'timber_term_get_meta_field', array( $this, 'term_get_meta_field' ), 10, 4 );
|
10 |
+
add_filter( 'timber_user_get_meta_field_pre', array( $this, 'user_get_meta_field' ), 10, 3 );
|
11 |
+
add_filter( 'timber_term_set_meta', array( $this, 'term_set_meta'), 10, 4 );
|
12 |
+
}
|
13 |
+
|
14 |
+
function post_get_meta( $customs, $post_id ) {
|
15 |
+
return $customs;
|
16 |
+
}
|
17 |
+
|
18 |
+
function post_get_meta_field( $value, $post_id, $field_name ) {
|
19 |
+
return get_field( $field_name, $post_id );
|
20 |
+
}
|
21 |
+
|
22 |
+
function term_get_meta_field( $value, $term_id, $field_name, $term ) {
|
23 |
+
$searcher = $term->taxonomy . "_" . $term->ID;
|
24 |
+
return get_field( $field_name, $searcher );
|
25 |
+
}
|
26 |
+
|
27 |
+
function term_set_meta( $value, $field, $term_id, $term ) {
|
28 |
+
$searcher = $term->taxonomy . "_" . $term->ID;
|
29 |
+
update_field( $field, $value, $searcher );
|
30 |
+
return $value;
|
31 |
+
}
|
32 |
+
|
33 |
+
function term_get_meta( $fields, $term_id, $term ) {
|
34 |
+
$searcher = $term->taxonomy . "_" . $term->ID; // save to a specific category
|
35 |
+
$fds = get_fields( $searcher );
|
36 |
+
if ( is_array( $fds ) ) {
|
37 |
+
foreach ( $fds as $key => $value ) {
|
38 |
+
$key = preg_replace( '/_/', '', $key, 1 );
|
39 |
+
$key = str_replace( $searcher, '', $key );
|
40 |
+
$key = preg_replace( '/_/', '', $key, 1 );
|
41 |
+
$field = get_field( $key, $searcher );
|
42 |
+
$fields[$key] = $field;
|
43 |
+
}
|
44 |
+
$fields = array_merge( $fields, $fds );
|
45 |
+
}
|
46 |
+
return $fields;
|
47 |
+
}
|
48 |
+
|
49 |
+
function user_get_meta( $fields, $user_id ) {
|
50 |
+
return $fields;
|
51 |
+
}
|
52 |
+
|
53 |
+
function user_get_meta_field( $value, $uid, $field ) {
|
54 |
+
return get_field( $field, 'user_' . $uid );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
|
lib/integrations/timber-command.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* These are methods that can be executed by WPCLI, other CLI mechanism or other external controllers
|
5 |
+
* @package timber
|
6 |
+
*/
|
7 |
+
class TimberCommand {
|
8 |
+
|
9 |
+
public static function clear_cache($mode = 'all'){
|
10 |
+
if (is_array($mode)){
|
11 |
+
$mode = reset($mode);
|
12 |
+
}
|
13 |
+
if ($mode == 'all') {
|
14 |
+
$twig_cache = self::clear_cache_twig();
|
15 |
+
$timber_cache = self::clear_cache_timber();
|
16 |
+
if ($twig_cache && $timber_cache){
|
17 |
+
return true;
|
18 |
+
}
|
19 |
+
} else if ($mode == 'twig') {
|
20 |
+
return self::clear_cache_twig();
|
21 |
+
} else if ($mode == 'timber') {
|
22 |
+
return self::clear_cache_timber();
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
static function clear_cache_timber(){
|
27 |
+
$loader = new TimberLoader();
|
28 |
+
return $loader->clear_cache_timber();
|
29 |
+
}
|
30 |
+
|
31 |
+
static function clear_cache_twig(){
|
32 |
+
$loader = new TimberLoader();
|
33 |
+
return $loader->clear_cache_twig();
|
34 |
+
}
|
35 |
+
|
36 |
+
}
|
lib/integrations/wpcli-timber.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if (!class_exists('WP_CLI_Command')) {
|
3 |
+
return;
|
4 |
+
}
|
5 |
+
|
6 |
+
class Timber_WP_CLI_Command extends WP_CLI_Command {
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Clears Timber and Twig's Cache
|
10 |
+
*
|
11 |
+
* ## EXAMPLES
|
12 |
+
*
|
13 |
+
* wp timber clear_cache
|
14 |
+
*
|
15 |
+
*/
|
16 |
+
public function clear_cache($mode = 'all') {
|
17 |
+
TimberCommand::clear_cache($mode);
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Clears Twig's Cache
|
22 |
+
*
|
23 |
+
* ## EXAMPLES
|
24 |
+
*
|
25 |
+
* wp timber clear_cache_twig
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
function clear_cache_twig(){
|
29 |
+
$clear = TimberCommand::clear_cache_twig();
|
30 |
+
if ($clear){
|
31 |
+
WP_CLI::success('Cleared contents of twig cache');
|
32 |
+
} else {
|
33 |
+
WP_CLI::warning('Failed to clear twig cache');
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Clears Timber's Cache
|
39 |
+
*
|
40 |
+
* ## EXAMPLES
|
41 |
+
*
|
42 |
+
* wp timber clear_cache_timber
|
43 |
+
*
|
44 |
+
*/
|
45 |
+
function clear_cache_timber() {
|
46 |
+
$clear = TimberCommand::clear_cache_timber();
|
47 |
+
$message = 'Failed to clear timber cache';
|
48 |
+
if ($clear){
|
49 |
+
$message = "Cleared contents of Timber's Cache";
|
50 |
+
WP_CLI::success($message);
|
51 |
+
} else {
|
52 |
+
WP_CLI::warning($message);
|
53 |
+
}
|
54 |
+
return $message;
|
55 |
+
}
|
56 |
+
|
57 |
+
}
|
lib/timber-admin.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class TimberAdmin {
|
4 |
+
|
5 |
+
public static function init() {
|
6 |
+
$action = add_action('in_plugin_update_message-timber-library/timber.php', array(__CLASS__, 'in_plugin_update_message'), 10, 2);
|
7 |
+
|
8 |
+
return add_filter( 'plugin_row_meta', array( __CLASS__, 'meta_links' ), 10, 2 );
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param array $links
|
13 |
+
* @param string $file
|
14 |
+
* @return array
|
15 |
+
*/
|
16 |
+
public static function meta_links( $links, $file ) {
|
17 |
+
if ( strstr( $file, '/timber.php' ) ) {
|
18 |
+
unset($links[2]);
|
19 |
+
$links[] = '<a href="/wp-admin/plugin-install.php?tab=plugin-information&plugin=timber-library&TB_iframe=true&width=600&height=550" class="thickbox" aria-label="More information about Timber" data-title="Timber">View details</a>';
|
20 |
+
$links[] = '<a href="http://upstatement.com/timber" target="_blank">Homepage</a>';
|
21 |
+
$links[] = '<a href="https://github.com/jarednova/timber/wiki" target="_blank">Documentation</a>';
|
22 |
+
$links[] = '<a href="https://github.com/jarednova/timber/wiki/getting-started" target="_blank">Starter Guide</a>';
|
23 |
+
return $links;
|
24 |
+
}
|
25 |
+
return $links;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* in_plugin_update_message
|
30 |
+
*
|
31 |
+
* Displays an update message for plugin list screens.
|
32 |
+
* Shows only the version updates from the current until the newest version
|
33 |
+
*
|
34 |
+
* @type function
|
35 |
+
* @date 4/22/16
|
36 |
+
*
|
37 |
+
* @param {array} $plugin_data
|
38 |
+
* @param {object} $r
|
39 |
+
*/
|
40 |
+
public static function in_plugin_update_message( $plugin_data, $r ) {
|
41 |
+
$m = '<hr />';
|
42 |
+
if ( version_compare("1.0.0", $plugin_data['new_version'], "<=") ) {
|
43 |
+
$m .= '<p><b>Warning:</b> Timber 1.0 removed a number of features and methods. Before upgrading please test your theme on a local or staging site to ensure that your theme will work with the newest version.</p>';
|
44 |
+
|
45 |
+
} else if ( version_compare("1.0.0", $plugin_data['Version'], ">") ) {
|
46 |
+
$m .= '<p><b>Warning:</b> Timber 1.0 will remove a number of features and methods. Before upgrading please test your theme on a local or staging site to ensure that your theme will work with the newest version.</p>';
|
47 |
+
}
|
48 |
+
|
49 |
+
|
50 |
+
$m .= '<p><strong>Is your theme in active development?</strong> That is, is someone actively in PHP files writing new code? If you answered "no", then <i>do not upgrade to version 1.0</i>. You will not benefit from Timber 1.0</p>';
|
51 |
+
|
52 |
+
$m .= '<p>Read the <strong><a href="https://github.com/timber/timber/wiki/1.0-Upgrade-Guide">Upgrade Guide</a></strong> for more information</p>';
|
53 |
+
|
54 |
+
if ( version_compare("0.22.6", $plugin_data['Version']) > 0 ) {
|
55 |
+
$m .= "<p>You can <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";
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
|
60 |
+
|
61 |
+
|
62 |
+
// show message
|
63 |
+
echo '<br />'.sprintf($m, admin_url('edit.php?post_type=acf-field-group&page=acf-settings-updates'), 'http://www.advancedcustomfields.com/pro');
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
}
|
lib/{Archives.php → timber-archives.php}
RENAMED
@@ -1,13 +1,6 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\URLHelper;
|
7 |
-
|
8 |
/**
|
9 |
* The TimberArchives class is used to generate a menu based on the date archives of your posts. The [Nieman Foundation News site](http://nieman.harvard.edu/news/) has an example of how the output can be used in a real site ([screenshot](https://cloud.githubusercontent.com/assets/1298086/9610076/3cdca596-50a5-11e5-82fd-acb74c09c482.png)).
|
10 |
-
*
|
11 |
* @example
|
12 |
* ```php
|
13 |
* $context['archives'] = new TimberArchives( $args );
|
@@ -37,8 +30,8 @@ use Timber\URLHelper;
|
|
37 |
* </ul>
|
38 |
* ```
|
39 |
*/
|
40 |
-
class
|
41 |
-
|
42 |
public $base = '';
|
43 |
/**
|
44 |
* @api
|
@@ -62,8 +55,6 @@ class Archives extends Core {
|
|
62 |
* @param string $base any additional paths that need to be prepended to the URLs that are generated, for example: "tags"
|
63 |
*/
|
64 |
function __construct( $args = null, $base = '' ) {
|
65 |
-
|
66 |
-
|
67 |
$this->init($args, $base);
|
68 |
}
|
69 |
|
@@ -86,7 +77,7 @@ class Archives extends Core {
|
|
86 |
protected function get_archives_link( $url, $text ) {
|
87 |
$ret = array();
|
88 |
$ret['text'] = $ret['title'] = $ret['name'] = wptexturize($text);
|
89 |
-
$ret['url'] = $ret['link'] = esc_url(
|
90 |
return $ret;
|
91 |
}
|
92 |
|
@@ -106,13 +97,13 @@ class Archives extends Core {
|
|
106 |
$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";
|
107 |
$key = md5($query);
|
108 |
$key = "wp_get_archives:$key:$last_changed";
|
109 |
-
if (
|
110 |
$results = $wpdb->get_results($query);
|
111 |
wp_cache_set($key, $results, 'posts');
|
112 |
}
|
113 |
-
if (
|
114 |
-
foreach ( (array)
|
115 |
-
$url = get_year_link($result->year);
|
116 |
$text = sprintf('%d', $result->year);
|
117 |
$output[] = $this->get_archives_link($url, $text);
|
118 |
}
|
@@ -146,28 +137,28 @@ class Archives extends Core {
|
|
146 |
. "ORDER BY post_date $order $limit";
|
147 |
$key = md5($query);
|
148 |
$key = "wp_get_archives:$key:$last_changed";
|
149 |
-
if (
|
150 |
$results = $wpdb->get_results($query);
|
151 |
wp_cache_set($key, $results, 'posts');
|
152 |
}
|
153 |
-
if (
|
154 |
-
foreach (
|
155 |
$url = get_month_link($result->year, $result->month);
|
156 |
-
if (
|
157 |
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($result->month), $result->year);
|
158 |
} else {
|
159 |
$text = sprintf(__('%1$s'), $wp_locale->get_month($result->month));
|
160 |
}
|
161 |
-
if (
|
162 |
$output[$result->year][] = $this->get_archives_link($url, $text);
|
163 |
} else {
|
164 |
$output[] = $this->get_archives_link($url, $text);
|
165 |
}
|
166 |
}
|
167 |
}
|
168 |
-
if (
|
169 |
$out2 = array();
|
170 |
-
foreach (
|
171 |
$out2[] = array('name' => $year, 'children' => $months);
|
172 |
}
|
173 |
return $out2;
|
@@ -208,7 +199,7 @@ class Archives extends Core {
|
|
208 |
|
209 |
if ( !empty($args['limit']) ) {
|
210 |
$limit = absint($limit);
|
211 |
-
$limit = ' LIMIT '
|
212 |
}
|
213 |
|
214 |
$order = strtoupper($order);
|
@@ -229,7 +220,7 @@ class Archives extends Core {
|
|
229 |
$archive_week_start_date_format = 'Y/m/d';
|
230 |
$archive_week_end_date_format = 'Y/m/d';
|
231 |
|
232 |
-
if (
|
233 |
$archive_day_date_format = get_option('date_format');
|
234 |
$archive_week_start_date_format = get_option('date_format');
|
235 |
$archive_week_end_date_format = get_option('date_format');
|
@@ -241,7 +232,7 @@ class Archives extends Core {
|
|
241 |
|
242 |
$output = array();
|
243 |
$last_changed = wp_cache_get('last_changed', 'posts');
|
244 |
-
if (
|
245 |
$last_changed = microtime();
|
246 |
wp_cache_set('last_changed', $last_changed, 'posts');
|
247 |
}
|
@@ -255,14 +246,14 @@ class Archives extends Core {
|
|
255 |
$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";
|
256 |
$key = md5($query);
|
257 |
$key = "wp_get_archives:$key:$last_changed";
|
258 |
-
if (
|
259 |
$results = $wpdb->get_results($query);
|
260 |
$cache = array();
|
261 |
$cache[$key] = $results;
|
262 |
wp_cache_set($key, $results, 'posts');
|
263 |
}
|
264 |
if ( $results ) {
|
265 |
-
foreach ( (array)
|
266 |
$url = get_day_link($result->year, $result->month, $result->dayofmonth);
|
267 |
$date = sprintf('%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth);
|
268 |
$text = mysql2date($archive_day_date_format, $date);
|
@@ -275,13 +266,13 @@ class Archives extends Core {
|
|
275 |
. "count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
|
276 |
$key = md5($query);
|
277 |
$key = "wp_get_archives:$key:$last_changed";
|
278 |
-
if (
|
279 |
$results = $wpdb->get_results($query);
|
280 |
wp_cache_set($key, $results, 'posts');
|
281 |
}
|
282 |
$arc_w_last = '';
|
283 |
if ( $results ) {
|
284 |
-
foreach ( (array)
|
285 |
if ( $result->week != $arc_w_last ) {
|
286 |
$arc_year = $result->yr;
|
287 |
$arc_w_last = $result->week;
|
@@ -289,7 +280,7 @@ class Archives extends Core {
|
|
289 |
$arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']);
|
290 |
$arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']);
|
291 |
$url = sprintf('%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&', '=', $result->week);
|
292 |
-
$text = $arc_week_start
|
293 |
$output[] = $this->get_archives_link($url, $text);
|
294 |
}
|
295 |
}
|
@@ -304,10 +295,10 @@ class Archives extends Core {
|
|
304 |
wp_cache_set($key, $results, 'posts');
|
305 |
}
|
306 |
if ( $results ) {
|
307 |
-
foreach ( (array)
|
308 |
-
if (
|
309 |
$url = get_permalink($result);
|
310 |
-
if (
|
311 |
/** This filter is documented in wp-includes/post-template.php */
|
312 |
$text = strip_tags(apply_filters('the_title', $result->post_title, $result->ID));
|
313 |
} else {
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* The TimberArchives class is used to generate a menu based on the date archives of your posts. The [Nieman Foundation News site](http://nieman.harvard.edu/news/) has an example of how the output can be used in a real site ([screenshot](https://cloud.githubusercontent.com/assets/1298086/9610076/3cdca596-50a5-11e5-82fd-acb74c09c482.png)).
|
|
|
4 |
* @example
|
5 |
* ```php
|
6 |
* $context['archives'] = new TimberArchives( $args );
|
30 |
* </ul>
|
31 |
* ```
|
32 |
*/
|
33 |
+
class TimberArchives extends TimberCore {
|
34 |
+
|
35 |
public $base = '';
|
36 |
/**
|
37 |
* @api
|
55 |
* @param string $base any additional paths that need to be prepended to the URLs that are generated, for example: "tags"
|
56 |
*/
|
57 |
function __construct( $args = null, $base = '' ) {
|
|
|
|
|
58 |
$this->init($args, $base);
|
59 |
}
|
60 |
|
77 |
protected function get_archives_link( $url, $text ) {
|
78 |
$ret = array();
|
79 |
$ret['text'] = $ret['title'] = $ret['name'] = wptexturize($text);
|
80 |
+
$ret['url'] = $ret['link'] = esc_url(TimberURLHelper::prepend_to_url($url, $this->base));
|
81 |
return $ret;
|
82 |
}
|
83 |
|
97 |
$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";
|
98 |
$key = md5($query);
|
99 |
$key = "wp_get_archives:$key:$last_changed";
|
100 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
101 |
$results = $wpdb->get_results($query);
|
102 |
wp_cache_set($key, $results, 'posts');
|
103 |
}
|
104 |
+
if ($results) {
|
105 |
+
foreach ( (array)$results as $result ) {
|
106 |
+
$url = get_year_link( $result->year );
|
107 |
$text = sprintf('%d', $result->year);
|
108 |
$output[] = $this->get_archives_link($url, $text);
|
109 |
}
|
137 |
. "ORDER BY post_date $order $limit";
|
138 |
$key = md5($query);
|
139 |
$key = "wp_get_archives:$key:$last_changed";
|
140 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
141 |
$results = $wpdb->get_results($query);
|
142 |
wp_cache_set($key, $results, 'posts');
|
143 |
}
|
144 |
+
if ($results) {
|
145 |
+
foreach ((array)$results as $result) {
|
146 |
$url = get_month_link($result->year, $result->month);
|
147 |
+
if ($show_year && !$nested) {
|
148 |
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($result->month), $result->year);
|
149 |
} else {
|
150 |
$text = sprintf(__('%1$s'), $wp_locale->get_month($result->month));
|
151 |
}
|
152 |
+
if ($nested) {
|
153 |
$output[$result->year][] = $this->get_archives_link($url, $text);
|
154 |
} else {
|
155 |
$output[] = $this->get_archives_link($url, $text);
|
156 |
}
|
157 |
}
|
158 |
}
|
159 |
+
if ($nested) {
|
160 |
$out2 = array();
|
161 |
+
foreach ($output as $year => $months) {
|
162 |
$out2[] = array('name' => $year, 'children' => $months);
|
163 |
}
|
164 |
return $out2;
|
199 |
|
200 |
if ( !empty($args['limit']) ) {
|
201 |
$limit = absint($limit);
|
202 |
+
$limit = ' LIMIT ' . $limit;
|
203 |
}
|
204 |
|
205 |
$order = strtoupper($order);
|
220 |
$archive_week_start_date_format = 'Y/m/d';
|
221 |
$archive_week_end_date_format = 'Y/m/d';
|
222 |
|
223 |
+
if (!$archive_date_format_over_ride) {
|
224 |
$archive_day_date_format = get_option('date_format');
|
225 |
$archive_week_start_date_format = get_option('date_format');
|
226 |
$archive_week_end_date_format = get_option('date_format');
|
232 |
|
233 |
$output = array();
|
234 |
$last_changed = wp_cache_get('last_changed', 'posts');
|
235 |
+
if (!$last_changed) {
|
236 |
$last_changed = microtime();
|
237 |
wp_cache_set('last_changed', $last_changed, 'posts');
|
238 |
}
|
246 |
$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";
|
247 |
$key = md5($query);
|
248 |
$key = "wp_get_archives:$key:$last_changed";
|
249 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
250 |
$results = $wpdb->get_results($query);
|
251 |
$cache = array();
|
252 |
$cache[$key] = $results;
|
253 |
wp_cache_set($key, $results, 'posts');
|
254 |
}
|
255 |
if ( $results ) {
|
256 |
+
foreach ( (array)$results as $result ) {
|
257 |
$url = get_day_link($result->year, $result->month, $result->dayofmonth);
|
258 |
$date = sprintf('%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth);
|
259 |
$text = mysql2date($archive_day_date_format, $date);
|
266 |
. "count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
|
267 |
$key = md5($query);
|
268 |
$key = "wp_get_archives:$key:$last_changed";
|
269 |
+
if (!$results = wp_cache_get($key, 'posts')) {
|
270 |
$results = $wpdb->get_results($query);
|
271 |
wp_cache_set($key, $results, 'posts');
|
272 |
}
|
273 |
$arc_w_last = '';
|
274 |
if ( $results ) {
|
275 |
+
foreach ( (array)$results as $result ) {
|
276 |
if ( $result->week != $arc_w_last ) {
|
277 |
$arc_year = $result->yr;
|
278 |
$arc_w_last = $result->week;
|
280 |
$arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']);
|
281 |
$arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']);
|
282 |
$url = sprintf('%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&', '=', $result->week);
|
283 |
+
$text = $arc_week_start . $archive_week_separator . $arc_week_end;
|
284 |
$output[] = $this->get_archives_link($url, $text);
|
285 |
}
|
286 |
}
|
295 |
wp_cache_set($key, $results, 'posts');
|
296 |
}
|
297 |
if ( $results ) {
|
298 |
+
foreach ( (array)$results as $result ) {
|
299 |
+
if ($result->post_date != '0000-00-00 00:00:00') {
|
300 |
$url = get_permalink($result);
|
301 |
+
if ($result->post_title) {
|
302 |
/** This filter is documented in wp-includes/post-template.php */
|
303 |
$text = strip_tags(apply_filters('the_title', $result->post_title, $result->ID));
|
304 |
} else {
|
lib/{Comment.php → timber-comment.php}
RENAMED
@@ -1,11 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\User;
|
6 |
-
use Timber\Core;
|
7 |
-
use Timber\CoreInterface;
|
8 |
-
|
9 |
/**
|
10 |
* The TimberComment class is used to view the output of comments. 99% of the time this will be in the context of the comments on a post. However you can also fetch a comment directly using its comment ID.
|
11 |
* @example
|
@@ -25,9 +19,9 @@ use Timber\CoreInterface;
|
|
25 |
* <p class="comment-attribution">- Sullivan Ballou</p>
|
26 |
* ```
|
27 |
*/
|
28 |
-
class
|
29 |
|
30 |
-
public $PostClass = '
|
31 |
public $object_type = 'comment';
|
32 |
|
33 |
public static $representation = 'comment';
|
@@ -46,7 +40,7 @@ class Comment extends Core implements CoreInterface {
|
|
46 |
/**
|
47 |
* @param int $cid
|
48 |
*/
|
49 |
-
function __construct(
|
50 |
$this->init($cid);
|
51 |
}
|
52 |
|
@@ -58,9 +52,9 @@ class Comment extends Core implements CoreInterface {
|
|
58 |
* @internal
|
59 |
* @param integer $cid
|
60 |
*/
|
61 |
-
function init(
|
62 |
$comment_data = $cid;
|
63 |
-
if (
|
64 |
$comment_data = get_comment($cid);
|
65 |
}
|
66 |
$this->import($comment_data);
|
@@ -89,14 +83,14 @@ class Comment extends Core implements CoreInterface {
|
|
89 |
* <li>Rebecca Pearl, who is a author</li>
|
90 |
* </ol>
|
91 |
* ```
|
92 |
-
* @return
|
93 |
*/
|
94 |
public function author() {
|
95 |
-
if (
|
96 |
-
return new
|
97 |
} else {
|
98 |
-
$author = new
|
99 |
-
if (
|
100 |
$author->name = $this->comment_author;
|
101 |
} else {
|
102 |
$author->name = 'Anonymous';
|
@@ -119,22 +113,22 @@ class Comment extends Core implements CoreInterface {
|
|
119 |
* @param string $default
|
120 |
* @return bool|mixed|string
|
121 |
*/
|
122 |
-
public function avatar(
|
123 |
-
if (
|
124 |
return false;
|
125 |
}
|
126 |
-
if (
|
127 |
$size = '92';
|
128 |
}
|
129 |
|
130 |
$email = $this->avatar_email();
|
131 |
$email_hash = '';
|
132 |
-
if (
|
133 |
$email_hash = md5(strtolower(trim($email)));
|
134 |
}
|
135 |
$host = $this->avatar_host($email_hash);
|
136 |
$default = $this->avatar_default($default, $email, $size, $host);
|
137 |
-
if (
|
138 |
$avatar = $this->avatar_out($default, $host, $email_hash, $size);
|
139 |
} else {
|
140 |
$avatar = $default;
|
@@ -187,7 +181,7 @@ class Comment extends Core implements CoreInterface {
|
|
187 |
*/
|
188 |
public function date( $date_format = '' ) {
|
189 |
$df = $date_format ? $date_format : get_option('date_format');
|
190 |
-
$the_date = (string)
|
191 |
return apply_filters('get_comment_date ', $the_date, $df);
|
192 |
}
|
193 |
|
@@ -212,7 +206,7 @@ class Comment extends Core implements CoreInterface {
|
|
212 |
*/
|
213 |
public function time( $time_format = '' ) {
|
214 |
$tf = $time_format ? $time_format : get_option('time_format');
|
215 |
-
$the_time = (string)
|
216 |
return apply_filters('get_comment_time', $the_time, $tf);
|
217 |
}
|
218 |
|
@@ -220,7 +214,7 @@ class Comment extends Core implements CoreInterface {
|
|
220 |
* @param string $field_name
|
221 |
* @return mixed
|
222 |
*/
|
223 |
-
public function meta(
|
224 |
return $this->get_meta_field($field_name);
|
225 |
}
|
226 |
|
@@ -237,15 +231,15 @@ class Comment extends Core implements CoreInterface {
|
|
237 |
* @param int $comment_id
|
238 |
* @return mixed
|
239 |
*/
|
240 |
-
protected function get_meta_fields(
|
241 |
-
if (
|
242 |
$comment_id = $this->ID;
|
243 |
}
|
244 |
//Could not find a WP function to fetch all comment meta data, so I made one.
|
245 |
apply_filters('timber_comment_get_meta_pre', array(), $comment_id);
|
246 |
$comment_metas = get_comment_meta($comment_id);
|
247 |
-
foreach (
|
248 |
-
if (
|
249 |
$cm = $cm[0];
|
250 |
}
|
251 |
}
|
@@ -254,14 +248,13 @@ class Comment extends Core implements CoreInterface {
|
|
254 |
}
|
255 |
|
256 |
/**
|
257 |
-
*
|
258 |
* @internal
|
259 |
* @param string $field_name
|
260 |
* @return mixed
|
261 |
*/
|
262 |
-
protected function get_meta_field(
|
263 |
$value = apply_filters('timber_comment_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
264 |
-
if (
|
265 |
$value = get_comment_meta($this->ID, $field_name, true);
|
266 |
}
|
267 |
$value = apply_filters('timber_comment_get_meta_field', $value, $this->ID, $field_name, $this);
|
@@ -276,7 +269,7 @@ class Comment extends Core implements CoreInterface {
|
|
276 |
*/
|
277 |
public function reply_link( $reply_text = 'Reply' ) {
|
278 |
if ( is_singular() && comments_open() && get_option('thread_comments') ) {
|
279 |
-
wp_enqueue_script('comment-reply');
|
280 |
}
|
281 |
|
282 |
// Get the comments depth option from the admin panel
|
@@ -291,7 +284,7 @@ class Comment extends Core implements CoreInterface {
|
|
291 |
'max_depth' => $max_depth,
|
292 |
);
|
293 |
|
294 |
-
return get_comment_reply_link($args, $this->ID, $this->post_id);
|
295 |
}
|
296 |
|
297 |
/* AVATAR Stuff
|
@@ -302,9 +295,9 @@ class Comment extends Core implements CoreInterface {
|
|
302 |
* @return string
|
303 |
*/
|
304 |
protected function avatar_email() {
|
305 |
-
$id = (int)
|
306 |
$user = get_userdata($id);
|
307 |
-
if (
|
308 |
$email = $user->user_email;
|
309 |
} else {
|
310 |
$email = $this->comment_author_email;
|
@@ -317,11 +310,11 @@ class Comment extends Core implements CoreInterface {
|
|
317 |
* @param string $email_hash
|
318 |
* @return string
|
319 |
*/
|
320 |
-
protected function avatar_host(
|
321 |
-
if (
|
322 |
$host = 'https://secure.gravatar.com';
|
323 |
} else {
|
324 |
-
if (
|
325 |
$host = sprintf("http://%d.gravatar.com", (hexdec($email_hash[0]) % 2));
|
326 |
} else {
|
327 |
$host = 'http://0.gravatar.com';
|
@@ -339,30 +332,30 @@ class Comment extends Core implements CoreInterface {
|
|
339 |
* @param string $host
|
340 |
* @return string
|
341 |
*/
|
342 |
-
protected function avatar_default(
|
343 |
-
if (
|
344 |
-
$default = home_url()
|
345 |
}
|
346 |
|
347 |
-
if (
|
348 |
$avatar_default = get_option('avatar_default');
|
349 |
-
if (
|
350 |
$default = 'mystery';
|
351 |
} else {
|
352 |
$default = $avatar_default;
|
353 |
}
|
354 |
}
|
355 |
-
if (
|
356 |
-
$default = $host.'/avatar/ad516503a11cd5ca435acc9bb6523536?s='
|
357 |
// ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com')
|
358 |
-
} else if (
|
359 |
$default = $email ? 'blank' : includes_url('images/blank.gif');
|
360 |
-
} else if (
|
361 |
$default = '';
|
362 |
-
} else if (
|
363 |
-
$default = $host.'/avatar/?s='
|
364 |
-
} else if (
|
365 |
-
$default = $host.'/avatar/?d='
|
366 |
}
|
367 |
return $default;
|
368 |
}
|
@@ -375,13 +368,13 @@ class Comment extends Core implements CoreInterface {
|
|
375 |
* @param string $size
|
376 |
* @return mixed
|
377 |
*/
|
378 |
-
protected function avatar_out(
|
379 |
-
$out = $host.'/avatar/'
|
380 |
$rating = get_option('avatar_rating');
|
381 |
-
if (
|
382 |
-
$out .= '&r='
|
383 |
}
|
384 |
return str_replace('&', '&', esc_url($out));
|
385 |
}
|
386 |
|
387 |
-
}
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* The TimberComment class is used to view the output of comments. 99% of the time this will be in the context of the comments on a post. However you can also fetch a comment directly using its comment ID.
|
5 |
* @example
|
19 |
* <p class="comment-attribution">- Sullivan Ballou</p>
|
20 |
* ```
|
21 |
*/
|
22 |
+
class TimberComment extends TimberCore implements TimberCoreInterface {
|
23 |
|
24 |
+
public $PostClass = 'TimberPost';
|
25 |
public $object_type = 'comment';
|
26 |
|
27 |
public static $representation = 'comment';
|
40 |
/**
|
41 |
* @param int $cid
|
42 |
*/
|
43 |
+
function __construct($cid) {
|
44 |
$this->init($cid);
|
45 |
}
|
46 |
|
52 |
* @internal
|
53 |
* @param integer $cid
|
54 |
*/
|
55 |
+
function init($cid) {
|
56 |
$comment_data = $cid;
|
57 |
+
if (is_integer($cid)) {
|
58 |
$comment_data = get_comment($cid);
|
59 |
}
|
60 |
$this->import($comment_data);
|
83 |
* <li>Rebecca Pearl, who is a author</li>
|
84 |
* </ol>
|
85 |
* ```
|
86 |
+
* @return TimberUser
|
87 |
*/
|
88 |
public function author() {
|
89 |
+
if ($this->user_id) {
|
90 |
+
return new TimberUser($this->user_id);
|
91 |
} else {
|
92 |
+
$author = new TimberUser(0);
|
93 |
+
if (isset($this->comment_author) && $this->comment_author) {
|
94 |
$author->name = $this->comment_author;
|
95 |
} else {
|
96 |
$author->name = 'Anonymous';
|
113 |
* @param string $default
|
114 |
* @return bool|mixed|string
|
115 |
*/
|
116 |
+
public function avatar($size = 92, $default = '') {
|
117 |
+
if (!get_option('show_avatars')) {
|
118 |
return false;
|
119 |
}
|
120 |
+
if (!is_numeric($size)) {
|
121 |
$size = '92';
|
122 |
}
|
123 |
|
124 |
$email = $this->avatar_email();
|
125 |
$email_hash = '';
|
126 |
+
if (!empty($email)) {
|
127 |
$email_hash = md5(strtolower(trim($email)));
|
128 |
}
|
129 |
$host = $this->avatar_host($email_hash);
|
130 |
$default = $this->avatar_default($default, $email, $size, $host);
|
131 |
+
if (!empty($email)) {
|
132 |
$avatar = $this->avatar_out($default, $host, $email_hash, $size);
|
133 |
} else {
|
134 |
$avatar = $default;
|
181 |
*/
|
182 |
public function date( $date_format = '' ) {
|
183 |
$df = $date_format ? $date_format : get_option('date_format');
|
184 |
+
$the_date = (string)mysql2date($df, $this->comment_date);
|
185 |
return apply_filters('get_comment_date ', $the_date, $df);
|
186 |
}
|
187 |
|
206 |
*/
|
207 |
public function time( $time_format = '' ) {
|
208 |
$tf = $time_format ? $time_format : get_option('time_format');
|
209 |
+
$the_time = (string)mysql2date($tf, $this->comment_date);
|
210 |
return apply_filters('get_comment_time', $the_time, $tf);
|
211 |
}
|
212 |
|
214 |
* @param string $field_name
|
215 |
* @return mixed
|
216 |
*/
|
217 |
+
public function meta($field_name) {
|
218 |
return $this->get_meta_field($field_name);
|
219 |
}
|
220 |
|
231 |
* @param int $comment_id
|
232 |
* @return mixed
|
233 |
*/
|
234 |
+
protected function get_meta_fields($comment_id = null) {
|
235 |
+
if ($comment_id === null) {
|
236 |
$comment_id = $this->ID;
|
237 |
}
|
238 |
//Could not find a WP function to fetch all comment meta data, so I made one.
|
239 |
apply_filters('timber_comment_get_meta_pre', array(), $comment_id);
|
240 |
$comment_metas = get_comment_meta($comment_id);
|
241 |
+
foreach ($comment_metas as &$cm) {
|
242 |
+
if (is_array($cm) && count($cm) == 1) {
|
243 |
$cm = $cm[0];
|
244 |
}
|
245 |
}
|
248 |
}
|
249 |
|
250 |
/**
|
|
|
251 |
* @internal
|
252 |
* @param string $field_name
|
253 |
* @return mixed
|
254 |
*/
|
255 |
+
protected function get_meta_field($field_name) {
|
256 |
$value = apply_filters('timber_comment_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
257 |
+
if ($value === null) {
|
258 |
$value = get_comment_meta($this->ID, $field_name, true);
|
259 |
}
|
260 |
$value = apply_filters('timber_comment_get_meta_field', $value, $this->ID, $field_name, $this);
|
269 |
*/
|
270 |
public function reply_link( $reply_text = 'Reply' ) {
|
271 |
if ( is_singular() && comments_open() && get_option('thread_comments') ) {
|
272 |
+
wp_enqueue_script( 'comment-reply' );
|
273 |
}
|
274 |
|
275 |
// Get the comments depth option from the admin panel
|
284 |
'max_depth' => $max_depth,
|
285 |
);
|
286 |
|
287 |
+
return get_comment_reply_link( $args, $this->ID, $this->post_id );
|
288 |
}
|
289 |
|
290 |
/* AVATAR Stuff
|
295 |
* @return string
|
296 |
*/
|
297 |
protected function avatar_email() {
|
298 |
+
$id = (int)$this->user_id;
|
299 |
$user = get_userdata($id);
|
300 |
+
if ($user) {
|
301 |
$email = $user->user_email;
|
302 |
} else {
|
303 |
$email = $this->comment_author_email;
|
310 |
* @param string $email_hash
|
311 |
* @return string
|
312 |
*/
|
313 |
+
protected function avatar_host($email_hash) {
|
314 |
+
if (is_ssl()) {
|
315 |
$host = 'https://secure.gravatar.com';
|
316 |
} else {
|
317 |
+
if (!empty($email_hash)) {
|
318 |
$host = sprintf("http://%d.gravatar.com", (hexdec($email_hash[0]) % 2));
|
319 |
} else {
|
320 |
$host = 'http://0.gravatar.com';
|
332 |
* @param string $host
|
333 |
* @return string
|
334 |
*/
|
335 |
+
protected function avatar_default($default, $email, $size, $host) {
|
336 |
+
if (substr($default, 0, 1) == '/') {
|
337 |
+
$default = home_url() . $default;
|
338 |
}
|
339 |
|
340 |
+
if (empty($default)) {
|
341 |
$avatar_default = get_option('avatar_default');
|
342 |
+
if (empty($avatar_default)) {
|
343 |
$default = 'mystery';
|
344 |
} else {
|
345 |
$default = $avatar_default;
|
346 |
}
|
347 |
}
|
348 |
+
if ('mystery' == $default) {
|
349 |
+
$default = $host . '/avatar/ad516503a11cd5ca435acc9bb6523536?s=' . $size;
|
350 |
// ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com')
|
351 |
+
} else if ('blank' == $default) {
|
352 |
$default = $email ? 'blank' : includes_url('images/blank.gif');
|
353 |
+
} else if (!empty($email) && 'gravatar_default' == $default) {
|
354 |
$default = '';
|
355 |
+
} else if ('gravatar_default' == $default) {
|
356 |
+
$default = $host . '/avatar/?s=' . $size;
|
357 |
+
} else if (empty($email) && !strstr($default, 'http://')) {
|
358 |
+
$default = $host . '/avatar/?d=' . $default . '&s=' . $size;
|
359 |
}
|
360 |
return $default;
|
361 |
}
|
368 |
* @param string $size
|
369 |
* @return mixed
|
370 |
*/
|
371 |
+
protected function avatar_out($default, $host, $email_hash, $size) {
|
372 |
+
$out = $host . '/avatar/' . $email_hash . '?s=' . $size . '&d=' . urlencode($default);
|
373 |
$rating = get_option('avatar_rating');
|
374 |
+
if (!empty($rating)) {
|
375 |
+
$out .= '&r=' . $rating;
|
376 |
}
|
377 |
return str_replace('&', '&', esc_url($out));
|
378 |
}
|
379 |
|
380 |
+
}
|
lib/{CoreInterface.php → timber-core-interface.php}
RENAMED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
interface CoreInterface {
|
6 |
|
7 |
public function __call( $field, $args );
|
8 |
|
1 |
<?php
|
2 |
|
3 |
+
interface TimberCoreInterface {
|
|
|
|
|
4 |
|
5 |
public function __call( $field, $args );
|
6 |
|
lib/timber-core.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class TimberCore {
|
4 |
+
|
5 |
+
public $id;
|
6 |
+
public $ID;
|
7 |
+
public $object_type;
|
8 |
+
|
9 |
+
/**
|
10 |
+
*
|
11 |
+
*
|
12 |
+
* @return boolean
|
13 |
+
*/
|
14 |
+
function __isset( $field ) {
|
15 |
+
if ( isset( $this->$field ) ) {
|
16 |
+
return $this->$field;
|
17 |
+
}
|
18 |
+
return false;
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* This is helpful for twig to return properties and methods see: https://github.com/fabpot/Twig/issues/2
|
23 |
+
* @return mixed
|
24 |
+
*/
|
25 |
+
function __call( $field, $args ) {
|
26 |
+
return $this->__get( $field );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* This is helpful for twig to return properties and methods see: https://github.com/fabpot/Twig/issues/2
|
31 |
+
*
|
32 |
+
* @return mixed
|
33 |
+
*/
|
34 |
+
function __get( $field ) {
|
35 |
+
if ( property_exists($this, $field) ) {
|
36 |
+
return $this->$field;
|
37 |
+
}
|
38 |
+
if ( method_exists($this, 'meta') && $meta_value = $this->meta( $field ) ) {
|
39 |
+
return $this->$field = $meta_value;
|
40 |
+
}
|
41 |
+
if ( method_exists($this, $field) ) {
|
42 |
+
return $this->$field = $this->$field();
|
43 |
+
}
|
44 |
+
return $this->$field = false;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Takes an array or object and adds the properties to the parent object
|
49 |
+
* @example
|
50 |
+
* ```php
|
51 |
+
* $data = array('airplane' => '757-200', 'flight' => '5316');
|
52 |
+
* $post = new TimberPost()
|
53 |
+
* $post->import(data);
|
54 |
+
* echo $post->airplane; //757-200
|
55 |
+
* ```
|
56 |
+
* @param array|object $info an object or array you want to grab data from to attach to the Timber object
|
57 |
+
*/
|
58 |
+
function import( $info, $force = false ) {
|
59 |
+
if ( is_object( $info ) ) {
|
60 |
+
$info = get_object_vars( $info );
|
61 |
+
}
|
62 |
+
if ( is_array( $info ) ) {
|
63 |
+
foreach ( $info as $key => $value ) {
|
64 |
+
if ( !empty( $key ) && $force ) {
|
65 |
+
$this->$key = $value;
|
66 |
+
} else if ( !empty( $key ) && !method_exists($this, $key) ){
|
67 |
+
$this->$key = $value;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @ignore
|
76 |
+
* @param string $key
|
77 |
+
* @param mixed $value
|
78 |
+
*/
|
79 |
+
function update( $key, $value ) {
|
80 |
+
update_metadata( $this->object_type, $this->ID, $key, $value );
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Can you edit this post/term/user? Well good for you. You're no better than me.
|
85 |
+
* @example
|
86 |
+
* ```twig
|
87 |
+
* {% if post.can_edit %}
|
88 |
+
* <a href="{{ post.edit_link }}">Edit</a>
|
89 |
+
* {% endif %}
|
90 |
+
* ```
|
91 |
+
* ```html
|
92 |
+
* <a href="http://example.org/wp-admin/edit.php?p=242">Edit</a>
|
93 |
+
* ```
|
94 |
+
* @return bool
|
95 |
+
*/
|
96 |
+
function can_edit() {
|
97 |
+
if ( !function_exists( 'current_user_can' ) ) {
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
if ( current_user_can( 'edit_post', $this->ID ) ) {
|
101 |
+
return true;
|
102 |
+
}
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
*
|
108 |
+
*
|
109 |
+
* @return array
|
110 |
+
*/
|
111 |
+
function get_method_values() {
|
112 |
+
$ret = array();
|
113 |
+
$ret['can_edit'] = $this->can_edit();
|
114 |
+
return $ret;
|
115 |
+
}
|
116 |
+
|
117 |
+
}
|
lib/timber-function-wrapper.php
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class TimberFunctionWrapper {
|
4 |
+
|
5 |
+
private $_class;
|
6 |
+
private $_function;
|
7 |
+
private $_args;
|
8 |
+
private $_use_ob;
|
9 |
+
|
10 |
+
public function __toString() {
|
11 |
+
try {
|
12 |
+
return (string)$this->call();
|
13 |
+
} catch (Exception $e) {
|
14 |
+
return 'Caught exception: ' . $e->getMessage() . "\n";
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
*
|
20 |
+
*
|
21 |
+
* @param callable $function
|
22 |
+
* @param array $args
|
23 |
+
* @param bool $return_output_buffer
|
24 |
+
*/
|
25 |
+
public function __construct( $function, $args = array(), $return_output_buffer = false ) {
|
26 |
+
if( is_array( $function ) ) {
|
27 |
+
if( (is_string( $function[0] ) && class_exists( $function[0] ) ) || gettype( $function[0] ) === 'object' ) {
|
28 |
+
$this->_class = $function[0];
|
29 |
+
}
|
30 |
+
|
31 |
+
if( is_string( $function[1] ) ) $this->_function = $function[1];
|
32 |
+
} else {
|
33 |
+
$this->_function = $function;
|
34 |
+
}
|
35 |
+
|
36 |
+
$this->_args = $args;
|
37 |
+
$this->_use_ob = $return_output_buffer;
|
38 |
+
|
39 |
+
add_filter( 'get_twig', array( &$this, 'add_to_twig' ) );
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
*
|
45 |
+
* @param Twig_Environment $twig
|
46 |
+
* @return Twig_Environment
|
47 |
+
*/
|
48 |
+
public function add_to_twig( $twig ) {
|
49 |
+
$wrapper = $this;
|
50 |
+
|
51 |
+
$twig->addFunction( new Twig_SimpleFunction( $this->_function, function () use ( $wrapper ) {
|
52 |
+
return call_user_func_array( array( $wrapper, 'call' ), func_get_args() );
|
53 |
+
} ) );
|
54 |
+
|
55 |
+
return $twig;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
*
|
60 |
+
*
|
61 |
+
* @return string
|
62 |
+
*/
|
63 |
+
public function call() {
|
64 |
+
$args = $this->_parse_args( func_get_args(), $this->_args );
|
65 |
+
$callable = ( isset( $this->_class ) ) ? array( $this->_class, $this->_function ) : $this->_function;
|
66 |
+
|
67 |
+
if ( $this->_use_ob ) {
|
68 |
+
return TimberHelper::ob_function( $callable, $args );
|
69 |
+
} else {
|
70 |
+
return call_user_func_array( $callable, $args );
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
*
|
76 |
+
*
|
77 |
+
* @param array $args
|
78 |
+
* @param array $defaults
|
79 |
+
* @return array
|
80 |
+
*/
|
81 |
+
private function _parse_args( $args, $defaults ) {
|
82 |
+
$_arg = reset( $defaults );
|
83 |
+
|
84 |
+
foreach ( $args as $index => $arg ) {
|
85 |
+
$defaults[$index] = is_null( $arg ) ? $_arg : $arg;
|
86 |
+
$_arg = next( $defaults );
|
87 |
+
}
|
88 |
+
|
89 |
+
return $defaults;
|
90 |
+
}
|
91 |
+
|
92 |
+
}
|
lib/{Helper.php → timber-helper.php}
RENAMED
@@ -1,14 +1,9 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\FunctionWrapper;
|
6 |
-
use Timber\URLHelper;
|
7 |
-
|
8 |
/**
|
9 |
* As the name suggests these are helpers for Timber (and you!) when developing. You can find additional (mainly internally-focused helpers) in TimberURLHelper
|
10 |
*/
|
11 |
-
class
|
12 |
|
13 |
/**
|
14 |
* A utility for a one-stop shop for Transients
|
@@ -31,17 +26,17 @@ class Helper {
|
|
31 |
* @return mixed
|
32 |
*/
|
33 |
public static function transient( $slug, $callback, $transient_time = 0, $lock_timeout = 5, $force = false ) {
|
34 |
-
$slug = apply_filters('timber/transient/slug', $slug);
|
35 |
|
36 |
-
$enable_transients = ($transient_time === false || (defined('WP_DISABLE_TRANSIENTS') && WP_DISABLE_TRANSIENTS)) ? false : true;
|
37 |
-
$data = $enable_transients ? get_transient($slug) : false;
|
38 |
|
39 |
if ( false === $data ) {
|
40 |
|
41 |
-
if ( $enable_transients && self::_is_transient_locked($slug) ) {
|
42 |
|
43 |
-
$force = apply_filters('timber_force_transients', $force);
|
44 |
-
$force = apply_filters('timber_force_transient_'
|
45 |
|
46 |
if ( !$force ) {
|
47 |
//the server is currently executing the process.
|
@@ -54,15 +49,14 @@ class Helper {
|
|
54 |
|
55 |
// lock timeout shouldn't be higher than 5 seconds, unless
|
56 |
// remote calls with high timeouts are made here
|
57 |
-
if ( $enable_transients )
|
58 |
-
|
59 |
-
}
|
60 |
|
61 |
$data = $callback();
|
62 |
|
63 |
if ( $enable_transients ) {
|
64 |
-
set_transient($slug, $data, $transient_time);
|
65 |
-
self::_unlock_transient($slug);
|
66 |
}
|
67 |
|
68 |
}
|
@@ -77,7 +71,7 @@ class Helper {
|
|
77 |
* @param integer $lock_timeout
|
78 |
*/
|
79 |
static function _lock_transient( $slug, $lock_timeout ) {
|
80 |
-
set_transient($slug.'_lock', true, $lock_timeout);
|
81 |
}
|
82 |
|
83 |
/**
|
@@ -85,7 +79,7 @@ class Helper {
|
|
85 |
* @param string $slug
|
86 |
*/
|
87 |
static function _unlock_transient( $slug ) {
|
88 |
-
delete_transient($slug.'_lock', true);
|
89 |
}
|
90 |
|
91 |
/**
|
@@ -93,7 +87,7 @@ class Helper {
|
|
93 |
* @param string $slug
|
94 |
*/
|
95 |
static function _is_transient_locked( $slug ) {
|
96 |
-
return (bool)
|
97 |
}
|
98 |
|
99 |
/* These are for measuring page render time */
|
@@ -105,7 +99,7 @@ class Helper {
|
|
105 |
*/
|
106 |
public static function start_timer() {
|
107 |
$time = microtime();
|
108 |
-
$time = explode(' ', $time);
|
109 |
$time = $time[1] + $time[0];
|
110 |
return $time;
|
111 |
}
|
@@ -123,11 +117,11 @@ class Helper {
|
|
123 |
*/
|
124 |
public static function stop_timer( $start ) {
|
125 |
$time = microtime();
|
126 |
-
$time = explode(' ', $time);
|
127 |
$time = $time[1] + $time[0];
|
128 |
$finish = $time;
|
129 |
-
$total_time = round(($finish - $start), 4);
|
130 |
-
return $total_time.' seconds.';
|
131 |
}
|
132 |
|
133 |
/* Function Utilities
|
@@ -159,22 +153,24 @@ class Helper {
|
|
159 |
* @param array $args
|
160 |
* @return string
|
161 |
*/
|
162 |
-
public static function ob_function( $function, $args = array(null) ) {
|
163 |
ob_start();
|
164 |
-
call_user_func_array($function, $args);
|
165 |
$data = ob_get_contents();
|
166 |
ob_end_clean();
|
167 |
return $data;
|
168 |
}
|
169 |
|
170 |
/**
|
171 |
-
*
|
172 |
-
*
|
173 |
-
* @param
|
174 |
-
* @
|
|
|
|
|
175 |
*/
|
176 |
public static function function_wrapper( $function_name, $defaults = array(), $return_output_buffer = false ) {
|
177 |
-
return new
|
178 |
}
|
179 |
|
180 |
/**
|
@@ -187,20 +183,12 @@ class Helper {
|
|
187 |
if ( !WP_DEBUG ) {
|
188 |
return;
|
189 |
}
|
190 |
-
if ( is_object($arg) || is_array($arg) ) {
|
191 |
-
$arg = print_r($arg, true);
|
192 |
}
|
193 |
-
return error_log($arg);
|
194 |
}
|
195 |
|
196 |
-
/**
|
197 |
-
* @param string $message that you want to output
|
198 |
-
* @return void
|
199 |
-
*/
|
200 |
-
public static function warn( $message ) {
|
201 |
-
return trigger_error($message, E_USER_WARNING);
|
202 |
-
}
|
203 |
-
|
204 |
/**
|
205 |
*
|
206 |
*
|
@@ -209,8 +197,8 @@ class Helper {
|
|
209 |
* @return string
|
210 |
*/
|
211 |
public static function get_wp_title( $separator = ' ', $seplocation = 'left' ) {
|
212 |
-
$separator = apply_filters('timber_wp_title_seperator', $separator);
|
213 |
-
return trim(wp_title($separator, false, $seplocation));
|
214 |
}
|
215 |
|
216 |
/* Text Utilities
|
@@ -227,33 +215,33 @@ class Helper {
|
|
227 |
*/
|
228 |
public static function trim_words( $text, $num_words = 55, $more = null, $allowed_tags = 'p a span b i br blockquote' ) {
|
229 |
if ( null === $more ) {
|
230 |
-
$more = __('…');
|
231 |
}
|
232 |
$original_text = $text;
|
233 |
$allowed_tag_string = '';
|
234 |
-
foreach ( explode(' ', apply_filters('timber/trim_words/allowed_tags', $allowed_tags)) as $tag ) {
|
235 |
-
$allowed_tag_string .= '<'
|
236 |
}
|
237 |
-
$text = strip_tags($text, $allowed_tag_string);
|
238 |
/* translators: If your word count is based on single characters (East Asian characters), enter 'characters'. Otherwise, enter 'words'. Do not translate into your own language. */
|
239 |
-
if ( 'characters' == _x('words', 'word count: words or characters?') && preg_match('/^utf\-?8$/i', get_option('blog_charset')) ) {
|
240 |
-
$text = trim(preg_replace("/[\n\r\t ]+/", ' ', $text), ' ');
|
241 |
-
preg_match_all('/./u', $text, $words_array);
|
242 |
-
$words_array = array_slice($words_array[0], 0, $num_words + 1);
|
243 |
$sep = '';
|
244 |
} else {
|
245 |
-
$words_array = preg_split("/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY);
|
246 |
$sep = ' ';
|
247 |
}
|
248 |
-
if ( count($words_array) > $num_words ) {
|
249 |
-
array_pop($words_array);
|
250 |
-
$text = implode($sep, $words_array);
|
251 |
-
$text = $text
|
252 |
} else {
|
253 |
-
$text = implode($sep, $words_array);
|
254 |
}
|
255 |
-
$text = self::close_tags($text);
|
256 |
-
return apply_filters('wp_trim_words', $text, $num_words, $more, $original_text);
|
257 |
}
|
258 |
|
259 |
/**
|
@@ -264,30 +252,87 @@ class Helper {
|
|
264 |
*/
|
265 |
public static function close_tags( $html ) {
|
266 |
//put all opened tags into an array
|
267 |
-
preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
|
268 |
$openedtags = $result[1];
|
269 |
//put all closed tags into an array
|
270 |
-
preg_match_all('#</([a-z]+)>#iU', $html, $result);
|
271 |
$closedtags = $result[1];
|
272 |
-
$len_opened = count($openedtags);
|
273 |
// all tags are closed
|
274 |
-
if ( count($closedtags) == $len_opened ) {
|
275 |
return $html;
|
276 |
}
|
277 |
-
$openedtags = array_reverse($openedtags);
|
278 |
// close tags
|
279 |
for ( $i = 0; $i < $len_opened; $i++ ) {
|
280 |
-
if ( !in_array($openedtags[$i], $closedtags) ) {
|
281 |
-
$html .= '</'
|
282 |
} else {
|
283 |
-
unset($closedtags[array_search($openedtags[$i], $closedtags)]);
|
284 |
}
|
285 |
}
|
286 |
-
$html = str_replace(array('</br>',
|
287 |
-
$html = str_replace(array('<br>',
|
288 |
return $html;
|
289 |
}
|
290 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
/* Object Utilities
|
292 |
======================== */
|
293 |
|
@@ -299,7 +344,7 @@ class Helper {
|
|
299 |
* @return void
|
300 |
*/
|
301 |
public static function osort( &$array, $prop ) {
|
302 |
-
usort($array, function( $a, $b ) use ($prop) {
|
303 |
return $a->$prop > $b->$prop ? 1 : -1;
|
304 |
} );
|
305 |
}
|
@@ -311,10 +356,10 @@ class Helper {
|
|
311 |
* @return bool
|
312 |
*/
|
313 |
public static function is_array_assoc( $arr ) {
|
314 |
-
if ( !is_array($arr) ) {
|
315 |
return false;
|
316 |
}
|
317 |
-
return (bool)
|
318 |
}
|
319 |
|
320 |
/**
|
@@ -324,10 +369,10 @@ class Helper {
|
|
324 |
* @return stdClass
|
325 |
*/
|
326 |
public static function array_to_object( $array ) {
|
327 |
-
$obj = new
|
328 |
foreach ( $array as $k => $v ) {
|
329 |
-
if ( is_array($v) ) {
|
330 |
-
$obj->{$k} = self::array_to_object($v); //RECURSION
|
331 |
} else {
|
332 |
$obj->{$k} = $v;
|
333 |
}
|
@@ -344,10 +389,10 @@ class Helper {
|
|
344 |
* @return bool|int
|
345 |
*/
|
346 |
public static function get_object_index_by_property( $array, $key, $value ) {
|
347 |
-
if ( is_array($array) ) {
|
348 |
$i = 0;
|
349 |
foreach ( $array as $arr ) {
|
350 |
-
if ( is_array($arr) ) {
|
351 |
if ( $arr[$key] == $value ) {
|
352 |
return $i;
|
353 |
}
|
@@ -372,15 +417,15 @@ class Helper {
|
|
372 |
* @throws Exception
|
373 |
*/
|
374 |
public static function get_object_by_property( $array, $key, $value ) {
|
375 |
-
if ( is_array($array) ) {
|
376 |
foreach ( $array as $arr ) {
|
377 |
if ( $arr->$key == $value ) {
|
378 |
return $arr;
|
379 |
}
|
380 |
}
|
381 |
} else {
|
382 |
-
throw new
|
383 |
-
|
384 |
}
|
385 |
}
|
386 |
|
@@ -392,8 +437,8 @@ class Helper {
|
|
392 |
* @return array
|
393 |
*/
|
394 |
public static function array_truncate( $array, $len ) {
|
395 |
-
if ( sizeof($array) > $len ) {
|
396 |
-
$array = array_splice($array, 0, $len);
|
397 |
}
|
398 |
return $array;
|
399 |
}
|
@@ -408,11 +453,11 @@ class Helper {
|
|
408 |
* @return bool
|
409 |
*/
|
410 |
public static function is_true( $value ) {
|
411 |
-
if ( isset($value) ) {
|
412 |
-
if (
|
413 |
$value = strtolower($value);
|
414 |
}
|
415 |
-
if ( ($value == 'true' || $value === 1 || $value === '1' || $value == true) && $value !== false && $value !== 'false'
|
416 |
return true;
|
417 |
}
|
418 |
}
|
@@ -426,7 +471,7 @@ class Helper {
|
|
426 |
* @return bool
|
427 |
*/
|
428 |
public static function iseven( $i ) {
|
429 |
-
return ($i % 2) == 0;
|
430 |
}
|
431 |
|
432 |
/**
|
@@ -436,7 +481,7 @@ class Helper {
|
|
436 |
* @return bool
|
437 |
*/
|
438 |
public static function isodd( $i ) {
|
439 |
-
return ($i % 2) != 0;
|
440 |
}
|
441 |
|
442 |
/* Links, Forms, Etc. Utilities
|
@@ -468,28 +513,28 @@ class Helper {
|
|
468 |
'current' => 0,
|
469 |
'show_all' => false,
|
470 |
'prev_next' => false,
|
471 |
-
'prev_text' => __('« Previous'),
|
472 |
-
'next_text' => __('Next »'),
|
473 |
'end_size' => 1,
|
474 |
'mid_size' => 2,
|
475 |
'type' => 'array',
|
476 |
'add_args' => false, // array of query args to add
|
477 |
'add_fragment' => ''
|
478 |
);
|
479 |
-
$args = wp_parse_args($args, $defaults);
|
480 |
// Who knows what else people pass in $args
|
481 |
-
$args['total'] = intval((int)
|
482 |
if ( $args['total'] < 2 ) {
|
483 |
return array();
|
484 |
}
|
485 |
-
$args['current'] = (int)
|
486 |
-
$args['end_size'] = 0 < (int)
|
487 |
-
$args['mid_size'] = 0 <= (int)
|
488 |
-
$args['add_args'] = is_array($args['add_args']) ? $args['add_args'] : false;
|
489 |
$page_links = array();
|
490 |
$dots = false;
|
491 |
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
492 |
-
$n_display = number_format_i18n($n);
|
493 |
if ( $n == $args['current'] ) {
|
494 |
$page_links[] = array(
|
495 |
'class' => 'page-number page-numbers current',
|
@@ -500,18 +545,18 @@ class Helper {
|
|
500 |
);
|
501 |
$dots = true;
|
502 |
} else {
|
503 |
-
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']) ) {
|
504 |
-
$link = str_replace('%_%', 1 == $n ? '' : $args['format'], $args['base']);
|
505 |
-
$link = str_replace('%#%', $n, $link);
|
506 |
-
$link = trailingslashit($link).ltrim($args['add_fragment'], '/');
|
507 |
if ( $args['add_args'] ) {
|
508 |
-
$link = rtrim(add_query_arg($args['add_args'], $link), '/');
|
509 |
}
|
510 |
$link = str_replace(' ', '+', $link);
|
511 |
-
$link = untrailingslashit($link);
|
512 |
$page_links[] = array(
|
513 |
'class' => 'page-number page-numbers',
|
514 |
-
'link' => esc_url(apply_filters('paginate_links', $link)),
|
515 |
'title' => $n_display,
|
516 |
'name' => $n_display,
|
517 |
'current' => $args['current'] == $n
|
@@ -520,7 +565,7 @@ class Helper {
|
|
520 |
} elseif ( $dots && !$args['show_all'] ) {
|
521 |
$page_links[] = array(
|
522 |
'class' => 'dots',
|
523 |
-
'title' => __('…')
|
524 |
);
|
525 |
$dots = false;
|
526 |
}
|
@@ -530,10 +575,94 @@ class Helper {
|
|
530 |
}
|
531 |
|
532 |
/**
|
533 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
*/
|
535 |
-
function
|
536 |
-
|
537 |
-
return URLHelper::get_current_url();
|
538 |
}
|
539 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* As the name suggests these are helpers for Timber (and you!) when developing. You can find additional (mainly internally-focused helpers) in TimberURLHelper
|
5 |
*/
|
6 |
+
class TimberHelper {
|
7 |
|
8 |
/**
|
9 |
* A utility for a one-stop shop for Transients
|
26 |
* @return mixed
|
27 |
*/
|
28 |
public static function transient( $slug, $callback, $transient_time = 0, $lock_timeout = 5, $force = false ) {
|
29 |
+
$slug = apply_filters( 'timber/transient/slug', $slug );
|
30 |
|
31 |
+
$enable_transients = ( $transient_time === false || ( defined( 'WP_DISABLE_TRANSIENTS' ) && WP_DISABLE_TRANSIENTS ) ) ? false : true;
|
32 |
+
$data = $enable_transients ? get_transient( $slug ) : false;
|
33 |
|
34 |
if ( false === $data ) {
|
35 |
|
36 |
+
if ( $enable_transients && self::_is_transient_locked( $slug ) ) {
|
37 |
|
38 |
+
$force = apply_filters( 'timber_force_transients', $force );
|
39 |
+
$force = apply_filters( 'timber_force_transient_' . $slug, $force );
|
40 |
|
41 |
if ( !$force ) {
|
42 |
//the server is currently executing the process.
|
49 |
|
50 |
// lock timeout shouldn't be higher than 5 seconds, unless
|
51 |
// remote calls with high timeouts are made here
|
52 |
+
if ( $enable_transients )
|
53 |
+
self::_lock_transient( $slug, $lock_timeout );
|
|
|
54 |
|
55 |
$data = $callback();
|
56 |
|
57 |
if ( $enable_transients ) {
|
58 |
+
set_transient( $slug, $data, $transient_time );
|
59 |
+
self::_unlock_transient( $slug );
|
60 |
}
|
61 |
|
62 |
}
|
71 |
* @param integer $lock_timeout
|
72 |
*/
|
73 |
static function _lock_transient( $slug, $lock_timeout ) {
|
74 |
+
set_transient( $slug . '_lock', true, $lock_timeout );
|
75 |
}
|
76 |
|
77 |
/**
|
79 |
* @param string $slug
|
80 |
*/
|
81 |
static function _unlock_transient( $slug ) {
|
82 |
+
delete_transient( $slug . '_lock', true );
|
83 |
}
|
84 |
|
85 |
/**
|
87 |
* @param string $slug
|
88 |
*/
|
89 |
static function _is_transient_locked( $slug ) {
|
90 |
+
return (bool)get_transient( $slug . '_lock' );
|
91 |
}
|
92 |
|
93 |
/* These are for measuring page render time */
|
99 |
*/
|
100 |
public static function start_timer() {
|
101 |
$time = microtime();
|
102 |
+
$time = explode( ' ', $time );
|
103 |
$time = $time[1] + $time[0];
|
104 |
return $time;
|
105 |
}
|
117 |
*/
|
118 |
public static function stop_timer( $start ) {
|
119 |
$time = microtime();
|
120 |
+
$time = explode( ' ', $time );
|
121 |
$time = $time[1] + $time[0];
|
122 |
$finish = $time;
|
123 |
+
$total_time = round( ( $finish - $start ), 4 );
|
124 |
+
return $total_time . ' seconds.';
|
125 |
}
|
126 |
|
127 |
/* Function Utilities
|
153 |
* @param array $args
|
154 |
* @return string
|
155 |
*/
|
156 |
+
public static function ob_function( $function, $args = array( null ) ) {
|
157 |
ob_start();
|
158 |
+
call_user_func_array( $function, $args );
|
159 |
$data = ob_get_contents();
|
160 |
ob_end_clean();
|
161 |
return $data;
|
162 |
}
|
163 |
|
164 |
/**
|
165 |
+
*
|
166 |
+
*
|
167 |
+
* @param string $function_name
|
168 |
+
* @param integer[] $defaults
|
169 |
+
* @param bool $return_output_buffer
|
170 |
+
* @return TimberFunctionWrapper
|
171 |
*/
|
172 |
public static function function_wrapper( $function_name, $defaults = array(), $return_output_buffer = false ) {
|
173 |
+
return new TimberFunctionWrapper( $function_name, $defaults, $return_output_buffer );
|
174 |
}
|
175 |
|
176 |
/**
|
183 |
if ( !WP_DEBUG ) {
|
184 |
return;
|
185 |
}
|
186 |
+
if ( is_object( $arg ) || is_array( $arg ) ) {
|
187 |
+
$arg = print_r( $arg, true );
|
188 |
}
|
189 |
+
return error_log( $arg );
|
190 |
}
|
191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
/**
|
193 |
*
|
194 |
*
|
197 |
* @return string
|
198 |
*/
|
199 |
public static function get_wp_title( $separator = ' ', $seplocation = 'left' ) {
|
200 |
+
$separator = apply_filters( 'timber_wp_title_seperator', $separator );
|
201 |
+
return trim( wp_title( $separator, false, $seplocation ) );
|
202 |
}
|
203 |
|
204 |
/* Text Utilities
|
215 |
*/
|
216 |
public static function trim_words( $text, $num_words = 55, $more = null, $allowed_tags = 'p a span b i br blockquote' ) {
|
217 |
if ( null === $more ) {
|
218 |
+
$more = __( '…' );
|
219 |
}
|
220 |
$original_text = $text;
|
221 |
$allowed_tag_string = '';
|
222 |
+
foreach ( explode( ' ', apply_filters( 'timber/trim_words/allowed_tags', $allowed_tags ) ) as $tag ) {
|
223 |
+
$allowed_tag_string .= '<' . $tag . '>';
|
224 |
}
|
225 |
+
$text = strip_tags( $text, $allowed_tag_string );
|
226 |
/* translators: If your word count is based on single characters (East Asian characters), enter 'characters'. Otherwise, enter 'words'. Do not translate into your own language. */
|
227 |
+
if ( 'characters' == _x( 'words', 'word count: words or characters?' ) && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) {
|
228 |
+
$text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
|
229 |
+
preg_match_all( '/./u', $text, $words_array );
|
230 |
+
$words_array = array_slice( $words_array[0], 0, $num_words + 1 );
|
231 |
$sep = '';
|
232 |
} else {
|
233 |
+
$words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
|
234 |
$sep = ' ';
|
235 |
}
|
236 |
+
if ( count( $words_array ) > $num_words ) {
|
237 |
+
array_pop( $words_array );
|
238 |
+
$text = implode( $sep, $words_array );
|
239 |
+
$text = $text . $more;
|
240 |
} else {
|
241 |
+
$text = implode( $sep, $words_array );
|
242 |
}
|
243 |
+
$text = self::close_tags( $text );
|
244 |
+
return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text );
|
245 |
}
|
246 |
|
247 |
/**
|
252 |
*/
|
253 |
public static function close_tags( $html ) {
|
254 |
//put all opened tags into an array
|
255 |
+
preg_match_all( '#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result );
|
256 |
$openedtags = $result[1];
|
257 |
//put all closed tags into an array
|
258 |
+
preg_match_all( '#</([a-z]+)>#iU', $html, $result );
|
259 |
$closedtags = $result[1];
|
260 |
+
$len_opened = count( $openedtags );
|
261 |
// all tags are closed
|
262 |
+
if ( count( $closedtags ) == $len_opened ) {
|
263 |
return $html;
|
264 |
}
|
265 |
+
$openedtags = array_reverse( $openedtags );
|
266 |
// close tags
|
267 |
for ( $i = 0; $i < $len_opened; $i++ ) {
|
268 |
+
if ( !in_array( $openedtags[$i], $closedtags ) ) {
|
269 |
+
$html .= '</' . $openedtags[$i] . '>';
|
270 |
} else {
|
271 |
+
unset( $closedtags[array_search( $openedtags[$i], $closedtags )] );
|
272 |
}
|
273 |
}
|
274 |
+
$html = str_replace(array('</br>','</hr>','</wbr>'), '', $html);
|
275 |
+
$html = str_replace(array('<br>','<hr>','<wbr>'), array('<br />','<hr />','<wbr />'), $html);
|
276 |
return $html;
|
277 |
}
|
278 |
|
279 |
+
/* WordPress Query Utilities
|
280 |
+
======================== */
|
281 |
+
|
282 |
+
/**
|
283 |
+
* @param string $key
|
284 |
+
* @param string $value
|
285 |
+
* @return array|int
|
286 |
+
* @deprecated 0.20.0
|
287 |
+
*/
|
288 |
+
public static function get_posts_by_meta( $key, $value ) {
|
289 |
+
global $wpdb;
|
290 |
+
$query = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s", $key, $value );
|
291 |
+
$results = $wpdb->get_col( $query );
|
292 |
+
$pids = array();
|
293 |
+
foreach ( $results as $result ) {
|
294 |
+
if ( get_post( $result ) ) {
|
295 |
+
$pids[] = $result;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
if ( count( $pids ) ) {
|
299 |
+
return $pids;
|
300 |
+
}
|
301 |
+
return 0;
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
*
|
306 |
+
*
|
307 |
+
* @param string $key
|
308 |
+
* @param string $value
|
309 |
+
* @return int
|
310 |
+
* @deprecated 0.20.0
|
311 |
+
*/
|
312 |
+
public static function get_post_by_meta( $key, $value ) {
|
313 |
+
global $wpdb;
|
314 |
+
$query = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s ORDER BY post_id", $key, $value );
|
315 |
+
$results = $wpdb->get_col( $query );
|
316 |
+
foreach ( $results as $result ) {
|
317 |
+
if ( $result && get_post( $result ) ) {
|
318 |
+
return $result;
|
319 |
+
}
|
320 |
+
}
|
321 |
+
return 0;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
*
|
326 |
+
* @deprecated 0.21.8
|
327 |
+
* @param int $ttid
|
328 |
+
* @return mixed
|
329 |
+
*/
|
330 |
+
public static function get_term_id_by_term_taxonomy_id( $ttid ) {
|
331 |
+
global $wpdb;
|
332 |
+
$query = $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %s", $ttid );
|
333 |
+
return $wpdb->get_var( $query );
|
334 |
+
}
|
335 |
+
|
336 |
/* Object Utilities
|
337 |
======================== */
|
338 |
|
344 |
* @return void
|
345 |
*/
|
346 |
public static function osort( &$array, $prop ) {
|
347 |
+
usort( $array, function ( $a, $b ) use ( $prop ) {
|
348 |
return $a->$prop > $b->$prop ? 1 : -1;
|
349 |
} );
|
350 |
}
|
356 |
* @return bool
|
357 |
*/
|
358 |
public static function is_array_assoc( $arr ) {
|
359 |
+
if ( !is_array( $arr ) ) {
|
360 |
return false;
|
361 |
}
|
362 |
+
return (bool)count( array_filter( array_keys( $arr ), 'is_string' ) );
|
363 |
}
|
364 |
|
365 |
/**
|
369 |
* @return stdClass
|
370 |
*/
|
371 |
public static function array_to_object( $array ) {
|
372 |
+
$obj = new stdClass;
|
373 |
foreach ( $array as $k => $v ) {
|
374 |
+
if ( is_array( $v ) ) {
|
375 |
+
$obj->{$k} = self::array_to_object( $v ); //RECURSION
|
376 |
} else {
|
377 |
$obj->{$k} = $v;
|
378 |
}
|
389 |
* @return bool|int
|
390 |
*/
|
391 |
public static function get_object_index_by_property( $array, $key, $value ) {
|
392 |
+
if ( is_array( $array ) ) {
|
393 |
$i = 0;
|
394 |
foreach ( $array as $arr ) {
|
395 |
+
if ( is_array( $arr ) ) {
|
396 |
if ( $arr[$key] == $value ) {
|
397 |
return $i;
|
398 |
}
|
417 |
* @throws Exception
|
418 |
*/
|
419 |
public static function get_object_by_property( $array, $key, $value ) {
|
420 |
+
if ( is_array( $array ) ) {
|
421 |
foreach ( $array as $arr ) {
|
422 |
if ( $arr->$key == $value ) {
|
423 |
return $arr;
|
424 |
}
|
425 |
}
|
426 |
} else {
|
427 |
+
throw new InvalidArgumentException( '$array is not an array, got:' );
|
428 |
+
TimberHelper::error_log( $array );
|
429 |
}
|
430 |
}
|
431 |
|
437 |
* @return array
|
438 |
*/
|
439 |
public static function array_truncate( $array, $len ) {
|
440 |
+
if ( sizeof( $array ) > $len ) {
|
441 |
+
$array = array_splice( $array, 0, $len );
|
442 |
}
|
443 |
return $array;
|
444 |
}
|
453 |
* @return bool
|
454 |
*/
|
455 |
public static function is_true( $value ) {
|
456 |
+
if ( isset( $value ) ) {
|
457 |
+
if (is_string($value)) {
|
458 |
$value = strtolower($value);
|
459 |
}
|
460 |
+
if ( ($value == 'true' || $value === 1 || $value === '1' || $value == true) && $value !== false && $value !== 'false') {
|
461 |
return true;
|
462 |
}
|
463 |
}
|
471 |
* @return bool
|
472 |
*/
|
473 |
public static function iseven( $i ) {
|
474 |
+
return ( $i % 2 ) == 0;
|
475 |
}
|
476 |
|
477 |
/**
|
481 |
* @return bool
|
482 |
*/
|
483 |
public static function isodd( $i ) {
|
484 |
+
return ( $i % 2 ) != 0;
|
485 |
}
|
486 |
|
487 |
/* Links, Forms, Etc. Utilities
|
513 |
'current' => 0,
|
514 |
'show_all' => false,
|
515 |
'prev_next' => false,
|
516 |
+
'prev_text' => __( '« Previous' ),
|
517 |
+
'next_text' => __( 'Next »' ),
|
518 |
'end_size' => 1,
|
519 |
'mid_size' => 2,
|
520 |
'type' => 'array',
|
521 |
'add_args' => false, // array of query args to add
|
522 |
'add_fragment' => ''
|
523 |
);
|
524 |
+
$args = wp_parse_args( $args, $defaults );
|
525 |
// Who knows what else people pass in $args
|
526 |
+
$args['total'] = intval( (int)$args['total'] );
|
527 |
if ( $args['total'] < 2 ) {
|
528 |
return array();
|
529 |
}
|
530 |
+
$args['current'] = (int)$args['current'];
|
531 |
+
$args['end_size'] = 0 < (int)$args['end_size'] ? (int)$args['end_size'] : 1; // Out of bounds? Make it the default.
|
532 |
+
$args['mid_size'] = 0 <= (int)$args['mid_size'] ? (int)$args['mid_size'] : 2;
|
533 |
+
$args['add_args'] = is_array( $args['add_args'] ) ? $args['add_args'] : false;
|
534 |
$page_links = array();
|
535 |
$dots = false;
|
536 |
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
537 |
+
$n_display = number_format_i18n( $n );
|
538 |
if ( $n == $args['current'] ) {
|
539 |
$page_links[] = array(
|
540 |
'class' => 'page-number page-numbers current',
|
545 |
);
|
546 |
$dots = true;
|
547 |
} else {
|
548 |
+
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'] ) ) {
|
549 |
+
$link = str_replace( '%_%', 1 == $n ? '' : $args['format'], $args['base'] );
|
550 |
+
$link = str_replace( '%#%', $n, $link );
|
551 |
+
$link = trailingslashit( $link ) . ltrim( $args['add_fragment'], '/' );
|
552 |
if ( $args['add_args'] ) {
|
553 |
+
$link = rtrim( add_query_arg( $args['add_args'], $link ), '/' );
|
554 |
}
|
555 |
$link = str_replace(' ', '+', $link);
|
556 |
+
$link = untrailingslashit( $link );
|
557 |
$page_links[] = array(
|
558 |
'class' => 'page-number page-numbers',
|
559 |
+
'link' => esc_url( apply_filters( 'paginate_links', $link ) ),
|
560 |
'title' => $n_display,
|
561 |
'name' => $n_display,
|
562 |
'current' => $args['current'] == $n
|
565 |
} elseif ( $dots && !$args['show_all'] ) {
|
566 |
$page_links[] = array(
|
567 |
'class' => 'dots',
|
568 |
+
'title' => __( '…' )
|
569 |
);
|
570 |
$dots = false;
|
571 |
}
|
575 |
}
|
576 |
|
577 |
/**
|
578 |
+
* @deprecated 0.18.0
|
579 |
+
*/
|
580 |
+
static function get_current_url() {
|
581 |
+
return TimberURLHelper::get_current_url();
|
582 |
+
}
|
583 |
+
|
584 |
+
/**
|
585 |
+
* @deprecated 0.18.0
|
586 |
*/
|
587 |
+
static function is_url( $url ) {
|
588 |
+
return TimberURLHelper::is_url( $url );
|
|
|
589 |
}
|
590 |
+
|
591 |
+
/**
|
592 |
+
* @deprecated 0.18.0
|
593 |
+
*/
|
594 |
+
static function get_path_base() {
|
595 |
+
return TimberURLHelper::get_path_base();
|
596 |
+
}
|
597 |
+
|
598 |
+
/**
|
599 |
+
* @deprecated 0.18.0
|
600 |
+
*/
|
601 |
+
static function get_rel_url( $url, $force = false ) {
|
602 |
+
return TimberURLHelper::get_rel_url( $url, $force );
|
603 |
+
}
|
604 |
+
|
605 |
+
/**
|
606 |
+
* @deprecated 0.18.0
|
607 |
+
*/
|
608 |
+
static function is_local( $url ) {
|
609 |
+
return TimberURLHelper::is_local( $url );
|
610 |
+
}
|
611 |
+
|
612 |
+
/**
|
613 |
+
* @deprecated 0.18.0
|
614 |
+
*/
|
615 |
+
static function get_full_path( $src ) {
|
616 |
+
return TimberURLHelper::get_full_path( $src );
|
617 |
+
}
|
618 |
+
|
619 |
+
/**
|
620 |
+
* @deprecated 0.18.0
|
621 |
+
*/
|
622 |
+
static function get_rel_path( $src ) {
|
623 |
+
return TimberURLHelper::get_rel_path( $src );
|
624 |
+
}
|
625 |
+
|
626 |
+
/**
|
627 |
+
* @deprecated 0.18.0
|
628 |
+
*/
|
629 |
+
static function remove_double_slashes( $url ) {
|
630 |
+
return TimberURLHelper::remove_double_slashes( $url );
|
631 |
+
}
|
632 |
+
|
633 |
+
/**
|
634 |
+
* @deprecated 0.18.0
|
635 |
+
*/
|
636 |
+
static function prepend_to_url( $url, $path ) {
|
637 |
+
return TimberURLHelper::prepend_to_url( $url, $path );
|
638 |
+
}
|
639 |
+
|
640 |
+
/**
|
641 |
+
* @deprecated 0.18.0
|
642 |
+
*/
|
643 |
+
static function preslashit( $path ) {
|
644 |
+
return TimberURLHelper::preslashit( $path );
|
645 |
+
}
|
646 |
+
|
647 |
+
/**
|
648 |
+
* @deprecated 0.18.0
|
649 |
+
*/
|
650 |
+
static function is_external( $url ) {
|
651 |
+
return TimberURLHelper::is_external( $url );
|
652 |
+
}
|
653 |
+
|
654 |
+
/**
|
655 |
+
* @deprecated 0.18.0
|
656 |
+
*/
|
657 |
+
static function download_url( $url, $timeout = 300 ) {
|
658 |
+
return TimberURLHelper::download_url( $url, $timeout );
|
659 |
+
}
|
660 |
+
|
661 |
+
/**
|
662 |
+
* @deprecated 0.18.0
|
663 |
+
*/
|
664 |
+
static function get_params( $i = -1 ) {
|
665 |
+
return TimberURLHelper::get_params( $i );
|
666 |
+
}
|
667 |
+
|
668 |
+
}
|
lib/{ImageHelper.php → timber-image-helper.php}
RENAMED
@@ -1,18 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Image;
|
6 |
-
use Timber\Image\Operation\ToJpg;
|
7 |
-
use Timber\Image\Operation\Resize;
|
8 |
-
use Timber\Image\Operation\Retina;
|
9 |
-
use Timber\Image\Operation\Letterbox;
|
10 |
-
|
11 |
-
use Timber\URLHelper;
|
12 |
-
|
13 |
/**
|
14 |
* Implements the Twig image filters:
|
15 |
-
* https://github.com/
|
16 |
* - resize
|
17 |
* - retina
|
18 |
* - letterbox
|
@@ -23,7 +13,7 @@ use Timber\URLHelper;
|
|
23 |
* - most of the work is common to all filters (URL analysis, directory gymnastics, file caching, error management) and done by private static functions
|
24 |
* - the specific part (actual image processing) is delegated to dedicated subclasses of TimberImageOperation
|
25 |
*/
|
26 |
-
class
|
27 |
|
28 |
const BASE_UPLOADS = 1;
|
29 |
const BASE_CONTENT = 2;
|
@@ -62,7 +52,7 @@ class ImageHelper {
|
|
62 |
return $src;
|
63 |
}
|
64 |
}
|
65 |
-
$op = new
|
66 |
return self::_operate($src, $op, $force);
|
67 |
}
|
68 |
|
@@ -101,7 +91,7 @@ class ImageHelper {
|
|
101 |
* @return string url to the new image
|
102 |
*/
|
103 |
public static function retina_resize( $src, $multiplier = 2, $force = false ) {
|
104 |
-
$op = new
|
105 |
return self::_operate($src, $op, $force);
|
106 |
}
|
107 |
|
@@ -116,7 +106,7 @@ class ImageHelper {
|
|
116 |
return false;
|
117 |
}
|
118 |
//its a gif so test
|
119 |
-
if
|
120 |
return false;
|
121 |
}
|
122 |
$count = 0;
|
@@ -128,13 +118,13 @@ class ImageHelper {
|
|
128 |
|
129 |
// We read through the file til we reach the end of the file, or we've found
|
130 |
// at least 2 frame headers
|
131 |
-
while
|
132 |
$chunk = fread($fh, 1024 * 100); //read 100kb at a time
|
133 |
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches);
|
134 |
-
|
135 |
|
136 |
-
|
137 |
-
|
138 |
}
|
139 |
|
140 |
/**
|
@@ -149,7 +139,7 @@ class ImageHelper {
|
|
149 |
* @return mixed|null|string
|
150 |
*/
|
151 |
public static function letterbox( $src, $w, $h, $color = '#000000', $force = false ) {
|
152 |
-
$op = new
|
153 |
return self::_operate($src, $op, $force);
|
154 |
}
|
155 |
|
@@ -161,7 +151,7 @@ class ImageHelper {
|
|
161 |
* @return string
|
162 |
*/
|
163 |
public static function img_to_jpg( $src, $bghex = '#FFFFFF', $force = false ) {
|
164 |
-
$op = new
|
165 |
return self::_operate($src, $op, $force);
|
166 |
}
|
167 |
|
@@ -169,13 +159,13 @@ class ImageHelper {
|
|
169 |
* Deletes all resized versions of an image when the source is deleted
|
170 |
*/
|
171 |
protected static function add_actions() {
|
172 |
-
add_action('delete_attachment', function( $post_id ) {
|
173 |
-
$post = get_post($post_id);
|
174 |
-
$image_types = array('image/jpeg', 'image/png', 'image/gif', 'image/jpg');
|
175 |
-
if ( in_array($post->post_mime_type, $image_types) ) {
|
176 |
-
$attachment = new
|
177 |
if ( $attachment->file_loc ) {
|
178 |
-
|
179 |
}
|
180 |
}
|
181 |
} );
|
@@ -186,9 +176,9 @@ class ImageHelper {
|
|
186 |
* for example /wp-content or /content
|
187 |
*/
|
188 |
protected static function add_constants() {
|
189 |
-
if ( !defined('WP_CONTENT_SUBDIR') ) {
|
190 |
-
$wp_content_path = str_replace(home_url(), '', WP_CONTENT_URL);
|
191 |
-
define('WP_CONTENT_SUBDIR', $wp_content_path);
|
192 |
}
|
193 |
}
|
194 |
|
@@ -198,8 +188,8 @@ class ImageHelper {
|
|
198 |
* @return void
|
199 |
*/
|
200 |
static function add_filters() {
|
201 |
-
add_filter('upload_dir', function( $arr ) {
|
202 |
-
$arr['relative'] = str_replace(home_url(), '', $arr['baseurl']);
|
203 |
return $arr;
|
204 |
} );
|
205 |
}
|
@@ -211,17 +201,17 @@ class ImageHelper {
|
|
211 |
* or: http://example.org/wp-content/uploads/2015/my-pic.jpg
|
212 |
*/
|
213 |
static function delete_generated_files( $local_file ) {
|
214 |
-
if (
|
215 |
-
$local_file =
|
216 |
}
|
217 |
-
$info = pathinfo($local_file);
|
218 |
$dir = $info['dirname'];
|
219 |
$ext = $info['extension'];
|
220 |
$filename = $info['filename'];
|
221 |
-
self::process_delete_generated_files($filename, $ext, $dir, '-[0-9999999]*', '-[0-9]*x[0-9]*-c-[a-z]*.');
|
222 |
-
self::process_delete_generated_files($filename, $ext, $dir, '-lbox-[0-9999999]*', '-lbox-[0-9]*x[0-9]*-[a-zA-Z0-9]*.');
|
223 |
-
self::process_delete_generated_files($filename, 'jpg', $dir, '-tojpg.*');
|
224 |
-
self::process_delete_generated_files($filename, 'jpg', $dir, '-tojpg-[0-9999999]*');
|
225 |
}
|
226 |
|
227 |
/**
|
@@ -239,17 +229,18 @@ class ImageHelper {
|
|
239 |
* @param string $match_pattern pattern of files to go forth and delete
|
240 |
*/
|
241 |
protected static function process_delete_generated_files( $filename, $ext, $dir, $search_pattern, $match_pattern = null ) {
|
242 |
-
$searcher = '/'
|
243 |
-
foreach ( glob($dir
|
244 |
-
$regexdir = str_replace('/', '\/', $dir);
|
245 |
-
$pattern = '/'.($regexdir).'\/'
|
246 |
-
$match = preg_match($pattern, $found_file);
|
247 |
-
if (
|
248 |
-
unlink($found_file);
|
249 |
}
|
250 |
}
|
251 |
}
|
252 |
|
|
|
253 |
/**
|
254 |
* Determines the filepath corresponding to a given URL
|
255 |
*
|
@@ -258,7 +249,7 @@ class ImageHelper {
|
|
258 |
*/
|
259 |
public static function get_server_location( $url ) {
|
260 |
// if we're already an absolute dir, just return
|
261 |
-
if ( 0 === strpos($url, ABSPATH) ) {
|
262 |
return $url;
|
263 |
}
|
264 |
// otherwise, analyze URL then build mapping path
|
@@ -277,14 +268,14 @@ class ImageHelper {
|
|
277 |
$upload = wp_upload_dir();
|
278 |
$dir = $upload['path'];
|
279 |
$filename = $file;
|
280 |
-
$file = parse_url($file);
|
281 |
-
$path_parts = pathinfo($file['path']);
|
282 |
-
$basename = md5($filename);
|
283 |
$ext = 'jpg';
|
284 |
-
if ( isset($path_parts['extension']) ) {
|
285 |
$ext = $path_parts['extension'];
|
286 |
}
|
287 |
-
return $dir.'/'
|
288 |
}
|
289 |
|
290 |
/**
|
@@ -294,27 +285,27 @@ class ImageHelper {
|
|
294 |
* @return string the URL to the downloaded file
|
295 |
*/
|
296 |
public static function sideload_image( $file ) {
|
297 |
-
$loc = self::get_sideloaded_file_loc($file);
|
298 |
-
if ( file_exists($loc) ) {
|
299 |
-
return
|
300 |
}
|
301 |
// Download file to temp location
|
302 |
-
if ( !function_exists('download_url') ) {
|
303 |
-
require_once ABSPATH.'/wp-admin/includes/file.php';
|
304 |
}
|
305 |
-
$tmp = download_url($file);
|
306 |
-
preg_match('/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches);
|
307 |
$file_array = array();
|
308 |
-
$file_array['name'] = basename($matches[0]);
|
309 |
$file_array['tmp_name'] = $tmp;
|
310 |
// If error storing temporarily, unlink
|
311 |
-
if ( is_wp_error($tmp) ) {
|
312 |
-
@unlink($file_array['tmp_name']);
|
313 |
$file_array['tmp_name'] = '';
|
314 |
}
|
315 |
// do the validation and storage stuff
|
316 |
-
$locinfo = pathinfo($loc);
|
317 |
-
$file = wp_upload_bits($locinfo['basename'], null, file_get_contents($file_array['tmp_name']));
|
318 |
return $file['url'];
|
319 |
}
|
320 |
|
@@ -326,10 +317,10 @@ class ImageHelper {
|
|
326 |
* @param string $url an URL (absolute or relative) pointing to an image
|
327 |
* @return array an array (see keys in code below)
|
328 |
*/
|
329 |
-
private static function analyze_url(
|
330 |
$result = array(
|
331 |
'url' => $url, // the initial url
|
332 |
-
'absolute' =>
|
333 |
'base' => 0, // is the image in uploads dir, or in content dir (theme or plugin)
|
334 |
'subdir' => '', // the path between base (uploads or content) and file
|
335 |
'filename' => '', // the filename, without extension
|
@@ -338,32 +329,31 @@ class ImageHelper {
|
|
338 |
);
|
339 |
$upload_dir = wp_upload_dir();
|
340 |
$tmp = $url;
|
341 |
-
if ( 0 === strpos($tmp, ABSPATH) ) {
|
342 |
-
// we've been given a dir, not an url
|
343 |
$result['absolute'] = true;
|
344 |
if ( 0 === strpos($tmp, $upload_dir['basedir']) ) {
|
345 |
-
$result['base']
|
346 |
$tmp = str_replace($upload_dir['basedir'], '', $tmp);
|
347 |
}
|
348 |
if ( 0 === strpos($tmp, WP_CONTENT_DIR) ) {
|
349 |
-
$result['base']
|
350 |
$tmp = str_replace(WP_CONTENT_DIR, '', $tmp);
|
351 |
}
|
352 |
} else {
|
353 |
-
if (
|
354 |
$tmp = home_url().$tmp;
|
355 |
}
|
356 |
-
if (
|
357 |
-
$result['base']
|
358 |
$tmp = str_replace($upload_dir['baseurl'], '', $tmp);
|
359 |
}
|
360 |
-
if (
|
361 |
-
$result['base']
|
362 |
$tmp = str_replace(content_url(), '', $tmp);
|
363 |
}
|
364 |
}
|
365 |
$parts = pathinfo($tmp);
|
366 |
-
$result['subdir'] =
|
367 |
$result['filename'] = $parts['filename'];
|
368 |
$result['extension'] = $parts['extension'];
|
369 |
$result['basename'] = $parts['basename'];
|
@@ -380,20 +370,20 @@ class ImageHelper {
|
|
380 |
* @param bool $absolute should the returned URL be absolute (include protocol+host), or relative
|
381 |
* @return string the URL
|
382 |
*/
|
383 |
-
private static function _get_file_url(
|
384 |
$url = '';
|
385 |
-
if
|
386 |
$upload_dir = wp_upload_dir();
|
387 |
$url = $upload_dir['baseurl'];
|
388 |
}
|
389 |
-
if
|
390 |
$url = content_url();
|
391 |
}
|
392 |
-
if
|
393 |
$url .= $subdir;
|
394 |
}
|
395 |
$url .= '/'.$filename;
|
396 |
-
if
|
397 |
$url = str_replace(home_url(), '', $url);
|
398 |
}
|
399 |
// $url = TimberURLHelper::remove_double_slashes( $url);
|
@@ -408,16 +398,16 @@ class ImageHelper {
|
|
408 |
* @param string $filename file name, including extension (but no path)
|
409 |
* @return string the file location
|
410 |
*/
|
411 |
-
private static function _get_file_path(
|
412 |
$path = '';
|
413 |
-
if
|
414 |
$upload_dir = wp_upload_dir();
|
415 |
$path = $upload_dir['basedir'];
|
416 |
}
|
417 |
-
if
|
418 |
$path = WP_CONTENT_DIR;
|
419 |
}
|
420 |
-
if
|
421 |
$path .= $subdir;
|
422 |
}
|
423 |
$path .= '/'.$filename;
|
@@ -439,14 +429,14 @@ class ImageHelper {
|
|
439 |
*
|
440 |
*/
|
441 |
private static function _operate( $src, $op, $force = false ) {
|
442 |
-
if ( empty($src) ) {
|
443 |
return '';
|
444 |
}
|
445 |
$external = false;
|
446 |
|
447 |
// if external image, load it first
|
448 |
-
if (
|
449 |
-
$src = self::sideload_image($src);
|
450 |
$external = true;
|
451 |
}
|
452 |
// break down URL into components
|
@@ -468,24 +458,20 @@ class ImageHelper {
|
|
468 |
$au['subdir'],
|
469 |
$au['basename']
|
470 |
);
|
471 |
-
|
472 |
-
$new_url = apply_filters( 'timber/image/new_url', $new_url );
|
473 |
-
$new_server_path = apply_filters( 'timber/image/new_path', $new_server_path );
|
474 |
-
|
475 |
// if already exists...
|
476 |
-
if ( file_exists($new_server_path) ) {
|
477 |
if ( $force ) {
|
478 |
// Force operation - warning: will regenerate the image on every pageload, use for testing purposes only!
|
479 |
-
unlink($new_server_path);
|
480 |
} else {
|
481 |
// return existing file (caching)
|
482 |
return $new_url;
|
483 |
}
|
484 |
}
|
485 |
// otherwise generate result file
|
486 |
-
if
|
487 |
-
if
|
488 |
-
$new_url = strtolower($new_url);
|
489 |
}
|
490 |
return $new_url;
|
491 |
} else {
|
@@ -497,9 +483,9 @@ class ImageHelper {
|
|
497 |
|
498 |
// -- the below methods are just used for unit testing the URL generation code
|
499 |
//
|
500 |
-
static function get_letterbox_file_url(
|
501 |
$au = self::analyze_url($url);
|
502 |
-
$op = new
|
503 |
$new_url = self::_get_file_url(
|
504 |
$au['base'],
|
505 |
$au['subdir'],
|
@@ -508,9 +494,9 @@ class ImageHelper {
|
|
508 |
);
|
509 |
return $new_url;
|
510 |
}
|
511 |
-
public static function get_letterbox_file_path(
|
512 |
$au = self::analyze_url($url);
|
513 |
-
$op = new
|
514 |
$new_path = self::_get_file_path(
|
515 |
$au['base'],
|
516 |
$au['subdir'],
|
@@ -518,9 +504,9 @@ class ImageHelper {
|
|
518 |
);
|
519 |
return $new_path;
|
520 |
}
|
521 |
-
static function get_resize_file_url(
|
522 |
$au = self::analyze_url($url);
|
523 |
-
$op = new
|
524 |
$new_url = self::_get_file_url(
|
525 |
$au['base'],
|
526 |
$au['subdir'],
|
@@ -529,9 +515,9 @@ class ImageHelper {
|
|
529 |
);
|
530 |
return $new_url;
|
531 |
}
|
532 |
-
static function get_resize_file_path(
|
533 |
$au = self::analyze_url($url);
|
534 |
-
$op = new
|
535 |
$new_path = self::_get_file_path(
|
536 |
$au['base'],
|
537 |
$au['subdir'],
|
@@ -539,4 +525,6 @@ class ImageHelper {
|
|
539 |
);
|
540 |
return $new_path;
|
541 |
}
|
542 |
-
|
|
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Implements the Twig image filters:
|
5 |
+
* https://github.com/jarednova/timber/wiki/Image-cookbook#arbitrary-resizing-of-images
|
6 |
* - resize
|
7 |
* - retina
|
8 |
* - letterbox
|
13 |
* - most of the work is common to all filters (URL analysis, directory gymnastics, file caching, error management) and done by private static functions
|
14 |
* - the specific part (actual image processing) is delegated to dedicated subclasses of TimberImageOperation
|
15 |
*/
|
16 |
+
class TimberImageHelper {
|
17 |
|
18 |
const BASE_UPLOADS = 1;
|
19 |
const BASE_CONTENT = 2;
|
52 |
return $src;
|
53 |
}
|
54 |
}
|
55 |
+
$op = new TimberImageOperationResize($w, $h, $crop);
|
56 |
return self::_operate($src, $op, $force);
|
57 |
}
|
58 |
|
91 |
* @return string url to the new image
|
92 |
*/
|
93 |
public static function retina_resize( $src, $multiplier = 2, $force = false ) {
|
94 |
+
$op = new TimberImageOperationRetina($multiplier);
|
95 |
return self::_operate($src, $op, $force);
|
96 |
}
|
97 |
|
106 |
return false;
|
107 |
}
|
108 |
//its a gif so test
|
109 |
+
if( !($fh = @fopen($file, 'rb')) ) {
|
110 |
return false;
|
111 |
}
|
112 |
$count = 0;
|
118 |
|
119 |
// We read through the file til we reach the end of the file, or we've found
|
120 |
// at least 2 frame headers
|
121 |
+
while(!feof($fh) && $count < 2) {
|
122 |
$chunk = fread($fh, 1024 * 100); //read 100kb at a time
|
123 |
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches);
|
124 |
+
}
|
125 |
|
126 |
+
fclose($fh);
|
127 |
+
return $count > 1;
|
128 |
}
|
129 |
|
130 |
/**
|
139 |
* @return mixed|null|string
|
140 |
*/
|
141 |
public static function letterbox( $src, $w, $h, $color = '#000000', $force = false ) {
|
142 |
+
$op = new TimberImageOperationLetterbox($w, $h, $color);
|
143 |
return self::_operate($src, $op, $force);
|
144 |
}
|
145 |
|
151 |
* @return string
|
152 |
*/
|
153 |
public static function img_to_jpg( $src, $bghex = '#FFFFFF', $force = false ) {
|
154 |
+
$op = new TimberImageOperationToJpg($bghex);
|
155 |
return self::_operate($src, $op, $force);
|
156 |
}
|
157 |
|
159 |
* Deletes all resized versions of an image when the source is deleted
|
160 |
*/
|
161 |
protected static function add_actions() {
|
162 |
+
add_action( 'delete_attachment', function ( $post_id ) {
|
163 |
+
$post = get_post( $post_id );
|
164 |
+
$image_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/jpg' );
|
165 |
+
if ( in_array( $post->post_mime_type, $image_types ) ) {
|
166 |
+
$attachment = new TimberImage( $post_id );
|
167 |
if ( $attachment->file_loc ) {
|
168 |
+
TimberImageHelper::delete_generated_files( $attachment->file_loc );
|
169 |
}
|
170 |
}
|
171 |
} );
|
176 |
* for example /wp-content or /content
|
177 |
*/
|
178 |
protected static function add_constants() {
|
179 |
+
if ( !defined( 'WP_CONTENT_SUBDIR' ) ) {
|
180 |
+
$wp_content_path = str_replace( home_url(), '', WP_CONTENT_URL );
|
181 |
+
define( 'WP_CONTENT_SUBDIR', $wp_content_path );
|
182 |
}
|
183 |
}
|
184 |
|
188 |
* @return void
|
189 |
*/
|
190 |
static function add_filters() {
|
191 |
+
add_filter( 'upload_dir', function ( $arr ) {
|
192 |
+
$arr['relative'] = str_replace( home_url(), '', $arr['baseurl'] );
|
193 |
return $arr;
|
194 |
} );
|
195 |
}
|
201 |
* or: http://example.org/wp-content/uploads/2015/my-pic.jpg
|
202 |
*/
|
203 |
static function delete_generated_files( $local_file ) {
|
204 |
+
if (TimberURLHelper::is_absolute( $local_file ) ) {
|
205 |
+
$local_file = TimberURLHelper::url_to_file_system( $local_file );
|
206 |
}
|
207 |
+
$info = pathinfo( $local_file );
|
208 |
$dir = $info['dirname'];
|
209 |
$ext = $info['extension'];
|
210 |
$filename = $info['filename'];
|
211 |
+
self::process_delete_generated_files( $filename, $ext, $dir, '-[0-9999999]*', '-[0-9]*x[0-9]*-c-[a-z]*.' );
|
212 |
+
self::process_delete_generated_files( $filename, $ext, $dir, '-lbox-[0-9999999]*', '-lbox-[0-9]*x[0-9]*-[a-zA-Z0-9]*.' );
|
213 |
+
self::process_delete_generated_files( $filename, 'jpg', $dir, '-tojpg.*' );
|
214 |
+
self::process_delete_generated_files( $filename, 'jpg', $dir, '-tojpg-[0-9999999]*' );
|
215 |
}
|
216 |
|
217 |
/**
|
229 |
* @param string $match_pattern pattern of files to go forth and delete
|
230 |
*/
|
231 |
protected static function process_delete_generated_files( $filename, $ext, $dir, $search_pattern, $match_pattern = null ) {
|
232 |
+
$searcher = '/' . $filename . $search_pattern;
|
233 |
+
foreach ( glob( $dir . $searcher ) as $found_file ) {
|
234 |
+
$regexdir = str_replace( '/', '\/', $dir );
|
235 |
+
$pattern = '/' . ( $regexdir ) . '\/' . $filename . $match_pattern . $ext . '/';
|
236 |
+
$match = preg_match( $pattern, $found_file );
|
237 |
+
if ( ! $match_pattern || $match ) {
|
238 |
+
unlink( $found_file );
|
239 |
}
|
240 |
}
|
241 |
}
|
242 |
|
243 |
+
|
244 |
/**
|
245 |
* Determines the filepath corresponding to a given URL
|
246 |
*
|
249 |
*/
|
250 |
public static function get_server_location( $url ) {
|
251 |
// if we're already an absolute dir, just return
|
252 |
+
if ( 0 === strpos( $url, ABSPATH ) ) {
|
253 |
return $url;
|
254 |
}
|
255 |
// otherwise, analyze URL then build mapping path
|
268 |
$upload = wp_upload_dir();
|
269 |
$dir = $upload['path'];
|
270 |
$filename = $file;
|
271 |
+
$file = parse_url( $file );
|
272 |
+
$path_parts = pathinfo( $file['path'] );
|
273 |
+
$basename = md5( $filename );
|
274 |
$ext = 'jpg';
|
275 |
+
if ( isset( $path_parts['extension'] ) ) {
|
276 |
$ext = $path_parts['extension'];
|
277 |
}
|
278 |
+
return $dir . '/' . $basename . '.' . $ext;
|
279 |
}
|
280 |
|
281 |
/**
|
285 |
* @return string the URL to the downloaded file
|
286 |
*/
|
287 |
public static function sideload_image( $file ) {
|
288 |
+
$loc = self::get_sideloaded_file_loc( $file );
|
289 |
+
if ( file_exists( $loc ) ) {
|
290 |
+
return TimberURLHelper::preslashit( TimberURLHelper::get_rel_path( $loc ) );
|
291 |
}
|
292 |
// Download file to temp location
|
293 |
+
if ( !function_exists( 'download_url' ) ) {
|
294 |
+
require_once ABSPATH . '/wp-admin/includes/file.php';
|
295 |
}
|
296 |
+
$tmp = download_url( $file );
|
297 |
+
preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
|
298 |
$file_array = array();
|
299 |
+
$file_array['name'] = basename( $matches[0] );
|
300 |
$file_array['tmp_name'] = $tmp;
|
301 |
// If error storing temporarily, unlink
|
302 |
+
if ( is_wp_error( $tmp ) ) {
|
303 |
+
@unlink( $file_array['tmp_name'] );
|
304 |
$file_array['tmp_name'] = '';
|
305 |
}
|
306 |
// do the validation and storage stuff
|
307 |
+
$locinfo = pathinfo( $loc );
|
308 |
+
$file = wp_upload_bits( $locinfo['basename'], null, file_get_contents( $file_array['tmp_name'] ) );
|
309 |
return $file['url'];
|
310 |
}
|
311 |
|
317 |
* @param string $url an URL (absolute or relative) pointing to an image
|
318 |
* @return array an array (see keys in code below)
|
319 |
*/
|
320 |
+
private static function analyze_url($url) {
|
321 |
$result = array(
|
322 |
'url' => $url, // the initial url
|
323 |
+
'absolute' => TimberURLHelper::is_absolute($url), // is the url absolute or relative (to home_url)
|
324 |
'base' => 0, // is the image in uploads dir, or in content dir (theme or plugin)
|
325 |
'subdir' => '', // the path between base (uploads or content) and file
|
326 |
'filename' => '', // the filename, without extension
|
329 |
);
|
330 |
$upload_dir = wp_upload_dir();
|
331 |
$tmp = $url;
|
332 |
+
if ( 0 === strpos($tmp, ABSPATH) ) { // we've been given a dir, not an url
|
|
|
333 |
$result['absolute'] = true;
|
334 |
if ( 0 === strpos($tmp, $upload_dir['basedir']) ) {
|
335 |
+
$result['base']= self::BASE_UPLOADS; // upload based
|
336 |
$tmp = str_replace($upload_dir['basedir'], '', $tmp);
|
337 |
}
|
338 |
if ( 0 === strpos($tmp, WP_CONTENT_DIR) ) {
|
339 |
+
$result['base']= self::BASE_CONTENT; // content based
|
340 |
$tmp = str_replace(WP_CONTENT_DIR, '', $tmp);
|
341 |
}
|
342 |
} else {
|
343 |
+
if (!$result['absolute']) {
|
344 |
$tmp = home_url().$tmp;
|
345 |
}
|
346 |
+
if (0 === strpos($tmp, $upload_dir['baseurl'])) {
|
347 |
+
$result['base']= self::BASE_UPLOADS; // upload based
|
348 |
$tmp = str_replace($upload_dir['baseurl'], '', $tmp);
|
349 |
}
|
350 |
+
if (0 === strpos($tmp, content_url())) {
|
351 |
+
$result['base']= self::BASE_CONTENT; // content-based
|
352 |
$tmp = str_replace(content_url(), '', $tmp);
|
353 |
}
|
354 |
}
|
355 |
$parts = pathinfo($tmp);
|
356 |
+
$result['subdir'] = $parts['dirname'];
|
357 |
$result['filename'] = $parts['filename'];
|
358 |
$result['extension'] = $parts['extension'];
|
359 |
$result['basename'] = $parts['basename'];
|
370 |
* @param bool $absolute should the returned URL be absolute (include protocol+host), or relative
|
371 |
* @return string the URL
|
372 |
*/
|
373 |
+
private static function _get_file_url($base, $subdir, $filename, $absolute) {
|
374 |
$url = '';
|
375 |
+
if( self::BASE_UPLOADS == $base ) {
|
376 |
$upload_dir = wp_upload_dir();
|
377 |
$url = $upload_dir['baseurl'];
|
378 |
}
|
379 |
+
if( self::BASE_CONTENT == $base ) {
|
380 |
$url = content_url();
|
381 |
}
|
382 |
+
if(!empty($subdir)) {
|
383 |
$url .= $subdir;
|
384 |
}
|
385 |
$url .= '/'.$filename;
|
386 |
+
if(!$absolute) {
|
387 |
$url = str_replace(home_url(), '', $url);
|
388 |
}
|
389 |
// $url = TimberURLHelper::remove_double_slashes( $url);
|
398 |
* @param string $filename file name, including extension (but no path)
|
399 |
* @return string the file location
|
400 |
*/
|
401 |
+
private static function _get_file_path($base, $subdir, $filename) {
|
402 |
$path = '';
|
403 |
+
if(self::BASE_UPLOADS == $base) {
|
404 |
$upload_dir = wp_upload_dir();
|
405 |
$path = $upload_dir['basedir'];
|
406 |
}
|
407 |
+
if(self::BASE_CONTENT == $base) {
|
408 |
$path = WP_CONTENT_DIR;
|
409 |
}
|
410 |
+
if(!empty($subdir)) {
|
411 |
$path .= $subdir;
|
412 |
}
|
413 |
$path .= '/'.$filename;
|
429 |
*
|
430 |
*/
|
431 |
private static function _operate( $src, $op, $force = false ) {
|
432 |
+
if ( empty( $src ) ) {
|
433 |
return '';
|
434 |
}
|
435 |
$external = false;
|
436 |
|
437 |
// if external image, load it first
|
438 |
+
if ( TimberURLHelper::is_external_content( $src ) ) {
|
439 |
+
$src = self::sideload_image( $src );
|
440 |
$external = true;
|
441 |
}
|
442 |
// break down URL into components
|
458 |
$au['subdir'],
|
459 |
$au['basename']
|
460 |
);
|
|
|
|
|
|
|
|
|
461 |
// if already exists...
|
462 |
+
if ( file_exists( $new_server_path ) ) {
|
463 |
if ( $force ) {
|
464 |
// Force operation - warning: will regenerate the image on every pageload, use for testing purposes only!
|
465 |
+
unlink( $new_server_path );
|
466 |
} else {
|
467 |
// return existing file (caching)
|
468 |
return $new_url;
|
469 |
}
|
470 |
}
|
471 |
// otherwise generate result file
|
472 |
+
if($op->run($old_server_path, $new_server_path)) {
|
473 |
+
if( get_class( $op ) === 'TimberImageOperationResize' && $external ) {
|
474 |
+
$new_url = strtolower( $new_url );
|
475 |
}
|
476 |
return $new_url;
|
477 |
} else {
|
483 |
|
484 |
// -- the below methods are just used for unit testing the URL generation code
|
485 |
//
|
486 |
+
static function get_letterbox_file_url($url, $w, $h, $color) {
|
487 |
$au = self::analyze_url($url);
|
488 |
+
$op = new TimberImageOperationLetterbox($w, $h, $color);
|
489 |
$new_url = self::_get_file_url(
|
490 |
$au['base'],
|
491 |
$au['subdir'],
|
494 |
);
|
495 |
return $new_url;
|
496 |
}
|
497 |
+
public static function get_letterbox_file_path($url, $w, $h, $color ) {
|
498 |
$au = self::analyze_url($url);
|
499 |
+
$op = new TimberImageOperationLetterbox($w, $h, $color);
|
500 |
$new_path = self::_get_file_path(
|
501 |
$au['base'],
|
502 |
$au['subdir'],
|
504 |
);
|
505 |
return $new_path;
|
506 |
}
|
507 |
+
static function get_resize_file_url($url, $w, $h, $crop) {
|
508 |
$au = self::analyze_url($url);
|
509 |
+
$op = new TimberImageOperationResize($w, $h, $crop);
|
510 |
$new_url = self::_get_file_url(
|
511 |
$au['base'],
|
512 |
$au['subdir'],
|
515 |
);
|
516 |
return $new_url;
|
517 |
}
|
518 |
+
static function get_resize_file_path($url, $w, $h, $crop) {
|
519 |
$au = self::analyze_url($url);
|
520 |
+
$op = new TimberImageOperationResize($w, $h, $crop);
|
521 |
$new_path = self::_get_file_path(
|
522 |
$au['base'],
|
523 |
$au['subdir'],
|
525 |
);
|
526 |
return $new_path;
|
527 |
}
|
528 |
+
|
529 |
+
|
530 |
+
}
|
lib/{Image.php → timber-image.php}
RENAMED
@@ -1,13 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\CoreInterface;
|
6 |
-
use Timber\Helper;
|
7 |
-
use Timber\Post;
|
8 |
-
use Timber\URLHelper;
|
9 |
-
|
10 |
-
|
11 |
/**
|
12 |
* If TimberPost is the class you're going to spend the most time, TimberImage is the class you're going to have the most fun with.
|
13 |
* @example
|
@@ -45,7 +37,7 @@ use Timber\URLHelper;
|
|
45 |
* </article>
|
46 |
* ```
|
47 |
*/
|
48 |
-
class
|
49 |
|
50 |
protected $_can_edit;
|
51 |
protected $_dimensions;
|
@@ -96,7 +88,7 @@ class Image extends Post implements CoreInterface {
|
|
96 |
* ```
|
97 |
* @param int|string $iid
|
98 |
*/
|
99 |
-
public function __construct(
|
100 |
$this->init($iid);
|
101 |
}
|
102 |
|
@@ -104,8 +96,8 @@ class Image extends Post implements CoreInterface {
|
|
104 |
* @return string the src of the file
|
105 |
*/
|
106 |
public function __toString() {
|
107 |
-
if ( $this->
|
108 |
-
return $this->
|
109 |
}
|
110 |
return '';
|
111 |
}
|
@@ -123,7 +115,7 @@ class Image extends Post implements CoreInterface {
|
|
123 |
* @param string $dim
|
124 |
* @return array|int
|
125 |
*/
|
126 |
-
protected function get_dimensions(
|
127 |
if ( isset($this->_dimensions) ) {
|
128 |
return $this->get_dimensions_loaded($dim);
|
129 |
}
|
@@ -141,7 +133,7 @@ class Image extends Post implements CoreInterface {
|
|
141 |
* @param string|null $dim
|
142 |
* @return array|int
|
143 |
*/
|
144 |
-
protected function get_dimensions_loaded(
|
145 |
if ( $dim === null ) {
|
146 |
return $this->_dimensions;
|
147 |
}
|
@@ -154,42 +146,31 @@ class Image extends Post implements CoreInterface {
|
|
154 |
return null;
|
155 |
}
|
156 |
|
157 |
-
/**
|
158 |
-
* @return array
|
159 |
-
*/
|
160 |
-
protected function get_post_custom($iid) {
|
161 |
-
$pc = get_post_custom($iid);
|
162 |
-
if ( is_bool($pc) ) {
|
163 |
-
return array();
|
164 |
-
}
|
165 |
-
return $pc;
|
166 |
-
}
|
167 |
-
|
168 |
/**
|
169 |
* @internal
|
170 |
* @param int $iid the id number of the image in the WP database
|
171 |
*/
|
172 |
protected function get_image_info( $iid ) {
|
173 |
$image_info = $iid;
|
174 |
-
if (
|
175 |
$image_info = wp_get_attachment_metadata($iid);
|
176 |
-
if (
|
177 |
$image_info = array();
|
178 |
}
|
179 |
-
$image_custom =
|
180 |
$basic = get_post($iid);
|
181 |
-
if (
|
182 |
-
if (
|
183 |
$this->caption = $basic->post_excerpt;
|
184 |
}
|
185 |
$image_custom = array_merge($image_custom, get_object_vars($basic));
|
186 |
}
|
187 |
return array_merge($image_info, $image_custom);
|
188 |
}
|
189 |
-
if (
|
190 |
return $image_info['image'];
|
191 |
}
|
192 |
-
if (
|
193 |
return get_object_vars($image_info);
|
194 |
}
|
195 |
return $iid;
|
@@ -200,9 +181,9 @@ class Image extends Post implements CoreInterface {
|
|
200 |
* @param string $url for evaluation
|
201 |
* @return string with http/https corrected depending on what's appropriate for server
|
202 |
*/
|
203 |
-
protected static function _maybe_secure_url(
|
204 |
if ( is_ssl() && strpos($url, 'https') !== 0 && strpos($url, 'http') === 0 ) {
|
205 |
-
$url = 'https'.substr($url, strlen('http'));
|
206 |
}
|
207 |
return $url;
|
208 |
}
|
@@ -222,12 +203,8 @@ class Image extends Post implements CoreInterface {
|
|
222 |
* @param int $iid
|
223 |
*/
|
224 |
function init( $iid = false ) {
|
225 |
-
if (
|
226 |
-
|
227 |
-
$iid = (int) $iid->ID;
|
228 |
-
}
|
229 |
-
if ( !is_numeric($iid) && is_string($iid) ) {
|
230 |
-
if ( strstr($iid, '://') ) {
|
231 |
$this->init_with_url($iid);
|
232 |
return;
|
233 |
}
|
@@ -238,23 +215,23 @@ class Image extends Post implements CoreInterface {
|
|
238 |
|
239 |
$relative = false;
|
240 |
$iid_lower = strtolower($iid);
|
241 |
-
foreach
|
242 |
if ( $relative ) {
|
243 |
-
$this->init_with_relative_path($iid);
|
244 |
return;
|
245 |
}
|
246 |
-
} else if ( $iid instanceof
|
247 |
-
$ref = new
|
248 |
$post = $ref->getParentClass()->newInstance($iid->ID);
|
249 |
-
if (
|
250 |
return $this->init((int) $post->_thumbnail_id);
|
251 |
}
|
252 |
return $this->init($iid->ID);
|
253 |
-
} else if ( $iid instanceof
|
254 |
/**
|
255 |
* This will catch TimberPost and any post classes that extend TimberPost,
|
256 |
* see http://php.net/manual/en/internals2.opcodes.instanceof.php#109108
|
257 |
-
* and https://github.com/
|
258 |
*/
|
259 |
$iid = (int) $iid->_thumbnail_id;
|
260 |
}
|
@@ -265,10 +242,10 @@ class Image extends Post implements CoreInterface {
|
|
265 |
$basedir = self::wp_upload_dir();
|
266 |
$basedir = $basedir['basedir'];
|
267 |
if ( isset($this->file) ) {
|
268 |
-
$this->file_loc = $basedir.DIRECTORY_SEPARATOR
|
269 |
} else if ( isset($this->_wp_attached_file) ) {
|
270 |
$this->file = reset($this->_wp_attached_file);
|
271 |
-
$this->file_loc = $basedir.DIRECTORY_SEPARATOR
|
272 |
}
|
273 |
if ( isset($image_info['id']) ) {
|
274 |
$this->ID = $image_info['id'];
|
@@ -276,17 +253,17 @@ class Image extends Post implements CoreInterface {
|
|
276 |
$this->ID = $iid;
|
277 |
}
|
278 |
if ( isset($this->ID) ) {
|
279 |
-
$custom =
|
280 |
-
foreach (
|
281 |
$this->$key = $value[0];
|
282 |
}
|
283 |
$this->id = $this->ID;
|
284 |
} else {
|
285 |
if ( is_array($iid) || is_object($iid) ) {
|
286 |
-
|
287 |
-
|
288 |
} else {
|
289 |
-
|
290 |
}
|
291 |
}
|
292 |
}
|
@@ -296,8 +273,8 @@ class Image extends Post implements CoreInterface {
|
|
296 |
* @param string $relative_path
|
297 |
*/
|
298 |
protected function init_with_relative_path( $relative_path ) {
|
299 |
-
$this->abs_url = home_url($relative_path);
|
300 |
-
$file_path =
|
301 |
$this->file_loc = $file_path;
|
302 |
$this->file = $file_path;
|
303 |
}
|
@@ -307,7 +284,7 @@ class Image extends Post implements CoreInterface {
|
|
307 |
* @param string $file_path
|
308 |
*/
|
309 |
protected function init_with_file_path( $file_path ) {
|
310 |
-
$url =
|
311 |
$this->abs_url = $url;
|
312 |
$this->file_loc = $file_path;
|
313 |
$this->file = $file_path;
|
@@ -317,11 +294,11 @@ class Image extends Post implements CoreInterface {
|
|
317 |
* @internal
|
318 |
* @param string $url
|
319 |
*/
|
320 |
-
protected function init_with_url(
|
321 |
$this->abs_url = $url;
|
322 |
-
if (
|
323 |
-
$this->file =
|
324 |
-
$this->file_loc =
|
325 |
}
|
326 |
}
|
327 |
|
@@ -416,7 +393,7 @@ class Image extends Post implements CoreInterface {
|
|
416 |
* @return string the /relative/path/to/the/file
|
417 |
*/
|
418 |
public function path() {
|
419 |
-
return
|
420 |
}
|
421 |
|
422 |
/**
|
@@ -432,7 +409,7 @@ class Image extends Post implements CoreInterface {
|
|
432 |
* ```
|
433 |
* @return bool|string
|
434 |
*/
|
435 |
-
public function src(
|
436 |
if ( isset($this->abs_url) ) {
|
437 |
return $this->_maybe_secure_url($this->abs_url);
|
438 |
}
|
@@ -453,11 +430,19 @@ class Image extends Post implements CoreInterface {
|
|
453 |
$dir = self::wp_upload_dir();
|
454 |
$base = $dir['baseurl'];
|
455 |
|
456 |
-
$src = trailingslashit($this->_maybe_secure_url($base))
|
457 |
$src = apply_filters('timber/image/src', $src, $this->ID);
|
458 |
return apply_filters('timber_image_src', $src, $this->ID);
|
459 |
}
|
460 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
461 |
/**
|
462 |
* @api
|
463 |
* @example
|
@@ -473,34 +458,69 @@ class Image extends Post implements CoreInterface {
|
|
473 |
return $this->get_dimensions('width');
|
474 |
}
|
475 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
476 |
/**
|
477 |
* @deprecated 0.21.9 use TimberImage::src
|
478 |
* @internal
|
479 |
* @param string $size
|
480 |
* @return bool|string
|
481 |
*/
|
482 |
-
|
483 |
-
|
484 |
-
return $this->src($size);
|
485 |
}
|
486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
|
488 |
/**
|
489 |
-
* @deprecated
|
490 |
* @return string
|
491 |
*/
|
492 |
-
|
493 |
-
|
494 |
-
return $this->src($size);
|
495 |
}
|
496 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
497 |
|
498 |
/**
|
499 |
-
* @
|
|
|
|
|
500 |
* @return string
|
501 |
*/
|
502 |
-
|
503 |
-
|
504 |
-
return $this->src($size);
|
505 |
}
|
506 |
-
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* If TimberPost is the class you're going to spend the most time, TimberImage is the class you're going to have the most fun with.
|
5 |
* @example
|
37 |
* </article>
|
38 |
* ```
|
39 |
*/
|
40 |
+
class TimberImage extends TimberPost implements TimberCoreInterface {
|
41 |
|
42 |
protected $_can_edit;
|
43 |
protected $_dimensions;
|
88 |
* ```
|
89 |
* @param int|string $iid
|
90 |
*/
|
91 |
+
public function __construct($iid) {
|
92 |
$this->init($iid);
|
93 |
}
|
94 |
|
96 |
* @return string the src of the file
|
97 |
*/
|
98 |
public function __toString() {
|
99 |
+
if ( $this->get_src() ) {
|
100 |
+
return $this->get_src();
|
101 |
}
|
102 |
return '';
|
103 |
}
|
115 |
* @param string $dim
|
116 |
* @return array|int
|
117 |
*/
|
118 |
+
protected function get_dimensions($dim = null) {
|
119 |
if ( isset($this->_dimensions) ) {
|
120 |
return $this->get_dimensions_loaded($dim);
|
121 |
}
|
133 |
* @param string|null $dim
|
134 |
* @return array|int
|
135 |
*/
|
136 |
+
protected function get_dimensions_loaded($dim) {
|
137 |
if ( $dim === null ) {
|
138 |
return $this->_dimensions;
|
139 |
}
|
146 |
return null;
|
147 |
}
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
/**
|
150 |
* @internal
|
151 |
* @param int $iid the id number of the image in the WP database
|
152 |
*/
|
153 |
protected function get_image_info( $iid ) {
|
154 |
$image_info = $iid;
|
155 |
+
if (is_numeric($iid)) {
|
156 |
$image_info = wp_get_attachment_metadata($iid);
|
157 |
+
if (!is_array($image_info)) {
|
158 |
$image_info = array();
|
159 |
}
|
160 |
+
$image_custom = get_post_custom($iid);
|
161 |
$basic = get_post($iid);
|
162 |
+
if ($basic) {
|
163 |
+
if (isset($basic->post_excerpt)) {
|
164 |
$this->caption = $basic->post_excerpt;
|
165 |
}
|
166 |
$image_custom = array_merge($image_custom, get_object_vars($basic));
|
167 |
}
|
168 |
return array_merge($image_info, $image_custom);
|
169 |
}
|
170 |
+
if (is_array($image_info) && isset($image_info['image'])) {
|
171 |
return $image_info['image'];
|
172 |
}
|
173 |
+
if (is_object($image_info)) {
|
174 |
return get_object_vars($image_info);
|
175 |
}
|
176 |
return $iid;
|
181 |
* @param string $url for evaluation
|
182 |
* @return string with http/https corrected depending on what's appropriate for server
|
183 |
*/
|
184 |
+
protected static function _maybe_secure_url($url) {
|
185 |
if ( is_ssl() && strpos($url, 'https') !== 0 && strpos($url, 'http') === 0 ) {
|
186 |
+
$url = 'https' . substr($url, strlen('http'));
|
187 |
}
|
188 |
return $url;
|
189 |
}
|
203 |
* @param int $iid
|
204 |
*/
|
205 |
function init( $iid = false ) {
|
206 |
+
if ( !is_numeric( $iid ) && is_string( $iid ) ) {
|
207 |
+
if (strstr($iid, '://')) {
|
|
|
|
|
|
|
|
|
208 |
$this->init_with_url($iid);
|
209 |
return;
|
210 |
}
|
215 |
|
216 |
$relative = false;
|
217 |
$iid_lower = strtolower($iid);
|
218 |
+
foreach( $this->file_types as $type ) { if( strstr( $iid_lower, $type ) ) { $relative = true; break; } };
|
219 |
if ( $relative ) {
|
220 |
+
$this->init_with_relative_path( $iid );
|
221 |
return;
|
222 |
}
|
223 |
+
} else if ( $iid instanceof WP_Post ) {
|
224 |
+
$ref = new ReflectionClass($this);
|
225 |
$post = $ref->getParentClass()->newInstance($iid->ID);
|
226 |
+
if (isset($post->_thumbnail_id) && $post->_thumbnail_id) {
|
227 |
return $this->init((int) $post->_thumbnail_id);
|
228 |
}
|
229 |
return $this->init($iid->ID);
|
230 |
+
} else if ( $iid instanceof TimberPost ) {
|
231 |
/**
|
232 |
* This will catch TimberPost and any post classes that extend TimberPost,
|
233 |
* see http://php.net/manual/en/internals2.opcodes.instanceof.php#109108
|
234 |
+
* and https://github.com/jarednova/timber/wiki/Extending-Timber
|
235 |
*/
|
236 |
$iid = (int) $iid->_thumbnail_id;
|
237 |
}
|
242 |
$basedir = self::wp_upload_dir();
|
243 |
$basedir = $basedir['basedir'];
|
244 |
if ( isset($this->file) ) {
|
245 |
+
$this->file_loc = $basedir . DIRECTORY_SEPARATOR . $this->file;
|
246 |
} else if ( isset($this->_wp_attached_file) ) {
|
247 |
$this->file = reset($this->_wp_attached_file);
|
248 |
+
$this->file_loc = $basedir . DIRECTORY_SEPARATOR . $this->file;
|
249 |
}
|
250 |
if ( isset($image_info['id']) ) {
|
251 |
$this->ID = $image_info['id'];
|
253 |
$this->ID = $iid;
|
254 |
}
|
255 |
if ( isset($this->ID) ) {
|
256 |
+
$custom = get_post_custom($this->ID);
|
257 |
+
foreach ($custom as $key => $value) {
|
258 |
$this->$key = $value[0];
|
259 |
}
|
260 |
$this->id = $this->ID;
|
261 |
} else {
|
262 |
if ( is_array($iid) || is_object($iid) ) {
|
263 |
+
TimberHelper::error_log('Not able to init in TimberImage with iid=');
|
264 |
+
TimberHelper::error_log($iid);
|
265 |
} else {
|
266 |
+
TimberHelper::error_log('Not able to init in TimberImage with iid=' . $iid);
|
267 |
}
|
268 |
}
|
269 |
}
|
273 |
* @param string $relative_path
|
274 |
*/
|
275 |
protected function init_with_relative_path( $relative_path ) {
|
276 |
+
$this->abs_url = home_url( $relative_path );
|
277 |
+
$file_path = TimberURLHelper::get_full_path( $relative_path );
|
278 |
$this->file_loc = $file_path;
|
279 |
$this->file = $file_path;
|
280 |
}
|
284 |
* @param string $file_path
|
285 |
*/
|
286 |
protected function init_with_file_path( $file_path ) {
|
287 |
+
$url = TimberURLHelper::file_system_to_url( $file_path );
|
288 |
$this->abs_url = $url;
|
289 |
$this->file_loc = $file_path;
|
290 |
$this->file = $file_path;
|
294 |
* @internal
|
295 |
* @param string $url
|
296 |
*/
|
297 |
+
protected function init_with_url($url) {
|
298 |
$this->abs_url = $url;
|
299 |
+
if ( TimberURLHelper::is_local($url) ) {
|
300 |
+
$this->file = ABSPATH . TimberURLHelper::get_rel_url($url);
|
301 |
+
$this->file_loc = ABSPATH . TimberURLHelper::get_rel_url($url);
|
302 |
}
|
303 |
}
|
304 |
|
393 |
* @return string the /relative/path/to/the/file
|
394 |
*/
|
395 |
public function path() {
|
396 |
+
return TimberURLHelper::get_rel_path($this->src());
|
397 |
}
|
398 |
|
399 |
/**
|
409 |
* ```
|
410 |
* @return bool|string
|
411 |
*/
|
412 |
+
public function src($size = '') {
|
413 |
if ( isset($this->abs_url) ) {
|
414 |
return $this->_maybe_secure_url($this->abs_url);
|
415 |
}
|
430 |
$dir = self::wp_upload_dir();
|
431 |
$base = $dir['baseurl'];
|
432 |
|
433 |
+
$src = trailingslashit($this->_maybe_secure_url($base)) . $this->file;
|
434 |
$src = apply_filters('timber/image/src', $src, $this->ID);
|
435 |
return apply_filters('timber_image_src', $src, $this->ID);
|
436 |
}
|
437 |
|
438 |
+
/**
|
439 |
+
* @deprecated use src() instead
|
440 |
+
* @return string
|
441 |
+
*/
|
442 |
+
function url() {
|
443 |
+
return $this->get_src();
|
444 |
+
}
|
445 |
+
|
446 |
/**
|
447 |
* @api
|
448 |
* @example
|
458 |
return $this->get_dimensions('width');
|
459 |
}
|
460 |
|
461 |
+
|
462 |
+
/**
|
463 |
+
* @deprecated 0.21.9 use TimberImage::width() instead
|
464 |
+
* @internal
|
465 |
+
* @return int
|
466 |
+
*/
|
467 |
+
function get_width() {
|
468 |
+
return $this->width();
|
469 |
+
}
|
470 |
+
|
471 |
+
/**
|
472 |
+
* @deprecated 0.21.9 use TimberImage::height() instead
|
473 |
+
* @internal
|
474 |
+
* @return int
|
475 |
+
*/
|
476 |
+
function get_height() {
|
477 |
+
return $this->height();
|
478 |
+
}
|
479 |
+
|
480 |
/**
|
481 |
* @deprecated 0.21.9 use TimberImage::src
|
482 |
* @internal
|
483 |
* @param string $size
|
484 |
* @return bool|string
|
485 |
*/
|
486 |
+
function get_src( $size = '' ) {
|
487 |
+
return $this->src( $size );
|
|
|
488 |
}
|
489 |
|
490 |
+
/**
|
491 |
+
* @deprecated 0.21.9 use TimberImage::path()
|
492 |
+
* @internal
|
493 |
+
* @return string
|
494 |
+
*/
|
495 |
+
function get_path() {
|
496 |
+
return $this->link();
|
497 |
+
}
|
498 |
|
499 |
/**
|
500 |
+
* @deprecated use src() instead
|
501 |
* @return string
|
502 |
*/
|
503 |
+
function get_url() {
|
504 |
+
return $this->get_src();
|
|
|
505 |
}
|
506 |
|
507 |
+
/**
|
508 |
+
* @internal
|
509 |
+
* @deprecated 0.21.8
|
510 |
+
* @return bool|TimberPost
|
511 |
+
*/
|
512 |
+
function get_parent() {
|
513 |
+
return $this->parent();
|
514 |
+
}
|
515 |
|
516 |
/**
|
517 |
+
* @internal
|
518 |
+
* @deprecated 0.21.9
|
519 |
+
* @see TimberImage::alt
|
520 |
* @return string
|
521 |
*/
|
522 |
+
function get_alt() {
|
523 |
+
return $this->alt();
|
|
|
524 |
}
|
525 |
+
|
526 |
+
}
|
lib/timber-integrations.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* This is for integrating external plugins into timber
|
5 |
+
* @package timber
|
6 |
+
*/
|
7 |
+
class TimberIntegrations {
|
8 |
+
public static function init() {
|
9 |
+
|
10 |
+
add_action( 'init', array( __CLASS__, 'maybe_init_acftimber' ) );
|
11 |
+
|
12 |
+
if ( class_exists( 'WP_CLI_Command' ) ) {
|
13 |
+
WP_CLI::add_command( 'timber', 'Timber_WP_CLI_Command' );
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function maybe_init_acftimber() {
|
18 |
+
|
19 |
+
if ( class_exists( 'ACF' ) ) {
|
20 |
+
new ACFTimber();
|
21 |
+
}
|
22 |
+
|
23 |
+
}
|
24 |
+
}
|
lib/{Loader.php → timber-loader.php}
RENAMED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
class Loader {
|
6 |
|
7 |
const CACHEGROUP = 'timberloader';
|
8 |
|
@@ -28,7 +26,7 @@ class Loader {
|
|
28 |
/**
|
29 |
* @param bool|string $caller the calling directory or false
|
30 |
*/
|
31 |
-
function __construct(
|
32 |
$this->locations = $this->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);
|
@@ -41,10 +39,10 @@ class Loader {
|
|
41 |
* @param string $cache_mode
|
42 |
* @return bool|string
|
43 |
*/
|
44 |
-
function render(
|
45 |
// Different $expires if user is anonymous or logged in
|
46 |
-
if (
|
47 |
-
if (
|
48 |
$expires = $expires[1];
|
49 |
} else {
|
50 |
$expires = $expires[0];
|
@@ -53,15 +51,15 @@ class Loader {
|
|
53 |
|
54 |
$key = null;
|
55 |
$output = false;
|
56 |
-
if (
|
57 |
ksort($data);
|
58 |
-
$key = md5($file.json_encode($data));
|
59 |
$output = $this->get_cache($key, self::CACHEGROUP, $cache_mode);
|
60 |
}
|
61 |
|
62 |
-
if (
|
63 |
$twig = $this->get_twig();
|
64 |
-
if (
|
65 |
$loader = $this->get_loader();
|
66 |
$result = $loader->getCacheKey($file);
|
67 |
do_action('timber_loader_render_file', $result);
|
@@ -71,7 +69,7 @@ class Loader {
|
|
71 |
$output = $twig->render($file, $data);
|
72 |
}
|
73 |
|
74 |
-
if (
|
75 |
$this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode);
|
76 |
}
|
77 |
$output = apply_filters('timber_output', $output);
|
@@ -82,11 +80,11 @@ class Loader {
|
|
82 |
* @param array $filenames
|
83 |
* @return bool
|
84 |
*/
|
85 |
-
public function choose_template(
|
86 |
-
if (
|
87 |
/* its an array so we have to figure out which one the dev wants */
|
88 |
-
foreach (
|
89 |
-
if (
|
90 |
return $filename;
|
91 |
}
|
92 |
}
|
@@ -99,10 +97,10 @@ class Loader {
|
|
99 |
* @param string $file
|
100 |
* @return bool
|
101 |
*/
|
102 |
-
protected function template_exists(
|
103 |
-
foreach (
|
104 |
-
$look_for = trailingslashit($dir)
|
105 |
-
if (
|
106 |
return true;
|
107 |
}
|
108 |
}
|
@@ -116,18 +114,18 @@ class Loader {
|
|
116 |
$theme_locs = array();
|
117 |
$child_loc = get_stylesheet_directory();
|
118 |
$parent_loc = get_template_directory();
|
119 |
-
if (
|
120 |
$child_loc = str_replace('/', '\\', $child_loc);
|
121 |
$parent_loc = str_replace('/', '\\', $parent_loc);
|
122 |
}
|
123 |
$theme_locs[] = $child_loc;
|
124 |
-
foreach (
|
125 |
-
$theme_locs[] = trailingslashit($child_loc).trailingslashit($dirname);
|
126 |
}
|
127 |
-
if (
|
128 |
$theme_locs[] = $parent_loc;
|
129 |
-
foreach (
|
130 |
-
$theme_locs[] = trailingslashit($parent_loc).trailingslashit($dirname);
|
131 |
}
|
132 |
}
|
133 |
//now make sure theres a trailing slash on everything
|
@@ -140,25 +138,24 @@ class Loader {
|
|
140 |
* @return string[] the names of directores, ie: array('templats', 'views');
|
141 |
*/
|
142 |
private function get_locations_theme_dir() {
|
143 |
-
if (
|
144 |
return array(Timber::$dirname);
|
145 |
}
|
146 |
return Timber::$dirname;
|
147 |
}
|
148 |
|
149 |
/**
|
150 |
-
*
|
151 |
* @return array
|
152 |
*/
|
153 |
function get_locations_user() {
|
154 |
$locs = array();
|
155 |
-
if (
|
156 |
-
if (
|
157 |
Timber::$locations = array(Timber::$locations);
|
158 |
}
|
159 |
-
foreach (
|
160 |
$tloc = realpath($tloc);
|
161 |
-
if (
|
162 |
$locs[] = $tloc;
|
163 |
}
|
164 |
}
|
@@ -170,16 +167,16 @@ class Loader {
|
|
170 |
* @param bool|string $caller the calling directory
|
171 |
* @return array
|
172 |
*/
|
173 |
-
function get_locations_caller(
|
174 |
$locs = array();
|
175 |
-
if (
|
176 |
$caller = trailingslashit($caller);
|
177 |
-
if (
|
178 |
$locs[] = $caller;
|
179 |
}
|
180 |
-
foreach (
|
181 |
-
$caller_sub = $caller.trailingslashit($dirname);
|
182 |
-
if (
|
183 |
$locs[] = $caller_sub;
|
184 |
}
|
185 |
}
|
@@ -191,7 +188,7 @@ class Loader {
|
|
191 |
* @param bool|string $caller the calling directory (or false)
|
192 |
* @return array
|
193 |
*/
|
194 |
-
function get_locations(
|
195 |
//prioirty: user locations, caller (but not theme), child theme, parent theme, caller
|
196 |
$locs = array();
|
197 |
$locs = array_merge($locs, $this->get_locations_user());
|
@@ -207,26 +204,26 @@ class Loader {
|
|
207 |
}
|
208 |
|
209 |
/**
|
210 |
-
* @return
|
211 |
*/
|
212 |
function get_loader() {
|
213 |
$paths = array();
|
214 |
-
foreach (
|
215 |
$loc = realpath($loc);
|
216 |
-
if (
|
217 |
$loc = realpath($loc);
|
218 |
$paths[] = $loc;
|
219 |
} else {
|
220 |
//error_log($loc.' is not a directory');
|
221 |
}
|
222 |
}
|
223 |
-
if (
|
224 |
$paths[] = '/';
|
225 |
} else {
|
226 |
$paths[] = ABSPATH;
|
227 |
}
|
228 |
$paths = apply_filters('timber/loader/paths', $paths);
|
229 |
-
$loader = new
|
230 |
return $loader;
|
231 |
}
|
232 |
|
@@ -236,22 +233,22 @@ class Loader {
|
|
236 |
function get_twig() {
|
237 |
$loader = $this->get_loader();
|
238 |
$params = array('debug' => WP_DEBUG, 'autoescape' => false);
|
239 |
-
if (
|
240 |
$params['autoescape'] = Timber::$autoescape;
|
241 |
}
|
242 |
-
if (
|
243 |
Timber::$twig_cache = true;
|
244 |
}
|
245 |
-
if (
|
246 |
-
$twig_cache_loc = apply_filters('timber/cache/location', TIMBER_LOC.'/cache/twig');
|
247 |
-
if (
|
248 |
mkdir($twig_cache_loc, 0777, true);
|
249 |
}
|
250 |
$params['cache'] = $twig_cache_loc;
|
251 |
}
|
252 |
-
$twig = new
|
253 |
if ( WP_DEBUG ) {
|
254 |
-
$twig->addExtension(new
|
255 |
}
|
256 |
$twig->addExtension($this->_get_cache_extension());
|
257 |
|
@@ -261,26 +258,26 @@ class Loader {
|
|
261 |
return $twig;
|
262 |
}
|
263 |
|
264 |
-
public function clear_cache_timber(
|
265 |
//_transient_timberloader
|
266 |
$object_cache = false;
|
267 |
-
if (
|
268 |
$object_cache = true;
|
269 |
}
|
270 |
$cache_mode = $this->_get_cache_mode($cache_mode);
|
271 |
-
if (
|
272 |
global $wpdb;
|
273 |
$query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%');
|
274 |
-
$wpdb->query($query);
|
275 |
return true;
|
276 |
-
} else if (
|
277 |
global $wpdb;
|
278 |
$query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%');
|
279 |
-
$wpdb->query($query);
|
280 |
return true;
|
281 |
-
} else if (
|
282 |
global $wp_object_cache;
|
283 |
-
if (
|
284 |
unset($wp_object_cache->cache[self::CACHEGROUP]);
|
285 |
return true;
|
286 |
}
|
@@ -292,7 +289,7 @@ class Loader {
|
|
292 |
$twig = $this->get_twig();
|
293 |
$twig->clearCacheFiles();
|
294 |
$cache = $twig->getCache();
|
295 |
-
if (
|
296 |
self::rrmdir($twig->getCache());
|
297 |
return true;
|
298 |
}
|
@@ -302,16 +299,16 @@ class Loader {
|
|
302 |
/**
|
303 |
* @param string|false $dirPath
|
304 |
*/
|
305 |
-
public static function rrmdir(
|
306 |
-
if (
|
307 |
-
throw new
|
308 |
}
|
309 |
-
if (
|
310 |
$dirPath .= '/';
|
311 |
}
|
312 |
-
$files = glob($dirPath.'*', GLOB_MARK);
|
313 |
-
foreach (
|
314 |
-
if (
|
315 |
self::rrmdir($file);
|
316 |
} else {
|
317 |
unlink($file);
|
@@ -326,9 +323,9 @@ class Loader {
|
|
326 |
private function _get_cache_extension() {
|
327 |
|
328 |
$key_generator = new \Timber\Cache\KeyGenerator();
|
329 |
-
$cache_provider = new \Timber\Cache\WPObjectCacheAdapter($this);
|
330 |
-
$cache_strategy = new \Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy($cache_provider, $key_generator);
|
331 |
-
$cache_extension = new \Asm89\Twig\CacheExtension\Extension($cache_strategy);
|
332 |
|
333 |
return $cache_extension;
|
334 |
}
|
@@ -339,10 +336,10 @@ class Loader {
|
|
339 |
* @param string $cache_mode
|
340 |
* @return bool
|
341 |
*/
|
342 |
-
public function get_cache(
|
343 |
$object_cache = false;
|
344 |
|
345 |
-
if (
|
346 |
$object_cache = true;
|
347 |
}
|
348 |
|
@@ -350,14 +347,15 @@ class Loader {
|
|
350 |
|
351 |
$value = false;
|
352 |
|
353 |
-
$trans_key = substr($group.'_'
|
354 |
-
if (
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
|
|
361 |
|
362 |
return $value;
|
363 |
}
|
@@ -370,27 +368,27 @@ class Loader {
|
|
370 |
* @param string $cache_mode
|
371 |
* @return string|boolean
|
372 |
*/
|
373 |
-
public function set_cache(
|
374 |
$object_cache = false;
|
375 |
|
376 |
-
if (
|
377 |
$object_cache = true;
|
378 |
}
|
379 |
|
380 |
-
if (
|
381 |
-
|
382 |
-
}
|
383 |
|
384 |
$cache_mode = self::_get_cache_mode($cache_mode);
|
385 |
-
$trans_key = substr($group.'_'
|
386 |
-
|
387 |
-
if (
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
|
|
394 |
|
395 |
return $value;
|
396 |
}
|
@@ -399,13 +397,13 @@ class Loader {
|
|
399 |
* @param string $cache_mode
|
400 |
* @return string
|
401 |
*/
|
402 |
-
private function _get_cache_mode(
|
403 |
-
if (
|
404 |
$cache_mode = $this->cache_mode;
|
405 |
}
|
406 |
|
407 |
// Fallback if self::$cache_mode did not get a valid value
|
408 |
-
if (
|
409 |
$cache_mode = self::CACHE_OBJECT;
|
410 |
}
|
411 |
|
1 |
<?php
|
2 |
|
3 |
+
class TimberLoader {
|
|
|
|
|
4 |
|
5 |
const CACHEGROUP = 'timberloader';
|
6 |
|
26 |
/**
|
27 |
* @param bool|string $caller the calling directory or false
|
28 |
*/
|
29 |
+
function __construct($caller = false) {
|
30 |
$this->locations = $this->get_locations($caller);
|
31 |
$this->cache_mode = apply_filters('timber_cache_mode', $this->cache_mode);
|
32 |
$this->cache_mode = apply_filters('timber/cache/mode', $this->cache_mode);
|
39 |
* @param string $cache_mode
|
40 |
* @return bool|string
|
41 |
*/
|
42 |
+
function render($file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT) {
|
43 |
// Different $expires if user is anonymous or logged in
|
44 |
+
if (is_array($expires)) {
|
45 |
+
if (is_user_logged_in() && isset($expires[1])) {
|
46 |
$expires = $expires[1];
|
47 |
} else {
|
48 |
$expires = $expires[0];
|
51 |
|
52 |
$key = null;
|
53 |
$output = false;
|
54 |
+
if (false !== $expires) {
|
55 |
ksort($data);
|
56 |
+
$key = md5($file . json_encode($data));
|
57 |
$output = $this->get_cache($key, self::CACHEGROUP, $cache_mode);
|
58 |
}
|
59 |
|
60 |
+
if (false === $output || null === $output) {
|
61 |
$twig = $this->get_twig();
|
62 |
+
if (strlen($file)) {
|
63 |
$loader = $this->get_loader();
|
64 |
$result = $loader->getCacheKey($file);
|
65 |
do_action('timber_loader_render_file', $result);
|
69 |
$output = $twig->render($file, $data);
|
70 |
}
|
71 |
|
72 |
+
if (false !== $output && false !== $expires && null !== $key) {
|
73 |
$this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode);
|
74 |
}
|
75 |
$output = apply_filters('timber_output', $output);
|
80 |
* @param array $filenames
|
81 |
* @return bool
|
82 |
*/
|
83 |
+
public function choose_template($filenames) {
|
84 |
+
if (is_array($filenames)) {
|
85 |
/* its an array so we have to figure out which one the dev wants */
|
86 |
+
foreach ($filenames as $filename) {
|
87 |
+
if (self::template_exists($filename)) {
|
88 |
return $filename;
|
89 |
}
|
90 |
}
|
97 |
* @param string $file
|
98 |
* @return bool
|
99 |
*/
|
100 |
+
protected function template_exists($file) {
|
101 |
+
foreach ($this->locations as $dir) {
|
102 |
+
$look_for = trailingslashit($dir) . $file;
|
103 |
+
if (file_exists($look_for)) {
|
104 |
return true;
|
105 |
}
|
106 |
}
|
114 |
$theme_locs = array();
|
115 |
$child_loc = get_stylesheet_directory();
|
116 |
$parent_loc = get_template_directory();
|
117 |
+
if (DIRECTORY_SEPARATOR == '\\') {
|
118 |
$child_loc = str_replace('/', '\\', $child_loc);
|
119 |
$parent_loc = str_replace('/', '\\', $parent_loc);
|
120 |
}
|
121 |
$theme_locs[] = $child_loc;
|
122 |
+
foreach ($this->get_locations_theme_dir() as $dirname) {
|
123 |
+
$theme_locs[] = trailingslashit($child_loc) . trailingslashit($dirname);
|
124 |
}
|
125 |
+
if ($child_loc != $parent_loc) {
|
126 |
$theme_locs[] = $parent_loc;
|
127 |
+
foreach ($this->get_locations_theme_dir() as $dirname) {
|
128 |
+
$theme_locs[] = trailingslashit($parent_loc) . trailingslashit($dirname);
|
129 |
}
|
130 |
}
|
131 |
//now make sure theres a trailing slash on everything
|
138 |
* @return string[] the names of directores, ie: array('templats', 'views');
|
139 |
*/
|
140 |
private function get_locations_theme_dir() {
|
141 |
+
if (is_string(Timber::$dirname)) {
|
142 |
return array(Timber::$dirname);
|
143 |
}
|
144 |
return Timber::$dirname;
|
145 |
}
|
146 |
|
147 |
/**
|
|
|
148 |
* @return array
|
149 |
*/
|
150 |
function get_locations_user() {
|
151 |
$locs = array();
|
152 |
+
if (isset(Timber::$locations)) {
|
153 |
+
if (is_string(Timber::$locations)) {
|
154 |
Timber::$locations = array(Timber::$locations);
|
155 |
}
|
156 |
+
foreach (Timber::$locations as $tloc) {
|
157 |
$tloc = realpath($tloc);
|
158 |
+
if (is_dir($tloc)) {
|
159 |
$locs[] = $tloc;
|
160 |
}
|
161 |
}
|
167 |
* @param bool|string $caller the calling directory
|
168 |
* @return array
|
169 |
*/
|
170 |
+
function get_locations_caller($caller = false) {
|
171 |
$locs = array();
|
172 |
+
if ($caller && is_string($caller)) {
|
173 |
$caller = trailingslashit($caller);
|
174 |
+
if (is_dir($caller)) {
|
175 |
$locs[] = $caller;
|
176 |
}
|
177 |
+
foreach ($this->get_locations_theme_dir() as $dirname) {
|
178 |
+
$caller_sub = $caller . trailingslashit($dirname);
|
179 |
+
if (is_dir($caller_sub)) {
|
180 |
$locs[] = $caller_sub;
|
181 |
}
|
182 |
}
|
188 |
* @param bool|string $caller the calling directory (or false)
|
189 |
* @return array
|
190 |
*/
|
191 |
+
function get_locations($caller = false) {
|
192 |
//prioirty: user locations, caller (but not theme), child theme, parent theme, caller
|
193 |
$locs = array();
|
194 |
$locs = array_merge($locs, $this->get_locations_user());
|
204 |
}
|
205 |
|
206 |
/**
|
207 |
+
* @return Twig_Loader_Filesystem
|
208 |
*/
|
209 |
function get_loader() {
|
210 |
$paths = array();
|
211 |
+
foreach ($this->locations as $loc) {
|
212 |
$loc = realpath($loc);
|
213 |
+
if (is_dir($loc)) {
|
214 |
$loc = realpath($loc);
|
215 |
$paths[] = $loc;
|
216 |
} else {
|
217 |
//error_log($loc.' is not a directory');
|
218 |
}
|
219 |
}
|
220 |
+
if (!ini_get('open_basedir')) {
|
221 |
$paths[] = '/';
|
222 |
} else {
|
223 |
$paths[] = ABSPATH;
|
224 |
}
|
225 |
$paths = apply_filters('timber/loader/paths', $paths);
|
226 |
+
$loader = new Twig_Loader_Filesystem($paths);
|
227 |
return $loader;
|
228 |
}
|
229 |
|
233 |
function get_twig() {
|
234 |
$loader = $this->get_loader();
|
235 |
$params = array('debug' => WP_DEBUG, 'autoescape' => false);
|
236 |
+
if (isset(Timber::$autoescape)) {
|
237 |
$params['autoescape'] = Timber::$autoescape;
|
238 |
}
|
239 |
+
if (Timber::$cache === true) {
|
240 |
Timber::$twig_cache = true;
|
241 |
}
|
242 |
+
if (Timber::$twig_cache) {
|
243 |
+
$twig_cache_loc = apply_filters( 'timber/cache/location', TIMBER_LOC . '/cache/twig' );
|
244 |
+
if (!file_exists($twig_cache_loc)) {
|
245 |
mkdir($twig_cache_loc, 0777, true);
|
246 |
}
|
247 |
$params['cache'] = $twig_cache_loc;
|
248 |
}
|
249 |
+
$twig = new Twig_Environment($loader, $params);
|
250 |
if ( WP_DEBUG ) {
|
251 |
+
$twig->addExtension(new Twig_Extension_Debug());
|
252 |
}
|
253 |
$twig->addExtension($this->_get_cache_extension());
|
254 |
|
258 |
return $twig;
|
259 |
}
|
260 |
|
261 |
+
public function clear_cache_timber($cache_mode = self::CACHE_USE_DEFAULT){
|
262 |
//_transient_timberloader
|
263 |
$object_cache = false;
|
264 |
+
if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) {
|
265 |
$object_cache = true;
|
266 |
}
|
267 |
$cache_mode = $this->_get_cache_mode($cache_mode);
|
268 |
+
if (self::CACHE_TRANSIENT === $cache_mode) {
|
269 |
global $wpdb;
|
270 |
$query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%');
|
271 |
+
$wpdb->query( $query );
|
272 |
return true;
|
273 |
+
} else if (self::CACHE_SITE_TRANSIENT === $cache_mode) {
|
274 |
global $wpdb;
|
275 |
$query = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE '%s'", '_transient_timberloader_%');
|
276 |
+
$wpdb->query( $query );
|
277 |
return true;
|
278 |
+
} else if (self::CACHE_OBJECT === $cache_mode && $object_cache) {
|
279 |
global $wp_object_cache;
|
280 |
+
if (isset($wp_object_cache->cache[self::CACHEGROUP])){
|
281 |
unset($wp_object_cache->cache[self::CACHEGROUP]);
|
282 |
return true;
|
283 |
}
|
289 |
$twig = $this->get_twig();
|
290 |
$twig->clearCacheFiles();
|
291 |
$cache = $twig->getCache();
|
292 |
+
if ($cache){
|
293 |
self::rrmdir($twig->getCache());
|
294 |
return true;
|
295 |
}
|
299 |
/**
|
300 |
* @param string|false $dirPath
|
301 |
*/
|
302 |
+
public static function rrmdir($dirPath) {
|
303 |
+
if (! is_dir($dirPath)) {
|
304 |
+
throw new InvalidArgumentException("$dirPath must be a directory");
|
305 |
}
|
306 |
+
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
|
307 |
$dirPath .= '/';
|
308 |
}
|
309 |
+
$files = glob($dirPath . '*', GLOB_MARK);
|
310 |
+
foreach ($files as $file) {
|
311 |
+
if (is_dir($file)) {
|
312 |
self::rrmdir($file);
|
313 |
} else {
|
314 |
unlink($file);
|
323 |
private function _get_cache_extension() {
|
324 |
|
325 |
$key_generator = new \Timber\Cache\KeyGenerator();
|
326 |
+
$cache_provider = new \Timber\Cache\WPObjectCacheAdapter( $this );
|
327 |
+
$cache_strategy = new \Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy( $cache_provider, $key_generator );
|
328 |
+
$cache_extension = new \Asm89\Twig\CacheExtension\Extension( $cache_strategy );
|
329 |
|
330 |
return $cache_extension;
|
331 |
}
|
336 |
* @param string $cache_mode
|
337 |
* @return bool
|
338 |
*/
|
339 |
+
public function get_cache($key, $group = self::CACHEGROUP, $cache_mode = self::CACHE_USE_DEFAULT) {
|
340 |
$object_cache = false;
|
341 |
|
342 |
+
if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) {
|
343 |
$object_cache = true;
|
344 |
}
|
345 |
|
347 |
|
348 |
$value = false;
|
349 |
|
350 |
+
$trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN);
|
351 |
+
if (self::CACHE_TRANSIENT === $cache_mode)
|
352 |
+
$value = get_transient($trans_key);
|
353 |
+
|
354 |
+
elseif (self::CACHE_SITE_TRANSIENT === $cache_mode)
|
355 |
+
$value = get_site_transient($trans_key);
|
356 |
+
|
357 |
+
elseif (self::CACHE_OBJECT === $cache_mode && $object_cache)
|
358 |
+
$value = wp_cache_get($key, $group);
|
359 |
|
360 |
return $value;
|
361 |
}
|
368 |
* @param string $cache_mode
|
369 |
* @return string|boolean
|
370 |
*/
|
371 |
+
public function set_cache($key, $value, $group = self::CACHEGROUP, $expires = 0, $cache_mode = self::CACHE_USE_DEFAULT) {
|
372 |
$object_cache = false;
|
373 |
|
374 |
+
if (isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache'])) {
|
375 |
$object_cache = true;
|
376 |
}
|
377 |
|
378 |
+
if ((int)$expires < 1)
|
379 |
+
$expires = 0;
|
|
|
380 |
|
381 |
$cache_mode = self::_get_cache_mode($cache_mode);
|
382 |
+
$trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN);
|
383 |
+
|
384 |
+
if (self::CACHE_TRANSIENT === $cache_mode)
|
385 |
+
set_transient($trans_key, $value, $expires);
|
386 |
+
|
387 |
+
elseif (self::CACHE_SITE_TRANSIENT === $cache_mode)
|
388 |
+
set_site_transient($trans_key, $value, $expires);
|
389 |
+
|
390 |
+
elseif (self::CACHE_OBJECT === $cache_mode && $object_cache)
|
391 |
+
wp_cache_set($key, $value, $group, $expires);
|
392 |
|
393 |
return $value;
|
394 |
}
|
397 |
* @param string $cache_mode
|
398 |
* @return string
|
399 |
*/
|
400 |
+
private function _get_cache_mode($cache_mode) {
|
401 |
+
if (empty($cache_mode) || self::CACHE_USE_DEFAULT === $cache_mode) {
|
402 |
$cache_mode = $this->cache_mode;
|
403 |
}
|
404 |
|
405 |
// Fallback if self::$cache_mode did not get a valid value
|
406 |
+
if (!in_array($cache_mode, self::$cache_modes)) {
|
407 |
$cache_mode = self::CACHE_OBJECT;
|
408 |
}
|
409 |
|
lib/{MenuItem.php → timber-menu-item.php}
RENAMED
@@ -1,13 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\CoreInterface;
|
7 |
-
|
8 |
-
use Timber\URLHelper;
|
9 |
-
|
10 |
-
class MenuItem extends Core implements CoreInterface {
|
11 |
|
12 |
public $children;
|
13 |
public $has_child_class = false;
|
@@ -33,13 +26,13 @@ class MenuItem extends Core implements CoreInterface {
|
|
33 |
*/
|
34 |
public function __construct( $data ) {
|
35 |
$data = (object) $data;
|
36 |
-
$this->import($data);
|
37 |
-
$this->import_classes($data);
|
38 |
-
if ( isset($this->name) ) {
|
39 |
$this->_name = $this->name;
|
40 |
}
|
41 |
$this->name = $this->name();
|
42 |
-
$this->add_class('menu-item-'
|
43 |
$this->menu_object = $data;
|
44 |
}
|
45 |
|
@@ -56,7 +49,7 @@ class MenuItem extends Core implements CoreInterface {
|
|
56 |
*/
|
57 |
public function add_class( $class_name ) {
|
58 |
$this->classes[] = $class_name;
|
59 |
-
$this->class .= ' '
|
60 |
}
|
61 |
|
62 |
/**
|
@@ -68,7 +61,7 @@ class MenuItem extends Core implements CoreInterface {
|
|
68 |
if ( $title = $this->title() ) {
|
69 |
return $title;
|
70 |
}
|
71 |
-
if ( isset($this->_name) ) {
|
72 |
return $this->_name;
|
73 |
}
|
74 |
return '';
|
@@ -89,10 +82,10 @@ class MenuItem extends Core implements CoreInterface {
|
|
89 |
* @return string the slug of the menu item kinda-like-this
|
90 |
*/
|
91 |
public function slug() {
|
92 |
-
if ( !isset($this->master_object) ) {
|
93 |
$this->master_object = $this->get_master_object();
|
94 |
}
|
95 |
-
if ( isset($this->master_object->post_name) && $this->master_object->post_name ) {
|
96 |
return $this->master_object->post_name;
|
97 |
}
|
98 |
return $this->post_name;
|
@@ -103,29 +96,34 @@ class MenuItem extends Core implements CoreInterface {
|
|
103 |
* @return mixed whatever object (Post, Term, etc.) the menu item represents
|
104 |
*/
|
105 |
protected function get_master_object() {
|
106 |
-
if ( isset($this->_menu_item_object_id) ) {
|
107 |
-
return new $this->PostClass($this->_menu_item_object_id);
|
108 |
}
|
109 |
}
|
110 |
|
111 |
/**
|
112 |
* @internal
|
113 |
* @see TimberMenuItem::link
|
114 |
-
* @deprecated 1.0
|
115 |
* @return string an absolute URL http://example.org/my-page
|
116 |
*/
|
117 |
function get_link() {
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
}
|
120 |
|
121 |
/**
|
122 |
* @internal
|
123 |
* @see TimberMenuItem::path()
|
124 |
-
* @deprecated 1.0
|
125 |
* @return string a relative url /my-page
|
126 |
*/
|
127 |
function get_path() {
|
128 |
-
return $this->
|
129 |
}
|
130 |
|
131 |
/**
|
@@ -135,15 +133,15 @@ class MenuItem extends Core implements CoreInterface {
|
|
135 |
*/
|
136 |
function add_child( $item ) {
|
137 |
if ( !$this->has_child_class ) {
|
138 |
-
$this->add_class('menu-item-has-children');
|
139 |
$this->has_child_class = true;
|
140 |
}
|
141 |
-
if ( !isset($this->children) ) {
|
142 |
$this->children = array();
|
143 |
}
|
144 |
$this->children[] = $item;
|
145 |
$item->level = $this->level + 1;
|
146 |
-
if (
|
147 |
$this->update_child_levels();
|
148 |
}
|
149 |
}
|
@@ -154,8 +152,8 @@ class MenuItem extends Core implements CoreInterface {
|
|
154 |
* @return bool
|
155 |
*/
|
156 |
function update_child_levels() {
|
157 |
-
if (
|
158 |
-
foreach
|
159 |
$child->level = $this->level + 1;
|
160 |
$child->update_child_levels();
|
161 |
}
|
@@ -172,10 +170,10 @@ class MenuItem extends Core implements CoreInterface {
|
|
172 |
if ( is_array($data) ) {
|
173 |
$data = (object) $data;
|
174 |
}
|
175 |
-
$this->classes = array_merge($this->classes, $data->classes);
|
176 |
-
$this->classes = array_unique($this->classes);
|
177 |
-
$this->classes = apply_filters('nav_menu_css_class', $this->classes, $this);
|
178 |
-
$this->class = trim(implode(' ', $this->classes));
|
179 |
}
|
180 |
|
181 |
/**
|
@@ -184,7 +182,7 @@ class MenuItem extends Core implements CoreInterface {
|
|
184 |
* @return array|bool
|
185 |
*/
|
186 |
function get_children() {
|
187 |
-
if ( isset($this->children) ) {
|
188 |
return $this->children;
|
189 |
}
|
190 |
return false;
|
@@ -203,7 +201,7 @@ class MenuItem extends Core implements CoreInterface {
|
|
203 |
if ( $this->type != 'custom' ) {
|
204 |
return false;
|
205 |
}
|
206 |
-
return
|
207 |
}
|
208 |
|
209 |
/**
|
@@ -211,10 +209,10 @@ class MenuItem extends Core implements CoreInterface {
|
|
211 |
* @return mixed whatever value is storied in the database
|
212 |
*/
|
213 |
public function meta( $key ) {
|
214 |
-
if ( is_object($this->menu_object) && method_exists($this->menu_object, 'meta') ) {
|
215 |
-
return $this->menu_object->meta($key);
|
216 |
}
|
217 |
-
if ( isset($this->$key) ) {
|
218 |
return $this->$key;
|
219 |
}
|
220 |
}
|
@@ -251,26 +249,7 @@ class MenuItem extends Core implements CoreInterface {
|
|
251 |
* @return string a full URL like http://mysite.com/thing/
|
252 |
*/
|
253 |
public function link() {
|
254 |
-
|
255 |
-
if ( isset($this->_menu_item_type) && $this->_menu_item_type == 'custom' ) {
|
256 |
-
$this->url = $this->_menu_item_url;
|
257 |
-
} else if ( isset($this->menu_object) && method_exists($this->menu_object, 'get_link') ) {
|
258 |
-
$this->url = $this->menu_object->get_link();
|
259 |
-
}
|
260 |
-
}
|
261 |
-
return $this->url;
|
262 |
-
}
|
263 |
-
|
264 |
-
/**
|
265 |
-
* Gets the link a menu item points at
|
266 |
-
* @internal
|
267 |
-
* @deprecated since 0.21.7 use link instead
|
268 |
-
* @see link()
|
269 |
-
* @return string a full URL like http://mysite.com/thing/
|
270 |
-
*/
|
271 |
-
public function permalink() {
|
272 |
-
Helper::warn('{{item.permalink}} is deprecated, use {{item.link}} instead');
|
273 |
-
return $this->link();
|
274 |
}
|
275 |
|
276 |
/**
|
@@ -285,7 +264,28 @@ class MenuItem extends Core implements CoreInterface {
|
|
285 |
* @return string the path of a URL like /foo
|
286 |
*/
|
287 |
public function path() {
|
288 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
}
|
290 |
|
291 |
/**
|
@@ -299,8 +299,9 @@ class MenuItem extends Core implements CoreInterface {
|
|
299 |
* @return string the public label like Foo
|
300 |
*/
|
301 |
public function title() {
|
302 |
-
if ( isset($this->__title) ) {
|
303 |
return $this->__title;
|
304 |
}
|
305 |
}
|
306 |
-
|
|
1 |
<?php
|
2 |
|
3 |
+
class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
public $children;
|
6 |
public $has_child_class = false;
|
26 |
*/
|
27 |
public function __construct( $data ) {
|
28 |
$data = (object) $data;
|
29 |
+
$this->import( $data );
|
30 |
+
$this->import_classes( $data );
|
31 |
+
if ( isset( $this->name ) ) {
|
32 |
$this->_name = $this->name;
|
33 |
}
|
34 |
$this->name = $this->name();
|
35 |
+
$this->add_class( 'menu-item-' . $this->ID );
|
36 |
$this->menu_object = $data;
|
37 |
}
|
38 |
|
49 |
*/
|
50 |
public function add_class( $class_name ) {
|
51 |
$this->classes[] = $class_name;
|
52 |
+
$this->class .= ' ' . $class_name;
|
53 |
}
|
54 |
|
55 |
/**
|
61 |
if ( $title = $this->title() ) {
|
62 |
return $title;
|
63 |
}
|
64 |
+
if ( isset( $this->_name ) ) {
|
65 |
return $this->_name;
|
66 |
}
|
67 |
return '';
|
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;
|
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 ) {
|
111 |
+
if ( isset( $this->_menu_item_type ) && $this->_menu_item_type == 'custom' ) {
|
112 |
+
$this->url = $this->_menu_item_url;
|
113 |
+
} else if ( isset( $this->menu_object ) && method_exists( $this->menu_object, 'get_link' ) ) {
|
114 |
+
$this->url = $this->menu_object->get_link();
|
115 |
+
}
|
116 |
+
}
|
117 |
+
return $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() );
|
127 |
}
|
128 |
|
129 |
/**
|
133 |
*/
|
134 |
function add_child( $item ) {
|
135 |
if ( !$this->has_child_class ) {
|
136 |
+
$this->add_class( 'menu-item-has-children' );
|
137 |
$this->has_child_class = true;
|
138 |
}
|
139 |
+
if ( !isset( $this->children ) ) {
|
140 |
$this->children = array();
|
141 |
}
|
142 |
$this->children[] = $item;
|
143 |
$item->level = $this->level + 1;
|
144 |
+
if ($item->children) {
|
145 |
$this->update_child_levels();
|
146 |
}
|
147 |
}
|
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 |
}
|
170 |
if ( is_array($data) ) {
|
171 |
$data = (object) $data;
|
172 |
}
|
173 |
+
$this->classes = array_merge( $this->classes, $data->classes );
|
174 |
+
$this->classes = array_unique( $this->classes );
|
175 |
+
$this->classes = apply_filters( 'nav_menu_css_class', $this->classes, $this );
|
176 |
+
$this->class = trim( implode( ' ', $this->classes ) );
|
177 |
}
|
178 |
|
179 |
/**
|
182 |
* @return array|bool
|
183 |
*/
|
184 |
function get_children() {
|
185 |
+
if ( isset( $this->children ) ) {
|
186 |
return $this->children;
|
187 |
}
|
188 |
return false;
|
201 |
if ( $this->type != 'custom' ) {
|
202 |
return false;
|
203 |
}
|
204 |
+
return TimberURLHelper::is_external( $this->url );
|
205 |
}
|
206 |
|
207 |
/**
|
209 |
* @return mixed whatever value is storied in the database
|
210 |
*/
|
211 |
public function meta( $key ) {
|
212 |
+
if ( is_object( $this->menu_object ) && method_exists( $this->menu_object, 'meta' ) ) {
|
213 |
+
return $this->menu_object->meta( $key );
|
214 |
}
|
215 |
+
if ( isset( $this->$key ) ) {
|
216 |
return $this->$key;
|
217 |
}
|
218 |
}
|
249 |
* @return string a full URL like http://mysite.com/thing/
|
250 |
*/
|
251 |
public function link() {
|
252 |
+
return $this->get_link();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
}
|
254 |
|
255 |
/**
|
264 |
* @return string the path of a URL like /foo
|
265 |
*/
|
266 |
public function path() {
|
267 |
+
return $this->get_path();
|
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 |
+
*/
|
277 |
+
public function permalink() {
|
278 |
+
return $this->get_link();
|
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 |
+
*/
|
287 |
+
public function get_permalink() {
|
288 |
+
return $this->get_link();
|
289 |
}
|
290 |
|
291 |
/**
|
299 |
* @return string the public label like Foo
|
300 |
*/
|
301 |
public function title() {
|
302 |
+
if ( isset( $this->__title ) ) {
|
303 |
return $this->__title;
|
304 |
}
|
305 |
}
|
306 |
+
|
307 |
+
}
|
lib/{Menu.php → timber-menu.php}
RENAMED
@@ -1,10 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\Post;
|
7 |
-
|
8 |
/**
|
9 |
* 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.)
|
10 |
* @example
|
@@ -32,11 +27,11 @@ use Timber\Post;
|
|
32 |
* <nav>
|
33 |
* <ul class="main-nav">
|
34 |
* {% for item in menu.get_items %}
|
35 |
-
* <li class="nav-main-item {{item.classes | join(' ')}}"><a class="nav-main-link" href="{{item.
|
36 |
* {% if item.get_children %}
|
37 |
* <ul class="nav-drop">
|
38 |
* {% for child in item.get_children %}
|
39 |
-
* <li class="nav-drop-item"><a href="{{child.
|
40 |
* {% endfor %}
|
41 |
* </ul>
|
42 |
* {% endif %}
|
@@ -46,10 +41,10 @@ use Timber\Post;
|
|
46 |
* </nav>
|
47 |
* ```
|
48 |
*/
|
49 |
-
class
|
50 |
|
51 |
-
public $MenuItemClass = '
|
52 |
-
public $PostClass = '
|
53 |
|
54 |
/**
|
55 |
* @api
|
@@ -80,18 +75,18 @@ class Menu extends Core {
|
|
80 |
/**
|
81 |
* @param int|string $slug
|
82 |
*/
|
83 |
-
function __construct(
|
84 |
$locations = get_nav_menu_locations();
|
85 |
-
if (
|
86 |
$menu_id = $slug;
|
87 |
-
} else if (
|
88 |
$menu_id = $this->get_menu_id_from_locations($slug, $locations);
|
89 |
-
} else if (
|
90 |
$menu_id = false;
|
91 |
} else {
|
92 |
$menu_id = $this->get_menu_id_from_terms($slug);
|
93 |
}
|
94 |
-
if (
|
95 |
$this->init($menu_id);
|
96 |
} else {
|
97 |
$this->init_as_page_menu();
|
@@ -102,11 +97,11 @@ class Menu extends Core {
|
|
102 |
* @internal
|
103 |
* @param int $menu_id
|
104 |
*/
|
105 |
-
protected function init(
|
106 |
$menu = wp_get_nav_menu_items($menu_id);
|
107 |
-
if (
|
108 |
_wp_menu_item_classes_by_context($menu);
|
109 |
-
if (
|
110 |
$menu = self::order_children($menu);
|
111 |
}
|
112 |
$this->items = $menu;
|
@@ -123,12 +118,12 @@ class Menu extends Core {
|
|
123 |
*/
|
124 |
protected function init_as_page_menu() {
|
125 |
$menu = get_pages();
|
126 |
-
if (
|
127 |
-
foreach
|
128 |
$mi->__title = $mi->post_title;
|
129 |
}
|
130 |
_wp_menu_item_classes_by_context($menu);
|
131 |
-
if (
|
132 |
$menu = self::order_children($menu);
|
133 |
}
|
134 |
$this->items = $menu;
|
@@ -141,14 +136,14 @@ class Menu extends Core {
|
|
141 |
* @param array $locations
|
142 |
* @return integer
|
143 |
*/
|
144 |
-
protected function get_menu_id_from_locations(
|
145 |
-
if (
|
146 |
$slug = $this->get_menu_id_from_terms($slug);
|
147 |
}
|
148 |
-
if (
|
149 |
$slug = array_search($slug, $locations);
|
150 |
}
|
151 |
-
if (
|
152 |
$menu_id = $locations[$slug];
|
153 |
return $menu_id;
|
154 |
}
|
@@ -159,21 +154,21 @@ class Menu extends Core {
|
|
159 |
* @param int $slug
|
160 |
* @return int
|
161 |
*/
|
162 |
-
protected function get_menu_id_from_terms(
|
163 |
-
if (
|
164 |
//we have a string so lets search for that
|
165 |
$menu_id = get_term_by('slug', $slug, 'nav_menu');
|
166 |
-
if (
|
167 |
return $menu_id;
|
168 |
}
|
169 |
$menu_id = get_term_by('name', $slug, 'nav_menu');
|
170 |
-
if (
|
171 |
return $menu_id;
|
172 |
}
|
173 |
}
|
174 |
$menus = get_terms('nav_menu', array('hide_empty' => true));
|
175 |
-
if (
|
176 |
-
if (
|
177 |
return $menus[0]->term_id;
|
178 |
}
|
179 |
}
|
@@ -185,9 +180,9 @@ class Menu extends Core {
|
|
185 |
* @param int $parent_id
|
186 |
* @return TimberMenuItem|null
|
187 |
*/
|
188 |
-
function find_parent_item_in_menu(
|
189 |
-
foreach (
|
190 |
-
if (
|
191 |
return $item;
|
192 |
}
|
193 |
}
|
@@ -198,29 +193,29 @@ class Menu extends Core {
|
|
198 |
* @param array $items
|
199 |
* @return array
|
200 |
*/
|
201 |
-
protected function order_children(
|
202 |
$index = array();
|
203 |
$menu = array();
|
204 |
-
foreach (
|
205 |
-
if (
|
206 |
//items from wp can come with a $title property which conflicts with methods
|
207 |
$item->__title = $item->title;
|
208 |
unset($item->title);
|
209 |
}
|
210 |
-
if
|
211 |
-
if (
|
212 |
$old_menu_item = $item;
|
213 |
$item = new $this->PostClass($item);
|
214 |
}
|
215 |
$menu_item = new $this->MenuItemClass($item);
|
216 |
-
if (
|
217 |
$menu_item->import_classes($old_menu_item);
|
218 |
}
|
219 |
$index[$item->ID] = $menu_item;
|
220 |
}
|
221 |
}
|
222 |
-
foreach (
|
223 |
-
if (
|
224 |
$index[$item->menu_item_parent]->add_child($item);
|
225 |
} else {
|
226 |
$menu[] = $item;
|
@@ -233,7 +228,7 @@ class Menu extends Core {
|
|
233 |
* @return array
|
234 |
*/
|
235 |
function get_items() {
|
236 |
-
if (
|
237 |
return $this->items;
|
238 |
}
|
239 |
return array();
|
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
|
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 %}
|
41 |
* </nav>
|
42 |
* ```
|
43 |
*/
|
44 |
+
class TimberMenu extends TimberCore {
|
45 |
|
46 |
+
public $MenuItemClass = 'TimberMenuItem';
|
47 |
+
public $PostClass = 'TimberPost';
|
48 |
|
49 |
/**
|
50 |
* @api
|
75 |
/**
|
76 |
* @param int|string $slug
|
77 |
*/
|
78 |
+
function __construct($slug = 0) {
|
79 |
$locations = get_nav_menu_locations();
|
80 |
+
if ($slug != 0 && is_numeric($slug)) {
|
81 |
$menu_id = $slug;
|
82 |
+
} else if (is_array($locations) && count($locations)) {
|
83 |
$menu_id = $this->get_menu_id_from_locations($slug, $locations);
|
84 |
+
} else if ($slug === false) {
|
85 |
$menu_id = false;
|
86 |
} else {
|
87 |
$menu_id = $this->get_menu_id_from_terms($slug);
|
88 |
}
|
89 |
+
if ($menu_id) {
|
90 |
$this->init($menu_id);
|
91 |
} else {
|
92 |
$this->init_as_page_menu();
|
97 |
* @internal
|
98 |
* @param int $menu_id
|
99 |
*/
|
100 |
+
protected function init($menu_id) {
|
101 |
$menu = wp_get_nav_menu_items($menu_id);
|
102 |
+
if ($menu) {
|
103 |
_wp_menu_item_classes_by_context($menu);
|
104 |
+
if (is_array($menu)){
|
105 |
$menu = self::order_children($menu);
|
106 |
}
|
107 |
$this->items = $menu;
|
118 |
*/
|
119 |
protected function init_as_page_menu() {
|
120 |
$menu = get_pages();
|
121 |
+
if ($menu) {
|
122 |
+
foreach($menu as $mi) {
|
123 |
$mi->__title = $mi->post_title;
|
124 |
}
|
125 |
_wp_menu_item_classes_by_context($menu);
|
126 |
+
if (is_array($menu)){
|
127 |
$menu = self::order_children($menu);
|
128 |
}
|
129 |
$this->items = $menu;
|
136 |
* @param array $locations
|
137 |
* @return integer
|
138 |
*/
|
139 |
+
protected function get_menu_id_from_locations($slug, $locations) {
|
140 |
+
if ($slug === 0) {
|
141 |
$slug = $this->get_menu_id_from_terms($slug);
|
142 |
}
|
143 |
+
if (is_numeric($slug)) {
|
144 |
$slug = array_search($slug, $locations);
|
145 |
}
|
146 |
+
if (isset($locations[$slug])) {
|
147 |
$menu_id = $locations[$slug];
|
148 |
return $menu_id;
|
149 |
}
|
154 |
* @param int $slug
|
155 |
* @return int
|
156 |
*/
|
157 |
+
protected function get_menu_id_from_terms($slug = 0) {
|
158 |
+
if (!is_numeric($slug) && is_string($slug)) {
|
159 |
//we have a string so lets search for that
|
160 |
$menu_id = get_term_by('slug', $slug, 'nav_menu');
|
161 |
+
if ($menu_id) {
|
162 |
return $menu_id;
|
163 |
}
|
164 |
$menu_id = get_term_by('name', $slug, 'nav_menu');
|
165 |
+
if ($menu_id) {
|
166 |
return $menu_id;
|
167 |
}
|
168 |
}
|
169 |
$menus = get_terms('nav_menu', array('hide_empty' => true));
|
170 |
+
if (is_array($menus) && count($menus)) {
|
171 |
+
if (isset($menus[0]->term_id)) {
|
172 |
return $menus[0]->term_id;
|
173 |
}
|
174 |
}
|
180 |
* @param int $parent_id
|
181 |
* @return TimberMenuItem|null
|
182 |
*/
|
183 |
+
function find_parent_item_in_menu($menu_items, $parent_id) {
|
184 |
+
foreach ($menu_items as &$item) {
|
185 |
+
if ($item->ID == $parent_id) {
|
186 |
return $item;
|
187 |
}
|
188 |
}
|
193 |
* @param array $items
|
194 |
* @return array
|
195 |
*/
|
196 |
+
protected function order_children($items) {
|
197 |
$index = array();
|
198 |
$menu = array();
|
199 |
+
foreach ($items as $item) {
|
200 |
+
if (isset($item->title)) {
|
201 |
//items from wp can come with a $title property which conflicts with methods
|
202 |
$item->__title = $item->title;
|
203 |
unset($item->title);
|
204 |
}
|
205 |
+
if(isset($item->ID)){
|
206 |
+
if (is_object($item) && get_class($item) == 'WP_Post'){
|
207 |
$old_menu_item = $item;
|
208 |
$item = new $this->PostClass($item);
|
209 |
}
|
210 |
$menu_item = new $this->MenuItemClass($item);
|
211 |
+
if (isset($old_menu_item)){
|
212 |
$menu_item->import_classes($old_menu_item);
|
213 |
}
|
214 |
$index[$item->ID] = $menu_item;
|
215 |
}
|
216 |
}
|
217 |
+
foreach ($index as $item) {
|
218 |
+
if (isset($item->menu_item_parent) && $item->menu_item_parent && isset($index[$item->menu_item_parent])) {
|
219 |
$index[$item->menu_item_parent]->add_child($item);
|
220 |
} else {
|
221 |
$menu[] = $item;
|
228 |
* @return array
|
229 |
*/
|
230 |
function get_items() {
|
231 |
+
if (is_array($this->items)) {
|
232 |
return $this->items;
|
233 |
}
|
234 |
return array();
|
lib/timber-page.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @ignore
|
5 |
+
* @deprecated 0.21.9
|
6 |
+
*/
|
7 |
+
class TimberPage extends TimberPost {
|
8 |
+
|
9 |
+
}
|
lib/timber-post-getter.php
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class TimberPostGetter {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @param mixed $query
|
7 |
+
* @param string $PostClass
|
8 |
+
* @return array|bool|null
|
9 |
+
*/
|
10 |
+
static function get_post($query = false, $PostClass = 'TimberPost') {
|
11 |
+
$posts = self::get_posts( $query, $PostClass );
|
12 |
+
if ( $post = reset($posts ) ) {
|
13 |
+
return $post;
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
|
18 |
+
$posts = self::query_posts( $query, $PostClass );
|
19 |
+
return apply_filters('timber_post_getter_get_posts', $posts->get_posts( $return_collection ));
|
20 |
+
}
|
21 |
+
|
22 |
+
static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
23 |
+
$posts = self::query_posts( $query, $PostClass );
|
24 |
+
if ( method_exists($posts, 'current') && $post = $posts->current() ) {
|
25 |
+
return $post;
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param mixed $query
|
31 |
+
* @param string $PostClass
|
32 |
+
* @return array|bool|null
|
33 |
+
*/
|
34 |
+
static function query_posts($query = false, $PostClass = 'TimberPost' ) {
|
35 |
+
if (self::is_post_class_or_class_map($query)) {
|
36 |
+
$PostClass = $query;
|
37 |
+
$query = false;
|
38 |
+
}
|
39 |
+
|
40 |
+
if (is_object($query) && !is_a($query, 'WP_Query') ){
|
41 |
+
// The only object other than a query is a type of post object
|
42 |
+
$query = array( $query );
|
43 |
+
}
|
44 |
+
|
45 |
+
if ( is_array( $query ) && count( $query ) && isset( $query[0] ) && is_object( $query[0] ) ) {
|
46 |
+
// We have an array of post objects that already have data
|
47 |
+
return new TimberPostsCollection( $query, $PostClass );
|
48 |
+
} else {
|
49 |
+
// We have a query (of sorts) to work with
|
50 |
+
$tqi = new TimberQueryIterator( $query, $PostClass );
|
51 |
+
return $tqi;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
static function get_pids($query){
|
56 |
+
$posts = self::get_posts($query);
|
57 |
+
$pids = array();
|
58 |
+
foreach($posts as $post){
|
59 |
+
if (isset($post->ID)){
|
60 |
+
$pids[] = $post->ID;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
return $pids;
|
64 |
+
}
|
65 |
+
|
66 |
+
static function loop_to_id() {
|
67 |
+
if (!self::wp_query_has_posts()) { return false; }
|
68 |
+
|
69 |
+
global $wp_query;
|
70 |
+
$post_num = property_exists($wp_query, 'current_post')
|
71 |
+
? $wp_query->current_post + 1
|
72 |
+
: 0
|
73 |
+
;
|
74 |
+
|
75 |
+
if (!isset($wp_query->posts[$post_num])) { return false; }
|
76 |
+
|
77 |
+
return $wp_query->posts[$post_num]->ID;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @return bool
|
82 |
+
*/
|
83 |
+
static function wp_query_has_posts() {
|
84 |
+
global $wp_query;
|
85 |
+
return ($wp_query && property_exists($wp_query, 'posts') && $wp_query->posts);
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @param string|array $arg
|
90 |
+
* @return bool
|
91 |
+
*/
|
92 |
+
static function is_post_class_or_class_map($arg){
|
93 |
+
if (is_string($arg) && class_exists($arg)) {
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
if (is_array($arg)) {
|
97 |
+
foreach ($arg as $item) {
|
98 |
+
if (is_string($item) && (class_exists($item) && is_subclass_of($item, 'TimberPost'))) {
|
99 |
+
return true;
|
100 |
+
}
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
104 |
+
}
|
lib/{Post.php → timber-post.php}
RENAMED
@@ -1,17 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\CoreInterface;
|
7 |
-
|
8 |
-
use Timber\Term;
|
9 |
-
use Timber\User;
|
10 |
-
use Timber\Image;
|
11 |
-
use Timber\Helper;
|
12 |
-
use Timber\URLHelper;
|
13 |
-
use Timber\PostGetter;
|
14 |
-
|
15 |
/**
|
16 |
* 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.
|
17 |
* @example
|
@@ -19,7 +7,7 @@ use Timber\PostGetter;
|
|
19 |
* <?php
|
20 |
* // single.php, see connected twig example
|
21 |
* $context = Timber::get_context();
|
22 |
-
* $context['post'] = new
|
23 |
* Timber::render('single.twig', $context);
|
24 |
* ?>
|
25 |
* ```
|
@@ -44,22 +32,22 @@ use Timber\PostGetter;
|
|
44 |
*
|
45 |
* @package Timber
|
46 |
*/
|
47 |
-
class
|
48 |
-
|
49 |
/**
|
50 |
* @var string $ImageClass the name of the class to handle images by default
|
51 |
*/
|
52 |
-
public $ImageClass = '
|
53 |
|
54 |
/**
|
55 |
* @var string $PostClass the name of the class to handle posts by default
|
56 |
*/
|
57 |
-
public $PostClass = '
|
58 |
|
59 |
/**
|
60 |
* @var string $TermClass the name of the class to handle terms by default
|
61 |
*/
|
62 |
-
public $TermClass = '
|
63 |
|
64 |
/**
|
65 |
* @var string $object_type what does this class represent in WordPress terms?
|
@@ -77,18 +65,25 @@ class Post extends Core implements CoreInterface {
|
|
77 |
*/
|
78 |
protected $_content;
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
/**
|
81 |
* @var string $_permalink the returned permalink from WP's get_permalink function
|
82 |
*/
|
83 |
protected $_permalink;
|
84 |
|
85 |
/**
|
86 |
-
* @var array $_next stores the results of the next
|
87 |
*/
|
88 |
protected $_next = array();
|
89 |
|
90 |
/**
|
91 |
-
* @var array $_prev stores the results of the previous
|
92 |
*/
|
93 |
protected $_prev = array();
|
94 |
|
@@ -161,13 +156,13 @@ class Post extends Core implements CoreInterface {
|
|
161 |
* If you send the constructor nothing it will try to figure out the current post id based on being inside The_Loop
|
162 |
* @example
|
163 |
* ```php
|
164 |
-
* $post = new
|
165 |
-
* $other_post = new
|
166 |
* ```
|
167 |
* @param mixed $pid
|
168 |
*/
|
169 |
-
public function __construct(
|
170 |
-
$pid = $this->determine_id($pid);
|
171 |
$this->init($pid);
|
172 |
}
|
173 |
|
@@ -177,7 +172,7 @@ class Post extends Core implements CoreInterface {
|
|
177 |
* @param mixed a value to test against
|
178 |
* @return int the numberic id we should be using for this post object
|
179 |
*/
|
180 |
-
protected function determine_id(
|
181 |
global $wp_query;
|
182 |
if ( $pid === null &&
|
183 |
isset($wp_query->queried_object_id)
|
@@ -186,18 +181,18 @@ class Post extends Core implements CoreInterface {
|
|
186 |
&& is_object($wp_query->queried_object)
|
187 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
188 |
) {
|
189 |
-
if
|
190 |
-
$pid = $this->get_post_preview_id($wp_query);
|
191 |
} else if ( !$pid ) {
|
192 |
$pid = $wp_query->queried_object_id;
|
193 |
}
|
194 |
-
} else if ( $pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id )
|
195 |
//hack for static page as home page
|
196 |
$pid = $wp_query->queried_object_id;
|
197 |
} else if ( $pid === null ) {
|
198 |
$gtid = false;
|
199 |
$maybe_post = get_post();
|
200 |
-
if ( isset($maybe_post->ID) )
|
201 |
$gtid = true;
|
202 |
}
|
203 |
if ( $gtid ) {
|
@@ -210,7 +205,7 @@ class Post extends Core implements CoreInterface {
|
|
210 |
}
|
211 |
}
|
212 |
}
|
213 |
-
if ( $pid === null && ($pid_from_loop =
|
214 |
$pid = $pid_from_loop;
|
215 |
}
|
216 |
return $pid;
|
@@ -226,28 +221,28 @@ class Post extends Core implements CoreInterface {
|
|
226 |
|
227 |
protected function get_post_preview_id( $query ) {
|
228 |
$can = array(
|
229 |
-
'edit_'
|
230 |
);
|
231 |
|
232 |
if ( $query->queried_object->author_id !== get_current_user_id() ) {
|
233 |
-
$can[] = 'edit_others_'
|
234 |
}
|
235 |
|
236 |
$can_preview = array();
|
237 |
|
238 |
-
foreach
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
}
|
243 |
|
244 |
-
if ( count($can_preview) !== count($can) ) {
|
245 |
-
|
246 |
}
|
247 |
|
248 |
-
$revisions = wp_get_post_revisions($query->queried_object_id);
|
249 |
|
250 |
-
if
|
251 |
$last = end($revisions);
|
252 |
return $last->ID;
|
253 |
}
|
@@ -256,11 +251,11 @@ class Post extends Core implements CoreInterface {
|
|
256 |
}
|
257 |
|
258 |
/**
|
259 |
-
* Initializes a
|
260 |
* @internal
|
261 |
* @param int|bool $pid
|
262 |
*/
|
263 |
-
protected function init(
|
264 |
if ( $pid === false ) {
|
265 |
$pid = get_the_ID();
|
266 |
}
|
@@ -277,13 +272,13 @@ class Post extends Core implements CoreInterface {
|
|
277 |
/**
|
278 |
* Get the URL that will edit the current post/object
|
279 |
* @internal
|
280 |
-
* @
|
281 |
-
* @codeCoverageIgnore
|
282 |
-
* @see Timber\Post::edit_link
|
283 |
* @return bool|string
|
284 |
*/
|
285 |
function get_edit_url() {
|
286 |
-
|
|
|
|
|
287 |
}
|
288 |
|
289 |
/**
|
@@ -347,11 +342,11 @@ class Post extends Core implements CoreInterface {
|
|
347 |
* @param string $post_name
|
348 |
* @return int
|
349 |
*/
|
350 |
-
static function get_post_id_by_name(
|
351 |
global $wpdb;
|
352 |
$query = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s LIMIT 1", $post_name);
|
353 |
$result = $wpdb->get_row($query);
|
354 |
-
if (
|
355 |
return null;
|
356 |
}
|
357 |
return $result->ID;
|
@@ -373,12 +368,12 @@ class Post extends Core implements CoreInterface {
|
|
373 |
* @param string $end The text to end the preview with (defaults to ...)
|
374 |
* @return string of the post preview
|
375 |
*/
|
376 |
-
function get_preview(
|
377 |
$text = '';
|
378 |
$trimmed = false;
|
379 |
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
380 |
if ( $force ) {
|
381 |
-
$text =
|
382 |
$trimmed = true;
|
383 |
} else {
|
384 |
$text = $this->post_excerpt;
|
@@ -388,13 +383,13 @@ class Post extends Core implements CoreInterface {
|
|
388 |
$pieces = explode($readmore_matches[0], $this->post_content);
|
389 |
$text = $pieces[0];
|
390 |
if ( $force ) {
|
391 |
-
$text =
|
392 |
$trimmed = true;
|
393 |
}
|
394 |
-
$text = do_shortcode($text);
|
395 |
}
|
396 |
if ( !strlen($text) ) {
|
397 |
-
$text =
|
398 |
$trimmed = true;
|
399 |
}
|
400 |
if ( !strlen(trim($text)) ) {
|
@@ -416,16 +411,16 @@ class Post extends Core implements CoreInterface {
|
|
416 |
$text = substr($text, 0, $last_p_tag);
|
417 |
}
|
418 |
if ( $last != '.' && $trimmed ) {
|
419 |
-
$text .= $end.' ';
|
420 |
}
|
421 |
}
|
422 |
$read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
|
423 |
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
424 |
-
$text .= ' <a href="'
|
425 |
} elseif ( $readmore ) {
|
426 |
-
$text .= ' <a href="'
|
427 |
}
|
428 |
-
if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
|
429 |
$text .= '</p>';
|
430 |
}
|
431 |
}
|
@@ -469,326 +464,252 @@ class Post extends Core implements CoreInterface {
|
|
469 |
}
|
470 |
|
471 |
/**
|
472 |
-
* @
|
473 |
-
* @
|
|
|
474 |
*/
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
|
|
480 |
}
|
481 |
-
return '';
|
482 |
}
|
483 |
|
484 |
/**
|
485 |
-
* Used internally by init, etc. to build TimberPost object
|
486 |
* @internal
|
487 |
-
* @
|
488 |
-
* @return
|
489 |
*/
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
return null;
|
494 |
}
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
$post->status = $post->post_status;
|
499 |
-
$post->id = $post->ID;
|
500 |
-
$post->slug = $post->post_name;
|
501 |
-
$customs = $this->get_post_custom($post->ID);
|
502 |
-
$post->custom = $customs;
|
503 |
-
$post = (object) array_merge((array) $customs, (array) $post);
|
504 |
-
return $post;
|
505 |
}
|
506 |
|
507 |
/**
|
508 |
-
*
|
509 |
-
*
|
510 |
-
*
|
511 |
-
* @
|
|
|
512 |
*/
|
513 |
-
|
514 |
-
return
|
515 |
}
|
516 |
|
517 |
-
|
518 |
/**
|
519 |
-
* Get the
|
520 |
-
*
|
521 |
-
* @
|
522 |
-
* @
|
523 |
-
* @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)?
|
524 |
-
* @return array
|
525 |
*/
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
$
|
532 |
-
|
533 |
-
|
534 |
-
$taxonomies = $tax;
|
535 |
-
}
|
536 |
-
if ( is_string($tax) ) {
|
537 |
-
if ( in_array($tax, array('all', 'any', '')) ) {
|
538 |
-
$taxonomies = get_object_taxonomies($this->post_type);
|
539 |
} else {
|
540 |
-
$
|
541 |
-
}
|
542 |
-
}
|
543 |
-
|
544 |
-
$term_class_objects = array();
|
545 |
-
|
546 |
-
foreach ( $taxonomies as $taxonomy ) {
|
547 |
-
if ( in_array($taxonomy, array('tag', 'tags')) ) {
|
548 |
-
$taxonomy = 'post_tag';
|
549 |
-
}
|
550 |
-
if ( $taxonomy == 'categories' ) {
|
551 |
-
$taxonomy = 'category';
|
552 |
-
}
|
553 |
-
|
554 |
-
$terms = wp_get_post_terms($this->ID, $taxonomy);
|
555 |
-
|
556 |
-
if ( is_wp_error($terms) ) {
|
557 |
-
/* @var $terms WP_Error */
|
558 |
-
Helper::error_log("Error retrieving terms for taxonomy '$taxonomy' on a post in timber-post.php");
|
559 |
-
Helper::error_log('tax = '.print_r($tax, true));
|
560 |
-
Helper::error_log('WP_Error: '.$terms->get_error_message());
|
561 |
-
|
562 |
-
return $term_class_objects;
|
563 |
}
|
564 |
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
if ( $merge && is_array($terms) ) {
|
571 |
-
$term_class_objects = array_merge($term_class_objects, $terms);
|
572 |
-
} else if ( count($terms) ) {
|
573 |
-
$term_class_objects[$taxonomy] = $terms;
|
574 |
}
|
|
|
575 |
}
|
576 |
-
return $
|
577 |
}
|
578 |
|
579 |
/**
|
580 |
-
*
|
581 |
-
* @
|
582 |
-
* @return bool
|
583 |
*/
|
584 |
-
function
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
|
|
|
|
592 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
593 |
}
|
594 |
-
return $ret;
|
595 |
}
|
596 |
-
return
|
597 |
}
|
598 |
|
599 |
/**
|
|
|
600 |
* @return string
|
601 |
*/
|
602 |
-
function
|
603 |
-
|
|
|
|
|
|
|
|
|
|
|
604 |
}
|
|
|
605 |
/**
|
606 |
-
*
|
607 |
-
*
|
608 |
-
*
|
609 |
-
*
|
610 |
-
*
|
611 |
-
* ```
|
612 |
-
*
|
613 |
-
* ```html
|
614 |
-
* This post is from <span>Recipes</span>
|
615 |
-
* ```
|
616 |
-
* @return mixed
|
617 |
*/
|
618 |
-
|
619 |
-
return
|
620 |
}
|
621 |
|
622 |
/**
|
623 |
-
*
|
|
|
|
|
|
|
624 |
*/
|
625 |
-
|
626 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
627 |
}
|
628 |
|
629 |
/**
|
630 |
-
*
|
631 |
-
* @
|
|
|
632 |
*/
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
$value = get_post_meta($this->ID, $field_name);
|
637 |
-
if ( is_array($value) && count($value) == 1 ) {
|
638 |
-
$value = $value[0];
|
639 |
-
}
|
640 |
-
if ( is_array($value) && count($value) == 0 ) {
|
641 |
-
$value = null;
|
642 |
-
}
|
643 |
}
|
644 |
-
|
645 |
-
$value = $this->convert($value, __CLASS__);
|
646 |
-
return $value;
|
647 |
}
|
648 |
|
649 |
/**
|
650 |
-
*
|
|
|
|
|
|
|
651 |
*/
|
652 |
-
function
|
653 |
-
|
|
|
|
|
654 |
}
|
655 |
|
656 |
/**
|
657 |
-
* Get the CSS classes for a post. For usage you should use `{{post.class}}` instead of `{{post.post_class}}`
|
658 |
* @internal
|
659 |
-
* @
|
660 |
-
* @see Timber\Post::$class
|
661 |
-
* @example
|
662 |
-
* ```twig
|
663 |
-
* <article class="{{ post.class }}">
|
664 |
-
* {# Some stuff here #}
|
665 |
-
* </article>
|
666 |
-
* ```
|
667 |
-
*
|
668 |
-
* ```html
|
669 |
-
* <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">
|
670 |
-
* {# Some stuff here #}
|
671 |
-
* </article>
|
672 |
-
* ```
|
673 |
-
* @return string a space-seperated list of classes
|
674 |
*/
|
675 |
-
|
676 |
-
|
677 |
-
$
|
678 |
-
$post = $this;
|
679 |
-
$class_array = get_post_class($class, $this->ID);
|
680 |
-
$post = $old_global_post;
|
681 |
-
if ( is_array($class_array) ) {
|
682 |
-
return implode(' ', $class_array);
|
683 |
-
}
|
684 |
-
return $class_array;
|
685 |
}
|
686 |
|
687 |
-
// Docs
|
688 |
-
|
689 |
/**
|
690 |
-
*
|
691 |
-
* @
|
|
|
|
|
692 |
*/
|
693 |
-
|
694 |
-
$
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
$
|
699 |
-
$
|
700 |
-
$
|
701 |
-
$
|
702 |
-
$
|
703 |
-
$
|
704 |
-
|
705 |
-
$ret['pagination'] = $this->pagination();
|
706 |
-
$ret['parent'] = $this->parent();
|
707 |
-
$ret['path'] = $this->path();
|
708 |
-
$ret['prev'] = $this->prev();
|
709 |
-
$ret['terms'] = $this->terms();
|
710 |
-
$ret['tags'] = $this->tags();
|
711 |
-
$ret['thumbnail'] = $this->thumbnail();
|
712 |
-
$ret['title'] = $this->title();
|
713 |
-
return $ret;
|
714 |
-
}
|
715 |
-
|
716 |
-
/**
|
717 |
-
* Return the author of a post
|
718 |
-
* @api
|
719 |
-
* @example
|
720 |
-
* ```twig
|
721 |
-
* <h1>{{post.title}}</h1>
|
722 |
-
* <p class="byline">
|
723 |
-
* <a href="{{post.author.link}}">{{post.author.name}}</a>
|
724 |
-
* </p>
|
725 |
-
* ```
|
726 |
-
* @return TimberUser|bool A TimberUser object if found, false if not
|
727 |
-
*/
|
728 |
-
public function author() {
|
729 |
-
return $this->get_author();
|
730 |
}
|
731 |
|
732 |
/**
|
733 |
-
*
|
734 |
-
* @
|
735 |
-
*
|
736 |
-
*
|
737 |
-
* ```
|
738 |
-
* ```html
|
739 |
-
* Last updated by Harper Lee
|
740 |
-
* ```
|
741 |
-
* @return TimberUser|bool A TimberUser object if found, false if not
|
742 |
*/
|
743 |
-
|
744 |
-
$
|
745 |
-
|
|
|
746 |
}
|
747 |
|
748 |
/**
|
749 |
-
*
|
750 |
-
* @
|
751 |
-
* @return
|
752 |
*/
|
753 |
-
|
754 |
-
|
|
|
|
|
755 |
}
|
756 |
|
757 |
/**
|
758 |
-
*
|
759 |
-
* @
|
760 |
-
*
|
761 |
-
* @return TimberTerm|null
|
762 |
*/
|
763 |
-
|
764 |
-
|
|
|
|
|
765 |
}
|
766 |
|
767 |
/**
|
768 |
-
*
|
769 |
-
*
|
770 |
-
* @
|
771 |
-
* @
|
772 |
-
* ```twig
|
773 |
-
* {% if post.children %}
|
774 |
-
* Here are the child pages:
|
775 |
-
* {% for child in page.children %}
|
776 |
-
* <a href="{{ child.link }}">{{ child.title }}</a>
|
777 |
-
* {% endfor %}
|
778 |
-
* {% endif %}
|
779 |
-
* ```
|
780 |
-
* @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
|
781 |
-
* @param string|bool $childPostClass _optional_ a custom post class (ex: 'MyTimber\Post') to return the objects as. By default (false) it will use Timber\Post::$post_class value.
|
782 |
* @return array
|
783 |
*/
|
784 |
-
|
785 |
if ( $childPostClass === false ) {
|
786 |
$childPostClass = $this->PostClass;
|
787 |
}
|
788 |
if ( $post_type == 'parent' ) {
|
789 |
$post_type = $this->post_type;
|
790 |
}
|
791 |
-
$children = get_children('post_parent='
|
792 |
foreach ( $children as &$child ) {
|
793 |
$child = new $childPostClass($child->ID);
|
794 |
}
|
@@ -796,28 +717,21 @@ class Post extends Core implements CoreInterface {
|
|
796 |
return $children;
|
797 |
}
|
798 |
|
|
|
799 |
/**
|
800 |
-
*
|
801 |
-
* @
|
802 |
-
* @
|
803 |
-
* @param
|
804 |
-
* @param string $
|
805 |
-
* @param string $
|
806 |
-
* @param string $
|
807 |
-
* @
|
808 |
-
*
|
809 |
-
* {# single.twig #}
|
810 |
-
* <h4>Comments:</h4>
|
811 |
-
* {% for comment in post.comments %}
|
812 |
-
* <div class="comment-{{comment.ID}} comment-order-{{loop.index}}">
|
813 |
-
* <p>{{comment.author.name}} said:</p>
|
814 |
-
* <p>{{comment.content}}</p>
|
815 |
-
* </div>
|
816 |
-
* {% endfor %}
|
817 |
-
* ```
|
818 |
-
* @return bool|array
|
819 |
*/
|
820 |
-
|
|
|
|
|
821 |
global $overridden_cpage, $user_ID;
|
822 |
$overridden_cpage = false;
|
823 |
|
@@ -825,50 +739,50 @@ class Post extends Core implements CoreInterface {
|
|
825 |
$comment_author_email = $commenter['comment_author_email'];
|
826 |
|
827 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
828 |
-
if ( $
|
829 |
-
$args['number'] = $
|
830 |
}
|
831 |
if ( strtolower($order) == 'wp' || strtolower($order) == 'wordpress' ) {
|
832 |
$args['order'] = get_option('comment_order');
|
833 |
}
|
834 |
|
835 |
if ( $user_ID ) {
|
836 |
-
$args['include_unapproved'] = array($user_ID);
|
837 |
-
} elseif ( !empty($comment_author_email) ) {
|
838 |
-
$args['include_unapproved'] = array($comment_author_email);
|
839 |
}
|
840 |
|
841 |
$comments = get_comments($args);
|
842 |
$timber_comments = array();
|
843 |
|
844 |
if ( '' == get_query_var('cpage') && get_option('page_comments') ) {
|
845 |
-
set_query_var('cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1);
|
846 |
$overridden_cpage = true;
|
847 |
}
|
848 |
|
849 |
-
foreach
|
850 |
$timber_comment = new $CommentClass($comment);
|
851 |
$timber_comments[$timber_comment->id] = $timber_comment;
|
852 |
}
|
853 |
|
854 |
// Build a flattened (depth=1) comment tree
|
855 |
$comments_tree = array();
|
856 |
-
foreach
|
857 |
-
if (
|
858 |
continue;
|
859 |
}
|
860 |
|
861 |
$tree_element = $comment;
|
862 |
do {
|
863 |
$tree_element = $timber_comments[$tree_element->comment_parent];
|
864 |
-
} while
|
865 |
|
866 |
$comments_tree[$tree_element->id][] = $comment->id;
|
867 |
}
|
868 |
|
869 |
// Add child comments to the relative "super parents"
|
870 |
-
foreach
|
871 |
-
foreach
|
872 |
$timber_comments[$comment_parent]->children[] = $timber_comments[$comment_child];
|
873 |
unset($timber_comments[$comment_child]);
|
874 |
}
|
@@ -880,664 +794,649 @@ class Post extends Core implements CoreInterface {
|
|
880 |
}
|
881 |
|
882 |
/**
|
883 |
-
*
|
884 |
-
* @
|
885 |
-
* @
|
886 |
-
*
|
887 |
-
* <div class="article">
|
888 |
-
* <h2>{{post.title}}</h2>
|
889 |
-
* <div class="content">{{ post.content }}</div>
|
890 |
-
* </div>
|
891 |
-
* ```
|
892 |
-
* @param int $page
|
893 |
-
* @return string
|
894 |
*/
|
895 |
-
|
896 |
-
|
897 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
898 |
}
|
899 |
-
|
900 |
-
|
901 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
902 |
}
|
903 |
-
if ( $
|
904 |
-
$
|
905 |
-
|
906 |
-
|
907 |
-
|
|
|
|
|
|
|
908 |
}
|
909 |
}
|
910 |
-
|
911 |
-
|
912 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
913 |
}
|
914 |
-
return $
|
915 |
}
|
916 |
|
917 |
/**
|
918 |
-
* @
|
|
|
|
|
919 |
*/
|
920 |
-
|
921 |
-
|
922 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
923 |
}
|
924 |
|
925 |
/**
|
926 |
-
*
|
927 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
928 |
* @example
|
929 |
* ```twig
|
930 |
-
*
|
931 |
-
*
|
932 |
-
*
|
|
|
|
|
933 |
* ```
|
934 |
-
*
|
935 |
-
* ```html
|
936 |
-
* Published on January 12, 2015
|
937 |
-
* OR
|
938 |
-
* Published on Jan 12th
|
939 |
-
* ```
|
940 |
-
* @param string $date_format
|
941 |
-
* @return string
|
942 |
*/
|
943 |
-
|
944 |
-
|
945 |
-
$the_date = (string) mysql2date($df, $this->post_date);
|
946 |
-
return apply_filters('get_the_date', $the_date, $df);
|
947 |
}
|
948 |
|
949 |
/**
|
950 |
-
*
|
951 |
-
* @
|
952 |
* @example
|
953 |
* ```twig
|
954 |
-
*
|
955 |
-
* OR
|
956 |
-
* Published at {{ post.time | time('G:i') }} // 13:25
|
957 |
* ```
|
958 |
-
*
|
959 |
* ```html
|
960 |
-
*
|
961 |
-
* OR
|
962 |
-
* Published at 13:25
|
963 |
* ```
|
964 |
-
* @param string $time_format
|
965 |
* @return string
|
966 |
*/
|
967 |
-
|
968 |
-
|
969 |
-
$the_time = (string) mysql2date($tf, $this->post_date);
|
970 |
-
return apply_filters('get_the_time', $the_time, $tf);
|
971 |
}
|
972 |
|
973 |
/**
|
974 |
-
*
|
975 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
976 |
*/
|
977 |
-
|
978 |
-
if ( $this->
|
979 |
-
return
|
|
|
|
|
|
|
|
|
980 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
981 |
}
|
982 |
|
983 |
/**
|
984 |
-
* @
|
985 |
-
* @return mixed
|
986 |
*/
|
987 |
-
|
988 |
-
|
|
|
989 |
}
|
990 |
-
|
991 |
/**
|
992 |
-
*
|
993 |
-
*
|
994 |
* @example
|
995 |
* ```twig
|
996 |
-
* <
|
|
|
|
|
|
|
|
|
997 |
* ```
|
998 |
-
* @return string ex: http://example.org/2015/07/my-awesome-post
|
999 |
-
*/
|
1000 |
-
public function link() {
|
1001 |
-
if ( isset($this->_permalink) ) {
|
1002 |
-
return $this->_permalink;
|
1003 |
-
}
|
1004 |
-
$this->_permalink = get_permalink($this->ID);
|
1005 |
-
return $this->_permalink;
|
1006 |
-
}
|
1007 |
-
|
1008 |
-
/**
|
1009 |
-
* @param string $field_name
|
1010 |
* @return mixed
|
1011 |
*/
|
1012 |
-
public function
|
1013 |
-
|
1014 |
-
//on the off-chance the field is actually named meta
|
1015 |
-
$field_name = 'meta';
|
1016 |
-
}
|
1017 |
-
return $this->get_field($field_name);
|
1018 |
}
|
1019 |
|
1020 |
/**
|
1021 |
-
* @return
|
1022 |
*/
|
1023 |
-
public function
|
1024 |
-
return $this->
|
1025 |
}
|
1026 |
|
1027 |
/**
|
1028 |
-
* @param string $
|
1029 |
-
* @return
|
1030 |
*/
|
1031 |
-
public function
|
1032 |
-
$
|
1033 |
-
$
|
1034 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1035 |
}
|
1036 |
|
1037 |
/**
|
1038 |
-
* @param string $
|
1039 |
-
* @return string
|
1040 |
*/
|
1041 |
-
|
1042 |
-
|
1043 |
}
|
1044 |
|
1045 |
/**
|
1046 |
-
* @
|
1047 |
-
* @param bool $in_same_cat
|
1048 |
* @return mixed
|
1049 |
*/
|
1050 |
-
|
1051 |
-
|
1052 |
-
global $post;
|
1053 |
-
$this->_next = array();
|
1054 |
-
$old_global = $post;
|
1055 |
-
$post = $this;
|
1056 |
-
if ( $in_same_term ) {
|
1057 |
-
$adjacent = get_adjacent_post(true, '', false, $in_same_term);
|
1058 |
-
} else {
|
1059 |
-
$adjacent = get_adjacent_post(false, '', false);
|
1060 |
-
}
|
1061 |
-
|
1062 |
-
if ( $adjacent ) {
|
1063 |
-
$this->_next[$in_same_term] = new $this->PostClass($adjacent);
|
1064 |
-
} else {
|
1065 |
-
$this->_next[$in_same_term] = false;
|
1066 |
-
}
|
1067 |
-
$post = $old_global;
|
1068 |
-
}
|
1069 |
-
return $this->_next[$in_same_term];
|
1070 |
}
|
1071 |
|
1072 |
/**
|
1073 |
-
* Get
|
1074 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1075 |
*/
|
1076 |
-
public function
|
1077 |
-
global $post
|
|
|
1078 |
$post = $this;
|
1079 |
-
$
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
$data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
|
1084 |
-
if ( $i == $page ) {
|
1085 |
-
$data['current'] = true;
|
1086 |
-
}
|
1087 |
-
$ret['pages'][] = $data;
|
1088 |
-
}
|
1089 |
-
$i = $page - 1;
|
1090 |
-
if ( $i ) {
|
1091 |
-
$link = self::get_wp_link_page($i);
|
1092 |
-
$ret['prev'] = array('link' => $link);
|
1093 |
-
}
|
1094 |
-
$i = $page + 1;
|
1095 |
-
if ( $i <= $numpages ) {
|
1096 |
-
$link = self::get_wp_link_page($i);
|
1097 |
-
$ret['next'] = array('link' => $link);
|
1098 |
-
}
|
1099 |
}
|
1100 |
-
return $
|
1101 |
}
|
1102 |
|
1103 |
-
|
1104 |
|
1105 |
/**
|
1106 |
-
*
|
1107 |
-
* @
|
1108 |
*/
|
1109 |
-
public function
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1124 |
}
|
1125 |
|
1126 |
/**
|
1127 |
-
*
|
1128 |
* @api
|
1129 |
* @example
|
1130 |
* ```twig
|
1131 |
-
*
|
|
|
|
|
|
|
1132 |
* ```
|
1133 |
-
* @return bool
|
1134 |
-
* @param string $field_name
|
1135 |
*/
|
1136 |
-
public function
|
1137 |
-
|
1138 |
-
return false;
|
1139 |
-
}
|
1140 |
-
return new $this->PostClass($this->post_parent);
|
1141 |
}
|
1142 |
|
1143 |
/**
|
1144 |
-
*
|
1145 |
-
* this will return just /2015/07/my-cool-post
|
1146 |
-
* @api
|
1147 |
* @example
|
1148 |
* ```twig
|
1149 |
-
*
|
1150 |
* ```
|
1151 |
-
*
|
|
|
|
|
|
|
1152 |
*/
|
1153 |
-
public function
|
1154 |
-
return
|
1155 |
}
|
1156 |
|
1157 |
/**
|
1158 |
-
* Get the
|
1159 |
* @api
|
1160 |
-
* @
|
1161 |
-
* ```twig
|
1162 |
-
* <h4>Prior Entry:</h4>
|
1163 |
-
* <h3>{{post.prev.title}}</h3>
|
1164 |
-
* <p>{{post.prev.get_preview(25)}}</p>
|
1165 |
-
* ```
|
1166 |
-
* @param bool $in_same_term
|
1167 |
-
* @return mixed
|
1168 |
*/
|
1169 |
-
public function
|
1170 |
-
|
1171 |
-
return $this->_prev[$in_same_term];
|
1172 |
-
}
|
1173 |
-
global $post;
|
1174 |
-
$old_global = $post;
|
1175 |
-
$post = $this;
|
1176 |
-
$within_taxonomy = ($in_same_term) ? $in_same_term : 'category';
|
1177 |
-
$adjacent = get_adjacent_post(($in_same_term), '', true, $within_taxonomy);
|
1178 |
-
$prev_in_taxonomy = false;
|
1179 |
-
if ( $adjacent ) {
|
1180 |
-
$prev_in_taxonomy = new $this->PostClass($adjacent);
|
1181 |
-
}
|
1182 |
-
$this->_prev[$in_same_term] = $prev_in_taxonomy;
|
1183 |
-
$post = $old_global;
|
1184 |
-
return $this->_prev[$in_same_term];
|
1185 |
}
|
1186 |
|
1187 |
/**
|
1188 |
-
*
|
1189 |
* @api
|
1190 |
-
*
|
|
|
1191 |
*/
|
1192 |
-
public function
|
1193 |
-
return $this->
|
1194 |
}
|
1195 |
|
1196 |
/**
|
1197 |
-
*
|
|
|
1198 |
* @api
|
1199 |
* @example
|
1200 |
* ```twig
|
1201 |
-
*
|
|
|
|
|
|
|
|
|
|
|
1202 |
* ```
|
1203 |
-
* @
|
|
|
|
|
1204 |
*/
|
1205 |
-
public function
|
1206 |
-
|
1207 |
-
$tid = get_post_thumbnail_id($this->ID);
|
1208 |
-
if ( $tid ) {
|
1209 |
-
//return new Image($tid);
|
1210 |
-
return new $this->ImageClass($tid);
|
1211 |
-
}
|
1212 |
-
}
|
1213 |
}
|
1214 |
|
1215 |
/**
|
1216 |
-
*
|
1217 |
* @api
|
|
|
|
|
|
|
|
|
|
|
1218 |
* @example
|
1219 |
* ```twig
|
1220 |
-
*
|
1221 |
-
*
|
1222 |
-
*
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
|
1228 |
-
|
1229 |
-
*
|
1230 |
-
* ===================================
|
1231 |
-
* DEPRECATED FUNCTIONS LIVE DOWN HERE
|
1232 |
-
* ===================================
|
1233 |
-
*
|
1234 |
-
*/
|
1235 |
-
|
1236 |
-
/**
|
1237 |
-
* Get the categories for a post
|
1238 |
-
* @internal
|
1239 |
-
* @deprecated since 1.0
|
1240 |
-
* @codeCoverageIgnore
|
1241 |
-
* @see Timber\Post::categories
|
1242 |
-
* @return array of TimberTerms
|
1243 |
*/
|
1244 |
-
function
|
1245 |
-
return $this->
|
1246 |
}
|
1247 |
|
1248 |
/**
|
1249 |
-
*
|
1250 |
-
* @
|
1251 |
-
* @
|
1252 |
-
*
|
1253 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
1254 |
*/
|
1255 |
-
function
|
1256 |
-
|
1257 |
-
if ( count($cats) && isset($cats[0]) ) {
|
1258 |
-
return $cats[0];
|
1259 |
-
}
|
1260 |
}
|
1261 |
|
1262 |
/**
|
1263 |
-
* @
|
1264 |
-
* @return TimberImage
|
1265 |
*/
|
1266 |
-
function
|
1267 |
-
return
|
1268 |
}
|
1269 |
|
1270 |
/**
|
1271 |
-
*
|
1272 |
-
* @
|
1273 |
-
* @deprecated since 1.0
|
1274 |
-
* @codeCoverageIgnore
|
1275 |
* @example
|
1276 |
* ```twig
|
1277 |
-
*
|
1278 |
-
*
|
1279 |
-
*
|
1280 |
-
* {% endfor %}
|
1281 |
-
* </ul>
|
1282 |
* ```
|
1283 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1284 |
*/
|
1285 |
-
function
|
1286 |
-
return $this->
|
1287 |
}
|
1288 |
|
1289 |
/**
|
1290 |
-
*
|
1291 |
-
* @
|
1292 |
-
* @deprecated since 1.0
|
1293 |
-
* @codeCoverageIgnore
|
1294 |
* @example
|
1295 |
* ```twig
|
1296 |
-
*
|
|
|
|
|
1297 |
* ```
|
|
|
1298 |
* ```html
|
1299 |
-
*
|
|
|
|
|
1300 |
* ```
|
|
|
1301 |
* @return string
|
1302 |
*/
|
1303 |
-
function
|
1304 |
-
|
|
|
|
|
1305 |
}
|
1306 |
|
1307 |
-
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
* ```
|
1313 |
-
* ```html
|
1314 |
-
* <div class="article-text"><p>Blah blah blah</p><p>More blah blah blah.</p></div>
|
1315 |
-
* ```
|
1316 |
-
* @param int $len
|
1317 |
-
* @param int $page
|
1318 |
-
* @return string
|
1319 |
-
*/
|
1320 |
-
function get_content( $len = -1, $page = 0 ) {
|
1321 |
-
if ( $len === 0 ) {
|
1322 |
-
$len = -1;
|
1323 |
-
}
|
1324 |
-
return $this->content($page, $len);
|
1325 |
}
|
1326 |
|
1327 |
/**
|
1328 |
-
* @
|
1329 |
-
* @deprecated since 1.0
|
1330 |
* @return mixed
|
1331 |
*/
|
1332 |
-
function
|
1333 |
-
return $this->
|
1334 |
}
|
1335 |
|
1336 |
/**
|
1337 |
-
*
|
1338 |
-
*
|
1339 |
-
* @
|
1340 |
-
*
|
1341 |
-
*
|
1342 |
-
*
|
1343 |
-
* @
|
1344 |
-
* @return array
|
1345 |
*/
|
1346 |
-
public function
|
1347 |
-
return $this->
|
1348 |
}
|
1349 |
|
1350 |
/**
|
1351 |
-
* @
|
1352 |
-
* @
|
1353 |
-
* @return string
|
1354 |
*/
|
1355 |
-
public function
|
1356 |
-
|
1357 |
-
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
* @internal
|
1362 |
-
* @see Timber\Post::date
|
1363 |
-
* @deprecated since 1.0
|
1364 |
-
* @codeCoverageIgnore
|
1365 |
-
* @param string $date_format
|
1366 |
-
* @return string
|
1367 |
-
*/
|
1368 |
-
function get_date( $date_format = '' ) {
|
1369 |
-
return $this->date($date_format);
|
1370 |
}
|
1371 |
|
1372 |
/**
|
1373 |
-
* @internal
|
1374 |
-
* @see Timber\Post::modified_date
|
1375 |
-
* @deprecated since 1.0
|
1376 |
-
* @codeCoverageIgnore
|
1377 |
-
* @param string $date_format
|
1378 |
* @return string
|
1379 |
*/
|
1380 |
-
function
|
1381 |
-
return $this->
|
1382 |
}
|
1383 |
|
1384 |
/**
|
1385 |
-
* @
|
1386 |
-
* @param string $time_format
|
1387 |
* @return string
|
1388 |
*/
|
1389 |
-
function
|
1390 |
-
|
1391 |
-
$the_time = get_post_modified_time($tf, false, $this->ID, true);
|
1392 |
-
return apply_filters('get_the_modified_time', $the_time, $time_format);
|
1393 |
}
|
1394 |
|
1395 |
/**
|
1396 |
-
* @
|
1397 |
-
* @
|
1398 |
-
* @deprecated since 1.0
|
1399 |
-
* @codeCoverageIgnore
|
1400 |
-
* @param string $post_type
|
1401 |
-
* @param bool|string $childPostClass
|
1402 |
-
* @return array
|
1403 |
*/
|
1404 |
-
function
|
1405 |
-
return $this->
|
1406 |
-
}
|
1407 |
-
|
1408 |
-
/**
|
1409 |
-
* Get the permalink for a post, but as a relative path
|
1410 |
-
* For example, where {{post.link}} would return "http://example.org/2015/07/04/my-cool-post"
|
1411 |
-
* this will return the relative version: "/2015/07/04/my-cool-post"
|
1412 |
-
* @internal
|
1413 |
-
* @deprecated since 1.0
|
1414 |
-
* @codeCoverageIgnore
|
1415 |
-
* @return string
|
1416 |
-
*/
|
1417 |
-
function get_path() {
|
1418 |
-
return $this->path();
|
1419 |
}
|
1420 |
|
1421 |
/**
|
1422 |
-
*
|
1423 |
-
* @
|
1424 |
-
* @
|
1425 |
-
* @codeCoverageIgnore
|
1426 |
-
* @param bool $taxonomy
|
1427 |
-
* @return TimberPost|boolean
|
1428 |
*/
|
1429 |
-
function
|
1430 |
-
return $this->
|
1431 |
}
|
1432 |
|
1433 |
/**
|
1434 |
-
*
|
1435 |
-
* @internal
|
1436 |
-
* @deprecated since 1.0
|
1437 |
-
* @codeCoverageIgnore
|
1438 |
-
* @return bool|TimberPost
|
1439 |
*/
|
1440 |
-
function
|
1441 |
-
return $this->
|
1442 |
}
|
1443 |
|
1444 |
/**
|
1445 |
-
* Gets a
|
1446 |
-
* @
|
1447 |
-
* @
|
1448 |
-
*
|
1449 |
-
*
|
1450 |
-
*
|
|
|
1451 |
*/
|
1452 |
-
function
|
1453 |
-
|
1454 |
-
return new User($this->post_author);
|
1455 |
-
}
|
1456 |
}
|
1457 |
|
1458 |
/**
|
1459 |
-
*
|
1460 |
-
*
|
1461 |
-
* @
|
1462 |
-
* @
|
|
|
|
|
|
|
|
|
1463 |
*/
|
1464 |
-
function
|
1465 |
-
return $this->
|
1466 |
-
}
|
1467 |
-
|
1468 |
-
/**
|
1469 |
-
* @internal
|
1470 |
-
* @see TimberPost::thumbnail
|
1471 |
-
* @deprecated since 1.0
|
1472 |
-
* @codeCoverageIgnore
|
1473 |
-
* @return null|TimberImage
|
1474 |
-
*/
|
1475 |
-
function get_thumbnail() {
|
1476 |
-
return $this->thumbnail();
|
1477 |
}
|
1478 |
|
1479 |
/**
|
1480 |
-
* @
|
1481 |
-
* @see TimberPost::link
|
1482 |
-
* @deprecated since 1.0
|
1483 |
-
* @codeCoverageIgnore
|
1484 |
* @return string
|
1485 |
*/
|
1486 |
-
function
|
1487 |
-
return $this->
|
1488 |
}
|
1489 |
|
1490 |
/**
|
1491 |
-
*
|
1492 |
-
*
|
1493 |
-
*
|
1494 |
-
*
|
1495 |
-
*
|
1496 |
-
*
|
1497 |
-
*
|
|
|
|
|
|
|
1498 |
*/
|
1499 |
-
function
|
1500 |
-
return $this->
|
1501 |
}
|
1502 |
|
1503 |
/**
|
1504 |
-
* Get the
|
1505 |
-
*
|
1506 |
-
* @
|
1507 |
-
* @
|
1508 |
-
* @param bool $taxonomy
|
1509 |
-
* @return
|
1510 |
*/
|
1511 |
-
function
|
1512 |
-
return $this->
|
1513 |
}
|
1514 |
|
1515 |
/**
|
1516 |
-
*
|
1517 |
-
* @
|
1518 |
-
* @see Timber\Post::pagination();
|
1519 |
-
* @deprecated since 1.0
|
1520 |
-
* @codeCoverageIgnore
|
1521 |
* @return array
|
1522 |
*/
|
1523 |
-
public function
|
1524 |
-
return $this->
|
1525 |
}
|
1526 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1527 |
|
1528 |
/**
|
1529 |
-
*
|
1530 |
-
* @
|
1531 |
-
* @
|
1532 |
-
*
|
1533 |
-
*
|
1534 |
-
*
|
1535 |
-
* @
|
1536 |
-
* @param string $CommentClass
|
1537 |
-
* @return array|mixed
|
1538 |
*/
|
1539 |
-
function
|
1540 |
-
return $this->
|
1541 |
}
|
1542 |
|
1543 |
}
|
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
|
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 |
* ```
|
32 |
*
|
33 |
* @package Timber
|
34 |
*/
|
35 |
+
class TimberPost extends TimberCore implements TimberCoreInterface {
|
36 |
+
|
37 |
/**
|
38 |
* @var string $ImageClass the name of the class to handle images by default
|
39 |
*/
|
40 |
+
public $ImageClass = 'TimberImage';
|
41 |
|
42 |
/**
|
43 |
* @var string $PostClass the name of the class to handle posts by default
|
44 |
*/
|
45 |
+
public $PostClass = 'TimberPost';
|
46 |
|
47 |
/**
|
48 |
* @var string $TermClass the name of the class to handle terms by default
|
49 |
*/
|
50 |
+
public $TermClass = 'TimberTerm';
|
51 |
|
52 |
/**
|
53 |
* @var string $object_type what does this class represent in WordPress terms?
|
65 |
*/
|
66 |
protected $_content;
|
67 |
|
68 |
+
/**
|
69 |
+
* @internal
|
70 |
+
* @var array $_get_terms stores the results of a get_terms method call
|
71 |
+
* @deprecated
|
72 |
+
*/
|
73 |
+
protected $_get_terms;
|
74 |
+
|
75 |
/**
|
76 |
* @var string $_permalink the returned permalink from WP's get_permalink function
|
77 |
*/
|
78 |
protected $_permalink;
|
79 |
|
80 |
/**
|
81 |
+
* @var array $_next stores the results of the next TimberPost in a set inside an array (in order to manage by-taxonomy)
|
82 |
*/
|
83 |
protected $_next = array();
|
84 |
|
85 |
/**
|
86 |
+
* @var array $_prev stores the results of the previous TimberPost in a set inside an array (in order to manage by-taxonomy)
|
87 |
*/
|
88 |
protected $_prev = array();
|
89 |
|
156 |
* If you send the constructor nothing it will try to figure out the current post id based on being inside The_Loop
|
157 |
* @example
|
158 |
* ```php
|
159 |
+
* $post = new TimberPost();
|
160 |
+
* $other_post = new TimberPost($random_post_id);
|
161 |
* ```
|
162 |
* @param mixed $pid
|
163 |
*/
|
164 |
+
public function __construct($pid = null) {
|
165 |
+
$pid = $this->determine_id( $pid );
|
166 |
$this->init($pid);
|
167 |
}
|
168 |
|
172 |
* @param mixed a value to test against
|
173 |
* @return int the numberic id we should be using for this post object
|
174 |
*/
|
175 |
+
protected function determine_id($pid) {
|
176 |
global $wp_query;
|
177 |
if ( $pid === null &&
|
178 |
isset($wp_query->queried_object_id)
|
181 |
&& is_object($wp_query->queried_object)
|
182 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
183 |
) {
|
184 |
+
if( isset( $_GET['preview'] ) && isset( $_GET['preview_nonce'] ) && wp_verify_nonce( $_GET['preview_nonce'], 'post_preview_' . $wp_query->queried_object_id ) ) {
|
185 |
+
$pid = $this->get_post_preview_id( $wp_query );
|
186 |
} else if ( !$pid ) {
|
187 |
$pid = $wp_query->queried_object_id;
|
188 |
}
|
189 |
+
} else if ( $pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
|
190 |
//hack for static page as home page
|
191 |
$pid = $wp_query->queried_object_id;
|
192 |
} else if ( $pid === null ) {
|
193 |
$gtid = false;
|
194 |
$maybe_post = get_post();
|
195 |
+
if ( isset($maybe_post->ID) ){
|
196 |
$gtid = true;
|
197 |
}
|
198 |
if ( $gtid ) {
|
205 |
}
|
206 |
}
|
207 |
}
|
208 |
+
if ( $pid === null && ($pid_from_loop = TimberPostGetter::loop_to_id()) ) {
|
209 |
$pid = $pid_from_loop;
|
210 |
}
|
211 |
return $pid;
|
221 |
|
222 |
protected function get_post_preview_id( $query ) {
|
223 |
$can = array(
|
224 |
+
'edit_' . $query->queried_object->post_type . 's',
|
225 |
);
|
226 |
|
227 |
if ( $query->queried_object->author_id !== get_current_user_id() ) {
|
228 |
+
$can[] = 'edit_others_' . $query->queried_object->post_type . 's';
|
229 |
}
|
230 |
|
231 |
$can_preview = array();
|
232 |
|
233 |
+
foreach( $can as $type ) {
|
234 |
+
if( current_user_can( $type ) ) {
|
235 |
+
$can_preview[] = true;
|
236 |
+
}
|
237 |
}
|
238 |
|
239 |
+
if ( count( $can_preview ) !== count( $can ) ) {
|
240 |
+
return;
|
241 |
}
|
242 |
|
243 |
+
$revisions = wp_get_post_revisions( $query->queried_object_id );
|
244 |
|
245 |
+
if( !empty( $revisions ) ) {
|
246 |
$last = end($revisions);
|
247 |
return $last->ID;
|
248 |
}
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
+
* Initializes a TimberPost
|
255 |
* @internal
|
256 |
* @param int|bool $pid
|
257 |
*/
|
258 |
+
protected function init($pid = false) {
|
259 |
if ( $pid === false ) {
|
260 |
$pid = get_the_ID();
|
261 |
}
|
272 |
/**
|
273 |
* Get the URL that will edit the current post/object
|
274 |
* @internal
|
275 |
+
* @see TimberPost::edit_link
|
|
|
|
|
276 |
* @return bool|string
|
277 |
*/
|
278 |
function get_edit_url() {
|
279 |
+
if ( $this->can_edit() ) {
|
280 |
+
return get_edit_post_link($this->ID);
|
281 |
+
}
|
282 |
}
|
283 |
|
284 |
/**
|
342 |
* @param string $post_name
|
343 |
* @return int
|
344 |
*/
|
345 |
+
static function get_post_id_by_name($post_name) {
|
346 |
global $wpdb;
|
347 |
$query = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s LIMIT 1", $post_name);
|
348 |
$result = $wpdb->get_row($query);
|
349 |
+
if (!$result) {
|
350 |
return null;
|
351 |
}
|
352 |
return $result->ID;
|
368 |
* @param string $end The text to end the preview with (defaults to ...)
|
369 |
* @return string of the post preview
|
370 |
*/
|
371 |
+
function get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '…') {
|
372 |
$text = '';
|
373 |
$trimmed = false;
|
374 |
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
375 |
if ( $force ) {
|
376 |
+
$text = TimberHelper::trim_words($this->post_excerpt, $len, false);
|
377 |
$trimmed = true;
|
378 |
} else {
|
379 |
$text = $this->post_excerpt;
|
383 |
$pieces = explode($readmore_matches[0], $this->post_content);
|
384 |
$text = $pieces[0];
|
385 |
if ( $force ) {
|
386 |
+
$text = TimberHelper::trim_words($text, $len, false);
|
387 |
$trimmed = true;
|
388 |
}
|
389 |
+
$text = do_shortcode( $text );
|
390 |
}
|
391 |
if ( !strlen($text) ) {
|
392 |
+
$text = TimberHelper::trim_words($this->get_content(), $len, false);
|
393 |
$trimmed = true;
|
394 |
}
|
395 |
if ( !strlen(trim($text)) ) {
|
411 |
$text = substr($text, 0, $last_p_tag);
|
412 |
}
|
413 |
if ( $last != '.' && $trimmed ) {
|
414 |
+
$text .= $end . ' ';
|
415 |
}
|
416 |
}
|
417 |
$read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
|
418 |
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
419 |
+
$text .= ' <a href="' . $this->get_permalink() . '" class="'.$read_more_class .'">' . trim($readmore_matches[1]) . '</a>';
|
420 |
} elseif ( $readmore ) {
|
421 |
+
$text .= ' <a href="' . $this->get_permalink() . '" class="'.$read_more_class .'">' . trim($readmore) . '</a>';
|
422 |
}
|
423 |
+
if ( !$strip && $last_p_tag && ( strpos($text, '<p>') || strpos($text, '<p ') ) ) {
|
424 |
$text .= '</p>';
|
425 |
}
|
426 |
}
|
464 |
}
|
465 |
|
466 |
/**
|
467 |
+
* @internal
|
468 |
+
* @see TimberPost::thumbnail
|
469 |
+
* @return null|TimberImage
|
470 |
*/
|
471 |
+
function get_thumbnail() {
|
472 |
+
if ( function_exists('get_post_thumbnail_id') ) {
|
473 |
+
$tid = get_post_thumbnail_id($this->ID);
|
474 |
+
if ( $tid ) {
|
475 |
+
return new $this->ImageClass($tid);
|
476 |
+
}
|
477 |
}
|
|
|
478 |
}
|
479 |
|
480 |
/**
|
|
|
481 |
* @internal
|
482 |
+
* @see TimberPost::link
|
483 |
+
* @return string
|
484 |
*/
|
485 |
+
function get_permalink() {
|
486 |
+
if ( isset($this->_permalink) ) {
|
487 |
+
return $this->_permalink;
|
|
|
488 |
}
|
489 |
+
$this->_permalink = get_permalink($this->ID);
|
490 |
+
return $this->_permalink;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
491 |
}
|
492 |
|
493 |
/**
|
494 |
+
* get the permalink for a post object
|
495 |
+
* In your templates you should use link:
|
496 |
+
* <a href="{{post.link}}">Read my post</a>
|
497 |
+
* @internal
|
498 |
+
* @return string
|
499 |
*/
|
500 |
+
function get_link() {
|
501 |
+
return $this->get_permalink();
|
502 |
}
|
503 |
|
|
|
504 |
/**
|
505 |
+
* Get the next post in WordPress's ordering
|
506 |
+
* @internal
|
507 |
+
* @param bool $taxonomy
|
508 |
+
* @return TimberPost|boolean
|
|
|
|
|
509 |
*/
|
510 |
+
function get_next( $taxonomy = false ) {
|
511 |
+
if ( !isset($this->_next) || !isset($this->_next[$taxonomy]) ) {
|
512 |
+
global $post;
|
513 |
+
$this->_next = array();
|
514 |
+
$old_global = $post;
|
515 |
+
$post = $this;
|
516 |
+
if ( $taxonomy ) {
|
517 |
+
$adjacent = get_adjacent_post(true, '', false, $taxonomy);
|
|
|
|
|
|
|
|
|
|
|
518 |
} else {
|
519 |
+
$adjacent = get_adjacent_post(false, '', false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
520 |
}
|
521 |
|
522 |
+
if ( $adjacent ) {
|
523 |
+
$this->_next[$taxonomy] = new $this->PostClass($adjacent);
|
524 |
+
} else {
|
525 |
+
$this->_next[$taxonomy] = false;
|
|
|
|
|
|
|
|
|
|
|
526 |
}
|
527 |
+
$post = $old_global;
|
528 |
}
|
529 |
+
return $this->_next[$taxonomy];
|
530 |
}
|
531 |
|
532 |
/**
|
533 |
+
* Get a data array of pagination so you can navigate to the previous/next for a paginated post
|
534 |
+
* @return array
|
|
|
535 |
*/
|
536 |
+
public function get_pagination() {
|
537 |
+
global $post, $page, $numpages, $multipage;
|
538 |
+
$post = $this;
|
539 |
+
$ret = array();
|
540 |
+
if ( $multipage ) {
|
541 |
+
for ( $i = 1; $i <= $numpages; $i++ ) {
|
542 |
+
$link = self::get_wp_link_page($i);
|
543 |
+
$data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
|
544 |
+
if ( $i == $page ) {
|
545 |
+
$data['current'] = true;
|
546 |
}
|
547 |
+
$ret['pages'][] = $data;
|
548 |
+
}
|
549 |
+
$i = $page - 1;
|
550 |
+
if ( $i ) {
|
551 |
+
$link = self::get_wp_link_page($i);
|
552 |
+
$ret['prev'] = array('link' => $link);
|
553 |
+
}
|
554 |
+
$i = $page + 1;
|
555 |
+
if ( $i <= $numpages ) {
|
556 |
+
$link = self::get_wp_link_page($i);
|
557 |
+
$ret['next'] = array('link' => $link);
|
558 |
}
|
|
|
559 |
}
|
560 |
+
return $ret;
|
561 |
}
|
562 |
|
563 |
/**
|
564 |
+
* @param int $i
|
565 |
* @return string
|
566 |
*/
|
567 |
+
protected static function get_wp_link_page($i) {
|
568 |
+
$link = _wp_link_page($i);
|
569 |
+
$link = new SimpleXMLElement($link . '</a>');
|
570 |
+
if ( isset($link['href']) ) {
|
571 |
+
return $link['href'];
|
572 |
+
}
|
573 |
+
return '';
|
574 |
}
|
575 |
+
|
576 |
/**
|
577 |
+
* Get the permalink for a post, but as a relative path
|
578 |
+
* For example, where {{post.link}} would return "http://example.org/2015/07/04/my-cool-post"
|
579 |
+
* this will return the relative version: "/2015/07/04/my-cool-post"
|
580 |
+
* @internal
|
581 |
+
* @return string
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
*/
|
583 |
+
function get_path() {
|
584 |
+
return TimberURLHelper::get_rel_url($this->get_link());
|
585 |
}
|
586 |
|
587 |
/**
|
588 |
+
* Get the next post in WordPress's ordering
|
589 |
+
* @internal
|
590 |
+
* @param bool $taxonomy
|
591 |
+
* @return TimberPost|boolean
|
592 |
*/
|
593 |
+
function get_prev( $taxonomy = false ) {
|
594 |
+
if ( isset($this->_prev) && isset($this->_prev[$taxonomy]) ) {
|
595 |
+
return $this->_prev[$taxonomy];
|
596 |
+
}
|
597 |
+
global $post;
|
598 |
+
$old_global = $post;
|
599 |
+
$post = $this;
|
600 |
+
$within_taxonomy = ($taxonomy) ? $taxonomy : 'category';
|
601 |
+
$adjacent = get_adjacent_post(($taxonomy), '', true, $within_taxonomy);
|
602 |
+
$prev_in_taxonomy = false;
|
603 |
+
if ( $adjacent ) {
|
604 |
+
$prev_in_taxonomy = new $this->PostClass($adjacent);
|
605 |
+
}
|
606 |
+
$this->_prev[$taxonomy] = $prev_in_taxonomy;
|
607 |
+
$post = $old_global;
|
608 |
+
return $this->_prev[$taxonomy];
|
609 |
}
|
610 |
|
611 |
/**
|
612 |
+
* Get the parent post of the post
|
613 |
+
* @internal
|
614 |
+
* @return bool|TimberPost
|
615 |
*/
|
616 |
+
function get_parent() {
|
617 |
+
if ( !$this->post_parent ) {
|
618 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
619 |
}
|
620 |
+
return new $this->PostClass($this->post_parent);
|
|
|
|
|
621 |
}
|
622 |
|
623 |
/**
|
624 |
+
* Gets a User object from the author of the post
|
625 |
+
* @internal
|
626 |
+
* @see TimberPost::author
|
627 |
+
* @return bool|TimberUser
|
628 |
*/
|
629 |
+
function get_author() {
|
630 |
+
if ( isset($this->post_author) ) {
|
631 |
+
return new TimberUser($this->post_author);
|
632 |
+
}
|
633 |
}
|
634 |
|
635 |
/**
|
|
|
636 |
* @internal
|
637 |
+
* @return bool|TimberUser
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
638 |
*/
|
639 |
+
function get_modified_author() {
|
640 |
+
$user_id = get_post_meta($this->ID, '_edit_last', true);
|
641 |
+
return ($user_id ? new TimberUser($user_id) : $this->get_author());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
642 |
}
|
643 |
|
|
|
|
|
644 |
/**
|
645 |
+
* Used internally by init, etc. to build TimberPost object
|
646 |
+
* @internal
|
647 |
+
* @param int $pid
|
648 |
+
* @return null|object|WP_Post
|
649 |
*/
|
650 |
+
protected function get_info($pid) {
|
651 |
+
$post = $this->prepare_post_info($pid);
|
652 |
+
if ( !isset($post->post_status) ) {
|
653 |
+
return null;
|
654 |
+
}
|
655 |
+
$post->status = $post->post_status;
|
656 |
+
$post->id = $post->ID;
|
657 |
+
$post->slug = $post->post_name;
|
658 |
+
$customs = $this->get_post_custom($post->ID);
|
659 |
+
$post->custom = $customs;
|
660 |
+
$post = (object) array_merge((array)$customs, (array)$post);
|
661 |
+
return $post;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
662 |
}
|
663 |
|
664 |
/**
|
665 |
+
* @internal
|
666 |
+
* @see TimberPost::date
|
667 |
+
* @param string $date_format
|
668 |
+
* @return string
|
|
|
|
|
|
|
|
|
|
|
669 |
*/
|
670 |
+
function get_date( $date_format = '' ) {
|
671 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
672 |
+
$the_date = (string)mysql2date($df, $this->post_date);
|
673 |
+
return apply_filters('get_the_date', $the_date, $df);
|
674 |
}
|
675 |
|
676 |
/**
|
677 |
+
* @internal
|
678 |
+
* @param string $date_format
|
679 |
+
* @return string
|
680 |
*/
|
681 |
+
function get_modified_date( $date_format = '' ) {
|
682 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
683 |
+
$the_time = $this->get_modified_time($df);
|
684 |
+
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
685 |
}
|
686 |
|
687 |
/**
|
688 |
+
* @internal
|
689 |
+
* @param string $time_format
|
690 |
+
* @return string
|
|
|
691 |
*/
|
692 |
+
function get_modified_time( $time_format = '' ) {
|
693 |
+
$tf = $time_format ? $time_format : get_option('time_format');
|
694 |
+
$the_time = get_post_modified_time($tf, false, $this->ID, true);
|
695 |
+
return apply_filters('get_the_modified_time', $the_time, $time_format);
|
696 |
}
|
697 |
|
698 |
/**
|
699 |
+
* @internal
|
700 |
+
* @see TimberPost::children
|
701 |
+
* @param string $post_type
|
702 |
+
* @param bool|string $childPostClass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
703 |
* @return array
|
704 |
*/
|
705 |
+
function get_children( $post_type = 'any', $childPostClass = false ) {
|
706 |
if ( $childPostClass === false ) {
|
707 |
$childPostClass = $this->PostClass;
|
708 |
}
|
709 |
if ( $post_type == 'parent' ) {
|
710 |
$post_type = $this->post_type;
|
711 |
}
|
712 |
+
$children = get_children('post_parent=' . $this->ID . '&post_type=' . $post_type . '&numberposts=-1&orderby=menu_order title&order=ASC&post_status=publish');
|
713 |
foreach ( $children as &$child ) {
|
714 |
$child = new $childPostClass($child->ID);
|
715 |
}
|
717 |
return $children;
|
718 |
}
|
719 |
|
720 |
+
|
721 |
/**
|
722 |
+
* Get the comments for a post
|
723 |
+
* @internal
|
724 |
+
* @see TimberPost::comments
|
725 |
+
* @param int $ct
|
726 |
+
* @param string $order
|
727 |
+
* @param string $type
|
728 |
+
* @param string $status
|
729 |
+
* @param string $CommentClass
|
730 |
+
* @return array|mixed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
731 |
*/
|
732 |
+
|
733 |
+
function get_comments($ct = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment') {
|
734 |
+
|
735 |
global $overridden_cpage, $user_ID;
|
736 |
$overridden_cpage = false;
|
737 |
|
739 |
$comment_author_email = $commenter['comment_author_email'];
|
740 |
|
741 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
742 |
+
if ( $ct > 0 ) {
|
743 |
+
$args['number'] = $ct;
|
744 |
}
|
745 |
if ( strtolower($order) == 'wp' || strtolower($order) == 'wordpress' ) {
|
746 |
$args['order'] = get_option('comment_order');
|
747 |
}
|
748 |
|
749 |
if ( $user_ID ) {
|
750 |
+
$args['include_unapproved'] = array( $user_ID );
|
751 |
+
} elseif ( ! empty( $comment_author_email ) ) {
|
752 |
+
$args['include_unapproved'] = array( $comment_author_email );
|
753 |
}
|
754 |
|
755 |
$comments = get_comments($args);
|
756 |
$timber_comments = array();
|
757 |
|
758 |
if ( '' == get_query_var('cpage') && get_option('page_comments') ) {
|
759 |
+
set_query_var( 'cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1 );
|
760 |
$overridden_cpage = true;
|
761 |
}
|
762 |
|
763 |
+
foreach($comments as $key => &$comment) {
|
764 |
$timber_comment = new $CommentClass($comment);
|
765 |
$timber_comments[$timber_comment->id] = $timber_comment;
|
766 |
}
|
767 |
|
768 |
// Build a flattened (depth=1) comment tree
|
769 |
$comments_tree = array();
|
770 |
+
foreach( $timber_comments as $key => $comment ) {
|
771 |
+
if ( ! $comment->is_child() ) {
|
772 |
continue;
|
773 |
}
|
774 |
|
775 |
$tree_element = $comment;
|
776 |
do {
|
777 |
$tree_element = $timber_comments[$tree_element->comment_parent];
|
778 |
+
} while( $tree_element->is_child() );
|
779 |
|
780 |
$comments_tree[$tree_element->id][] = $comment->id;
|
781 |
}
|
782 |
|
783 |
// Add child comments to the relative "super parents"
|
784 |
+
foreach($comments_tree as $comment_parent => $comment_children) {
|
785 |
+
foreach($comment_children as $comment_child) {
|
786 |
$timber_comments[$comment_parent]->children[] = $timber_comments[$comment_child];
|
787 |
unset($timber_comments[$comment_child]);
|
788 |
}
|
794 |
}
|
795 |
|
796 |
/**
|
797 |
+
* Get the categories for a post
|
798 |
+
* @internal
|
799 |
+
* @see TimberPost::categories
|
800 |
+
* @return array of TimberTerms
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
801 |
*/
|
802 |
+
function get_categories() {
|
803 |
+
return $this->get_terms('category');
|
804 |
+
}
|
805 |
+
|
806 |
+
/**
|
807 |
+
* @internal
|
808 |
+
* @see TimberPost::category
|
809 |
+
* @return mixed
|
810 |
+
*/
|
811 |
+
function get_category( ) {
|
812 |
+
$cats = $this->get_categories();
|
813 |
+
if ( count($cats) && isset($cats[0]) ) {
|
814 |
+
return $cats[0];
|
815 |
}
|
816 |
+
}
|
817 |
+
|
818 |
+
/**
|
819 |
+
* @internal
|
820 |
+
* @param string|array $tax
|
821 |
+
* @param bool $merge
|
822 |
+
* @param string $TermClass
|
823 |
+
* @return array
|
824 |
+
*/
|
825 |
+
function get_terms( $tax = '', $merge = true, $TermClass = '' ) {
|
826 |
+
|
827 |
+
$TermClass = $TermClass ?: $this->TermClass;
|
828 |
+
|
829 |
+
if ( is_string($merge) && class_exists($merge) ) {
|
830 |
+
$TermClass = $merge;
|
831 |
}
|
832 |
+
if ( is_array($tax) ) {
|
833 |
+
$taxonomies = $tax;
|
834 |
+
}
|
835 |
+
if ( is_string($tax) ) {
|
836 |
+
if ( in_array($tax, array('all','any','')) ) {
|
837 |
+
$taxonomies = get_object_taxonomies($this->post_type);
|
838 |
+
} else {
|
839 |
+
$taxonomies = array($tax);
|
840 |
}
|
841 |
}
|
842 |
+
|
843 |
+
$term_class_objects = array();
|
844 |
+
|
845 |
+
foreach ( $taxonomies as $taxonomy ) {
|
846 |
+
if ( in_array($taxonomy, array('tag','tags')) ) {
|
847 |
+
$taxonomy = 'post_tag';
|
848 |
+
}
|
849 |
+
if ( $taxonomy == 'categories' ) {
|
850 |
+
$taxonomy = 'category';
|
851 |
+
}
|
852 |
+
|
853 |
+
$terms = wp_get_post_terms($this->ID, $taxonomy);
|
854 |
+
|
855 |
+
if ( is_wp_error($terms) ) {
|
856 |
+
/* @var $terms WP_Error */
|
857 |
+
TimberHelper::error_log("Error retrieving terms for taxonomy '$taxonomy' on a post in timber-post.php");
|
858 |
+
TimberHelper::error_log('tax = ' . print_r($tax, true));
|
859 |
+
TimberHelper::error_log('WP_Error: ' . $terms->get_error_message());
|
860 |
+
|
861 |
+
return $term_class_objects;
|
862 |
+
}
|
863 |
+
|
864 |
+
// map over array of wordpress terms, and transform them into instances of the TermClass
|
865 |
+
$terms = array_map(function($term) use ($TermClass, $taxonomy) {
|
866 |
+
return call_user_func(array($TermClass, 'from'), $term->term_id, $taxonomy);
|
867 |
+
}, $terms);
|
868 |
+
|
869 |
+
if ( $merge && is_array($terms) ) {
|
870 |
+
$term_class_objects = array_merge($term_class_objects, $terms);
|
871 |
+
} else if ( count($terms) ) {
|
872 |
+
$term_class_objects[$taxonomy] = $terms;
|
873 |
+
}
|
874 |
}
|
875 |
+
return $term_class_objects;
|
876 |
}
|
877 |
|
878 |
/**
|
879 |
+
* @param string|int $term_name_or_id
|
880 |
+
* @param string $taxonomy
|
881 |
+
* @return bool
|
882 |
*/
|
883 |
+
function has_term( $term_name_or_id, $taxonomy = 'all' ) {
|
884 |
+
if ( $taxonomy == 'all' || $taxonomy == 'any' ) {
|
885 |
+
$taxes = get_object_taxonomies($this->post_type, 'names');
|
886 |
+
$ret = false;
|
887 |
+
foreach ( $taxes as $tax ) {
|
888 |
+
if ( has_term($term_name_or_id, $tax, $this->ID) ) {
|
889 |
+
$ret = true;
|
890 |
+
break;
|
891 |
+
}
|
892 |
+
}
|
893 |
+
return $ret;
|
894 |
+
}
|
895 |
+
return has_term($term_name_or_id, $taxonomy, $this->ID);
|
896 |
}
|
897 |
|
898 |
/**
|
899 |
+
* @param string $field
|
900 |
+
* @return TimberImage
|
901 |
+
*/
|
902 |
+
function get_image( $field ) {
|
903 |
+
return new $this->ImageClass($this->$field);
|
904 |
+
}
|
905 |
+
|
906 |
+
/**
|
907 |
+
* Gets an array of tags for you to use
|
908 |
+
* @internal
|
909 |
* @example
|
910 |
* ```twig
|
911 |
+
* <ul class="tags">
|
912 |
+
* {% for tag in post.tags %}
|
913 |
+
* <li>{{tag.name}}</li>
|
914 |
+
* {% endfor %}
|
915 |
+
* </ul>
|
916 |
* ```
|
917 |
+
* @return array
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
918 |
*/
|
919 |
+
function get_tags() {
|
920 |
+
return $this->get_terms('post_tag');
|
|
|
|
|
921 |
}
|
922 |
|
923 |
/**
|
924 |
+
* Outputs the title with filters applied
|
925 |
+
* @internal
|
926 |
* @example
|
927 |
* ```twig
|
928 |
+
* <h1>{{post.get_title}}</h1>
|
|
|
|
|
929 |
* ```
|
|
|
930 |
* ```html
|
931 |
+
* <h1>Hello World!</h1>
|
|
|
|
|
932 |
* ```
|
|
|
933 |
* @return string
|
934 |
*/
|
935 |
+
function get_title() {
|
936 |
+
return apply_filters('the_title', $this->post_title, $this->ID);
|
|
|
|
|
937 |
}
|
938 |
|
939 |
/**
|
940 |
+
* Displays the content of the post with filters, shortcodes and wpautop applied
|
941 |
+
* @example
|
942 |
+
* ```twig
|
943 |
+
* <div class="article-text">{{post.get_content}}</div>
|
944 |
+
* ```
|
945 |
+
* ```html
|
946 |
+
* <div class="article-text"><p>Blah blah blah</p><p>More blah blah blah.</p></div>
|
947 |
+
* ```
|
948 |
+
* @param int $len
|
949 |
+
* @param int $page
|
950 |
+
* @return string
|
951 |
*/
|
952 |
+
function get_content( $len = 0, $page = 0 ) {
|
953 |
+
if ( $len == 0 && $page == 0 && $this->_content ) {
|
954 |
+
return $this->_content;
|
955 |
+
}
|
956 |
+
$content = $this->post_content;
|
957 |
+
if ( $len ) {
|
958 |
+
$content = wp_trim_words($content, $len);
|
959 |
}
|
960 |
+
if ( $page ) {
|
961 |
+
$contents = explode('<!--nextpage-->', $content);
|
962 |
+
$page--;
|
963 |
+
if ( count($contents) > $page ) {
|
964 |
+
$content = $contents[$page];
|
965 |
+
}
|
966 |
+
}
|
967 |
+
$content = apply_filters('the_content', ($content));
|
968 |
+
if ( $len == 0 && $page == 0 ) {
|
969 |
+
$this->_content = $content;
|
970 |
+
}
|
971 |
+
return $content;
|
972 |
}
|
973 |
|
974 |
/**
|
975 |
+
* @return string
|
|
|
976 |
*/
|
977 |
+
function get_paged_content() {
|
978 |
+
global $page;
|
979 |
+
return $this->get_content(0, $page);
|
980 |
}
|
|
|
981 |
/**
|
982 |
+
*
|
983 |
+
* Here is my summary
|
984 |
* @example
|
985 |
* ```twig
|
986 |
+
* This post is from <span>{{ post.get_post_type.labels.plural }}</span>
|
987 |
+
* ```
|
988 |
+
*
|
989 |
+
* ```html
|
990 |
+
* This post is from <span>Recipes</span>
|
991 |
* ```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
992 |
* @return mixed
|
993 |
*/
|
994 |
+
public function get_post_type() {
|
995 |
+
return get_post_type_object($this->post_type);
|
|
|
|
|
|
|
|
|
996 |
}
|
997 |
|
998 |
/**
|
999 |
+
* @return int the number of comments on a post
|
1000 |
*/
|
1001 |
+
public function get_comment_count() {
|
1002 |
+
return get_comments_number($this->ID);
|
1003 |
}
|
1004 |
|
1005 |
/**
|
1006 |
+
* @param string $field_name
|
1007 |
+
* @return mixed
|
1008 |
*/
|
1009 |
+
public function get_field( $field_name ) {
|
1010 |
+
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
1011 |
+
if ( $value === null ) {
|
1012 |
+
$value = get_post_meta($this->ID, $field_name);
|
1013 |
+
if ( is_array($value) && count($value) == 1 ) {
|
1014 |
+
$value = $value[0];
|
1015 |
+
}
|
1016 |
+
if ( is_array($value) && count($value) == 0 ) {
|
1017 |
+
$value = null;
|
1018 |
+
}
|
1019 |
+
}
|
1020 |
+
$value = apply_filters('timber_post_get_meta_field', $value, $this->ID, $field_name, $this);
|
1021 |
+
return $value;
|
1022 |
}
|
1023 |
|
1024 |
/**
|
1025 |
+
* @param string $field_name
|
|
|
1026 |
*/
|
1027 |
+
function import_field( $field_name ) {
|
1028 |
+
$this->$field_name = $this->get_field($field_name);
|
1029 |
}
|
1030 |
|
1031 |
/**
|
1032 |
+
* @internal
|
|
|
1033 |
* @return mixed
|
1034 |
*/
|
1035 |
+
function get_format() {
|
1036 |
+
return get_post_format($this->ID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1037 |
}
|
1038 |
|
1039 |
/**
|
1040 |
+
* Get the CSS classes for a post. For usage you should use `{{post.class}}` instead of `{{post.post_class}}`
|
1041 |
+
* @internal
|
1042 |
+
* @param string $class additional classes you want to add
|
1043 |
+
* @see TimberPost::$class
|
1044 |
+
* @example
|
1045 |
+
* ```twig
|
1046 |
+
* <article class="{{ post.class }}">
|
1047 |
+
* {# Some stuff here #}
|
1048 |
+
* </article>
|
1049 |
+
* ```
|
1050 |
+
*
|
1051 |
+
* ```html
|
1052 |
+
* <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">
|
1053 |
+
* {# Some stuff here #}
|
1054 |
+
* </article>
|
1055 |
+
* ```
|
1056 |
+
* @return string a space-seperated list of classes
|
1057 |
*/
|
1058 |
+
public function post_class( $class='' ) {
|
1059 |
+
global $post;
|
1060 |
+
$old_global_post = $post;
|
1061 |
$post = $this;
|
1062 |
+
$class_array = get_post_class($class, $this->ID);
|
1063 |
+
$post = $old_global_post;
|
1064 |
+
if ( is_array($class_array) ){
|
1065 |
+
return implode(' ', $class_array);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1066 |
}
|
1067 |
+
return $class_array;
|
1068 |
}
|
1069 |
|
1070 |
+
// Docs
|
1071 |
|
1072 |
/**
|
1073 |
+
* @return array
|
1074 |
+
* @codeCoverageIgnore
|
1075 |
*/
|
1076 |
+
public function get_method_values() {
|
1077 |
+
$ret = parent::get_method_values();
|
1078 |
+
$ret['author'] = $this->author();
|
1079 |
+
$ret['categories'] = $this->categories();
|
1080 |
+
$ret['category'] = $this->category();
|
1081 |
+
$ret['children'] = $this->children();
|
1082 |
+
$ret['comments'] = $this->comments();
|
1083 |
+
$ret['content'] = $this->content();
|
1084 |
+
$ret['edit_link'] = $this->edit_link();
|
1085 |
+
$ret['format'] = $this->format();
|
1086 |
+
$ret['link'] = $this->link();
|
1087 |
+
$ret['next'] = $this->next();
|
1088 |
+
$ret['pagination'] = $this->pagination();
|
1089 |
+
$ret['parent'] = $this->parent();
|
1090 |
+
$ret['path'] = $this->path();
|
1091 |
+
$ret['prev'] = $this->prev();
|
1092 |
+
$ret['terms'] = $this->terms();
|
1093 |
+
$ret['tags'] = $this->tags();
|
1094 |
+
$ret['thumbnail'] = $this->thumbnail();
|
1095 |
+
$ret['title'] = $this->title();
|
1096 |
+
return $ret;
|
1097 |
}
|
1098 |
|
1099 |
/**
|
1100 |
+
* Return the author of a post
|
1101 |
* @api
|
1102 |
* @example
|
1103 |
* ```twig
|
1104 |
+
* <h1>{{post.title}}</h1>
|
1105 |
+
* <p class="byline">
|
1106 |
+
* <a href="{{post.author.link}}">{{post.author.name}}</a>
|
1107 |
+
* </p>
|
1108 |
* ```
|
1109 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
|
|
1110 |
*/
|
1111 |
+
public function author() {
|
1112 |
+
return $this->get_author();
|
|
|
|
|
|
|
1113 |
}
|
1114 |
|
1115 |
/**
|
1116 |
+
* Get the author (WordPress user) who last modified the post
|
|
|
|
|
1117 |
* @example
|
1118 |
* ```twig
|
1119 |
+
* Last updated by {{ post.modified_author.name }}
|
1120 |
* ```
|
1121 |
+
* ```html
|
1122 |
+
* Last updated by Harper Lee
|
1123 |
+
* ```
|
1124 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
1125 |
*/
|
1126 |
+
public function modified_author() {
|
1127 |
+
return $this->get_modified_author();
|
1128 |
}
|
1129 |
|
1130 |
/**
|
1131 |
+
* Get the categoires on a particular post
|
1132 |
* @api
|
1133 |
+
* @return array of TimberTerms
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1134 |
*/
|
1135 |
+
public function categories() {
|
1136 |
+
return $this->get_terms('category');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1137 |
}
|
1138 |
|
1139 |
/**
|
1140 |
+
* Returns a category attached to a post
|
1141 |
* @api
|
1142 |
+
* If mulitpuile categories are set, it will return just the first one
|
1143 |
+
* @return TimberTerm|null
|
1144 |
*/
|
1145 |
+
public function category() {
|
1146 |
+
return $this->get_category();
|
1147 |
}
|
1148 |
|
1149 |
/**
|
1150 |
+
* Returns an array of children on the post as TimberPosts
|
1151 |
+
* (or other claass as you define).
|
1152 |
* @api
|
1153 |
* @example
|
1154 |
* ```twig
|
1155 |
+
* {% if post.children %}
|
1156 |
+
* Here are the child pages:
|
1157 |
+
* {% for child in page.children %}
|
1158 |
+
* <a href="{{ child.link }}">{{ child.title }}</a>
|
1159 |
+
* {% endfor %}
|
1160 |
+
* {% endif %}
|
1161 |
* ```
|
1162 |
+
* @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
|
1163 |
+
* @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.
|
1164 |
+
* @return array
|
1165 |
*/
|
1166 |
+
public function children( $post_type = 'any', $childPostClass = false ) {
|
1167 |
+
return $this->get_children( $post_type, $childPostClass );
|
|
|
|
|
|
|
|
|
|
|
|
|
1168 |
}
|
1169 |
|
1170 |
/**
|
1171 |
+
* Gets the comments on a TimberPost and returns them as an array of [TimberComments](#TimberComment) (or whatever comment class you set).
|
1172 |
* @api
|
1173 |
+
* @param int $count Set the number of comments you want to get. `0` is analogous to "all"
|
1174 |
+
* @param string $order use ordering set in WordPress admin, or a different scheme
|
1175 |
+
* @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
|
1176 |
+
* @param string $status Could be 'pending', etc.
|
1177 |
+
* @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)
|
1178 |
* @example
|
1179 |
* ```twig
|
1180 |
+
* {# single.twig #}
|
1181 |
+
* <h4>Comments:</h4>
|
1182 |
+
* {% for comment in post.comments %}
|
1183 |
+
* <div class="comment-{{comment.ID}} comment-order-{{loop.index}}">
|
1184 |
+
* <p>{{comment.author.name}} said:</p>
|
1185 |
+
* <p>{{comment.content}}</p>
|
1186 |
+
* </div>
|
1187 |
+
* {% endfor %}
|
1188 |
+
* ```
|
1189 |
+
* @return bool|array
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1190 |
*/
|
1191 |
+
public function comments( $count = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment' ) {
|
1192 |
+
return $this->get_comments($count, $order, $type, $status, $CommentClass);
|
1193 |
}
|
1194 |
|
1195 |
/**
|
1196 |
+
* 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).
|
1197 |
+
* @api
|
1198 |
+
* @example
|
1199 |
+
* ```twig
|
1200 |
+
* <div class="article">
|
1201 |
+
* <h2>{{post.title}}</h2>
|
1202 |
+
* <div class="content">{{ post.content }}</div>
|
1203 |
+
* </div>
|
1204 |
+
* ```
|
1205 |
+
* @param int $page
|
1206 |
+
* @return string
|
1207 |
*/
|
1208 |
+
public function content( $page = 0 ) {
|
1209 |
+
return $this->get_content(0, $page);
|
|
|
|
|
|
|
1210 |
}
|
1211 |
|
1212 |
/**
|
1213 |
+
* @return string
|
|
|
1214 |
*/
|
1215 |
+
public function paged_content() {
|
1216 |
+
return $this->get_paged_content();
|
1217 |
}
|
1218 |
|
1219 |
/**
|
1220 |
+
* Get the date to use in your template!
|
1221 |
+
* @api
|
|
|
|
|
1222 |
* @example
|
1223 |
* ```twig
|
1224 |
+
* Published on {{ post.date }} // Uses WP's formatting set in Admin
|
1225 |
+
* OR
|
1226 |
+
* Published on {{ post.date | date('F jS') }} // Jan 12th
|
|
|
|
|
1227 |
* ```
|
1228 |
+
*
|
1229 |
+
* ```html
|
1230 |
+
* Published on January 12, 2015
|
1231 |
+
* OR
|
1232 |
+
* Published on Jan 12th
|
1233 |
+
* ```
|
1234 |
+
* @param string $date_format
|
1235 |
+
* @return string
|
1236 |
*/
|
1237 |
+
public function date( $date_format = '' ) {
|
1238 |
+
return $this->get_date($date_format);
|
1239 |
}
|
1240 |
|
1241 |
/**
|
1242 |
+
* Get the time to use in your template
|
1243 |
+
* @api
|
|
|
|
|
1244 |
* @example
|
1245 |
* ```twig
|
1246 |
+
* Published at {{ post.time }} // Uses WP's formatting set in Admin
|
1247 |
+
* OR
|
1248 |
+
* Published at {{ post.time | time('G:i') }} // 13:25
|
1249 |
* ```
|
1250 |
+
*
|
1251 |
* ```html
|
1252 |
+
* Published at 1:25 pm
|
1253 |
+
* OR
|
1254 |
+
* Published at 13:25
|
1255 |
* ```
|
1256 |
+
* @param string $time_format
|
1257 |
* @return string
|
1258 |
*/
|
1259 |
+
public function time( $time_format = '' ) {
|
1260 |
+
$tf = $time_format ? $time_format : get_option('time_format');
|
1261 |
+
$the_time = (string)mysql2date($tf, $this->post_date);
|
1262 |
+
return apply_filters('get_the_time', $the_time, $tf);
|
1263 |
}
|
1264 |
|
1265 |
+
/**
|
1266 |
+
* @return bool|string
|
1267 |
+
*/
|
1268 |
+
public function edit_link() {
|
1269 |
+
return $this->get_edit_url();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1270 |
}
|
1271 |
|
1272 |
/**
|
1273 |
+
* @api
|
|
|
1274 |
* @return mixed
|
1275 |
*/
|
1276 |
+
public function format() {
|
1277 |
+
return $this->get_format();
|
1278 |
}
|
1279 |
|
1280 |
/**
|
1281 |
+
* get the permalink for a post object
|
1282 |
+
* @api
|
1283 |
+
* @example
|
1284 |
+
* ```twig
|
1285 |
+
* <a href="{{post.link}}">Read my post</a>
|
1286 |
+
* ```
|
1287 |
+
* @return string ex: http://example.org/2015/07/my-awesome-post
|
|
|
1288 |
*/
|
1289 |
+
public function link() {
|
1290 |
+
return $this->get_permalink();
|
1291 |
}
|
1292 |
|
1293 |
/**
|
1294 |
+
* @param string $field_name
|
1295 |
+
* @return mixed
|
|
|
1296 |
*/
|
1297 |
+
public function meta( $field_name = null ) {
|
1298 |
+
if ( $field_name === null ) {
|
1299 |
+
//on the off-chance the field is actually named meta
|
1300 |
+
$field_name = 'meta';
|
1301 |
+
}
|
1302 |
+
return $this->get_field($field_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1303 |
}
|
1304 |
|
1305 |
/**
|
|
|
|
|
|
|
|
|
|
|
1306 |
* @return string
|
1307 |
*/
|
1308 |
+
public function name(){
|
1309 |
+
return $this->title();
|
1310 |
}
|
1311 |
|
1312 |
/**
|
1313 |
+
* @param string $date_format
|
|
|
1314 |
* @return string
|
1315 |
*/
|
1316 |
+
public function modified_date( $date_format = '' ) {
|
1317 |
+
return $this->get_modified_date($date_format);
|
|
|
|
|
1318 |
}
|
1319 |
|
1320 |
/**
|
1321 |
+
* @param string $time_format
|
1322 |
+
* @return string
|
|
|
|
|
|
|
|
|
|
|
1323 |
*/
|
1324 |
+
public function modified_time( $time_format = '' ) {
|
1325 |
+
return $this->get_modified_time($time_format);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1326 |
}
|
1327 |
|
1328 |
/**
|
1329 |
+
* @api
|
1330 |
+
* @param bool $in_same_cat
|
1331 |
+
* @return mixed
|
|
|
|
|
|
|
1332 |
*/
|
1333 |
+
public function next( $in_same_cat = false ) {
|
1334 |
+
return $this->get_next($in_same_cat);
|
1335 |
}
|
1336 |
|
1337 |
/**
|
1338 |
+
* @return array
|
|
|
|
|
|
|
|
|
1339 |
*/
|
1340 |
+
public function pagination() {
|
1341 |
+
return $this->get_pagination();
|
1342 |
}
|
1343 |
|
1344 |
/**
|
1345 |
+
* Gets the parent (if one exists) from a post as a TimberPost object (or whatever is set in TimberPost::$PostClass)
|
1346 |
+
* @api
|
1347 |
+
* @example
|
1348 |
+
* ```twig
|
1349 |
+
* Parent page: <a href="{{ post.parent.link }}">{{ post.parent.title }}</a>
|
1350 |
+
* ```
|
1351 |
+
* @return bool|TimberPost
|
1352 |
*/
|
1353 |
+
public function parent() {
|
1354 |
+
return $this->get_parent();
|
|
|
|
|
1355 |
}
|
1356 |
|
1357 |
/**
|
1358 |
+
* Gets the relative path of a WP Post, so while link() will return http://example.org/2015/07/my-cool-post
|
1359 |
+
* this will return just /2015/07/my-cool-post
|
1360 |
+
* @api
|
1361 |
+
* @example
|
1362 |
+
* ```twig
|
1363 |
+
* <a href="{{post.path}}">{{post.title}}</a>
|
1364 |
+
* ```
|
1365 |
+
* @return string
|
1366 |
*/
|
1367 |
+
public function path() {
|
1368 |
+
return $this->get_path();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1369 |
}
|
1370 |
|
1371 |
/**
|
1372 |
+
* @deprecated 0.20.0 use link() instead
|
|
|
|
|
|
|
1373 |
* @return string
|
1374 |
*/
|
1375 |
+
public function permalink() {
|
1376 |
+
return $this->get_permalink();
|
1377 |
}
|
1378 |
|
1379 |
/**
|
1380 |
+
* Get the previous post in a set
|
1381 |
+
* @api
|
1382 |
+
* @example
|
1383 |
+
* ```twig
|
1384 |
+
* <h4>Prior Entry:</h4>
|
1385 |
+
* <h3>{{post.prev.title}}</h3>
|
1386 |
+
* <p>{{post.prev.get_preview(25)}}</p>
|
1387 |
+
* ```
|
1388 |
+
* @param bool $in_same_cat
|
1389 |
+
* @return mixed
|
1390 |
*/
|
1391 |
+
public function prev( $in_same_cat = false ) {
|
1392 |
+
return $this->get_prev($in_same_cat);
|
1393 |
}
|
1394 |
|
1395 |
/**
|
1396 |
+
* Get the terms associated with the post
|
1397 |
+
* This goes across all taxonomies by default
|
1398 |
+
* @api
|
1399 |
+
* @param string|array $tax What taxonom(y|ies) to pull from. Defaults to all registered taxonomies for the post type. 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.
|
1400 |
+
* @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)?
|
1401 |
+
* @return array
|
1402 |
*/
|
1403 |
+
public function terms( $tax = '', $merge = true ) {
|
1404 |
+
return $this->get_terms($tax, $merge);
|
1405 |
}
|
1406 |
|
1407 |
/**
|
1408 |
+
* Gets the tags on a post, uses WP's post_tag taxonomy
|
1409 |
+
* @api
|
|
|
|
|
|
|
1410 |
* @return array
|
1411 |
*/
|
1412 |
+
public function tags() {
|
1413 |
+
return $this->get_tags();
|
1414 |
}
|
1415 |
|
1416 |
+
/**
|
1417 |
+
* get the featured image as a TimberImage
|
1418 |
+
* @api
|
1419 |
+
* @example
|
1420 |
+
* ```twig
|
1421 |
+
* <img src="{{post.thumbnail.src}}" />
|
1422 |
+
* ```
|
1423 |
+
* @return TimberImage|null of your thumbnail
|
1424 |
+
*/
|
1425 |
+
public function thumbnail() {
|
1426 |
+
return $this->get_thumbnail();
|
1427 |
+
}
|
1428 |
|
1429 |
/**
|
1430 |
+
* 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.
|
1431 |
+
* @api
|
1432 |
+
* @example
|
1433 |
+
* ```twig
|
1434 |
+
* <h1>{{ post.title }}</h1>
|
1435 |
+
* ```
|
1436 |
+
* @return string
|
|
|
|
|
1437 |
*/
|
1438 |
+
public function title() {
|
1439 |
+
return $this->get_title();
|
1440 |
}
|
1441 |
|
1442 |
}
|
lib/timber-posts-collection.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( !defined( 'ABSPATH' ) )
|
5 |
+
exit;
|
6 |
+
|
7 |
+
class TimberPostsCollection extends ArrayObject {
|
8 |
+
|
9 |
+
public function __construct( $posts = array(), $post_class = 'TimberPost' ) {
|
10 |
+
$returned_posts = array();
|
11 |
+
if ( is_null( $posts ) ){
|
12 |
+
$posts = array();
|
13 |
+
}
|
14 |
+
foreach ( $posts as $post_object ) {
|
15 |
+
$post_class_use = $post_class;
|
16 |
+
|
17 |
+
if ( is_array( $post_class ) ) {
|
18 |
+
$post_type = get_post_type( $post_object );
|
19 |
+
$post_class_use = 'TimberPost';
|
20 |
+
|
21 |
+
if ( isset( $post_class[$post_type] ) ) {
|
22 |
+
$post_class_use = $post_class[$post_type];
|
23 |
+
|
24 |
+
} else {
|
25 |
+
if ( is_array( $post_class ) ) {
|
26 |
+
TimberHelper::error_log( $post_type . ' of ' . $post_object->ID . ' not found in ' . print_r( $post_class, true ) );
|
27 |
+
} else {
|
28 |
+
TimberHelper::error_log( $post_type . ' not found in ' . $post_class );
|
29 |
+
}
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
// Don't create yet another object if $post_object is already of the right type
|
34 |
+
if ( is_a( $post_object, $post_class_use ) ) {
|
35 |
+
$post = $post_object;
|
36 |
+
} else {
|
37 |
+
$post = new $post_class_use( $post_object );
|
38 |
+
}
|
39 |
+
|
40 |
+
if ( isset( $post->ID ) ) {
|
41 |
+
$returned_posts[] = $post;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
$returned_posts = self::maybe_set_preview($returned_posts);
|
46 |
+
|
47 |
+
parent::__construct( $returned_posts, $flags = 0, 'TimberPostsIterator' );
|
48 |
+
}
|
49 |
+
|
50 |
+
public function get_posts() {
|
51 |
+
return $this->getArrayCopy();
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @param array $posts
|
56 |
+
* @return array
|
57 |
+
*/
|
58 |
+
static function maybe_set_preview( $posts ) {
|
59 |
+
if ( is_array( $posts ) && isset( $_GET['preview'] ) && $_GET['preview']
|
60 |
+
&& isset( $_GET['preview_id'] ) && $_GET['preview_id']
|
61 |
+
&& current_user_can( 'edit_post', $_GET['preview_id'] ) ) {
|
62 |
+
// No need to check the nonce, that already happened in _show_post_preview on init
|
63 |
+
|
64 |
+
$preview_id = $_GET['preview_id'];
|
65 |
+
foreach( $posts as &$post ) {
|
66 |
+
if ( is_object( $post ) && $post->ID == $preview_id ) {
|
67 |
+
// Based on _set_preview( $post ), but adds import_custom
|
68 |
+
$preview = wp_get_post_autosave( $preview_id );
|
69 |
+
if ( is_object($preview) ) {
|
70 |
+
|
71 |
+
$preview = sanitize_post($preview);
|
72 |
+
|
73 |
+
$post->post_content = $preview->post_content;
|
74 |
+
$post->post_title = $preview->post_title;
|
75 |
+
$post->post_excerpt = $preview->post_excerpt;
|
76 |
+
$post->import_custom( $preview_id );
|
77 |
+
|
78 |
+
add_filter( 'get_the_terms', '_wp_preview_terms_filter', 10, 3 );
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
return $posts;
|
86 |
+
}
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
class TimberPostsIterator extends ArrayIterator {
|
91 |
+
|
92 |
+
public function current() {
|
93 |
+
global $post;
|
94 |
+
$post = parent::current();
|
95 |
+
return $post;
|
96 |
+
}
|
97 |
+
}
|
lib/timber-query-iterator.php
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if ( !defined( 'ABSPATH' ) )
|
4 |
+
exit;
|
5 |
+
|
6 |
+
class TimberQueryIterator implements Iterator {
|
7 |
+
|
8 |
+
/**
|
9 |
+
*
|
10 |
+
*
|
11 |
+
* @var WP_Query
|
12 |
+
*/
|
13 |
+
private $_query = null;
|
14 |
+
private $_posts_class = 'TimberPost';
|
15 |
+
|
16 |
+
public function __construct( $query = false, $posts_class = 'TimberPost' ) {
|
17 |
+
add_action( 'pre_get_posts', array($this, 'fix_number_posts_wp_quirk' ));
|
18 |
+
if ( $posts_class )
|
19 |
+
$this->_posts_class = $posts_class;
|
20 |
+
|
21 |
+
if ( is_a( $query, 'WP_Query' ) ) {
|
22 |
+
// We got a full-fledged WP Query, look no further!
|
23 |
+
$the_query = $query;
|
24 |
+
|
25 |
+
} elseif ( false === $query ) {
|
26 |
+
// If query is explicitly set to false, use the main loop
|
27 |
+
global $wp_query;
|
28 |
+
$the_query =& $wp_query;
|
29 |
+
//if we're on a custom posts page?
|
30 |
+
$the_query = self::handle_maybe_custom_posts_page($the_query);
|
31 |
+
} elseif ( TimberHelper::is_array_assoc( $query ) || ( is_string( $query ) && strstr( $query, '=' ) ) ) {
|
32 |
+
// We have a regularly formed WP query string or array to use
|
33 |
+
$the_query = new WP_Query( $query );
|
34 |
+
|
35 |
+
} elseif ( is_numeric( $query ) || is_string( $query ) ) {
|
36 |
+
// We have what could be a post name or post ID to pull out
|
37 |
+
$the_query = self::get_query_from_string( $query );
|
38 |
+
|
39 |
+
} elseif ( is_array( $query ) && count( $query ) && ( is_integer( $query[0] ) || is_string( $query[0] ) ) ) {
|
40 |
+
// We have a list of pids (post IDs) to extract from
|
41 |
+
$the_query = self::get_query_from_array_of_ids( $query );
|
42 |
+
} elseif ( is_array($query) && empty($query)) {
|
43 |
+
// it's an empty array
|
44 |
+
$the_query = array();
|
45 |
+
} else {
|
46 |
+
TimberHelper::error_log( 'I have failed you! in ' . basename( __FILE__ ) . '::' . __LINE__ );
|
47 |
+
TimberHelper::error_log( $query );
|
48 |
+
|
49 |
+
// We have failed hard, at least let get something.
|
50 |
+
$the_query = new WP_Query();
|
51 |
+
}
|
52 |
+
|
53 |
+
$this->_query = $the_query;
|
54 |
+
|
55 |
+
}
|
56 |
+
|
57 |
+
public function get_posts( $return_collection = false ) {
|
58 |
+
if (isset($this->_query->posts)){
|
59 |
+
$posts = new TimberPostsCollection( $this->_query->posts, $this->_posts_class );
|
60 |
+
return ( $return_collection ) ? $posts : $posts->get_posts();
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
//
|
65 |
+
// GET POSTS
|
66 |
+
//
|
67 |
+
public static function get_query_from_array_of_ids( $query = array() ) {
|
68 |
+
if ( !is_array( $query ) || !count( $query ) )
|
69 |
+
return null;
|
70 |
+
|
71 |
+
return new WP_Query( array(
|
72 |
+
'post_type'=> 'any',
|
73 |
+
'ignore_sticky_posts' => true,
|
74 |
+
'post__in' => $query,
|
75 |
+
'orderby' => 'post__in',
|
76 |
+
'nopaging' => true
|
77 |
+
) );
|
78 |
+
}
|
79 |
+
|
80 |
+
public static function get_query_from_string( $string = '' ) {
|
81 |
+
$post_type = false;
|
82 |
+
|
83 |
+
if ( is_string( $string ) && strstr( $string, '#' ) ) {
|
84 |
+
//we have a post_type directive here
|
85 |
+
list( $post_type, $string ) = explode( '#', $string );
|
86 |
+
}
|
87 |
+
|
88 |
+
$query = array(
|
89 |
+
'post_type' => ( $post_type ) ? $post_type : 'any'
|
90 |
+
);
|
91 |
+
|
92 |
+
if ( is_numeric( $string ) ) {
|
93 |
+
$query['p'] = $string;
|
94 |
+
|
95 |
+
} else {
|
96 |
+
$query['name'] = $string;
|
97 |
+
}
|
98 |
+
|
99 |
+
return new WP_Query( $query );
|
100 |
+
}
|
101 |
+
|
102 |
+
//
|
103 |
+
// Iterator Interface
|
104 |
+
//
|
105 |
+
|
106 |
+
public function valid() {
|
107 |
+
return $this->_query->have_posts();
|
108 |
+
}
|
109 |
+
|
110 |
+
public function current() {
|
111 |
+
global $post;
|
112 |
+
|
113 |
+
$this->_query->the_post();
|
114 |
+
|
115 |
+
// Sets up the global post, but also return the post, for use in Twig template
|
116 |
+
$posts_class = $this->_posts_class;
|
117 |
+
return new $posts_class( $post );
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Don't implement next, because current already advances the loop
|
122 |
+
*/
|
123 |
+
final public function next() {}
|
124 |
+
|
125 |
+
public function rewind() {
|
126 |
+
$this->_query->rewind_posts();
|
127 |
+
}
|
128 |
+
|
129 |
+
public function key() {
|
130 |
+
$this->_query->current_post;
|
131 |
+
}
|
132 |
+
|
133 |
+
//get_posts users numberposts
|
134 |
+
static function fix_number_posts_wp_quirk( $query ) {
|
135 |
+
if (isset($query->query) && isset($query->query['numberposts'])
|
136 |
+
&& !isset($query->query['posts_per_page'])) {
|
137 |
+
$query->set( 'posts_per_page', $query->query['numberposts'] );
|
138 |
+
}
|
139 |
+
return $query;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* this will test for whether a custom page to display posts is active, and if so, set the query to the default
|
144 |
+
* @param WP_Query $query the original query recived from WordPress
|
145 |
+
* @return WP_Query
|
146 |
+
*/
|
147 |
+
static function handle_maybe_custom_posts_page( $query ) {
|
148 |
+
if ($custom_posts_page = get_option('page_for_posts')) {
|
149 |
+
if ( isset($query->query['p']) && $query->query['p'] == $custom_posts_page ) {
|
150 |
+
return new WP_Query(array('post_type' => 'post'));
|
151 |
+
}
|
152 |
+
}
|
153 |
+
return $query;
|
154 |
+
}
|
155 |
+
|
156 |
+
}
|
lib/{Request.php → timber-request.php}
RENAMED
@@ -1,15 +1,8 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\CoreInterface;
|
7 |
-
|
8 |
/**
|
9 |
* TimberRequest exposes $_GET and $_POST to the context
|
10 |
*/
|
11 |
-
|
12 |
-
class Request extends Core implements CoreInterface {
|
13 |
public $post = array();
|
14 |
public $get = array();
|
15 |
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* TimberRequest exposes $_GET and $_POST to the context
|
4 |
*/
|
5 |
+
class TimberRequest extends TimberCore implements TimberCoreInterface {
|
|
|
6 |
public $post = array();
|
7 |
public $get = array();
|
8 |
|
lib/timber-routes.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class TimberRoutes {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @deprecated since 0.21.1 use Upstatement/routes instead
|
7 |
+
*/
|
8 |
+
public static function init( $timber ) {
|
9 |
+
// Install ourselves in Timber
|
10 |
+
$timber->routes = new TimberRoutes();
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @param string $route
|
15 |
+
* @param callable $callback
|
16 |
+
* @deprecated since 0.21.1 use Upstatement/routes instead
|
17 |
+
*/
|
18 |
+
public static function add_route($route, $callback, $args = array()) {
|
19 |
+
Routes::map($route, $callback, $args);
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param array $template
|
24 |
+
* @param mixed $query
|
25 |
+
* @param int $status_code
|
26 |
+
* @param bool $tparams
|
27 |
+
* @return bool
|
28 |
+
* @deprecated since 0.21.1 use Upstatement/routes instead
|
29 |
+
*/
|
30 |
+
public static function load_view($template, $query = false, $status_code = 200, $tparams = false) {
|
31 |
+
Routes::load($template, $tparams, $query, $status_code);
|
32 |
+
}
|
33 |
+
}
|
lib/{Site.php → timber-site.php}
RENAMED
@@ -1,13 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\CoreInterface;
|
7 |
-
|
8 |
-
use Timber\Theme;
|
9 |
-
use Timber\Helper;
|
10 |
-
|
11 |
/**
|
12 |
* TimberSite gives you access to information you need about your site. In Multisite setups, you can get info on other sites in your network.
|
13 |
* @example
|
@@ -24,7 +16,7 @@ use Timber\Helper;
|
|
24 |
* My site is called Jared's blog, another site on my network is Upstatement.com
|
25 |
* ```
|
26 |
*/
|
27 |
-
class
|
28 |
|
29 |
/**
|
30 |
* @api
|
@@ -72,7 +64,7 @@ class Site extends Core implements CoreInterface {
|
|
72 |
|
73 |
/** @api
|
74 |
* @var string for people who like trackback spam
|
75 |
-
|
76 |
public $pingback_url;
|
77 |
public $siteurl;
|
78 |
/**
|
@@ -112,7 +104,7 @@ class Site extends Core implements CoreInterface {
|
|
112 |
function __construct( $site_name_or_id = null ) {
|
113 |
$this->init();
|
114 |
if ( is_multisite() ) {
|
115 |
-
$this->init_as_multisite($site_name_or_id);
|
116 |
} else {
|
117 |
$this->init_as_singlesite();
|
118 |
}
|
@@ -130,17 +122,17 @@ class Site extends Core implements CoreInterface {
|
|
130 |
$site_name_or_id = get_current_blog_id();
|
131 |
}
|
132 |
}
|
133 |
-
$info = get_blog_details($site_name_or_id);
|
134 |
-
$this->import($info);
|
135 |
$this->ID = $info->blog_id;
|
136 |
$this->id = $this->ID;
|
137 |
$this->name = $this->blogname;
|
138 |
$this->title = $this->blogname;
|
139 |
$this->url = $this->siteurl;
|
140 |
-
$theme_slug = get_blog_option($info->blog_id, 'stylesheet');
|
141 |
-
$this->theme = new
|
142 |
-
$this->description = get_blog_option($info->blog_id, 'blogdescription');
|
143 |
-
$this->admin_email = get_blog_option($info->blog_id, 'admin_email');
|
144 |
$this->multisite = true;
|
145 |
}
|
146 |
|
@@ -149,13 +141,13 @@ class Site extends Core implements CoreInterface {
|
|
149 |
* @internal
|
150 |
*/
|
151 |
protected function init_as_singlesite() {
|
152 |
-
$this->admin_email = get_bloginfo('admin_email');
|
153 |
-
$this->name = get_bloginfo('name');
|
154 |
$this->title = $this->name;
|
155 |
-
$this->description = get_bloginfo('description');
|
156 |
-
$this->url = get_bloginfo('url');
|
157 |
-
$this->theme = new
|
158 |
-
$this->language_attributes =
|
159 |
$this->multisite = false;
|
160 |
}
|
161 |
|
@@ -164,14 +156,16 @@ class Site extends Core implements CoreInterface {
|
|
164 |
* @internal
|
165 |
*/
|
166 |
protected function init() {
|
167 |
-
$this->rdf = get_bloginfo('rdf_url');
|
168 |
-
$this->rss = get_bloginfo('rss_url');
|
169 |
-
$this->rss2 = get_bloginfo('rss2_url');
|
170 |
-
$this->atom = get_bloginfo('atom_url');
|
171 |
-
$this->language = get_bloginfo('language');
|
172 |
-
$this->charset = get_bloginfo('charset');
|
173 |
-
$this->pingback = get_bloginfo('pingback_url');
|
174 |
-
$this->language_attributes =
|
|
|
|
|
175 |
}
|
176 |
|
177 |
/**
|
@@ -181,16 +175,34 @@ class Site extends Core implements CoreInterface {
|
|
181 |
* @return mixed
|
182 |
*/
|
183 |
function __get( $field ) {
|
184 |
-
if ( !isset($this->$field) ) {
|
185 |
if ( is_multisite() ) {
|
186 |
-
$this->$field = get_blog_option($this->ID, $field);
|
187 |
} else {
|
188 |
-
$this->$field = get_option($field);
|
189 |
}
|
190 |
}
|
191 |
return $this->$field;
|
192 |
}
|
193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
/**
|
195 |
* Returns the link to the site's home.
|
196 |
* @example
|
@@ -211,22 +223,11 @@ class Site extends Core implements CoreInterface {
|
|
211 |
return $this->url;
|
212 |
}
|
213 |
|
214 |
-
/**
|
215 |
-
* @deprecated 0.21.9
|
216 |
-
* @internal
|
217 |
-
* @return string
|
218 |
-
*/
|
219 |
-
function get_link() {
|
220 |
-
Helper::warn('{{site.get_link}} is deprecated, use {{site.link}}');
|
221 |
-
return $this->link();
|
222 |
-
}
|
223 |
-
|
224 |
-
|
225 |
/**
|
226 |
* @ignore
|
227 |
*/
|
228 |
public function meta( $field ) {
|
229 |
-
return $this->__get($field);
|
230 |
}
|
231 |
|
232 |
/**
|
@@ -236,11 +237,11 @@ class Site extends Core implements CoreInterface {
|
|
236 |
* @param mixed $value
|
237 |
*/
|
238 |
public function update( $key, $value ) {
|
239 |
-
$value = apply_filters('timber_site_set_meta', $value, $key, $this->ID, $this);
|
240 |
if ( is_multisite() ) {
|
241 |
-
update_blog_option($this->ID, $key, $value);
|
242 |
} else {
|
243 |
-
update_option($key, $value);
|
244 |
}
|
245 |
$this->$key = $value;
|
246 |
}
|
@@ -252,17 +253,7 @@ class Site extends Core implements CoreInterface {
|
|
252 |
* @return string
|
253 |
*/
|
254 |
function url() {
|
255 |
-
return $this->
|
256 |
-
}
|
257 |
-
|
258 |
-
/**
|
259 |
-
* @deprecated 0.21.9
|
260 |
-
* @internal
|
261 |
-
* @return string
|
262 |
-
*/
|
263 |
-
function get_url() {
|
264 |
-
Helper::warn('{{site.get_url}} is deprecated, use {{site.link}} instead');
|
265 |
-
return $this->link();
|
266 |
}
|
267 |
|
268 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* TimberSite gives you access to information you need about your site. In Multisite setups, you can get info on other sites in your network.
|
5 |
* @example
|
16 |
* My site is called Jared's blog, another site on my network is Upstatement.com
|
17 |
* ```
|
18 |
*/
|
19 |
+
class TimberSite extends TimberCore implements TimberCoreInterface {
|
20 |
|
21 |
/**
|
22 |
* @api
|
64 |
|
65 |
/** @api
|
66 |
* @var string for people who like trackback spam
|
67 |
+
*/
|
68 |
public $pingback_url;
|
69 |
public $siteurl;
|
70 |
/**
|
104 |
function __construct( $site_name_or_id = null ) {
|
105 |
$this->init();
|
106 |
if ( is_multisite() ) {
|
107 |
+
$this->init_as_multisite( $site_name_or_id );
|
108 |
} else {
|
109 |
$this->init_as_singlesite();
|
110 |
}
|
122 |
$site_name_or_id = get_current_blog_id();
|
123 |
}
|
124 |
}
|
125 |
+
$info = get_blog_details( $site_name_or_id );
|
126 |
+
$this->import( $info );
|
127 |
$this->ID = $info->blog_id;
|
128 |
$this->id = $this->ID;
|
129 |
$this->name = $this->blogname;
|
130 |
$this->title = $this->blogname;
|
131 |
$this->url = $this->siteurl;
|
132 |
+
$theme_slug = get_blog_option( $info->blog_id, 'stylesheet' );
|
133 |
+
$this->theme = new TimberTheme( $theme_slug );
|
134 |
+
$this->description = get_blog_option( $info->blog_id, 'blogdescription' );
|
135 |
+
$this->admin_email = get_blog_option( $info->blog_id, 'admin_email' );
|
136 |
$this->multisite = true;
|
137 |
}
|
138 |
|
141 |
* @internal
|
142 |
*/
|
143 |
protected function init_as_singlesite() {
|
144 |
+
$this->admin_email = get_bloginfo( 'admin_email' );
|
145 |
+
$this->name = get_bloginfo( 'name' );
|
146 |
$this->title = $this->name;
|
147 |
+
$this->description = get_bloginfo( 'description' );
|
148 |
+
$this->url = get_bloginfo( 'url' );
|
149 |
+
$this->theme = new TimberTheme();
|
150 |
+
$this->language_attributes = TimberHelper::function_wrapper( 'language_attributes' );
|
151 |
$this->multisite = false;
|
152 |
}
|
153 |
|
156 |
* @internal
|
157 |
*/
|
158 |
protected function init() {
|
159 |
+
$this->rdf = get_bloginfo( 'rdf_url' );
|
160 |
+
$this->rss = get_bloginfo( 'rss_url' );
|
161 |
+
$this->rss2 = get_bloginfo( 'rss2_url' );
|
162 |
+
$this->atom = get_bloginfo( 'atom_url' );
|
163 |
+
$this->language = get_bloginfo( 'language' );
|
164 |
+
$this->charset = get_bloginfo( 'charset' );
|
165 |
+
$this->pingback = get_bloginfo( 'pingback_url' );
|
166 |
+
$this->language_attributes = TimberHelper::function_wrapper( 'language_attributes' );
|
167 |
+
/* deprecated benath this comment */
|
168 |
+
$this->pingback_url = get_bloginfo( 'pingback_url' );
|
169 |
}
|
170 |
|
171 |
/**
|
175 |
* @return mixed
|
176 |
*/
|
177 |
function __get( $field ) {
|
178 |
+
if ( !isset( $this->$field ) ) {
|
179 |
if ( is_multisite() ) {
|
180 |
+
$this->$field = get_blog_option( $this->ID, $field );
|
181 |
} else {
|
182 |
+
$this->$field = get_option( $field );
|
183 |
}
|
184 |
}
|
185 |
return $this->$field;
|
186 |
}
|
187 |
|
188 |
+
/**
|
189 |
+
* @deprecated 0.21.9
|
190 |
+
* @internal
|
191 |
+
* @return string
|
192 |
+
*/
|
193 |
+
function get_link() {
|
194 |
+
return $this->link();
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* @deprecated 0.21.9
|
199 |
+
* @internal
|
200 |
+
* @return string
|
201 |
+
*/
|
202 |
+
function get_url() {
|
203 |
+
return $this->get_link();
|
204 |
+
}
|
205 |
+
|
206 |
/**
|
207 |
* Returns the link to the site's home.
|
208 |
* @example
|
223 |
return $this->url;
|
224 |
}
|
225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
/**
|
227 |
* @ignore
|
228 |
*/
|
229 |
public function meta( $field ) {
|
230 |
+
return $this->__get( $field );
|
231 |
}
|
232 |
|
233 |
/**
|
237 |
* @param mixed $value
|
238 |
*/
|
239 |
public function update( $key, $value ) {
|
240 |
+
$value = apply_filters( 'timber_site_set_meta', $value, $key, $this->ID, $this );
|
241 |
if ( is_multisite() ) {
|
242 |
+
update_blog_option( $this->ID, $key, $value );
|
243 |
} else {
|
244 |
+
update_option( $key, $value );
|
245 |
}
|
246 |
$this->$key = $value;
|
247 |
}
|
253 |
* @return string
|
254 |
*/
|
255 |
function url() {
|
256 |
+
return $this->get_link();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
}
|
258 |
|
259 |
}
|
lib/{TermGetter.php → timber-term-getter.php}
RENAMED
@@ -1,11 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
use Timber\Term;
|
6 |
-
use Timber\Helper;
|
7 |
-
|
8 |
-
class TermGetter {
|
9 |
|
10 |
/**
|
11 |
* @param string|array $args
|
@@ -13,7 +8,7 @@ class TermGetter {
|
|
13 |
* @param string $TermClass
|
14 |
* @return mixed
|
15 |
*/
|
16 |
-
public static function get_terms(
|
17 |
if ( is_string($maybe_args) && !strstr($maybe_args, '=') ) {
|
18 |
//the user is sending the $TermClass in the second argument
|
19 |
$TermClass = $maybe_args;
|
@@ -35,7 +30,7 @@ class TermGetter {
|
|
35 |
$parsed->args = array_merge($parsed->args, $maybe_args);
|
36 |
}
|
37 |
return self::handle_term_query($parsed->taxonomies, $parsed->args, $TermClass);
|
38 |
-
} else if ( is_array($args) &&
|
39 |
//its an associative array, like a good ole query
|
40 |
$parsed = self::get_term_query_from_assoc_array($args);
|
41 |
return self::handle_term_query($parsed->taxonomies, $parsed->args, $TermClass);
|
@@ -58,7 +53,7 @@ class TermGetter {
|
|
58 |
* @param string $TermClass
|
59 |
* @return mixed
|
60 |
*/
|
61 |
-
public static function handle_term_query(
|
62 |
if ( !isset($args['hide_empty']) ) {
|
63 |
$args['hide_empty'] = false;
|
64 |
}
|
@@ -69,7 +64,7 @@ class TermGetter {
|
|
69 |
$args['include'] = $args['term_id'];
|
70 |
}
|
71 |
$terms = get_terms($taxonomies, $args);
|
72 |
-
foreach (
|
73 |
$term = new $TermClass($term->term_id, $term->taxonomy);
|
74 |
}
|
75 |
return $terms;
|
@@ -79,7 +74,7 @@ class TermGetter {
|
|
79 |
* @param string $query_string
|
80 |
* @return stdClass
|
81 |
*/
|
82 |
-
protected static function get_term_query_from_query_string(
|
83 |
$args = array();
|
84 |
parse_str($query_string, $args);
|
85 |
$ret = self::get_term_query_from_assoc_array($args);
|
@@ -90,8 +85,8 @@ class TermGetter {
|
|
90 |
* @param string $taxs
|
91 |
* @return stdClass
|
92 |
*/
|
93 |
-
protected static function get_term_query_from_string(
|
94 |
-
$ret = new
|
95 |
$ret->args = array();
|
96 |
if ( is_string($taxs) ) {
|
97 |
$taxs = array($taxs);
|
@@ -104,8 +99,8 @@ class TermGetter {
|
|
104 |
* @param array $args
|
105 |
* @return stdClass
|
106 |
*/
|
107 |
-
public static function get_term_query_from_assoc_array(
|
108 |
-
$ret = new
|
109 |
$ret->args = $args;
|
110 |
if ( isset($ret->args['tax']) ) {
|
111 |
$ret->taxonomies = $ret->args['tax'];
|
@@ -131,7 +126,7 @@ class TermGetter {
|
|
131 |
* @param array $args
|
132 |
* @return stdClass
|
133 |
*/
|
134 |
-
public static function get_term_query_from_array(
|
135 |
if ( is_array($args) && !empty($args) ) {
|
136 |
//okay its an array with content
|
137 |
if ( is_int($args[0]) ) {
|
@@ -147,8 +142,8 @@ class TermGetter {
|
|
147 |
* @param integer[] $args
|
148 |
* @return stdClass
|
149 |
*/
|
150 |
-
public static function get_term_query_from_array_of_ids(
|
151 |
-
$ret = new
|
152 |
$ret->taxonomies = get_taxonomies();
|
153 |
$ret->args['include'] = $args;
|
154 |
return $ret;
|
@@ -158,8 +153,8 @@ class TermGetter {
|
|
158 |
* @param string[] $args
|
159 |
* @return stdClass
|
160 |
*/
|
161 |
-
public static function get_term_query_from_array_of_strings(
|
162 |
-
$ret = new
|
163 |
$ret->taxonomies = self::correct_taxonomy_names($args);
|
164 |
$ret->args = array();
|
165 |
return $ret;
|
@@ -169,11 +164,11 @@ class TermGetter {
|
|
169 |
* @param string|array $taxs
|
170 |
* @return array
|
171 |
*/
|
172 |
-
private static function correct_taxonomy_names(
|
173 |
if ( is_string($taxs) ) {
|
174 |
$taxs = array($taxs);
|
175 |
}
|
176 |
-
foreach (
|
177 |
if ( $tax == 'tags' || $tax == 'tag' ) {
|
178 |
$tax = 'post_tag';
|
179 |
} else if ( $tax == 'categories' ) {
|
1 |
<?php
|
2 |
|
3 |
+
class TimberTermGetter {
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
* @param string|array $args
|
8 |
* @param string $TermClass
|
9 |
* @return mixed
|
10 |
*/
|
11 |
+
public static function get_terms($args = null, $maybe_args = array(), $TermClass = 'TimberTerm') {
|
12 |
if ( is_string($maybe_args) && !strstr($maybe_args, '=') ) {
|
13 |
//the user is sending the $TermClass in the second argument
|
14 |
$TermClass = $maybe_args;
|
30 |
$parsed->args = array_merge($parsed->args, $maybe_args);
|
31 |
}
|
32 |
return self::handle_term_query($parsed->taxonomies, $parsed->args, $TermClass);
|
33 |
+
} else if ( is_array($args) && TimberHelper::is_array_assoc($args) ) {
|
34 |
//its an associative array, like a good ole query
|
35 |
$parsed = self::get_term_query_from_assoc_array($args);
|
36 |
return self::handle_term_query($parsed->taxonomies, $parsed->args, $TermClass);
|
53 |
* @param string $TermClass
|
54 |
* @return mixed
|
55 |
*/
|
56 |
+
public static function handle_term_query($taxonomies, $args, $TermClass) {
|
57 |
if ( !isset($args['hide_empty']) ) {
|
58 |
$args['hide_empty'] = false;
|
59 |
}
|
64 |
$args['include'] = $args['term_id'];
|
65 |
}
|
66 |
$terms = get_terms($taxonomies, $args);
|
67 |
+
foreach ($terms as &$term) {
|
68 |
$term = new $TermClass($term->term_id, $term->taxonomy);
|
69 |
}
|
70 |
return $terms;
|
74 |
* @param string $query_string
|
75 |
* @return stdClass
|
76 |
*/
|
77 |
+
protected static function get_term_query_from_query_string($query_string) {
|
78 |
$args = array();
|
79 |
parse_str($query_string, $args);
|
80 |
$ret = self::get_term_query_from_assoc_array($args);
|
85 |
* @param string $taxs
|
86 |
* @return stdClass
|
87 |
*/
|
88 |
+
protected static function get_term_query_from_string($taxs) {
|
89 |
+
$ret = new stdClass();
|
90 |
$ret->args = array();
|
91 |
if ( is_string($taxs) ) {
|
92 |
$taxs = array($taxs);
|
99 |
* @param array $args
|
100 |
* @return stdClass
|
101 |
*/
|
102 |
+
public static function get_term_query_from_assoc_array($args) {
|
103 |
+
$ret = new stdClass();
|
104 |
$ret->args = $args;
|
105 |
if ( isset($ret->args['tax']) ) {
|
106 |
$ret->taxonomies = $ret->args['tax'];
|
126 |
* @param array $args
|
127 |
* @return stdClass
|
128 |
*/
|
129 |
+
public static function get_term_query_from_array($args) {
|
130 |
if ( is_array($args) && !empty($args) ) {
|
131 |
//okay its an array with content
|
132 |
if ( is_int($args[0]) ) {
|
142 |
* @param integer[] $args
|
143 |
* @return stdClass
|
144 |
*/
|
145 |
+
public static function get_term_query_from_array_of_ids($args) {
|
146 |
+
$ret = new stdClass();
|
147 |
$ret->taxonomies = get_taxonomies();
|
148 |
$ret->args['include'] = $args;
|
149 |
return $ret;
|
153 |
* @param string[] $args
|
154 |
* @return stdClass
|
155 |
*/
|
156 |
+
public static function get_term_query_from_array_of_strings($args) {
|
157 |
+
$ret = new stdClass();
|
158 |
$ret->taxonomies = self::correct_taxonomy_names($args);
|
159 |
$ret->args = array();
|
160 |
return $ret;
|
164 |
* @param string|array $taxs
|
165 |
* @return array
|
166 |
*/
|
167 |
+
private static function correct_taxonomy_names($taxs) {
|
168 |
if ( is_string($taxs) ) {
|
169 |
$taxs = array($taxs);
|
170 |
}
|
171 |
+
foreach ($taxs as &$tax) {
|
172 |
if ( $tax == 'tags' || $tax == 'tag' ) {
|
173 |
$tax = 'post_tag';
|
174 |
} else if ( $tax == 'categories' ) {
|
lib/{Term.php → timber-term.php}
RENAMED
@@ -1,14 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\CoreInterface;
|
7 |
-
|
8 |
-
use Timber\Post;
|
9 |
-
use Timber\Helper;
|
10 |
-
use Timber\URLHelper;
|
11 |
-
|
12 |
/**
|
13 |
* Terms: WordPress has got 'em, you want 'em. Categories. Tags. Custom Taxonomies. You don't care, you're a fiend. Well let's get this under control
|
14 |
* @example
|
@@ -40,10 +30,10 @@ use Timber\URLHelper;
|
|
40 |
* </ul>
|
41 |
* ```
|
42 |
*/
|
43 |
-
class
|
44 |
|
45 |
-
public $PostClass = '
|
46 |
-
public $TermClass = '
|
47 |
|
48 |
public $object_type = 'term';
|
49 |
public static $representation = 'term';
|
@@ -65,10 +55,10 @@ class Term extends Core implements CoreInterface {
|
|
65 |
* @param string $tax
|
66 |
*/
|
67 |
public function __construct( $tid = null, $tax = '' ) {
|
68 |
-
if (
|
69 |
$tid = $this->get_term_from_query();
|
70 |
}
|
71 |
-
if (
|
72 |
$this->taxonomy = $tax;
|
73 |
}
|
74 |
$this->init($tid);
|
@@ -103,7 +93,7 @@ class Term extends Core implements CoreInterface {
|
|
103 |
global $wp_query;
|
104 |
if ( isset($wp_query->queried_object) ) {
|
105 |
$qo = $wp_query->queried_object;
|
106 |
-
if (
|
107 |
return $qo->term_id;
|
108 |
}
|
109 |
}
|
@@ -124,9 +114,9 @@ class Term extends Core implements CoreInterface {
|
|
124 |
$term->ID = $term->term_id;
|
125 |
} else if ( is_string($tid) ) {
|
126 |
//echo 'bad call using '.$tid;
|
127 |
-
//
|
128 |
}
|
129 |
-
if ( isset($term->ID) )
|
130 |
$term->id = $term->ID;
|
131 |
$this->import($term);
|
132 |
if ( isset($term->term_id) ) {
|
@@ -141,7 +131,7 @@ class Term extends Core implements CoreInterface {
|
|
141 |
* @param int $tid
|
142 |
* @return array
|
143 |
*/
|
144 |
-
protected function get_term_meta(
|
145 |
$customs = array();
|
146 |
$customs = apply_filters('timber_term_get_meta', $customs, $tid, $this);
|
147 |
return apply_filters('timber/term/meta', $customs, $tid, $this);
|
@@ -164,7 +154,7 @@ class Term extends Core implements CoreInterface {
|
|
164 |
global $wpdb;
|
165 |
$query = $wpdb->prepare("SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d LIMIT 1", $tid);
|
166 |
$tax = $wpdb->get_var($query);
|
167 |
-
if (
|
168 |
$this->taxonomy = $tax;
|
169 |
return get_term($tid, $tax);
|
170 |
}
|
@@ -216,7 +206,7 @@ class Term extends Core implements CoreInterface {
|
|
216 |
* @return string
|
217 |
*/
|
218 |
public function get_meta_field( $field_name ) {
|
219 |
-
if (
|
220 |
$field_value = '';
|
221 |
$field_value = apply_filters('timber_term_get_meta_field', $field_value, $this->ID, $field_name, $this);
|
222 |
$field_value = apply_filters('timber/term/meta/field', $field_value, $this->ID, $field_name, $this);
|
@@ -227,20 +217,23 @@ class Term extends Core implements CoreInterface {
|
|
227 |
|
228 |
/**
|
229 |
* @internal
|
230 |
-
* @deprecated since 1.0
|
231 |
* @return string
|
232 |
*/
|
233 |
public function get_path() {
|
234 |
-
|
|
|
|
|
|
|
235 |
}
|
236 |
|
237 |
/**
|
238 |
* @internal
|
239 |
-
* @deprecated since 1.0
|
240 |
* @return string
|
241 |
*/
|
242 |
public function get_link() {
|
243 |
-
|
|
|
|
|
244 |
}
|
245 |
|
246 |
/**
|
@@ -252,7 +245,7 @@ class Term extends Core implements CoreInterface {
|
|
252 |
* @return array|bool|null
|
253 |
*/
|
254 |
public function get_posts( $numberposts = 10, $post_type = 'any', $PostClass = '' ) {
|
255 |
-
if (
|
256 |
$PostClass = $this->PostClass;
|
257 |
}
|
258 |
$default_tax_query = array(array(
|
@@ -266,10 +259,10 @@ class Term extends Core implements CoreInterface {
|
|
266 |
parse_str($args, $new_args);
|
267 |
$args = $new_args;
|
268 |
$args['tax_query'] = $default_tax_query;
|
269 |
-
if (
|
270 |
$args['post_type'] = 'any';
|
271 |
}
|
272 |
-
if (
|
273 |
$PostClass = $post_type;
|
274 |
}
|
275 |
} else if ( is_array($numberposts) ) {
|
@@ -301,8 +294,8 @@ class Term extends Core implements CoreInterface {
|
|
301 |
public function get_children() {
|
302 |
if ( !isset($this->_children) ) {
|
303 |
$children = get_term_children($this->ID, $this->taxonomy);
|
304 |
-
foreach (
|
305 |
-
$child = new
|
306 |
}
|
307 |
$this->_children = $children;
|
308 |
}
|
@@ -316,7 +309,7 @@ class Term extends Core implements CoreInterface {
|
|
316 |
* @param mixed $value
|
317 |
*/
|
318 |
function update( $key, $value ) {
|
319 |
-
$value = apply_filters('timber_term_set_meta', $value, $key, $this->ID, $this);
|
320 |
$this->$key = $value;
|
321 |
}
|
322 |
|
@@ -338,11 +331,11 @@ class Term extends Core implements CoreInterface {
|
|
338 |
public function description() {
|
339 |
$prefix = '<p>';
|
340 |
$suffix = '</p>';
|
341 |
-
$desc = term_description($this->ID, $this->taxonomy);
|
342 |
-
if (
|
343 |
$desc = substr($desc, strlen($prefix));
|
344 |
}
|
345 |
-
$desc = preg_replace('/'.preg_quote('</p>', '/').'$/', '', $desc);
|
346 |
return trim($desc);
|
347 |
}
|
348 |
|
@@ -354,15 +347,21 @@ class Term extends Core implements CoreInterface {
|
|
354 |
return $this->get_edit_url();
|
355 |
}
|
356 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
|
358 |
/**
|
359 |
* @api
|
360 |
* @return string
|
361 |
*/
|
362 |
public function link() {
|
363 |
-
|
364 |
-
$link = apply_filters('timber_term_link', $link, $this);
|
365 |
-
return apply_filters('timber/term/link', $link, $this);
|
366 |
}
|
367 |
|
368 |
/**
|
@@ -379,10 +378,7 @@ class Term extends Core implements CoreInterface {
|
|
379 |
* @return string
|
380 |
*/
|
381 |
public function path() {
|
382 |
-
|
383 |
-
$rel = URLHelper::get_rel_url($link, true);
|
384 |
-
$rel = apply_filters('timber_term_path', $rel, $this);
|
385 |
-
return apply_filters('timber/term/path', $rel, $this);
|
386 |
}
|
387 |
|
388 |
/**
|
@@ -412,4 +408,22 @@ class Term extends Core implements CoreInterface {
|
|
412 |
public function title() {
|
413 |
return $this->name;
|
414 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
415 |
}
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Terms: WordPress has got 'em, you want 'em. Categories. Tags. Custom Taxonomies. You don't care, you're a fiend. Well let's get this under control
|
4 |
* @example
|
30 |
* </ul>
|
31 |
* ```
|
32 |
*/
|
33 |
+
class TimberTerm extends TimberCore implements TimberCoreInterface {
|
34 |
|
35 |
+
public $PostClass = 'TimberPost';
|
36 |
+
public $TermClass = 'TimberTerm';
|
37 |
|
38 |
public $object_type = 'term';
|
39 |
public static $representation = 'term';
|
55 |
* @param string $tax
|
56 |
*/
|
57 |
public function __construct( $tid = null, $tax = '' ) {
|
58 |
+
if ($tid === null) {
|
59 |
$tid = $this->get_term_from_query();
|
60 |
}
|
61 |
+
if (strlen($tax)) {
|
62 |
$this->taxonomy = $tax;
|
63 |
}
|
64 |
$this->init($tid);
|
93 |
global $wp_query;
|
94 |
if ( isset($wp_query->queried_object) ) {
|
95 |
$qo = $wp_query->queried_object;
|
96 |
+
if (isset($qo->term_id)) {
|
97 |
return $qo->term_id;
|
98 |
}
|
99 |
}
|
114 |
$term->ID = $term->term_id;
|
115 |
} else if ( is_string($tid) ) {
|
116 |
//echo 'bad call using '.$tid;
|
117 |
+
//TimberHelper::error_log(debug_backtrace());
|
118 |
}
|
119 |
+
if ( isset($term->ID) ){
|
120 |
$term->id = $term->ID;
|
121 |
$this->import($term);
|
122 |
if ( isset($term->term_id) ) {
|
131 |
* @param int $tid
|
132 |
* @return array
|
133 |
*/
|
134 |
+
protected function get_term_meta($tid) {
|
135 |
$customs = array();
|
136 |
$customs = apply_filters('timber_term_get_meta', $customs, $tid, $this);
|
137 |
return apply_filters('timber/term/meta', $customs, $tid, $this);
|
154 |
global $wpdb;
|
155 |
$query = $wpdb->prepare("SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d LIMIT 1", $tid);
|
156 |
$tax = $wpdb->get_var($query);
|
157 |
+
if (isset($tax) && strlen($tax)) {
|
158 |
$this->taxonomy = $tax;
|
159 |
return get_term($tid, $tax);
|
160 |
}
|
206 |
* @return string
|
207 |
*/
|
208 |
public function get_meta_field( $field_name ) {
|
209 |
+
if (!isset($this->$field_name)) {
|
210 |
$field_value = '';
|
211 |
$field_value = apply_filters('timber_term_get_meta_field', $field_value, $this->ID, $field_name, $this);
|
212 |
$field_value = apply_filters('timber/term/meta/field', $field_value, $this->ID, $field_name, $this);
|
217 |
|
218 |
/**
|
219 |
* @internal
|
|
|
220 |
* @return string
|
221 |
*/
|
222 |
public function get_path() {
|
223 |
+
$link = $this->get_link();
|
224 |
+
$rel = TimberURLHelper::get_rel_url($link, true);
|
225 |
+
$rel = apply_filters('timber_term_path', $rel, $this);
|
226 |
+
return apply_filters('timber/term/path', $rel, $this);
|
227 |
}
|
228 |
|
229 |
/**
|
230 |
* @internal
|
|
|
231 |
* @return string
|
232 |
*/
|
233 |
public function get_link() {
|
234 |
+
$link = get_term_link($this);
|
235 |
+
$link = apply_filters('timber_term_link', $link, $this);
|
236 |
+
return apply_filters('timber/term/link', $link, $this);
|
237 |
}
|
238 |
|
239 |
/**
|
245 |
* @return array|bool|null
|
246 |
*/
|
247 |
public function get_posts( $numberposts = 10, $post_type = 'any', $PostClass = '' ) {
|
248 |
+
if (!strlen($PostClass)) {
|
249 |
$PostClass = $this->PostClass;
|
250 |
}
|
251 |
$default_tax_query = array(array(
|
259 |
parse_str($args, $new_args);
|
260 |
$args = $new_args;
|
261 |
$args['tax_query'] = $default_tax_query;
|
262 |
+
if (!isset($args['post_type'])) {
|
263 |
$args['post_type'] = 'any';
|
264 |
}
|
265 |
+
if (class_exists($post_type)) {
|
266 |
$PostClass = $post_type;
|
267 |
}
|
268 |
} else if ( is_array($numberposts) ) {
|
294 |
public function get_children() {
|
295 |
if ( !isset($this->_children) ) {
|
296 |
$children = get_term_children($this->ID, $this->taxonomy);
|
297 |
+
foreach ($children as &$child) {
|
298 |
+
$child = new TimberTerm($child);
|
299 |
}
|
300 |
$this->_children = $children;
|
301 |
}
|
309 |
* @param mixed $value
|
310 |
*/
|
311 |
function update( $key, $value ) {
|
312 |
+
$value = apply_filters( 'timber_term_set_meta', $value, $key, $this->ID, $this );
|
313 |
$this->$key = $value;
|
314 |
}
|
315 |
|
331 |
public function description() {
|
332 |
$prefix = '<p>';
|
333 |
$suffix = '</p>';
|
334 |
+
$desc = term_description( $this->ID, $this->taxonomy );
|
335 |
+
if (substr($desc, 0, strlen($prefix)) == $prefix) {
|
336 |
$desc = substr($desc, strlen($prefix));
|
337 |
}
|
338 |
+
$desc = preg_replace('/'. preg_quote('</p>', '/') . '$/', '', $desc);
|
339 |
return trim($desc);
|
340 |
}
|
341 |
|
347 |
return $this->get_edit_url();
|
348 |
}
|
349 |
|
350 |
+
/**
|
351 |
+
* @internal
|
352 |
+
* @deprecated 0.21.8 use TimberTerm::link() instead
|
353 |
+
* @return string
|
354 |
+
*/
|
355 |
+
public function get_url() {
|
356 |
+
return $this->get_link();
|
357 |
+
}
|
358 |
|
359 |
/**
|
360 |
* @api
|
361 |
* @return string
|
362 |
*/
|
363 |
public function link() {
|
364 |
+
return $this->get_link();
|
|
|
|
|
365 |
}
|
366 |
|
367 |
/**
|
378 |
* @return string
|
379 |
*/
|
380 |
public function path() {
|
381 |
+
return $this->get_path();
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
/**
|
408 |
public function title() {
|
409 |
return $this->name;
|
410 |
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* @deprecated 0.21.9 use TimberTerm::link() instead
|
414 |
+
* @return string
|
415 |
+
*/
|
416 |
+
public function url() {
|
417 |
+
return $this->get_url();
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* @deprecated 0.20.0 this was a dumb idea
|
422 |
+
* @param int $i
|
423 |
+
* @return string
|
424 |
+
*/
|
425 |
+
function get_page( $i ) {
|
426 |
+
return $this->get_path() . '/page/' . $i;
|
427 |
+
}
|
428 |
+
|
429 |
}
|
lib/{Theme.php → timber-theme.php}
RENAMED
@@ -1,11 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\Theme;
|
7 |
-
use Timber\URLHelper;
|
8 |
-
|
9 |
/**
|
10 |
* 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:
|
11 |
* @example
|
@@ -23,7 +17,7 @@ use Timber\URLHelper;
|
|
23 |
* ```
|
24 |
* @package Timber
|
25 |
*/
|
26 |
-
class
|
27 |
|
28 |
/**
|
29 |
* @api
|
@@ -68,7 +62,7 @@ class Theme extends Core {
|
|
68 |
* We are currently using the My Theme theme.
|
69 |
* ```
|
70 |
*/
|
71 |
-
function __construct(
|
72 |
$this->init($slug);
|
73 |
}
|
74 |
|
@@ -76,14 +70,14 @@ class Theme extends Core {
|
|
76 |
* @internal
|
77 |
* @param string $slug
|
78 |
*/
|
79 |
-
protected function init(
|
80 |
$data = wp_get_theme($slug);
|
81 |
$this->name = $data->get('Name');
|
82 |
$ss = $data->get_stylesheet();
|
83 |
$this->slug = $ss;
|
84 |
|
85 |
-
if ( !function_exists('get_home_path') ) {
|
86 |
-
require_once(ABSPATH.'wp-admin/includes/file.php');
|
87 |
}
|
88 |
|
89 |
$this->uri = get_stylesheet_directory_uri();
|
@@ -92,7 +86,7 @@ class Theme extends Core {
|
|
92 |
$this->uri = get_template_directory_uri();
|
93 |
}
|
94 |
if ( $this->parent_slug && $this->parent_slug != $this->slug ) {
|
95 |
-
$this->parent = new
|
96 |
}
|
97 |
}
|
98 |
|
@@ -109,7 +103,7 @@ class Theme extends Core {
|
|
109 |
* @return string the relative path to the theme (ex: `/wp-content/themes/my-timber-theme`)
|
110 |
*/
|
111 |
public function path() {
|
112 |
-
return
|
113 |
}
|
114 |
|
115 |
/**
|
@@ -117,7 +111,7 @@ class Theme extends Core {
|
|
117 |
* @param bool $default
|
118 |
* @return string
|
119 |
*/
|
120 |
-
public function theme_mod(
|
121 |
return get_theme_mod($name, $default);
|
122 |
}
|
123 |
|
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
|
17 |
* ```
|
18 |
* @package Timber
|
19 |
*/
|
20 |
+
class TimberTheme extends TimberCore {
|
21 |
|
22 |
/**
|
23 |
* @api
|
62 |
* We are currently using the My Theme theme.
|
63 |
* ```
|
64 |
*/
|
65 |
+
function __construct($slug = null) {
|
66 |
$this->init($slug);
|
67 |
}
|
68 |
|
70 |
* @internal
|
71 |
* @param string $slug
|
72 |
*/
|
73 |
+
protected function init($slug = null) {
|
74 |
$data = wp_get_theme($slug);
|
75 |
$this->name = $data->get('Name');
|
76 |
$ss = $data->get_stylesheet();
|
77 |
$this->slug = $ss;
|
78 |
|
79 |
+
if ( ! function_exists( 'get_home_path' ) ) {
|
80 |
+
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
81 |
}
|
82 |
|
83 |
$this->uri = get_stylesheet_directory_uri();
|
86 |
$this->uri = get_template_directory_uri();
|
87 |
}
|
88 |
if ( $this->parent_slug && $this->parent_slug != $this->slug ) {
|
89 |
+
$this->parent = new TimberTheme($this->parent_slug);
|
90 |
}
|
91 |
}
|
92 |
|
103 |
* @return string the relative path to the theme (ex: `/wp-content/themes/my-timber-theme`)
|
104 |
*/
|
105 |
public function path() {
|
106 |
+
return TimberURLHelper::get_rel_url( $this->link() );
|
107 |
}
|
108 |
|
109 |
/**
|
111 |
* @param bool $default
|
112 |
* @return string
|
113 |
*/
|
114 |
+
public function theme_mod($name, $default = false) {
|
115 |
return get_theme_mod($name, $default);
|
116 |
}
|
117 |
|
lib/timber-twig.php
ADDED
@@ -0,0 +1,347 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class TimberTwig {
|
4 |
+
|
5 |
+
public static $dir_name;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @codeCoverageIgnore
|
9 |
+
*/
|
10 |
+
public static function init() {
|
11 |
+
new TimberTwig();
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @codeCoverageIgnore
|
16 |
+
*/
|
17 |
+
function __construct() {
|
18 |
+
add_action( 'timber/twig/filters', array( $this, 'add_timber_filters_deprecated' ) );
|
19 |
+
add_action( 'timber/twig/filters', array( $this, 'add_timber_filters' ) );
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* These are all deprecated and will be removed in 0.21.0
|
24 |
+
*
|
25 |
+
* @param Twig_Environment $twig
|
26 |
+
* @deprecated since 0.20.7
|
27 |
+
* @return Twig_Environment
|
28 |
+
*/
|
29 |
+
function add_timber_filters_deprecated( $twig ) {
|
30 |
+
$twig->addFilter( new Twig_SimpleFilter( 'get_src_from_attachment_id', 'twig_get_src_from_attachment_id' ) );
|
31 |
+
$twig->addFilter( new Twig_SimpleFilter( 'wp_body_class', array( $this, 'body_class' ) ) );
|
32 |
+
$twig->addFilter( new Twig_SimpleFilter( 'twitterify', array( 'TimberHelper', 'twitterify' ) ) );
|
33 |
+
$twig->addFilter( new Twig_SimpleFilter( 'twitterfy', array( 'TimberHelper', 'twitterify' ) ) );
|
34 |
+
$twig->addFilter( new Twig_SimpleFilter( 'string', function($arr, $glue = ' '){
|
35 |
+
return twig_join_filter($arr, $glue);
|
36 |
+
} ) );
|
37 |
+
return $twig;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
*
|
42 |
+
*
|
43 |
+
* @param Twig_Environment $twig
|
44 |
+
* @return Twig_Environment
|
45 |
+
*/
|
46 |
+
function add_timber_filters( $twig ) {
|
47 |
+
/* image filters */
|
48 |
+
$twig->addFilter( new Twig_SimpleFilter( 'resize', array( 'TimberImageHelper', 'resize' ) ) );
|
49 |
+
$twig->addFilter( new Twig_SimpleFilter( 'retina', array( 'TimberImageHelper', 'retina_resize' ) ) );
|
50 |
+
$twig->addFilter( new Twig_SimpleFilter( 'letterbox', array( 'TimberImageHelper', 'letterbox' ) ) );
|
51 |
+
$twig->addFilter( new Twig_SimpleFilter( 'tojpg', array( 'TimberImageHelper', 'img_to_jpg' ) ) );
|
52 |
+
|
53 |
+
/* debugging filters */
|
54 |
+
$twig->addFilter( new Twig_SimpleFilter( 'docs', 'twig_object_docs' ) );
|
55 |
+
$twig->addFilter( new Twig_SimpleFilter( 'get_class', 'get_class' ) );
|
56 |
+
$twig->addFilter( new Twig_SimpleFilter( 'get_type', 'get_type' ) );
|
57 |
+
$twig->addFilter( new Twig_SimpleFilter( 'print_r', function( $arr ) {
|
58 |
+
return print_r( $arr, true );
|
59 |
+
} ) );
|
60 |
+
$twig->addFilter( new Twig_SimpleFilter( 'print_a', function( $arr ) {
|
61 |
+
return '<pre>' . self::object_docs( $arr, true ) . '</pre>';
|
62 |
+
} ) );
|
63 |
+
|
64 |
+
/* other filters */
|
65 |
+
$twig->addFilter( new Twig_SimpleFilter( 'stripshortcodes', 'strip_shortcodes' ) );
|
66 |
+
$twig->addFilter( new Twig_SimpleFilter( 'array', array( $this, 'to_array' ) ) );
|
67 |
+
$twig->addFilter( new Twig_SimpleFilter( 'excerpt', 'wp_trim_words' ) );
|
68 |
+
$twig->addFilter( new Twig_SimpleFilter( 'function', array( $this, 'exec_function' ) ) );
|
69 |
+
$twig->addFilter( new Twig_SimpleFilter( 'pretags', array( $this, 'twig_pretags' ) ) );
|
70 |
+
$twig->addFilter( new Twig_SimpleFilter( 'sanitize', 'sanitize_title' ) );
|
71 |
+
$twig->addFilter( new Twig_SimpleFilter( 'shortcodes', 'do_shortcode' ) );
|
72 |
+
$twig->addFilter( new Twig_SimpleFilter( 'time_ago', array( $this, 'time_ago' ) ) );
|
73 |
+
$twig->addFilter( new Twig_SimpleFilter( 'wpautop', 'wpautop' ) );
|
74 |
+
$twig->addFilter( new Twig_SimpleFilter( 'list', array( $this, 'add_list_separators' ) ) );
|
75 |
+
|
76 |
+
$twig->addFilter( new Twig_SimpleFilter( 'relative', function ( $link ) {
|
77 |
+
return TimberURLHelper::get_rel_url( $link, true );
|
78 |
+
} ) );
|
79 |
+
|
80 |
+
$twig->addFilter( new Twig_SimpleFilter( 'date', array( $this, 'intl_date' ) ) );
|
81 |
+
|
82 |
+
$twig->addFilter( new Twig_SimpleFilter( 'truncate', function ( $text, $len ) {
|
83 |
+
return TimberHelper::trim_words( $text, $len );
|
84 |
+
} ) );
|
85 |
+
|
86 |
+
/* actions and filters */
|
87 |
+
$twig->addFunction( new Twig_SimpleFunction( 'action', function ( $context ) {
|
88 |
+
$args = func_get_args();
|
89 |
+
array_shift( $args );
|
90 |
+
$args[] = $context;
|
91 |
+
call_user_func_array( 'do_action', $args );
|
92 |
+
}, array( 'needs_context' => true ) ) );
|
93 |
+
|
94 |
+
$twig->addFilter( new Twig_SimpleFilter( 'apply_filters', function () {
|
95 |
+
$args = func_get_args();
|
96 |
+
$tag = current( array_splice( $args, 1, 1 ) );
|
97 |
+
|
98 |
+
return apply_filters_ref_array( $tag, $args );
|
99 |
+
} ) );
|
100 |
+
$twig->addFunction( new Twig_SimpleFunction( 'function', array( &$this, 'exec_function' ) ) );
|
101 |
+
$twig->addFunction( new Twig_SimpleFunction( 'fn', array( &$this, 'exec_function' ) ) );
|
102 |
+
|
103 |
+
$twig->addFunction( new Twig_SimpleFunction( 'shortcode', 'do_shortcode' ) );
|
104 |
+
|
105 |
+
/* TimberObjects */
|
106 |
+
$twig->addFunction( new Twig_SimpleFunction( 'TimberPost', function ( $pid, $PostClass = 'TimberPost' ) {
|
107 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
108 |
+
foreach ( $pid as &$p ) {
|
109 |
+
$p = new $PostClass( $p );
|
110 |
+
}
|
111 |
+
return $pid;
|
112 |
+
}
|
113 |
+
return new $PostClass( $pid );
|
114 |
+
} ) );
|
115 |
+
$twig->addFunction( new Twig_SimpleFunction( 'TimberImage', function ( $pid, $ImageClass = 'TimberImage' ) {
|
116 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
117 |
+
foreach ( $pid as &$p ) {
|
118 |
+
$p = new $ImageClass( $p );
|
119 |
+
}
|
120 |
+
return $pid;
|
121 |
+
}
|
122 |
+
return new $ImageClass( $pid );
|
123 |
+
} ) );
|
124 |
+
$twig->addFunction( new Twig_SimpleFunction( 'TimberTerm', function ( $pid, $TermClass = 'TimberTerm' ) {
|
125 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
126 |
+
foreach ( $pid as &$p ) {
|
127 |
+
$p = new $TermClass( $p );
|
128 |
+
}
|
129 |
+
return $pid;
|
130 |
+
}
|
131 |
+
return new $TermClass( $pid );
|
132 |
+
} ) );
|
133 |
+
$twig->addFunction( new Twig_SimpleFunction( 'TimberUser', function ( $pid, $UserClass = 'TimberUser' ) {
|
134 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
135 |
+
foreach ( $pid as &$p ) {
|
136 |
+
$p = new $UserClass( $p );
|
137 |
+
}
|
138 |
+
return $pid;
|
139 |
+
}
|
140 |
+
return new $UserClass( $pid );
|
141 |
+
} ) );
|
142 |
+
|
143 |
+
/* TimberObjects Alias */
|
144 |
+
$twig->addFunction( new Twig_SimpleFunction( 'Post', function ( $pid, $PostClass = 'TimberPost' ) {
|
145 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
146 |
+
foreach ( $pid as &$p ) {
|
147 |
+
$p = new $PostClass( $p );
|
148 |
+
}
|
149 |
+
return $pid;
|
150 |
+
}
|
151 |
+
return new $PostClass( $pid );
|
152 |
+
} ) );
|
153 |
+
$twig->addFunction( new Twig_SimpleFunction( 'Image', function ( $pid, $ImageClass = 'TimberImage' ) {
|
154 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
155 |
+
foreach ( $pid as &$p ) {
|
156 |
+
$p = new $ImageClass( $p );
|
157 |
+
}
|
158 |
+
return $pid;
|
159 |
+
}
|
160 |
+
return new $ImageClass( $pid );
|
161 |
+
} ) );
|
162 |
+
$twig->addFunction( new Twig_SimpleFunction( 'Term', function ( $pid, $TermClass = 'TimberTerm' ) {
|
163 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
164 |
+
foreach ( $pid as &$p ) {
|
165 |
+
$p = new $TermClass( $p );
|
166 |
+
}
|
167 |
+
return $pid;
|
168 |
+
}
|
169 |
+
return new $TermClass( $pid );
|
170 |
+
} ) );
|
171 |
+
$twig->addFunction( new Twig_SimpleFunction( 'User', function ( $pid, $UserClass = 'TimberUser' ) {
|
172 |
+
if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
|
173 |
+
foreach ( $pid as &$p ) {
|
174 |
+
$p = new $UserClass( $p );
|
175 |
+
}
|
176 |
+
return $pid;
|
177 |
+
}
|
178 |
+
return new $UserClass( $pid );
|
179 |
+
} ) );
|
180 |
+
|
181 |
+
/* bloginfo and translate */
|
182 |
+
$twig->addFunction( 'bloginfo', new Twig_SimpleFunction( 'bloginfo', function ( $show = '', $filter = 'raw' ) {
|
183 |
+
return get_bloginfo( $show, $filter );
|
184 |
+
} ) );
|
185 |
+
$twig->addFunction( '__', new Twig_SimpleFunction( '__', function ( $text, $domain = 'default' ) {
|
186 |
+
return __( $text, $domain );
|
187 |
+
} ) );
|
188 |
+
/* get_twig is deprecated, use timber/twig */
|
189 |
+
$twig = apply_filters( 'get_twig', $twig );
|
190 |
+
$twig = apply_filters( 'timber/twig', $twig );
|
191 |
+
return $twig;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
*
|
196 |
+
*
|
197 |
+
* @param mixed $arr
|
198 |
+
* @return array
|
199 |
+
*/
|
200 |
+
function to_array( $arr ) {
|
201 |
+
if ( is_array( $arr ) ) {
|
202 |
+
return $arr;
|
203 |
+
}
|
204 |
+
$arr = array( $arr );
|
205 |
+
return $arr;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
*
|
210 |
+
*
|
211 |
+
* @param string $function_name
|
212 |
+
* @return mixed
|
213 |
+
*/
|
214 |
+
function exec_function( $function_name ) {
|
215 |
+
$args = func_get_args();
|
216 |
+
array_shift( $args );
|
217 |
+
if ( is_string($function_name) ) {
|
218 |
+
$function_name = trim( $function_name );
|
219 |
+
}
|
220 |
+
return call_user_func_array( $function_name, ( $args ) );
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
*
|
225 |
+
*
|
226 |
+
* @param string $content
|
227 |
+
* @return string
|
228 |
+
*/
|
229 |
+
function twig_pretags( $content ) {
|
230 |
+
return preg_replace_callback( '|<pre.*>(.*)</pre|isU', array( &$this, 'convert_pre_entities' ), $content );
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
*
|
235 |
+
*
|
236 |
+
* @param array $matches
|
237 |
+
* @return string
|
238 |
+
*/
|
239 |
+
function convert_pre_entities( $matches ) {
|
240 |
+
return str_replace( $matches[1], htmlentities( $matches[1] ), $matches[0] );
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* @param mixed $body_classes
|
245 |
+
* @deprecated 0.20.7
|
246 |
+
* @return string
|
247 |
+
*/
|
248 |
+
function body_class( $body_classes ) {
|
249 |
+
ob_start();
|
250 |
+
if ( is_array( $body_classes ) ) {
|
251 |
+
$body_classes = explode( ' ', $body_classes );
|
252 |
+
}
|
253 |
+
body_class( $body_classes );
|
254 |
+
$return = ob_get_contents();
|
255 |
+
ob_end_clean();
|
256 |
+
return $return;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
*
|
261 |
+
*
|
262 |
+
* @param string $date
|
263 |
+
* @param string $format (optional)
|
264 |
+
* @return string
|
265 |
+
*/
|
266 |
+
function intl_date( $date, $format = null ) {
|
267 |
+
if ( $format === null ) {
|
268 |
+
$format = get_option( 'date_format' );
|
269 |
+
}
|
270 |
+
|
271 |
+
if ( $date instanceof DateTime ) {
|
272 |
+
$timestamp = $date->getTimestamp() + $date->getOffset();
|
273 |
+
} else if (is_numeric( $date ) && strtotime( $date ) === false ) {
|
274 |
+
$timestamp = intval( $date );
|
275 |
+
} else {
|
276 |
+
$timestamp = strtotime( $date );
|
277 |
+
}
|
278 |
+
|
279 |
+
return date_i18n( $format, $timestamp );
|
280 |
+
}
|
281 |
+
|
282 |
+
//debug
|
283 |
+
|
284 |
+
/**
|
285 |
+
*
|
286 |
+
*
|
287 |
+
* @param mixed $obj
|
288 |
+
* @param bool $methods
|
289 |
+
* @deprecated since 0.20.7
|
290 |
+
* @return string
|
291 |
+
*/
|
292 |
+
function object_docs( $obj, $methods = true ) {
|
293 |
+
$class = get_class( $obj );
|
294 |
+
$properties = (array)$obj;
|
295 |
+
if ( $methods ) {
|
296 |
+
/** @var array $methods */
|
297 |
+
$methods = $obj->get_method_values();
|
298 |
+
}
|
299 |
+
$rets = array_merge( $properties, $methods );
|
300 |
+
ksort( $rets );
|
301 |
+
$str = print_r( $rets, true );
|
302 |
+
$str = str_replace( 'Array', $class . ' Object', $str );
|
303 |
+
return $str;
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* @param int|string $from
|
308 |
+
* @param int|string $to
|
309 |
+
* @param string $format_past
|
310 |
+
* @param string $format_future
|
311 |
+
* @return string
|
312 |
+
*/
|
313 |
+
function time_ago( $from, $to = null, $format_past = '%s ago', $format_future = '%s from now' ) {
|
314 |
+
$to = $to === null ? time() : $to;
|
315 |
+
$to = is_int( $to ) ? $to : strtotime( $to );
|
316 |
+
$from = is_int( $from ) ? $from : strtotime( $from );
|
317 |
+
|
318 |
+
if ( $from < $to ) {
|
319 |
+
return sprintf( $format_past, human_time_diff( $from, $to ) );
|
320 |
+
} else {
|
321 |
+
return sprintf( $format_future, human_time_diff( $to, $from ) );
|
322 |
+
}
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* @param array $arr
|
327 |
+
* @param string $first_delimiter
|
328 |
+
* @param string $second_delimiter
|
329 |
+
* @return string
|
330 |
+
*/
|
331 |
+
function add_list_separators( $arr, $first_delimiter = ',', $second_delimiter = 'and' ) {
|
332 |
+
$length = count( $arr );
|
333 |
+
$list = '';
|
334 |
+
foreach( $arr as $index => $item ) {
|
335 |
+
if ( $index < $length - 2 ) {
|
336 |
+
$delimiter = $first_delimiter.' ';
|
337 |
+
} elseif ( $index == $length - 2 ) {
|
338 |
+
$delimiter = ' '.$second_delimiter.' ';
|
339 |
+
} else {
|
340 |
+
$delimiter = '';
|
341 |
+
}
|
342 |
+
$list = $list.$item.$delimiter;
|
343 |
+
}
|
344 |
+
return $list;
|
345 |
+
}
|
346 |
+
|
347 |
+
}
|
lib/{URLHelper.php → timber-url-helper.php}
RENAMED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
class URLHelper {
|
6 |
|
7 |
/**
|
8 |
*
|
@@ -11,13 +9,13 @@ class URLHelper {
|
|
11 |
*/
|
12 |
public static function get_current_url() {
|
13 |
$pageURL = "http://";
|
14 |
-
if ( isset($_SERVER['HTTPS']) && $_SERVER["HTTPS"] == "on" ) {
|
15 |
-
$pageURL = "https://"
|
16 |
}
|
17 |
if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
|
18 |
-
$pageURL .= self::get_host().":"
|
19 |
} else {
|
20 |
-
$pageURL .= self::get_host()
|
21 |
}
|
22 |
return $pageURL;
|
23 |
}
|
@@ -29,11 +27,11 @@ class URLHelper {
|
|
29 |
* @return bool
|
30 |
*/
|
31 |
public static function is_url( $url ) {
|
32 |
-
if ( !is_string($url) ) {
|
33 |
return false;
|
34 |
}
|
35 |
-
$url = strtolower($url);
|
36 |
-
if ( strstr($url, '://') ) {
|
37 |
return true;
|
38 |
}
|
39 |
return false;
|
@@ -45,12 +43,12 @@ class URLHelper {
|
|
45 |
* @return string
|
46 |
*/
|
47 |
public static function get_path_base() {
|
48 |
-
$struc = get_option('permalink_structure');
|
49 |
-
$struc = explode('/', $struc);
|
50 |
$p = '/';
|
51 |
foreach ( $struc as $s ) {
|
52 |
-
if ( !strstr($s, '%') && strlen($s) ) {
|
53 |
-
$p .= $s.'/';
|
54 |
}
|
55 |
}
|
56 |
return $p;
|
@@ -64,21 +62,21 @@ class URLHelper {
|
|
64 |
* @return string
|
65 |
*/
|
66 |
public static function get_rel_url( $url, $force = false ) {
|
67 |
-
$url_info = parse_url($url);
|
68 |
-
if ( isset($url_info['host']) && $url_info['host'] != self::get_host() && !$force ) {
|
69 |
return $url;
|
70 |
}
|
71 |
$link = '';
|
72 |
-
if ( isset($url_info['path']) ) {
|
73 |
$link = $url_info['path'];
|
74 |
}
|
75 |
-
if ( isset($url_info['query']) && strlen($url_info['query']) ) {
|
76 |
-
$link .= '?'
|
77 |
}
|
78 |
-
if ( isset($url_info['fragment']) && strlen($url_info['fragment']) ) {
|
79 |
-
$link .= '#'
|
80 |
}
|
81 |
-
$link =
|
82 |
return $link;
|
83 |
}
|
84 |
|
@@ -88,10 +86,10 @@ class URLHelper {
|
|
88 |
* @return string the HTTP_HOST or SERVER_NAME
|
89 |
*/
|
90 |
public static function get_host() {
|
91 |
-
if (
|
92 |
return $_SERVER['HTTP_HOST'];
|
93 |
}
|
94 |
-
if (
|
95 |
return $_SERVER['SERVER_NAME'];
|
96 |
}
|
97 |
return '';
|
@@ -104,7 +102,7 @@ class URLHelper {
|
|
104 |
* @return bool
|
105 |
*/
|
106 |
public static function is_local( $url ) {
|
107 |
-
if ( strstr($url, self::get_host()) ) {
|
108 |
return true;
|
109 |
}
|
110 |
return false;
|
@@ -118,8 +116,8 @@ class URLHelper {
|
|
118 |
*/
|
119 |
public static function get_full_path( $src ) {
|
120 |
$root = ABSPATH;
|
121 |
-
$old_root_path = $root
|
122 |
-
$old_root_path = str_replace('//', '/', $old_root_path);
|
123 |
return $old_root_path;
|
124 |
}
|
125 |
|
@@ -132,15 +130,15 @@ class URLHelper {
|
|
132 |
* @return string
|
133 |
*/
|
134 |
public static function url_to_file_system( $url ) {
|
135 |
-
$url_parts = parse_url($url);
|
136 |
-
$path = ABSPATH
|
137 |
-
$path = str_replace('//', '/', $path);
|
138 |
return $path;
|
139 |
}
|
140 |
|
141 |
public static function file_system_to_url( $fs ) {
|
142 |
-
$relative_path = self::get_rel_path($fs);
|
143 |
-
$home = home_url('/'.$relative_path);
|
144 |
return $home;
|
145 |
}
|
146 |
|
@@ -151,12 +149,12 @@ class URLHelper {
|
|
151 |
* @return string
|
152 |
*/
|
153 |
public static function get_rel_path( $src ) {
|
154 |
-
if ( strstr($src, ABSPATH) ) {
|
155 |
-
return str_replace(ABSPATH, '', $src);
|
156 |
}
|
157 |
//its outside the wordpress directory, alternate setups:
|
158 |
-
$src = str_replace(WP_CONTENT_DIR, '', $src);
|
159 |
-
return WP_CONTENT_SUBDIR
|
160 |
}
|
161 |
|
162 |
/**
|
@@ -166,9 +164,9 @@ class URLHelper {
|
|
166 |
* @return string
|
167 |
*/
|
168 |
public static function remove_double_slashes( $url ) {
|
169 |
-
$url = str_replace('//', '/', $url);
|
170 |
-
if ( strstr($url, 'http:') && !strstr($url, 'http://') ) {
|
171 |
-
$url = str_replace('http:/', 'http://', $url);
|
172 |
}
|
173 |
return $url;
|
174 |
}
|
@@ -181,19 +179,19 @@ class URLHelper {
|
|
181 |
* @return string
|
182 |
*/
|
183 |
public static function prepend_to_url( $url, $path ) {
|
184 |
-
if ( strstr(strtolower($url), 'http') ) {
|
185 |
-
$url_parts = parse_url($url);
|
186 |
-
$url = $url_parts['scheme'].'://'
|
187 |
-
if ( isset($url_parts['query']) ) {
|
188 |
$url .= $url_parts['query'];
|
189 |
}
|
190 |
-
if ( isset($url_parts['fragment']) ) {
|
191 |
$url .= $url_parts['fragment'];
|
192 |
}
|
193 |
} else {
|
194 |
-
$url = $url
|
195 |
}
|
196 |
-
return self::remove_double_slashes($url);
|
197 |
}
|
198 |
|
199 |
/**
|
@@ -203,8 +201,8 @@ class URLHelper {
|
|
203 |
* @return string
|
204 |
*/
|
205 |
public static function preslashit( $path ) {
|
206 |
-
if ( strpos($path, '/') != 0 ) {
|
207 |
-
$path = '/'
|
208 |
}
|
209 |
return $path;
|
210 |
}
|
@@ -215,7 +213,7 @@ class URLHelper {
|
|
215 |
* @return boolean true if $path is an absolute url, false if relative.
|
216 |
*/
|
217 |
public static function is_absolute( $path ) {
|
218 |
-
return (boolean) (strstr($path, 'http'));
|
219 |
}
|
220 |
|
221 |
/**
|
@@ -227,21 +225,21 @@ class URLHelper {
|
|
227 |
* @return boolean if $url points to an external location returns true
|
228 |
*/
|
229 |
public static function is_external_content( $url ) {
|
230 |
-
$is_external =
|
231 |
|
232 |
return $is_external;
|
233 |
}
|
234 |
|
235 |
-
private static function is_internal_content(
|
236 |
// using content_url() instead of site_url or home_url is IMPORTANT
|
237 |
// otherwise you run into errors with sites that:
|
238 |
// 1. use WPML plugin
|
239 |
// 2. or redefine content directory
|
240 |
-
$is_content_url = strstr($url, content_url());
|
241 |
|
242 |
// this case covers when the upload directory has been redefined
|
243 |
$upload_dir = wp_upload_dir();
|
244 |
-
$is_upload_url = strstr($url, $upload_dir['baseurl']);
|
245 |
|
246 |
return $is_content_url || $is_upload_url;
|
247 |
}
|
@@ -254,8 +252,8 @@ class URLHelper {
|
|
254 |
* true if it's a subdomain (http://cdn.example.org = true)
|
255 |
*/
|
256 |
public static function is_external( $url ) {
|
257 |
-
$has_http = strstr(strtolower($url), 'http');
|
258 |
-
$on_domain = strstr($url, self::get_host());
|
259 |
if ( $has_http && !$on_domain ) {
|
260 |
return true;
|
261 |
}
|
@@ -270,10 +268,41 @@ class URLHelper {
|
|
270 |
*/
|
271 |
public static function remove_trailing_slash( $link ) {
|
272 |
if ( $link != "/" )
|
273 |
-
$link = untrailingslashit($link);
|
274 |
return $link;
|
275 |
}
|
276 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
/**
|
278 |
* Returns the url parameters, for example for url http://example.org/blog/post/news/2014/whatever
|
279 |
* this will return array('blog', 'post', 'news', '2014', 'whatever');
|
@@ -283,10 +312,10 @@ class URLHelper {
|
|
283 |
* @return array|string
|
284 |
*/
|
285 |
public static function get_params( $i = false ) {
|
286 |
-
$args = explode('/', trim(strtolower($_SERVER['REQUEST_URI'])));
|
287 |
$newargs = array();
|
288 |
foreach ( $args as $arg ) {
|
289 |
-
if ( strlen($arg) ) {
|
290 |
$newargs[] = $arg;
|
291 |
}
|
292 |
}
|
@@ -295,9 +324,9 @@ class URLHelper {
|
|
295 |
}
|
296 |
if ( $i < 0 ) {
|
297 |
//count from end
|
298 |
-
$i = count($newargs) + $i;
|
299 |
}
|
300 |
-
if ( isset($newargs[$i]) ) {
|
301 |
return $newargs[$i];
|
302 |
}
|
303 |
}
|
1 |
<?php
|
2 |
|
3 |
+
class TimberURLHelper {
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
*
|
9 |
*/
|
10 |
public static function get_current_url() {
|
11 |
$pageURL = "http://";
|
12 |
+
if ( isset( $_SERVER['HTTPS'] ) && $_SERVER["HTTPS"] == "on" ) {
|
13 |
+
$pageURL = "https://";;
|
14 |
}
|
15 |
if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
|
16 |
+
$pageURL .= self::get_host() . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
|
17 |
} else {
|
18 |
+
$pageURL .= self::get_host() . $_SERVER["REQUEST_URI"];
|
19 |
}
|
20 |
return $pageURL;
|
21 |
}
|
27 |
* @return bool
|
28 |
*/
|
29 |
public static function is_url( $url ) {
|
30 |
+
if ( !is_string( $url ) ) {
|
31 |
return false;
|
32 |
}
|
33 |
+
$url = strtolower( $url );
|
34 |
+
if ( strstr( $url, '://' ) ) {
|
35 |
return true;
|
36 |
}
|
37 |
return false;
|
43 |
* @return string
|
44 |
*/
|
45 |
public static function get_path_base() {
|
46 |
+
$struc = get_option( 'permalink_structure' );
|
47 |
+
$struc = explode( '/', $struc );
|
48 |
$p = '/';
|
49 |
foreach ( $struc as $s ) {
|
50 |
+
if ( !strstr( $s, '%' ) && strlen( $s ) ) {
|
51 |
+
$p .= $s . '/';
|
52 |
}
|
53 |
}
|
54 |
return $p;
|
62 |
* @return string
|
63 |
*/
|
64 |
public static function get_rel_url( $url, $force = false ) {
|
65 |
+
$url_info = parse_url( $url );
|
66 |
+
if ( isset( $url_info['host'] ) && $url_info['host'] != self::get_host() && !$force ) {
|
67 |
return $url;
|
68 |
}
|
69 |
$link = '';
|
70 |
+
if ( isset( $url_info['path'] ) ) {
|
71 |
$link = $url_info['path'];
|
72 |
}
|
73 |
+
if ( isset( $url_info['query'] ) && strlen( $url_info['query'] ) ) {
|
74 |
+
$link .= '?' . $url_info['query'];
|
75 |
}
|
76 |
+
if ( isset( $url_info['fragment'] ) && strlen( $url_info['fragment'] ) ) {
|
77 |
+
$link .= '#' . $url_info['fragment'];
|
78 |
}
|
79 |
+
$link = TimberURLHelper::remove_double_slashes( $link );
|
80 |
return $link;
|
81 |
}
|
82 |
|
86 |
* @return string the HTTP_HOST or SERVER_NAME
|
87 |
*/
|
88 |
public static function get_host() {
|
89 |
+
if (isset($_SERVER['HTTP_HOST'])) {
|
90 |
return $_SERVER['HTTP_HOST'];
|
91 |
}
|
92 |
+
if (isset($_SERVER['SERVER_NAME'])) {
|
93 |
return $_SERVER['SERVER_NAME'];
|
94 |
}
|
95 |
return '';
|
102 |
* @return bool
|
103 |
*/
|
104 |
public static function is_local( $url ) {
|
105 |
+
if ( strstr( $url, self::get_host() ) ) {
|
106 |
return true;
|
107 |
}
|
108 |
return false;
|
116 |
*/
|
117 |
public static function get_full_path( $src ) {
|
118 |
$root = ABSPATH;
|
119 |
+
$old_root_path = $root . $src;
|
120 |
+
$old_root_path = str_replace( '//', '/', $old_root_path );
|
121 |
return $old_root_path;
|
122 |
}
|
123 |
|
130 |
* @return string
|
131 |
*/
|
132 |
public static function url_to_file_system( $url ) {
|
133 |
+
$url_parts = parse_url( $url );
|
134 |
+
$path = ABSPATH . $url_parts['path'];
|
135 |
+
$path = str_replace( '//', '/', $path );
|
136 |
return $path;
|
137 |
}
|
138 |
|
139 |
public static function file_system_to_url( $fs ) {
|
140 |
+
$relative_path = self::get_rel_path( $fs );
|
141 |
+
$home = home_url( '/'.$relative_path );
|
142 |
return $home;
|
143 |
}
|
144 |
|
149 |
* @return string
|
150 |
*/
|
151 |
public static function get_rel_path( $src ) {
|
152 |
+
if ( strstr( $src, ABSPATH ) ) {
|
153 |
+
return str_replace( ABSPATH, '', $src );
|
154 |
}
|
155 |
//its outside the wordpress directory, alternate setups:
|
156 |
+
$src = str_replace( WP_CONTENT_DIR, '', $src );
|
157 |
+
return WP_CONTENT_SUBDIR . $src;
|
158 |
}
|
159 |
|
160 |
/**
|
164 |
* @return string
|
165 |
*/
|
166 |
public static function remove_double_slashes( $url ) {
|
167 |
+
$url = str_replace( '//', '/', $url );
|
168 |
+
if ( strstr( $url, 'http:' ) && !strstr( $url, 'http://' ) ) {
|
169 |
+
$url = str_replace( 'http:/', 'http://', $url );
|
170 |
}
|
171 |
return $url;
|
172 |
}
|
179 |
* @return string
|
180 |
*/
|
181 |
public static function prepend_to_url( $url, $path ) {
|
182 |
+
if ( strstr( strtolower( $url ), 'http' ) ) {
|
183 |
+
$url_parts = parse_url( $url );
|
184 |
+
$url = $url_parts['scheme'] . '://' . $url_parts['host'] . $path . $url_parts['path'];
|
185 |
+
if ( isset( $url_parts['query'] ) ) {
|
186 |
$url .= $url_parts['query'];
|
187 |
}
|
188 |
+
if ( isset( $url_parts['fragment'] ) ) {
|
189 |
$url .= $url_parts['fragment'];
|
190 |
}
|
191 |
} else {
|
192 |
+
$url = $url . $path;
|
193 |
}
|
194 |
+
return self::remove_double_slashes( $url );
|
195 |
}
|
196 |
|
197 |
/**
|
201 |
* @return string
|
202 |
*/
|
203 |
public static function preslashit( $path ) {
|
204 |
+
if ( strpos( $path, '/' ) != 0 ) {
|
205 |
+
$path = '/' . $path;
|
206 |
}
|
207 |
return $path;
|
208 |
}
|
213 |
* @return boolean true if $path is an absolute url, false if relative.
|
214 |
*/
|
215 |
public static function is_absolute( $path ) {
|
216 |
+
return (boolean) ( strstr( $path, 'http' ) );
|
217 |
}
|
218 |
|
219 |
/**
|
225 |
* @return boolean if $url points to an external location returns true
|
226 |
*/
|
227 |
public static function is_external_content( $url ) {
|
228 |
+
$is_external = TimberURLHelper::is_absolute( $url ) && ! TimberURLHelper::is_internal_content( $url );
|
229 |
|
230 |
return $is_external;
|
231 |
}
|
232 |
|
233 |
+
private static function is_internal_content($url) {
|
234 |
// using content_url() instead of site_url or home_url is IMPORTANT
|
235 |
// otherwise you run into errors with sites that:
|
236 |
// 1. use WPML plugin
|
237 |
// 2. or redefine content directory
|
238 |
+
$is_content_url = strstr( $url, content_url() );
|
239 |
|
240 |
// this case covers when the upload directory has been redefined
|
241 |
$upload_dir = wp_upload_dir();
|
242 |
+
$is_upload_url = strstr( $url, $upload_dir['baseurl'] );
|
243 |
|
244 |
return $is_content_url || $is_upload_url;
|
245 |
}
|
252 |
* true if it's a subdomain (http://cdn.example.org = true)
|
253 |
*/
|
254 |
public static function is_external( $url ) {
|
255 |
+
$has_http = strstr( strtolower( $url ), 'http' );
|
256 |
+
$on_domain = strstr( $url, self::get_host() );
|
257 |
if ( $has_http && !$on_domain ) {
|
258 |
return true;
|
259 |
}
|
268 |
*/
|
269 |
public static function remove_trailing_slash( $link ) {
|
270 |
if ( $link != "/" )
|
271 |
+
$link = untrailingslashit( $link );
|
272 |
return $link;
|
273 |
}
|
274 |
|
275 |
+
/**
|
276 |
+
* Download an external file via a URL
|
277 |
+
*
|
278 |
+
* @param string $url
|
279 |
+
* @param int $timeout
|
280 |
+
* @return string|WP_Error the location of the temporay file name or an error
|
281 |
+
* @deprecated since 0.20.0
|
282 |
+
*/
|
283 |
+
static function download_url( $url, $timeout = 300 ) {
|
284 |
+
if ( !$url ) {
|
285 |
+
return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) );
|
286 |
+
}
|
287 |
+
|
288 |
+
$tmpfname = wp_tempnam( $url );
|
289 |
+
if ( !$tmpfname ) {
|
290 |
+
return new WP_Error( 'http_no_file', __( 'Could not create Temporary file.' ) );
|
291 |
+
}
|
292 |
+
|
293 |
+
$response = wp_remote_get( $url, array( 'timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname ) );
|
294 |
+
|
295 |
+
if ( is_wp_error( $response ) ) {
|
296 |
+
unlink( $tmpfname );
|
297 |
+
return $response;
|
298 |
+
}
|
299 |
+
if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
|
300 |
+
unlink( $tmpfname );
|
301 |
+
return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) );
|
302 |
+
}
|
303 |
+
return $tmpfname;
|
304 |
+
}
|
305 |
+
|
306 |
/**
|
307 |
* Returns the url parameters, for example for url http://example.org/blog/post/news/2014/whatever
|
308 |
* this will return array('blog', 'post', 'news', '2014', 'whatever');
|
312 |
* @return array|string
|
313 |
*/
|
314 |
public static function get_params( $i = false ) {
|
315 |
+
$args = explode( '/', trim( strtolower( $_SERVER['REQUEST_URI'] ) ) );
|
316 |
$newargs = array();
|
317 |
foreach ( $args as $arg ) {
|
318 |
+
if ( strlen( $arg ) ) {
|
319 |
$newargs[] = $arg;
|
320 |
}
|
321 |
}
|
324 |
}
|
325 |
if ( $i < 0 ) {
|
326 |
//count from end
|
327 |
+
$i = count( $newargs ) + $i;
|
328 |
}
|
329 |
+
if ( isset( $newargs[$i] ) ) {
|
330 |
return $newargs[$i];
|
331 |
}
|
332 |
}
|
lib/{User.php → timber-user.php}
RENAMED
@@ -1,14 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Core;
|
6 |
-
use Timber\CoreInterface;
|
7 |
-
|
8 |
-
use Timber\URLHelper;
|
9 |
-
|
10 |
-
use Timber\Image;
|
11 |
-
|
12 |
/**
|
13 |
* This is used in Timber to represent users retrived from WordPress. You can call `$my_user = new TimberUser(123);` directly, or access it through the `{{ post.author }}` method.
|
14 |
* @example
|
@@ -26,7 +17,7 @@ use Timber\Image;
|
|
26 |
* <p class="article-info">This article is called "Consider the Lobster" and it's by David Foster Wallace
|
27 |
* ```
|
28 |
*/
|
29 |
-
class
|
30 |
|
31 |
public $object_type = 'user';
|
32 |
public static $representation = 'user';
|
@@ -40,12 +31,6 @@ class User extends Core implements CoreInterface {
|
|
40 |
public $description;
|
41 |
public $display_name;
|
42 |
|
43 |
-
/**
|
44 |
-
* @api
|
45 |
-
* @var string|Image The URL of the author's avatar
|
46 |
-
*/
|
47 |
-
public $avatar;
|
48 |
-
|
49 |
/**
|
50 |
* @api
|
51 |
* @var string The first name of the user
|
@@ -68,7 +53,7 @@ class User extends Core implements CoreInterface {
|
|
68 |
/**
|
69 |
* @param int|bool $uid
|
70 |
*/
|
71 |
-
function __construct(
|
72 |
$this->init($uid);
|
73 |
}
|
74 |
|
@@ -99,7 +84,7 @@ class User extends Core implements CoreInterface {
|
|
99 |
* @param string $field_name
|
100 |
* @return null
|
101 |
*/
|
102 |
-
function get_meta(
|
103 |
return $this->get_meta_field($field_name);
|
104 |
}
|
105 |
|
@@ -108,7 +93,7 @@ class User extends Core implements CoreInterface {
|
|
108 |
* @param string $field
|
109 |
* @param mixed $value
|
110 |
*/
|
111 |
-
function __set(
|
112 |
if ( $field == 'name' ) {
|
113 |
$this->display_name = $value;
|
114 |
}
|
@@ -119,7 +104,7 @@ class User extends Core implements CoreInterface {
|
|
119 |
* @internal
|
120 |
* @param int|bool $uid The user ID to use
|
121 |
*/
|
122 |
-
protected function init(
|
123 |
if ( $uid === false ) {
|
124 |
$uid = get_current_user_id();
|
125 |
}
|
@@ -144,7 +129,6 @@ class User extends Core implements CoreInterface {
|
|
144 |
}
|
145 |
$this->id = $this->ID;
|
146 |
$this->name = $this->name();
|
147 |
-
$this->avatar = new Image(get_avatar_url($this->id));
|
148 |
$custom = $this->get_custom();
|
149 |
$this->import($custom);
|
150 |
}
|
@@ -153,7 +137,7 @@ class User extends Core implements CoreInterface {
|
|
153 |
* @param string $field_name
|
154 |
* @return mixed
|
155 |
*/
|
156 |
-
function get_meta_field(
|
157 |
$value = null;
|
158 |
$value = apply_filters('timber_user_get_meta_field_pre', $value, $this->ID, $field_name, $this);
|
159 |
if ( $value === null ) {
|
@@ -174,7 +158,7 @@ class User extends Core implements CoreInterface {
|
|
174 |
$um = get_user_meta($this->ID);
|
175 |
}
|
176 |
$custom = array();
|
177 |
-
foreach (
|
178 |
if ( is_array($value) && count($value) == 1 ) {
|
179 |
$value = $value[0];
|
180 |
}
|
@@ -209,7 +193,7 @@ class User extends Core implements CoreInterface {
|
|
209 |
* @param string $field_name
|
210 |
* @return mixed
|
211 |
*/
|
212 |
-
function meta(
|
213 |
return $this->get_meta_field($field_name);
|
214 |
}
|
215 |
|
@@ -218,7 +202,7 @@ class User extends Core implements CoreInterface {
|
|
218 |
* @return string ex: /author/lincoln
|
219 |
*/
|
220 |
public function path() {
|
221 |
-
return
|
222 |
}
|
223 |
|
224 |
/**
|
@@ -228,4 +212,37 @@ class User extends Core implements CoreInterface {
|
|
228 |
public function slug() {
|
229 |
return $this->user_nicename;
|
230 |
}
|
231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* This is used in Timber to represent users retrived from WordPress. You can call `$my_user = new TimberUser(123);` directly, or access it through the `{{ post.author }}` method.
|
5 |
* @example
|
17 |
* <p class="article-info">This article is called "Consider the Lobster" and it's by David Foster Wallace
|
18 |
* ```
|
19 |
*/
|
20 |
+
class TimberUser extends TimberCore implements TimberCoreInterface {
|
21 |
|
22 |
public $object_type = 'user';
|
23 |
public static $representation = 'user';
|
31 |
public $description;
|
32 |
public $display_name;
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* @api
|
36 |
* @var string The first name of the user
|
53 |
/**
|
54 |
* @param int|bool $uid
|
55 |
*/
|
56 |
+
function __construct($uid = false) {
|
57 |
$this->init($uid);
|
58 |
}
|
59 |
|
84 |
* @param string $field_name
|
85 |
* @return null
|
86 |
*/
|
87 |
+
function get_meta($field_name) {
|
88 |
return $this->get_meta_field($field_name);
|
89 |
}
|
90 |
|
93 |
* @param string $field
|
94 |
* @param mixed $value
|
95 |
*/
|
96 |
+
function __set($field, $value) {
|
97 |
if ( $field == 'name' ) {
|
98 |
$this->display_name = $value;
|
99 |
}
|
104 |
* @internal
|
105 |
* @param int|bool $uid The user ID to use
|
106 |
*/
|
107 |
+
protected function init($uid = false) {
|
108 |
if ( $uid === false ) {
|
109 |
$uid = get_current_user_id();
|
110 |
}
|
129 |
}
|
130 |
$this->id = $this->ID;
|
131 |
$this->name = $this->name();
|
|
|
132 |
$custom = $this->get_custom();
|
133 |
$this->import($custom);
|
134 |
}
|
137 |
* @param string $field_name
|
138 |
* @return mixed
|
139 |
*/
|
140 |
+
function get_meta_field($field_name) {
|
141 |
$value = null;
|
142 |
$value = apply_filters('timber_user_get_meta_field_pre', $value, $this->ID, $field_name, $this);
|
143 |
if ( $value === null ) {
|
158 |
$um = get_user_meta($this->ID);
|
159 |
}
|
160 |
$custom = array();
|
161 |
+
foreach ($um as $key => $value) {
|
162 |
if ( is_array($value) && count($value) == 1 ) {
|
163 |
$value = $value[0];
|
164 |
}
|
193 |
* @param string $field_name
|
194 |
* @return mixed
|
195 |
*/
|
196 |
+
function meta($field_name) {
|
197 |
return $this->get_meta_field($field_name);
|
198 |
}
|
199 |
|
202 |
* @return string ex: /author/lincoln
|
203 |
*/
|
204 |
public function path() {
|
205 |
+
return TimberURLHelper::get_rel_url($this->get_link());
|
206 |
}
|
207 |
|
208 |
/**
|
212 |
public function slug() {
|
213 |
return $this->user_nicename;
|
214 |
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* @deprecated 0.21.9
|
218 |
+
* @return string The link to a user's profile page
|
219 |
+
*/
|
220 |
+
function get_link() {
|
221 |
+
return $this->link();
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* @deprecated 0.21.8
|
226 |
+
* @return string ex: /author/lincoln
|
227 |
+
*/
|
228 |
+
function get_path() {
|
229 |
+
return $this->path();
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* @deprecated 0.21.8
|
234 |
+
* @return string
|
235 |
+
*/
|
236 |
+
function get_permalink() {
|
237 |
+
return $this->get_link();
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* @deprecated 0.21.8
|
242 |
+
* @return string
|
243 |
+
*/
|
244 |
+
function permalink() {
|
245 |
+
return $this->get_permalink();
|
246 |
+
}
|
247 |
+
|
248 |
+
}
|
lib/{Timber.php → timber.php}
RENAMED
@@ -1,20 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
namespace Timber;
|
4 |
-
|
5 |
-
use Timber\Twig;
|
6 |
-
use Timber\ImageHelper;
|
7 |
-
use Timber\Admin;
|
8 |
-
use Timber\Integrations;
|
9 |
-
use Timber\PostGetter;
|
10 |
-
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;
|
17 |
-
|
18 |
/**
|
19 |
* Timber Class.
|
20 |
*
|
@@ -39,8 +24,6 @@ class Timber {
|
|
39 |
public static $auto_meta = true;
|
40 |
public static $autoescape = false;
|
41 |
|
42 |
-
public static $context_cache = [];
|
43 |
-
|
44 |
/**
|
45 |
* @codeCoverageIgnore
|
46 |
*/
|
@@ -49,7 +32,6 @@ class Timber {
|
|
49 |
return;
|
50 |
}
|
51 |
$this->test_compatibility();
|
52 |
-
$this->backwards_compatibility();
|
53 |
$this->init_constants();
|
54 |
$this->init();
|
55 |
}
|
@@ -63,38 +45,27 @@ class Timber {
|
|
63 |
if ( is_admin() || $_SERVER['PHP_SELF'] == '/wp-login.php' ) {
|
64 |
return;
|
65 |
}
|
66 |
-
if ( version_compare(phpversion(), '5.3.0', '<') && !is_admin() ) {
|
67 |
-
trigger_error('Timber requires PHP 5.3.0 or greater. You have '.phpversion(), E_USER_ERROR);
|
68 |
-
}
|
69 |
-
if ( !class_exists('Twig_Autoloader') ) {
|
70 |
-
trigger_error('You have not run "composer install" to download required dependencies for Timber, you can read more on https://github.com/timber/timber#installation', E_USER_ERROR);
|
71 |
-
}
|
72 |
-
}
|
73 |
-
|
74 |
-
private function backwards_compatibility() {
|
75 |
-
if ( class_exists('TimberArchives') ) {
|
76 |
-
//already run, so bail
|
77 |
-
return;
|
78 |
}
|
79 |
-
|
80 |
-
|
81 |
-
foreach ( $names as $name ) {
|
82 |
-
class_alias('Timber\\'.$name, 'Timber'.$name);
|
83 |
}
|
84 |
}
|
85 |
|
86 |
function init_constants() {
|
87 |
-
defined("TIMBER_LOC") or define("TIMBER_LOC", realpath(dirname(__DIR__)));
|
88 |
}
|
89 |
|
90 |
/**
|
91 |
* @codeCoverageIgnore
|
92 |
*/
|
93 |
protected function init() {
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
98 |
}
|
99 |
|
100 |
/* Post Retrieval Routine
|
@@ -108,24 +79,18 @@ class Timber {
|
|
108 |
* @return array|bool|null
|
109 |
*/
|
110 |
public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
|
111 |
-
return
|
112 |
}
|
113 |
|
114 |
/**
|
115 |
* Get posts.
|
116 |
-
*
|
117 |
-
* ```php
|
118 |
-
* $posts = Timber::get_posts();
|
119 |
-
* $posts = Timber::get_posts('post_type = article')
|
120 |
-
* $posts = Timber::get_posts(array('post_type' => 'article', 'category_name' => 'sports')); // uses wp_query format.
|
121 |
-
* $posts = Timber::get_posts('post_type=any', array('portfolio' => 'MyPortfolioClass', 'alert' => 'MyAlertClass')); //use a classmap for the $PostClass
|
122 |
-
* ```
|
123 |
* @param mixed $query
|
124 |
-
* @param string
|
125 |
* @return array|bool|null
|
126 |
*/
|
127 |
public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
|
128 |
-
return
|
129 |
}
|
130 |
|
131 |
/**
|
@@ -136,7 +101,7 @@ class Timber {
|
|
136 |
* @return array|bool|null
|
137 |
*/
|
138 |
public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
139 |
-
return
|
140 |
}
|
141 |
|
142 |
/**
|
@@ -147,7 +112,17 @@ class Timber {
|
|
147 |
* @return array|bool|null
|
148 |
*/
|
149 |
public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
|
150 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
/* Term Retrieval
|
@@ -162,7 +137,7 @@ class Timber {
|
|
162 |
* @return mixed
|
163 |
*/
|
164 |
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
|
165 |
-
return
|
166 |
}
|
167 |
|
168 |
/* Site Retrieval
|
@@ -175,13 +150,13 @@ class Timber {
|
|
175 |
* @return array
|
176 |
*/
|
177 |
public static function get_sites( $blog_ids = false ) {
|
178 |
-
if ( !is_array($blog_ids) ) {
|
179 |
global $wpdb;
|
180 |
-
$blog_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id ASC");
|
181 |
}
|
182 |
$return = array();
|
183 |
foreach ( $blog_ids as $blog_id ) {
|
184 |
-
$return[] = new
|
185 |
}
|
186 |
return $return;
|
187 |
}
|
@@ -196,27 +171,22 @@ class Timber {
|
|
196 |
* @return array
|
197 |
*/
|
198 |
public static function get_context() {
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
self::$context_cache['posts'] = Timber::query_posts();
|
213 |
-
|
214 |
-
self::$context_cache = apply_filters('timber_context', self::$context_cache);
|
215 |
-
self::$context_cache = apply_filters('timber/context', self::$context_cache);
|
216 |
-
}
|
217 |
|
218 |
-
|
219 |
-
|
|
|
220 |
}
|
221 |
|
222 |
/**
|
@@ -229,27 +199,27 @@ class Timber {
|
|
229 |
* @param bool $via_render
|
230 |
* @return bool|string
|
231 |
*/
|
232 |
-
public static function compile( $filenames, $data = array(), $expires = false, $cache_mode =
|
233 |
$caller = self::get_calling_script_dir();
|
234 |
$caller_file = self::get_calling_script_file();
|
235 |
-
$caller_file = apply_filters('timber_calling_php_file', $caller_file);
|
236 |
-
$loader = new
|
237 |
-
$file = $loader->choose_template($filenames);
|
238 |
$output = '';
|
239 |
-
if ( is_null($data) ) {
|
240 |
$data = array();
|
241 |
}
|
242 |
-
if ( strlen($file) ) {
|
243 |
if ( $via_render ) {
|
244 |
-
$file = apply_filters('timber_render_file', $file);
|
245 |
-
$data = apply_filters('timber_render_data', $data);
|
246 |
} else {
|
247 |
-
$file = apply_filters('timber_compile_file', $file);
|
248 |
-
$data = apply_filters('timber_compile_data', $data);
|
249 |
}
|
250 |
-
$output = $loader->render($file, $data, $expires, $cache_mode);
|
251 |
}
|
252 |
-
do_action('timber_compile_done');
|
253 |
return $output;
|
254 |
}
|
255 |
|
@@ -261,10 +231,13 @@ class Timber {
|
|
261 |
* @return bool|string
|
262 |
*/
|
263 |
public static function compile_string( $string, $data = array() ) {
|
264 |
-
$dummy_loader = new
|
265 |
-
$
|
266 |
-
$
|
267 |
-
|
|
|
|
|
|
|
268 |
}
|
269 |
|
270 |
/**
|
@@ -276,15 +249,15 @@ class Timber {
|
|
276 |
* @param string $cache_mode
|
277 |
* @return bool|string
|
278 |
*/
|
279 |
-
public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode =
|
280 |
if ( $expires === true ) {
|
281 |
//if this is reading as true; the user probably is using the old $echo param
|
282 |
//so we should move all vars up by a spot
|
283 |
$expires = $cache_mode;
|
284 |
-
$cache_mode =
|
285 |
}
|
286 |
-
$output = self::compile($filenames, $data, $expires, $cache_mode, true);
|
287 |
-
$output = apply_filters('timber_compile_result', $output);
|
288 |
return $output;
|
289 |
}
|
290 |
|
@@ -297,8 +270,8 @@ class Timber {
|
|
297 |
* @param string $cache_mode
|
298 |
* @return bool|string
|
299 |
*/
|
300 |
-
public static function render( $filenames, $data = array(), $expires = false, $cache_mode =
|
301 |
-
$output =
|
302 |
echo $output;
|
303 |
return $output;
|
304 |
}
|
@@ -311,7 +284,7 @@ class Timber {
|
|
311 |
* @return bool|string
|
312 |
*/
|
313 |
public static function render_string( $string, $data = array() ) {
|
314 |
-
$compiled = self::compile_string($string, $data);
|
315 |
echo $compiled;
|
316 |
return $compiled;
|
317 |
}
|
@@ -331,10 +304,10 @@ class Timber {
|
|
331 |
if ( $sidebar == '' ) {
|
332 |
$sidebar = 'sidebar.php';
|
333 |
}
|
334 |
-
if ( strstr(strtolower($sidebar), '.php') ) {
|
335 |
-
return self::get_sidebar_from_php($sidebar, $data);
|
336 |
}
|
337 |
-
return self::compile($sidebar, $data);
|
338 |
}
|
339 |
|
340 |
/**
|
@@ -346,19 +319,19 @@ class Timber {
|
|
346 |
*/
|
347 |
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
348 |
$caller = self::get_calling_script_dir();
|
349 |
-
$loader = new
|
350 |
-
$uris = $loader->get_locations($caller);
|
351 |
ob_start();
|
352 |
$found = false;
|
353 |
foreach ( $uris as $uri ) {
|
354 |
-
if ( file_exists(trailingslashit($uri)
|
355 |
-
include trailingslashit($uri)
|
356 |
$found = true;
|
357 |
break;
|
358 |
}
|
359 |
}
|
360 |
if ( !$found ) {
|
361 |
-
|
362 |
}
|
363 |
$ret = ob_get_contents();
|
364 |
ob_end_clean();
|
@@ -375,9 +348,44 @@ class Timber {
|
|
375 |
* @return TimberFunctionWrapper
|
376 |
*/
|
377 |
public static function get_widgets( $widget_id ) {
|
378 |
-
return trim(
|
379 |
}
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
/* Pagination
|
382 |
================================ */
|
383 |
|
@@ -392,43 +400,43 @@ class Timber {
|
|
392 |
global $paged;
|
393 |
global $wp_rewrite;
|
394 |
$args = array();
|
395 |
-
$args['total'] = ceil($wp_query->found_posts / $wp_query->query_vars['posts_per_page']);
|
396 |
if ( $wp_rewrite->using_permalinks() ) {
|
397 |
-
$url = explode('?', get_pagenum_link(0));
|
398 |
-
if ( isset($url[1]) ) {
|
399 |
-
parse_str($url[1], $query);
|
400 |
$args['add_args'] = $query;
|
401 |
}
|
402 |
-
$args['format'] =
|
403 |
-
$args['base'] = trailingslashit($url[0]).'%_%';
|
404 |
} else {
|
405 |
$big = 999999999;
|
406 |
-
$args['base'] = str_replace($big, '%#%', esc_url(get_pagenum_link($big)));
|
407 |
}
|
408 |
$args['type'] = 'array';
|
409 |
-
$args['current'] = max(1, get_query_var('paged'));
|
410 |
-
$args['mid_size'] = max(9 - $args['current'], 3);
|
411 |
-
if ( is_int($prefs) ) {
|
412 |
$args['mid_size'] = $prefs - 2;
|
413 |
} else {
|
414 |
-
$args = array_merge($args, $prefs);
|
415 |
}
|
416 |
$data = array();
|
417 |
$data['current'] = $args['current'];
|
418 |
$data['total'] = $args['total'];
|
419 |
-
$data['pages'] =
|
420 |
-
$next = get_next_posts_page_link($args['total']);
|
421 |
if ( $next ) {
|
422 |
-
$data['next'] = array('link' => untrailingslashit($next), 'class' => 'page-numbers next');
|
423 |
}
|
424 |
-
$prev = previous_posts(false);
|
425 |
if ( $prev ) {
|
426 |
-
$data['prev'] = array('link' => untrailingslashit($prev), 'class' => 'page-numbers prev');
|
427 |
}
|
428 |
if ( $paged < 2 ) {
|
429 |
$data['prev'] = '';
|
430 |
}
|
431 |
-
if ( $data['total'] === (double) 0 ) {
|
432 |
$data['next'] = '';
|
433 |
}
|
434 |
return $data;
|
@@ -443,28 +451,14 @@ class Timber {
|
|
443 |
* @return string
|
444 |
*/
|
445 |
public static function get_calling_script_dir( $offset = 0 ) {
|
446 |
-
$caller = self::get_calling_script_file($offset);
|
447 |
-
if ( !is_null($caller) ) {
|
448 |
-
$pathinfo = pathinfo($caller);
|
449 |
$dir = $pathinfo['dirname'];
|
450 |
return $dir;
|
451 |
}
|
452 |
}
|
453 |
|
454 |
-
|
455 |
-
/**
|
456 |
-
* Add route.
|
457 |
-
*
|
458 |
-
* @param string $route
|
459 |
-
* @param callable $callback
|
460 |
-
* @param array $args
|
461 |
-
* @deprecated since 0.20.0 and will be removed in 1.1
|
462 |
-
*/
|
463 |
-
public static function add_route( $route, $callback, $args = array() ) {
|
464 |
-
Helper::warn('Timber::add_route (and accompanying methods for load_view, etc. Have been deprecated and will soon be removed. Please update your theme with Route::map. You can read more in the 1.0 Upgrade Guide: https://github.com/timber/timber/wiki/1.0-Upgrade-Guide');
|
465 |
-
\Routes::map($route, $callback, $args);
|
466 |
-
}
|
467 |
-
|
468 |
/**
|
469 |
* Get calling script file.
|
470 |
*
|
@@ -488,4 +482,6 @@ class Timber {
|
|
488 |
}
|
489 |
return $caller;
|
490 |
}
|
491 |
-
|
|
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Timber Class.
|
5 |
*
|
24 |
public static $auto_meta = true;
|
25 |
public static $autoescape = false;
|
26 |
|
|
|
|
|
27 |
/**
|
28 |
* @codeCoverageIgnore
|
29 |
*/
|
32 |
return;
|
33 |
}
|
34 |
$this->test_compatibility();
|
|
|
35 |
$this->init_constants();
|
36 |
$this->init();
|
37 |
}
|
45 |
if ( is_admin() || $_SERVER['PHP_SELF'] == '/wp-login.php' ) {
|
46 |
return;
|
47 |
}
|
48 |
+
if ( version_compare( phpversion(), '5.3.0', '<' ) && !is_admin() ) {
|
49 |
+
trigger_error( 'Timber requires PHP 5.3.0 or greater. You have '.phpversion(), E_USER_ERROR );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
+
if ( !class_exists( 'Twig_Autoloader' ) ) {
|
52 |
+
trigger_error( 'You have not run "composer install" to download required dependencies for Timber, you can read more on https://github.com/jarednova/timber#installation', E_USER_ERROR );
|
|
|
|
|
53 |
}
|
54 |
}
|
55 |
|
56 |
function init_constants() {
|
57 |
+
defined( "TIMBER_LOC" ) or define( "TIMBER_LOC", realpath( dirname(__DIR__) ) );
|
58 |
}
|
59 |
|
60 |
/**
|
61 |
* @codeCoverageIgnore
|
62 |
*/
|
63 |
protected function init() {
|
64 |
+
TimberTwig::init();
|
65 |
+
TimberRoutes::init( $this );
|
66 |
+
TimberImageHelper::init();
|
67 |
+
TimberAdmin::init();
|
68 |
+
TimberIntegrations::init();
|
69 |
}
|
70 |
|
71 |
/* Post Retrieval Routine
|
79 |
* @return array|bool|null
|
80 |
*/
|
81 |
public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
|
82 |
+
return TimberPostGetter::get_post( $query, $PostClass );
|
83 |
}
|
84 |
|
85 |
/**
|
86 |
* Get posts.
|
87 |
+
*
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
* @param mixed $query
|
89 |
+
* @param string $PostClass
|
90 |
* @return array|bool|null
|
91 |
*/
|
92 |
public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
|
93 |
+
return TimberPostGetter::get_posts( $query, $PostClass, $return_collection );
|
94 |
}
|
95 |
|
96 |
/**
|
101 |
* @return array|bool|null
|
102 |
*/
|
103 |
public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
104 |
+
return TimberPostGetter::query_post( $query, $PostClass );
|
105 |
}
|
106 |
|
107 |
/**
|
112 |
* @return array|bool|null
|
113 |
*/
|
114 |
public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
|
115 |
+
return TimberPostGetter::query_posts( $query, $PostClass );
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* WP_Query has posts.
|
120 |
+
*
|
121 |
+
* @return bool
|
122 |
+
* @deprecated since 0.20.0
|
123 |
+
*/
|
124 |
+
static function wp_query_has_posts() {
|
125 |
+
return TimberPostGetter::wp_query_has_posts();
|
126 |
}
|
127 |
|
128 |
/* Term Retrieval
|
137 |
* @return mixed
|
138 |
*/
|
139 |
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
|
140 |
+
return TimberTermGetter::get_terms( $args, $maybe_args, $TermClass );
|
141 |
}
|
142 |
|
143 |
/* Site Retrieval
|
150 |
* @return array
|
151 |
*/
|
152 |
public static function get_sites( $blog_ids = false ) {
|
153 |
+
if ( !is_array( $blog_ids ) ) {
|
154 |
global $wpdb;
|
155 |
+
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id ASC" );
|
156 |
}
|
157 |
$return = array();
|
158 |
foreach ( $blog_ids as $blog_id ) {
|
159 |
+
$return[] = new TimberSite( $blog_id );
|
160 |
}
|
161 |
return $return;
|
162 |
}
|
171 |
* @return array
|
172 |
*/
|
173 |
public static function get_context() {
|
174 |
+
$data = array();
|
175 |
+
$data['http_host'] = 'http://' . TimberURLHelper::get_host();
|
176 |
+
$data['wp_title'] = TimberHelper::get_wp_title();
|
177 |
+
$data['wp_head'] = TimberHelper::function_wrapper( 'wp_head' );
|
178 |
+
$data['wp_footer'] = TimberHelper::function_wrapper( 'wp_footer' );
|
179 |
+
$data['body_class'] = implode( ' ', get_body_class() );
|
180 |
+
|
181 |
+
$data['site'] = new TimberSite();
|
182 |
+
$data['request'] = new TimberRequest();
|
183 |
+
$data['theme'] = $data['site']->theme;
|
184 |
+
|
185 |
+
$data['posts'] = Timber::query_posts();
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
+
$data = apply_filters( 'timber_context', $data );
|
188 |
+
$data = apply_filters( 'timber/context', $data );
|
189 |
+
return $data;
|
190 |
}
|
191 |
|
192 |
/**
|
199 |
* @param bool $via_render
|
200 |
* @return bool|string
|
201 |
*/
|
202 |
+
public static function compile( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT, $via_render = false ) {
|
203 |
$caller = self::get_calling_script_dir();
|
204 |
$caller_file = self::get_calling_script_file();
|
205 |
+
$caller_file = apply_filters( 'timber_calling_php_file', $caller_file );
|
206 |
+
$loader = new TimberLoader( $caller );
|
207 |
+
$file = $loader->choose_template( $filenames );
|
208 |
$output = '';
|
209 |
+
if ( is_null( $data ) ) {
|
210 |
$data = array();
|
211 |
}
|
212 |
+
if ( strlen( $file ) ) {
|
213 |
if ( $via_render ) {
|
214 |
+
$file = apply_filters( 'timber_render_file', $file );
|
215 |
+
$data = apply_filters( 'timber_render_data', $data );
|
216 |
} else {
|
217 |
+
$file = apply_filters( 'timber_compile_file', $file );
|
218 |
+
$data = apply_filters( 'timber_compile_data', $data );
|
219 |
}
|
220 |
+
$output = $loader->render( $file, $data, $expires, $cache_mode );
|
221 |
}
|
222 |
+
do_action( 'timber_compile_done' );
|
223 |
return $output;
|
224 |
}
|
225 |
|
231 |
* @return bool|string
|
232 |
*/
|
233 |
public static function compile_string( $string, $data = array() ) {
|
234 |
+
$dummy_loader = new TimberLoader();
|
235 |
+
$dummy_loader->get_twig();
|
236 |
+
$loader = new Twig_Loader_String();
|
237 |
+
$twig = new Twig_Environment( $loader );
|
238 |
+
$twig = apply_filters( 'timber/twig/filters', $twig );
|
239 |
+
$twig = apply_filters( 'twig_apply_filters', $twig );
|
240 |
+
return $twig->render( $string, $data );
|
241 |
}
|
242 |
|
243 |
/**
|
249 |
* @param string $cache_mode
|
250 |
* @return bool|string
|
251 |
*/
|
252 |
+
public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT ) {
|
253 |
if ( $expires === true ) {
|
254 |
//if this is reading as true; the user probably is using the old $echo param
|
255 |
//so we should move all vars up by a spot
|
256 |
$expires = $cache_mode;
|
257 |
+
$cache_mode = TimberLoader::CACHE_USE_DEFAULT;
|
258 |
}
|
259 |
+
$output = self::compile( $filenames, $data, $expires, $cache_mode, true );
|
260 |
+
$output = apply_filters( 'timber_compile_result', $output );
|
261 |
return $output;
|
262 |
}
|
263 |
|
270 |
* @param string $cache_mode
|
271 |
* @return bool|string
|
272 |
*/
|
273 |
+
public static function render( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT ) {
|
274 |
+
$output = static::fetch( $filenames, $data, $expires, $cache_mode );
|
275 |
echo $output;
|
276 |
return $output;
|
277 |
}
|
284 |
* @return bool|string
|
285 |
*/
|
286 |
public static function render_string( $string, $data = array() ) {
|
287 |
+
$compiled = self::compile_string( $string, $data );
|
288 |
echo $compiled;
|
289 |
return $compiled;
|
290 |
}
|
304 |
if ( $sidebar == '' ) {
|
305 |
$sidebar = 'sidebar.php';
|
306 |
}
|
307 |
+
if ( strstr( strtolower( $sidebar ), '.php' ) ) {
|
308 |
+
return self::get_sidebar_from_php( $sidebar, $data );
|
309 |
}
|
310 |
+
return self::compile( $sidebar, $data );
|
311 |
}
|
312 |
|
313 |
/**
|
319 |
*/
|
320 |
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
321 |
$caller = self::get_calling_script_dir();
|
322 |
+
$loader = new TimberLoader();
|
323 |
+
$uris = $loader->get_locations( $caller );
|
324 |
ob_start();
|
325 |
$found = false;
|
326 |
foreach ( $uris as $uri ) {
|
327 |
+
if ( file_exists( trailingslashit( $uri ) . $sidebar ) ) {
|
328 |
+
include trailingslashit( $uri ) . $sidebar;
|
329 |
$found = true;
|
330 |
break;
|
331 |
}
|
332 |
}
|
333 |
if ( !$found ) {
|
334 |
+
TimberHelper::error_log( 'error loading your sidebar, check to make sure the file exists' );
|
335 |
}
|
336 |
$ret = ob_get_contents();
|
337 |
ob_end_clean();
|
348 |
* @return TimberFunctionWrapper
|
349 |
*/
|
350 |
public static function get_widgets( $widget_id ) {
|
351 |
+
return trim( TimberHelper::function_wrapper( 'dynamic_sidebar', array( $widget_id ), true ) );
|
352 |
}
|
353 |
|
354 |
+
|
355 |
+
/* Routes
|
356 |
+
================================ */
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Add route.
|
360 |
+
*
|
361 |
+
* @param string $route
|
362 |
+
* @param callable $callback
|
363 |
+
* @param array $args
|
364 |
+
* @deprecated since 0.20.0
|
365 |
+
*/
|
366 |
+
public static function add_route( $route, $callback, $args = array() ) {
|
367 |
+
Routes::map( $route, $callback, $args );
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Load template.
|
372 |
+
*
|
373 |
+
* @deprecated since 0.20.0
|
374 |
+
*/
|
375 |
+
public static function load_template( $template, $query = false, $status_code = 200, $tparams = false ) {
|
376 |
+
return Routes::load( $template, $tparams, $query, $status_code );
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Load view.
|
381 |
+
*
|
382 |
+
* @deprecated since 0.20.2
|
383 |
+
*/
|
384 |
+
public static function load_view( $template, $query = false, $status_code = 200, $tparams = false ) {
|
385 |
+
return Routes::load( $template, $tparams, $query, $status_code );
|
386 |
+
}
|
387 |
+
|
388 |
+
|
389 |
/* Pagination
|
390 |
================================ */
|
391 |
|
400 |
global $paged;
|
401 |
global $wp_rewrite;
|
402 |
$args = array();
|
403 |
+
$args['total'] = ceil( $wp_query->found_posts / $wp_query->query_vars['posts_per_page'] );
|
404 |
if ( $wp_rewrite->using_permalinks() ) {
|
405 |
+
$url = explode( '?', get_pagenum_link( 0 ) );
|
406 |
+
if ( isset( $url[1] ) ) {
|
407 |
+
parse_str( $url[1], $query );
|
408 |
$args['add_args'] = $query;
|
409 |
}
|
410 |
+
$args['format'] = 'page/%#%';
|
411 |
+
$args['base'] = trailingslashit( $url[0] ).'%_%';
|
412 |
} else {
|
413 |
$big = 999999999;
|
414 |
+
$args['base'] = str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) );
|
415 |
}
|
416 |
$args['type'] = 'array';
|
417 |
+
$args['current'] = max( 1, get_query_var( 'paged' ) );
|
418 |
+
$args['mid_size'] = max( 9 - $args['current'], 3 );
|
419 |
+
if ( is_int( $prefs ) ) {
|
420 |
$args['mid_size'] = $prefs - 2;
|
421 |
} else {
|
422 |
+
$args = array_merge( $args, $prefs );
|
423 |
}
|
424 |
$data = array();
|
425 |
$data['current'] = $args['current'];
|
426 |
$data['total'] = $args['total'];
|
427 |
+
$data['pages'] = TimberHelper::paginate_links( $args );
|
428 |
+
$next = get_next_posts_page_link( $args['total'] );
|
429 |
if ( $next ) {
|
430 |
+
$data['next'] = array( 'link' => untrailingslashit( $next ), 'class' => 'page-numbers next' );
|
431 |
}
|
432 |
+
$prev = previous_posts( false );
|
433 |
if ( $prev ) {
|
434 |
+
$data['prev'] = array( 'link' => untrailingslashit( $prev ), 'class' => 'page-numbers prev' );
|
435 |
}
|
436 |
if ( $paged < 2 ) {
|
437 |
$data['prev'] = '';
|
438 |
}
|
439 |
+
if ( $data['total'] === ( double ) 0 ) {
|
440 |
$data['next'] = '';
|
441 |
}
|
442 |
return $data;
|
451 |
* @return string
|
452 |
*/
|
453 |
public static function get_calling_script_dir( $offset = 0 ) {
|
454 |
+
$caller = self::get_calling_script_file( $offset );
|
455 |
+
if ( !is_null( $caller ) ) {
|
456 |
+
$pathinfo = pathinfo( $caller );
|
457 |
$dir = $pathinfo['dirname'];
|
458 |
return $dir;
|
459 |
}
|
460 |
}
|
461 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
/**
|
463 |
* Get calling script file.
|
464 |
*
|
482 |
}
|
483 |
return $caller;
|
484 |
}
|
485 |
+
|
486 |
+
|
487 |
+
}
|
readme.txt
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
=== Timber ===
|
2 |
-
Contributors: jarednova,
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
-
Stable tag:
|
6 |
Tested up to: 4.5.1
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
@@ -17,11 +17,11 @@ Once Timber is installed and activated in your plugin directory, it gives any Wo
|
|
17 |
|
18 |
### Looking for docs?
|
19 |
* **[Project Page](http://upstatement.com/timber)**
|
20 |
-
* [Timber Documentation](https://github.com/
|
21 |
* [Twig Reference (from SensioLabs)](http://twig.sensiolabs.org/doc/templates.html)
|
22 |
_Twig is the template language powering Timber; if you need a little background on what a template language is, [Twig's homepage has an overview](http://twig.sensiolabs.org/)_
|
23 |
-
* **[Video Tutorials](https://github.com/
|
24 |
-
* [Overview / Getting Started Guide](https://github.com/
|
25 |
|
26 |
#### Related Projects
|
27 |
* [**Timber Debug Bar**](http://wordpress.org/plugins/debug-bar-timber/) Adds a debug bar panel that will show you want template is in-use and the data sent to your twig file.
|
@@ -33,7 +33,7 @@ Nothing. Timber is meant for you to build a theme on. Like the [Starkers](https:
|
|
33 |
Timber is great for any WordPress developer who cares about writing good, maintainable code. It helps teams of designers and developers working together. At [Upstatement](http://upstatement.com) we made Timber because not everyone knows the ins-and-outs of the_loop(), WordPress codex and PHP (nor should they). With Timber your best WordPress dev can focus on building the .php files with requests from WordPress and pass the data into .twig files. Once there, designers can easily mark-up data and build out a site's look-and-feel.
|
34 |
|
35 |
#### Want to read more?
|
36 |
-
* [Timber on GitHub](http://github.com/
|
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 |
|
@@ -41,40 +41,12 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
41 |
|
42 |
== Changelog ==
|
43 |
|
44 |
-
= 1.0.1 =
|
45 |
-
* {{ user.avatar }} property is now available (thanks @connorjburton) d21eb85
|
46 |
-
* #947: Fix to pagination base (thanks @matsrietdijk) 270d7c2
|
47 |
-
* Fix to some namespacing issues (thanks @connorjburton) 0a8346a
|
48 |
-
* #958: Call the_post action to help other plugins (thanks @felthy) 4442703
|
49 |
-
* #976: Fixed problem with static declaration (@jarednova) c888606
|
50 |
-
* #978: Bug with arrays for post types (thanks @connorjburton) 571f6f8
|
51 |
-
|
52 |
-
= 1.0.0 =
|
53 |
-
* Added `{{ user }}` object to context
|
54 |
-
* Exposed translation functions
|
55 |
-
* Added better error reporting/warnings
|
56 |
-
* Fixed some things with function wrapper
|
57 |
-
* Timber is now namespaced, big big thanks to @connorjburton
|
58 |
-
* Cleanup of spacing
|
59 |
-
* Removed deprecated functions, added warning for key functions
|
60 |
-
* Updated version numbers and build script (@jarednova) 81a281e
|
61 |
-
* Corrected Routes -> /Routes which threw a fatal error (@jarednova) 26b6585
|
62 |
-
|
63 |
-
= 0.22.6 =
|
64 |
-
* New {{request}} object for post/get variables (thanks @connorjburton) #856
|
65 |
-
* New crop positions (thanks @salaros) #861
|
66 |
-
* Bug Fixes
|
67 |
-
|
68 |
-
* Fix to "next" in pagination (thanks @connorjburton) #900
|
69 |
-
* Fix to issue with tojpg filter's images not being deleted (thanks @connorjburton) #897
|
70 |
-
* `{{post.parent.children}}` used to return unpublished posts due to underlying behavior in WordPress, it now only returns published posts (thanks @connorjburton) #883
|
71 |
-
|
72 |
= 0.22.5 =
|
73 |
* Fixed errors in tests (thanks @lggorman)
|
74 |
* Fixed error in comments_link (thanks @tehlivi)
|
75 |
|
76 |
= 0.22.4 =
|
77 |
-
* Fixed [bug](https://github.com/
|
78 |
* Added tons of new tests and docs (thanks @lggorman and @jarednova)
|
79 |
|
80 |
= 0.22.3 =
|
@@ -89,7 +61,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
89 |
* Added support for animated gifs
|
90 |
|
91 |
= 0.22.1 =
|
92 |
-
* Added better support for [post.get_terms](https://github.com/
|
93 |
* Fix for issue with ACF date field (thanks @rpkoller)
|
94 |
* Fix for resizing jpEgs (thanks @eaton)
|
95 |
|
@@ -256,7 +228,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
256 |
* Hotfix on timber-admin error
|
257 |
|
258 |
= 0.17.0 =
|
259 |
-
* Now you can resize/crop images with positional preferences, thanks @mmikkel. Here are the docs: https://github.com/
|
260 |
* Removed the Timber Starter Guide from the admin, a link to the GitHub wiki suffices.
|
261 |
|
262 |
= 0.16.8 =
|
@@ -351,7 +323,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
351 |
* New Timber::compile method which _doesn't_ automatically echo. (Same args as Timber::render)
|
352 |
* Added post.get_next / post.get_prev for TimberPosts
|
353 |
* Fixed a thing to make get_preview easier when you want to omit the 'Read More' link
|
354 |
-
* Read the [Full Release Notes](https://github.com/
|
355 |
|
356 |
= 0.14.1 =
|
357 |
* Added hooks to play nicely with Timber Debug Bar
|
@@ -474,7 +446,7 @@ Please post on [StackOverflow under the "Timber" tag](http://stackoverflow.com/q
|
|
474 |
== Frequently Asked Questions ==
|
475 |
|
476 |
= Can it be used in an existing theme? =
|
477 |
-
You bet! Watch these **[video tutorials](https://github.com/
|
478 |
|
479 |
= Is it used in production? =
|
480 |
At Upstatement we've now used it on more than a dozen client sites. Hundreds of other sites use it too. You can check some of them out in the **[showcase](http://upstatement.com/timber/#showcase)**.
|
@@ -489,4 +461,4 @@ Whatever. It simplifies the silly stuff so that you can focus on building more c
|
|
489 |
As stated above, we're using it in dozens of sites (and dozens more planned) -- dozens of other developers are using it too. This isn't going anywhere. Twig is the chosen language for other PHP platforms like Symfony, Drupal 8 and Craft. WordPress will eventually adopt Twig too, I promise you that.
|
490 |
|
491 |
= Support? =
|
492 |
-
Leave a [GitHub issue](https://github.com/
|
1 |
=== Timber ===
|
2 |
+
Contributors: jarednova, lggorman
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
+
Stable tag: 0.22.6
|
6 |
Tested up to: 4.5.1
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
17 |
|
18 |
### Looking for docs?
|
19 |
* **[Project Page](http://upstatement.com/timber)**
|
20 |
+
* [Timber Documentation](https://github.com/jarednova/timber/wiki/)
|
21 |
* [Twig Reference (from SensioLabs)](http://twig.sensiolabs.org/doc/templates.html)
|
22 |
_Twig is the template language powering Timber; if you need a little background on what a template language is, [Twig's homepage has an overview](http://twig.sensiolabs.org/)_
|
23 |
+
* **[Video Tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)**
|
24 |
+
* [Overview / Getting Started Guide](https://github.com/jarednova/timber/wiki/getting-started)
|
25 |
|
26 |
#### Related Projects
|
27 |
* [**Timber Debug Bar**](http://wordpress.org/plugins/debug-bar-timber/) Adds a debug bar panel that will show you want template is in-use and the data sent to your twig file.
|
33 |
Timber is great for any WordPress developer who cares about writing good, maintainable code. It helps teams of designers and developers working together. At [Upstatement](http://upstatement.com) we made Timber because not everyone knows the ins-and-outs of the_loop(), WordPress codex and PHP (nor should they). With Timber your best WordPress dev can focus on building the .php files with requests from WordPress and pass the data into .twig files. Once there, designers can easily mark-up data and build out a site's look-and-feel.
|
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 |
|
41 |
|
42 |
== Changelog ==
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
= 0.22.5 =
|
45 |
* Fixed errors in tests (thanks @lggorman)
|
46 |
* Fixed error in comments_link (thanks @tehlivi)
|
47 |
|
48 |
= 0.22.4 =
|
49 |
+
* Fixed [bug](https://github.com/jarednova/timber/issues/785) in get_calling_script file (thanks @gwagroves)
|
50 |
* Added tons of new tests and docs (thanks @lggorman and @jarednova)
|
51 |
|
52 |
= 0.22.3 =
|
61 |
* Added support for animated gifs
|
62 |
|
63 |
= 0.22.1 =
|
64 |
+
* Added better support for [post.get_terms](https://github.com/jarednova/timber/pull/737) (thanks @aaemnnosttv)
|
65 |
* Fix for issue with ACF date field (thanks @rpkoller)
|
66 |
* Fix for resizing jpEgs (thanks @eaton)
|
67 |
|
228 |
* Hotfix on timber-admin error
|
229 |
|
230 |
= 0.17.0 =
|
231 |
+
* Now you can resize/crop images with positional preferences, thanks @mmikkel. Here are the docs: https://github.com/jarednova/timber/wiki/TimberImage#resize
|
232 |
* Removed the Timber Starter Guide from the admin, a link to the GitHub wiki suffices.
|
233 |
|
234 |
= 0.16.8 =
|
323 |
* New Timber::compile method which _doesn't_ automatically echo. (Same args as Timber::render)
|
324 |
* Added post.get_next / post.get_prev for TimberPosts
|
325 |
* Fixed a thing to make get_preview easier when you want to omit the 'Read More' link
|
326 |
+
* Read the [Full Release Notes](https://github.com/jarednova/timber/releases/tag/0.15.0)
|
327 |
|
328 |
= 0.14.1 =
|
329 |
* Added hooks to play nicely with Timber Debug Bar
|
446 |
== Frequently Asked Questions ==
|
447 |
|
448 |
= Can it be used in an existing theme? =
|
449 |
+
You bet! Watch these **[video tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials)** to see how.
|
450 |
|
451 |
= Is it used in production? =
|
452 |
At Upstatement we've now used it on more than a dozen client sites. Hundreds of other sites use it too. You can check some of them out in the **[showcase](http://upstatement.com/timber/#showcase)**.
|
461 |
As stated above, we're using it in dozens of sites (and dozens more planned) -- dozens of other developers are using it too. This isn't going anywhere. Twig is the chosen language for other PHP platforms like Symfony, Drupal 8 and Craft. WordPress will eventually adopt Twig too, I promise you that.
|
462 |
|
463 |
= Support? =
|
464 |
+
Leave a [GitHub issue](https://github.com/jarednova/timber/issues?state=open) and I'll holler back.
|
timber-starter-theme/single.php
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
$context = Timber::get_context();
|
13 |
$post = Timber::query_post();
|
14 |
$context['post'] = $post;
|
|
|
15 |
|
16 |
if ( post_password_required( $post->ID ) ) {
|
17 |
Timber::render( 'single-password.twig', $context );
|
12 |
$context = Timber::get_context();
|
13 |
$post = Timber::query_post();
|
14 |
$context['post'] = $post;
|
15 |
+
$context['comment_form'] = TimberHelper::get_comment_form();
|
16 |
|
17 |
if ( post_password_required( $post->ID ) ) {
|
18 |
Timber::render( 'single-password.twig', $context );
|
timber-starter-theme/templates/base.twig
CHANGED
@@ -11,7 +11,7 @@
|
|
11 |
{% block header %}
|
12 |
<div class="wrapper">
|
13 |
<h1 class="hdr-logo" role="banner">
|
14 |
-
<a class="hdr-logo-link" href="
|
15 |
</h1>
|
16 |
<nav id="nav-main" class="nav-main" role="navigation">
|
17 |
{% include "menu.twig" with {'menu': menu.get_items} %}
|
11 |
{% block header %}
|
12 |
<div class="wrapper">
|
13 |
<h1 class="hdr-logo" role="banner">
|
14 |
+
<a class="hdr-logo-link" href="/" rel="home">{{site.name}}</a>
|
15 |
</h1>
|
16 |
<nav id="nav-main" class="nav-main" role="navigation">
|
17 |
{% include "menu.twig" with {'menu': menu.get_items} %}
|
timber-starter-theme/templates/single.twig
CHANGED
@@ -12,11 +12,10 @@
|
|
12 |
{{post.content}}
|
13 |
</div>
|
14 |
</section>
|
15 |
-
{% if post.comment_status != 'closed' %}
|
16 |
<section class="comments">
|
17 |
<div class="respond">
|
18 |
<h3 class="h2">Comments</h3>
|
19 |
-
{{
|
20 |
</div>
|
21 |
<div class="responses">
|
22 |
{% for cmt in post.get_comments() %}
|
@@ -24,7 +23,6 @@
|
|
24 |
{% endfor %}
|
25 |
</div>
|
26 |
</section>
|
27 |
-
{% endif %}
|
28 |
</article>
|
29 |
</div><!-- /content-wrapper -->
|
30 |
{% endblock %}
|
12 |
{{post.content}}
|
13 |
</div>
|
14 |
</section>
|
|
|
15 |
<section class="comments">
|
16 |
<div class="respond">
|
17 |
<h3 class="h2">Comments</h3>
|
18 |
+
{{ comment_form }}
|
19 |
</div>
|
20 |
<div class="responses">
|
21 |
{% for cmt in post.get_comments() %}
|
23 |
{% endfor %}
|
24 |
</div>
|
25 |
</section>
|
|
|
26 |
</article>
|
27 |
</div><!-- /content-wrapper -->
|
28 |
{% endblock %}
|
timber.php
CHANGED
@@ -4,17 +4,24 @@ 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:
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
|
|
|
|
|
|
|
|
10 |
// we look for Composer files first in the plugins dir.
|
11 |
// then in the wp-content dir (site install).
|
12 |
// and finally in the current themes directories.
|
13 |
-
if (
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
) {
|
19 |
-
|
20 |
}
|
|
|
|
|
|
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: 0.22.6
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
+
|
11 |
+
global $wp_version;
|
12 |
+
global $timber;
|
13 |
+
|
14 |
// we look for Composer files first in the plugins dir.
|
15 |
// then in the wp-content dir (site install).
|
16 |
// and finally in the current themes directories.
|
17 |
+
if ( file_exists( $composer_autoload = __DIR__ . '/vendor/autoload.php' ) /* check in self */
|
18 |
+
|| file_exists( $composer_autoload = WP_CONTENT_DIR.'/vendor/autoload.php') /* check in wp-content */
|
19 |
+
|| file_exists( $composer_autoload = plugin_dir_path( __FILE__ ).'vendor/autoload.php') /* check in plugin directory */
|
20 |
+
|| file_exists( $composer_autoload = get_stylesheet_directory().'/vendor/autoload.php') /* check in child theme */
|
21 |
+
|| file_exists( $composer_autoload = get_template_directory().'/vendor/autoload.php') /* check in parent theme */
|
22 |
) {
|
23 |
+
require_once $composer_autoload;
|
24 |
}
|
25 |
+
|
26 |
+
$timber = new Timber();
|
27 |
+
Timber::$dirname = 'views';
|
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 ComposerAutoloaderInitea51aada03cf312d1b81bbbcbceabfc8::getLoader();
|
vendor/composer/autoload_classmap.php
CHANGED
@@ -6,5 +6,45 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
9 |
'AltoRouter' => $vendorDir . '/altorouter/altorouter/AltoRouter.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
);
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
+
'ACFTimber' => $baseDir . '/lib/integrations/acf-timber.php',
|
10 |
'AltoRouter' => $vendorDir . '/altorouter/altorouter/AltoRouter.php',
|
11 |
+
'Timber' => $baseDir . '/lib/timber.php',
|
12 |
+
'TimberAdmin' => $baseDir . '/lib/timber-admin.php',
|
13 |
+
'TimberArchives' => $baseDir . '/lib/timber-archives.php',
|
14 |
+
'TimberCommand' => $baseDir . '/lib/integrations/timber-command.php',
|
15 |
+
'TimberComment' => $baseDir . '/lib/timber-comment.php',
|
16 |
+
'TimberCore' => $baseDir . '/lib/timber-core.php',
|
17 |
+
'TimberCoreInterface' => $baseDir . '/lib/timber-core-interface.php',
|
18 |
+
'TimberFunctionWrapper' => $baseDir . '/lib/timber-function-wrapper.php',
|
19 |
+
'TimberHelper' => $baseDir . '/lib/timber-helper.php',
|
20 |
+
'TimberImage' => $baseDir . '/lib/timber-image.php',
|
21 |
+
'TimberImageHelper' => $baseDir . '/lib/timber-image-helper.php',
|
22 |
+
'TimberImageOperation' => $baseDir . '/lib/image/timber-image-operation.php',
|
23 |
+
'TimberImageOperationLetterbox' => $baseDir . '/lib/image/timber-image-operation-letterbox.php',
|
24 |
+
'TimberImageOperationResize' => $baseDir . '/lib/image/timber-image-operation-resize.php',
|
25 |
+
'TimberImageOperationRetina' => $baseDir . '/lib/image/timber-image-operation-retina.php',
|
26 |
+
'TimberImageOperationToJpg' => $baseDir . '/lib/image/timber-image-operation-tojpg.php',
|
27 |
+
'TimberIntegrations' => $baseDir . '/lib/timber-integrations.php',
|
28 |
+
'TimberLoader' => $baseDir . '/lib/timber-loader.php',
|
29 |
+
'TimberMenu' => $baseDir . '/lib/timber-menu.php',
|
30 |
+
'TimberMenuItem' => $baseDir . '/lib/timber-menu-item.php',
|
31 |
+
'TimberPage' => $baseDir . '/lib/timber-page.php',
|
32 |
+
'TimberPost' => $baseDir . '/lib/timber-post.php',
|
33 |
+
'TimberPostGetter' => $baseDir . '/lib/timber-post-getter.php',
|
34 |
+
'TimberPostsCollection' => $baseDir . '/lib/timber-posts-collection.php',
|
35 |
+
'TimberPostsIterator' => $baseDir . '/lib/timber-posts-collection.php',
|
36 |
+
'TimberQueryIterator' => $baseDir . '/lib/timber-query-iterator.php',
|
37 |
+
'TimberRequest' => $baseDir . '/lib/timber-request.php',
|
38 |
+
'TimberRoutes' => $baseDir . '/lib/timber-routes.php',
|
39 |
+
'TimberSite' => $baseDir . '/lib/timber-site.php',
|
40 |
+
'TimberTerm' => $baseDir . '/lib/timber-term.php',
|
41 |
+
'TimberTermGetter' => $baseDir . '/lib/timber-term-getter.php',
|
42 |
+
'TimberTheme' => $baseDir . '/lib/timber-theme.php',
|
43 |
+
'TimberTwig' => $baseDir . '/lib/timber-twig.php',
|
44 |
+
'TimberURLHelper' => $baseDir . '/lib/timber-url-helper.php',
|
45 |
+
'TimberUser' => $baseDir . '/lib/timber-user.php',
|
46 |
+
'Timber\\Cache\\KeyGenerator' => $baseDir . '/lib/cache/KeyGenerator.php',
|
47 |
+
'Timber\\Cache\\TimberKeyGeneratorInterface' => $baseDir . '/lib/cache/TimberKeyGeneratorInterface.php',
|
48 |
+
'Timber\\Cache\\WPObjectCacheAdapter' => $baseDir . '/lib/cache/WPObjectCacheAdapter.php',
|
49 |
+
'Timber_WP_CLI_Command' => $baseDir . '/lib/integrations/wpcli-timber.php',
|
50 |
);
|
vendor/composer/autoload_files.php
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// autoload_files.php @generated by Composer
|
4 |
-
|
5 |
-
$vendorDir = dirname(dirname(__FILE__));
|
6 |
-
$baseDir = dirname($vendorDir);
|
7 |
-
|
8 |
-
return array(
|
9 |
-
'cb78221880aa21d756cc44a8539bb425' => $baseDir . '/init.php',
|
10 |
-
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/composer/autoload_psr4.php
CHANGED
@@ -6,7 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
-
'Timber\\' => array($baseDir . '/lib'),
|
10 |
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
|
11 |
'' => array($vendorDir . '/asm89/twig-cache-extension/lib'),
|
12 |
);
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
9 |
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
|
10 |
'' => array($vendorDir . '/asm89/twig-cache-extension/lib'),
|
11 |
);
|
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 ComposerAutoloaderInit0f0eeb7542dd42954cb9afcc97bcfdce
|
|
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) {
|
@@ -40,20 +40,6 @@ class ComposerAutoloaderInit0f0eeb7542dd42954cb9afcc97bcfdce
|
|
40 |
|
41 |
$loader->register(true);
|
42 |
|
43 |
-
$includeFiles = require __DIR__ . '/autoload_files.php';
|
44 |
-
foreach ($includeFiles as $fileIdentifier => $file) {
|
45 |
-
composerRequire0f0eeb7542dd42954cb9afcc97bcfdce($fileIdentifier, $file);
|
46 |
-
}
|
47 |
-
|
48 |
return $loader;
|
49 |
}
|
50 |
}
|
51 |
-
|
52 |
-
function composerRequire0f0eeb7542dd42954cb9afcc97bcfdce($fileIdentifier, $file)
|
53 |
-
{
|
54 |
-
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
55 |
-
require $file;
|
56 |
-
|
57 |
-
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
58 |
-
}
|
59 |
-
}
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInitea51aada03cf312d1b81bbbcbceabfc8
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInitea51aada03cf312d1b81bbbcbceabfc8', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInitea51aada03cf312d1b81bbbcbceabfc8', 'loadClassLoader'));
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
40 |
|
41 |
$loader->register(true);
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
return $loader;
|
44 |
}
|
45 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/composer/installed.json
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
[
|
2 |
{
|
3 |
"name": "composer/installers",
|
4 |
-
"version": "v1.0.
|
5 |
-
"version_normalized": "1.0.
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/composer/installers.git",
|
9 |
-
"reference": "
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
-
"url": "https://api.github.com/repos/composer/installers/zipball/
|
14 |
-
"reference": "
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
@@ -25,7 +25,7 @@
|
|
25 |
"composer/composer": "1.0.*@dev",
|
26 |
"phpunit/phpunit": "4.1.*"
|
27 |
},
|
28 |
-
"time": "2016-04-
|
29 |
"type": "composer-plugin",
|
30 |
"extra": {
|
31 |
"class": "Composer\\Installers\\Plugin",
|
1 |
[
|
2 |
{
|
3 |
"name": "composer/installers",
|
4 |
+
"version": "v1.0.24",
|
5 |
+
"version_normalized": "1.0.24.0",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/composer/installers.git",
|
9 |
+
"reference": "1cf7cc4b89d5e8549bbb7d6ab1de75da13d27988"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/composer/installers/zipball/1cf7cc4b89d5e8549bbb7d6ab1de75da13d27988",
|
14 |
+
"reference": "1cf7cc4b89d5e8549bbb7d6ab1de75da13d27988",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
25 |
"composer/composer": "1.0.*@dev",
|
26 |
"phpunit/phpunit": "4.1.*"
|
27 |
},
|
28 |
+
"time": "2016-04-05 11:42:46",
|
29 |
"type": "composer-plugin",
|
30 |
"extra": {
|
31 |
"class": "Composer\\Installers\\Plugin",
|
vendor/composer/installers/README.md
CHANGED
@@ -83,7 +83,6 @@ is not needed to install packages with these frameworks:
|
|
83 |
| symfony1 | **`symfony1-plugin`**
|
84 |
| Tusk | `tusk-task`<br>`tusk-command`<br>`tusk-asset`
|
85 |
| TYPO3 Flow | `typo3-flow-package`<br>`typo3-flow-framework`<br>`typo3-flow-plugin`<br>`typo3-flow-site`<br>`typo3-flow-boilerplate`<br>`typo3-flow-build`
|
86 |
-
| TYPO3 CMS | `typo3-cms-extension` (Deprecated in this package, use the [TYPO3 CMS Installers](https://packagist.org/packages/typo3/cms-composer-installers) instead)
|
87 |
| Wolf CMS | `wolfcms-plugin`
|
88 |
| WordPress | <b>`wordpress-plugin`<br>`wordpress-theme`</b><br>`wordpress-muplugin`
|
89 |
| Zend | `zend-library`<br>`zend-extra`<br>`zend-module`
|
83 |
| symfony1 | **`symfony1-plugin`**
|
84 |
| Tusk | `tusk-task`<br>`tusk-command`<br>`tusk-asset`
|
85 |
| TYPO3 Flow | `typo3-flow-package`<br>`typo3-flow-framework`<br>`typo3-flow-plugin`<br>`typo3-flow-site`<br>`typo3-flow-boilerplate`<br>`typo3-flow-build`
|
|
|
86 |
| Wolf CMS | `wolfcms-plugin`
|
87 |
| WordPress | <b>`wordpress-plugin`<br>`wordpress-theme`</b><br>`wordpress-muplugin`
|
88 |
| Zend | `zend-library`<br>`zend-extra`<br>`zend-module`
|
vendor/composer/installers/src/Composer/Installers/Installer.php
CHANGED
@@ -65,7 +65,6 @@ class Installer extends LibraryInstaller
|
|
65 |
'symfony1' => 'Symfony1Installer',
|
66 |
'thelia' => 'TheliaInstaller',
|
67 |
'tusk' => 'TuskInstaller',
|
68 |
-
'typo3-cms' => 'TYPO3CmsInstaller',
|
69 |
'typo3-flow' => 'TYPO3FlowInstaller',
|
70 |
'whmcs' => 'WHMCSInstaller',
|
71 |
'wolfcms' => 'WolfCMSInstaller',
|
65 |
'symfony1' => 'Symfony1Installer',
|
66 |
'thelia' => 'TheliaInstaller',
|
67 |
'tusk' => 'TuskInstaller',
|
|
|
68 |
'typo3-flow' => 'TYPO3FlowInstaller',
|
69 |
'whmcs' => 'WHMCSInstaller',
|
70 |
'wolfcms' => 'WolfCMSInstaller',
|
vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Composer\Installers;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Extension installer for TYPO3 CMS
|
6 |
-
*
|
7 |
-
* @deprecated since 1.0.25, use https://packagist.org/packages/typo3/cms-composer-installers instead
|
8 |
-
*
|
9 |
-
* @author Sascha Egerer <sascha.egerer@dkd.de>
|
10 |
-
*/
|
11 |
-
class TYPO3CmsInstaller extends BaseInstaller
|
12 |
-
{
|
13 |
-
protected $locations = array(
|
14 |
-
'extension' => 'typo3conf/ext/{$name}/',
|
15 |
-
);
|
16 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/composer/installers/tests/Composer/Installers/Test/InstallerTest.php
CHANGED
@@ -169,7 +169,6 @@ class InstallerTest extends TestCase
|
|
169 |
array('tusk-task', true),
|
170 |
array('tusk-asset', true),
|
171 |
array('typo3-flow-plugin', true),
|
172 |
-
array('typo3-cms-extension', true),
|
173 |
array('whmcs-gateway', true),
|
174 |
array('wolfcms-plugin', true),
|
175 |
array('wordpress-plugin', true),
|
@@ -299,7 +298,6 @@ class InstallerTest extends TestCase
|
|
299 |
array('tusk-task', '.tusk/tasks/my_task/', 'shama/my_task'),
|
300 |
array('typo3-flow-package', 'Packages/Application/my_package/', 'shama/my_package'),
|
301 |
array('typo3-flow-build', 'Build/my_package/', 'shama/my_package'),
|
302 |
-
array('typo3-cms-extension', 'typo3conf/ext/my_extension/', 'shama/my_extension'),
|
303 |
array('whmcs-gateway', 'modules/gateways/gateway_name/', 'vendor/gateway_name'),
|
304 |
array('wolfcms-plugin', 'wolf/plugins/my_plugin/', 'shama/my_plugin'),
|
305 |
array('wordpress-plugin', 'wp-content/plugins/my_plugin/', 'shama/my_plugin'),
|
169 |
array('tusk-task', true),
|
170 |
array('tusk-asset', true),
|
171 |
array('typo3-flow-plugin', true),
|
|
|
172 |
array('whmcs-gateway', true),
|
173 |
array('wolfcms-plugin', true),
|
174 |
array('wordpress-plugin', true),
|
298 |
array('tusk-task', '.tusk/tasks/my_task/', 'shama/my_task'),
|
299 |
array('typo3-flow-package', 'Packages/Application/my_package/', 'shama/my_package'),
|
300 |
array('typo3-flow-build', 'Build/my_package/', 'shama/my_package'),
|
|
|
301 |
array('whmcs-gateway', 'modules/gateways/gateway_name/', 'vendor/gateway_name'),
|
302 |
array('wolfcms-plugin', 'wolf/plugins/my_plugin/', 'shama/my_plugin'),
|
303 |
array('wordpress-plugin', 'wp-content/plugins/my_plugin/', 'shama/my_plugin'),
|