Version Description
Download this release
Release Info
Developer | jarednova |
Plugin | Timber |
Version | 1.0.3 |
Comparing to | |
See all releases |
Code changes from version 0.22.6 to 1.0.3
- README.md +29 -21
- init.php +8 -0
- lib/Admin.php +70 -0
- lib/{timber-archives.php → Archives.php} +34 -25
- lib/{cache → Cache}/KeyGenerator.php +0 -0
- lib/{cache → Cache}/TimberKeyGeneratorInterface.php +0 -0
- lib/{cache → Cache}/WPObjectCacheAdapter.php +6 -6
- lib/{timber-comment.php → Comment.php} +56 -49
- lib/Core.php +118 -0
- lib/{timber-core-interface.php → CoreInterface.php} +3 -1
- lib/FunctionWrapper.php +98 -0
- lib/{timber-helper.php → Helper.php} +110 -239
- lib/{timber-image.php → Image.php} +76 -96
- lib/{image/timber-image-operation.php → Image/Operation.php} +13 -9
- lib/{image/timber-image-operation-letterbox.php → Image/Operation/Letterbox.php} +31 -25
- lib/{image/timber-image-operation-resize.php → Image/Operation/Resize.php} +44 -35
- lib/Image/Operation/Retina.php +80 -0
- lib/{image/timber-image-operation-tojpg.php → Image/Operation/ToJpg.php} +19 -15
- lib/{timber-image-helper.php → ImageHelper.php} +106 -94
- lib/Integrations.php +29 -0
- lib/Integrations/ACF.php +60 -0
- lib/Integrations/Command.php +40 -0
- lib/Integrations/Timber_WP_CLI_Command.php +62 -0
- lib/{timber-loader.php → Loader.php} +97 -95
- lib/{timber-menu.php → Menu.php} +43 -38
- lib/{timber-menu-item.php → MenuItem.php} +59 -60
- lib/{timber-post.php → Post.php} +781 -680
- lib/PostGetter.php +131 -0
- lib/PostsCollection.php +100 -0
- lib/QueryIterator.php +162 -0
- lib/{timber-request.php → Request.php} +8 -1
- lib/{timber-site.php → Site.php} +60 -51
- lib/{timber-term.php → Term.php} +41 -55
- lib/{timber-term-getter.php → TermGetter.php} +22 -17
- lib/{timber-theme.php → Theme.php} +14 -8
- lib/{timber.php → Timber.php} +142 -138
- lib/Twig.php +324 -0
- lib/{timber-url-helper.php → URLHelper.php} +60 -89
- lib/{timber-user.php → User.php} +26 -43
- lib/image/timber-image-operation-retina.php +0 -74
- lib/integrations/acf-timber.php +0 -58
- lib/integrations/timber-command.php +0 -36
- lib/integrations/wpcli-timber.php +0 -57
- lib/timber-admin.php +0 -67
- lib/timber-core.php +0 -117
- lib/timber-function-wrapper.php +0 -92
- lib/timber-integrations.php +0 -24
- lib/timber-page.php +0 -9
- lib/timber-post-getter.php +0 -104
- lib/timber-posts-collection.php +0 -97
- lib/timber-query-iterator.php +0 -156
- lib/timber-routes.php +0 -33
- lib/timber-twig.php +0 -347
- readme.txt +43 -12
- timber-starter-theme/single.php +0 -1
- timber-starter-theme/templates/base.twig +1 -1
- timber-starter-theme/templates/single.twig +3 -1
- timber.php +7 -14
- vendor/autoload.php +1 -1
- vendor/composer/autoload_classmap.php +0 -40
- vendor/composer/autoload_files.php +10 -0
- vendor/composer/autoload_psr4.php +1 -0
- vendor/composer/autoload_real.php +17 -3
- vendor/composer/installed.json +6 -6
- vendor/composer/installers/README.md +1 -0
- vendor/composer/installers/src/Composer/Installers/Installer.php +1 -0
- vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +16 -0
- vendor/composer/installers/tests/Composer/Installers/Test/InstallerTest.php +2 -0
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,23 +35,28 @@ 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 |
* * *
|
56 |
|
57 |
### Mission Statement
|
@@ -67,27 +72,30 @@ Nothing. Timber is meant for you to build a theme on. Like the [Starkers](https:
|
|
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/
|
71 |
-
* [**Timber Debug Bar**](https://github.com/
|
72 |
* [**TimberPhoton**](https://github.com/slimndap/TimberPhoton) Plug-in to use JetPack's free Photon image manipulation and CDN with Timber.
|
73 |
-
* [**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://
|
88 |
|
89 |
#### Contributing
|
90 |
-
Read the [contributor guidelines](https://github.com/
|
91 |
|
92 |
|
93 |
|
1 |
<div style="text-align:center">
|
2 |
+
<a href="http://timber.github.io/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="https://twitter.com/jarednova">@JaredNova</a>) and <a href="http://upstatement.com">Upstatement</a> (<a href="https://twitter.com/upstatement">@Upstatement</a>)</div>
|
5 |
</div>
|
6 |
|
7 |
+
[![Build Status](https://img.shields.io/travis/timber/timber/master.svg?style=flat-square)](https://travis-ci.org/timber/timber)
|
8 |
+
[![Coverage Status](https://img.shields.io/coveralls/timber/timber.svg?style=flat-square)](https://coveralls.io/r/timber/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/timber/timber.svg?style=flat-square)](https://scrutinizer-ci.com/g/timber/timber/?branch=master)
|
11 |
+
[![Latest Stable Version](https://img.shields.io/packagist/v/timber/timber.svg?style=flat-square)](https://packagist.org/packages/timber/timber)
|
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/timber/timber.svg?style=flat-square)](http://hhvm.h4cc.de/package/timber/timber)
|
14 |
+
[![Join the chat at https://gitter.im/timber/timber](https://img.shields.io/gitter/room/timber/timber.svg?style=flat-square)](https://gitter.im/timber/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/timber/timber/wiki)
|
39 |
* [Twig Reference](http://twig.sensiolabs.org/doc/templates.html)
|
40 |
+
* [Video Tutorials](https://github.com/timber/timber/wiki/Video-Tutorials)
|
41 |
+
* [Overview / Getting Started Guide](https://github.com/timber/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](https://wordpress.org/plugins/timber-library/) version.
|
48 |
|
49 |
```shell
|
50 |
+
composer require timber/timber
|
51 |
```
|
52 |
|
53 |
+
If your theme is not setup to pull in Composer's autoload file, you will need to
|
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 |
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/starter-theme) The "_s" of Timber to give you an easy start to the most basic theme you can build upon and customize.
|
76 |
+
* [**Timber Debug Bar**](https://github.com/timber/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.
|
77 |
* [**TimberPhoton**](https://github.com/slimndap/TimberPhoton) Plug-in to use JetPack's free Photon image manipulation and CDN with Timber.
|
78 |
+
* [**Timber CLI**](https://github.com/nclud/wp-timber-cli) A CLI for 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 by [@tjFogarty](https://github.com/tjFogarty)
|
88 |
+
* [**Twig for Timber Cheatsheet**](http://notlaura.com/the-twig-for-timber-cheatsheet/) by [@laras126](https://github.com/laras126)
|
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://timber.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.
|
96 |
|
97 |
#### Contributing
|
98 |
+
Read the [contributor guidelines](https://github.com/timber/timber/wiki#contributing) in the wiki.
|
99 |
|
100 |
|
101 |
|
init.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use Timber\Timber;
|
4 |
+
|
5 |
+
$timber = new Timber();
|
6 |
+
Timber::$dirname = 'views';
|
7 |
+
|
8 |
+
|
lib/Admin.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{timber-archives.php → Archives.php}
RENAMED
@@ -1,6 +1,13 @@
|
|
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,8 +37,8 @@
|
|
30 |
* </ul>
|
31 |
* ```
|
32 |
*/
|
33 |
-
class
|
34 |
-
|
35 |
public $base = '';
|
36 |
/**
|
37 |
* @api
|
@@ -55,6 +62,8 @@ class TimberArchives extends TimberCore {
|
|
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,7 +86,7 @@ class TimberArchives extends TimberCore {
|
|
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(
|
81 |
return $ret;
|
82 |
}
|
83 |
|
@@ -97,13 +106,13 @@ class TimberArchives extends TimberCore {
|
|
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(
|
107 |
$text = sprintf('%d', $result->year);
|
108 |
$output[] = $this->get_archives_link($url, $text);
|
109 |
}
|
@@ -137,28 +146,28 @@ class TimberArchives extends TimberCore {
|
|
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,7 +208,7 @@ class TimberArchives extends TimberCore {
|
|
199 |
|
200 |
if ( !empty($args['limit']) ) {
|
201 |
$limit = absint($limit);
|
202 |
-
$limit = ' LIMIT '
|
203 |
}
|
204 |
|
205 |
$order = strtoupper($order);
|
@@ -220,7 +229,7 @@ class TimberArchives extends TimberCore {
|
|
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,7 +241,7 @@ class TimberArchives extends TimberCore {
|
|
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,14 +255,14 @@ class TimberArchives extends TimberCore {
|
|
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,13 +275,13 @@ class TimberArchives extends TimberCore {
|
|
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,7 +289,7 @@ class TimberArchives extends TimberCore {
|
|
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
|
284 |
$output[] = $this->get_archives_link($url, $text);
|
285 |
}
|
286 |
}
|
@@ -295,10 +304,10 @@ class TimberArchives extends TimberCore {
|
|
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 {
|
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 |
* </ul>
|
38 |
* ```
|
39 |
*/
|
40 |
+
class Archives extends Core {
|
41 |
+
|
42 |
public $base = '';
|
43 |
/**
|
44 |
* @api
|
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 |
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(URLHelper::prepend_to_url($url, $this->base));
|
90 |
return $ret;
|
91 |
}
|
92 |
|
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 ( !$results = wp_cache_get($key, 'posts') ) {
|
110 |
$results = $wpdb->get_results($query);
|
111 |
wp_cache_set($key, $results, 'posts');
|
112 |
}
|
113 |
+
if ( $results ) {
|
114 |
+
foreach ( (array) $results as $result ) {
|
115 |
+
$url = get_year_link($result->year);
|
116 |
$text = sprintf('%d', $result->year);
|
117 |
$output[] = $this->get_archives_link($url, $text);
|
118 |
}
|
146 |
. "ORDER BY post_date $order $limit";
|
147 |
$key = md5($query);
|
148 |
$key = "wp_get_archives:$key:$last_changed";
|
149 |
+
if ( !$results = wp_cache_get($key, 'posts') ) {
|
150 |
$results = $wpdb->get_results($query);
|
151 |
wp_cache_set($key, $results, 'posts');
|
152 |
}
|
153 |
+
if ( $results ) {
|
154 |
+
foreach ( (array) $results as $result ) {
|
155 |
$url = get_month_link($result->year, $result->month);
|
156 |
+
if ( $show_year && !$nested ) {
|
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 ( $nested ) {
|
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 ( $nested ) {
|
169 |
$out2 = array();
|
170 |
+
foreach ( $output as $year => $months ) {
|
171 |
$out2[] = array('name' => $year, 'children' => $months);
|
172 |
}
|
173 |
return $out2;
|
208 |
|
209 |
if ( !empty($args['limit']) ) {
|
210 |
$limit = absint($limit);
|
211 |
+
$limit = ' LIMIT '.$limit;
|
212 |
}
|
213 |
|
214 |
$order = strtoupper($order);
|
229 |
$archive_week_start_date_format = 'Y/m/d';
|
230 |
$archive_week_end_date_format = 'Y/m/d';
|
231 |
|
232 |
+
if ( !$archive_date_format_over_ride ) {
|
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 |
|
242 |
$output = array();
|
243 |
$last_changed = wp_cache_get('last_changed', 'posts');
|
244 |
+
if ( !$last_changed ) {
|
245 |
$last_changed = microtime();
|
246 |
wp_cache_set('last_changed', $last_changed, 'posts');
|
247 |
}
|
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 ( !$results = wp_cache_get($key, 'posts') ) {
|
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) $results as $result ) {
|
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 |
. "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 ( !$results = wp_cache_get($key, 'posts') ) {
|
279 |
$results = $wpdb->get_results($query);
|
280 |
wp_cache_set($key, $results, 'posts');
|
281 |
}
|
282 |
$arc_w_last = '';
|
283 |
if ( $results ) {
|
284 |
+
foreach ( (array) $results as $result ) {
|
285 |
if ( $result->week != $arc_w_last ) {
|
286 |
$arc_year = $result->yr;
|
287 |
$arc_w_last = $result->week;
|
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.$archive_week_separator.$arc_week_end;
|
293 |
$output[] = $this->get_archives_link($url, $text);
|
294 |
}
|
295 |
}
|
304 |
wp_cache_set($key, $results, 'posts');
|
305 |
}
|
306 |
if ( $results ) {
|
307 |
+
foreach ( (array) $results as $result ) {
|
308 |
+
if ( $result->post_date != '0000-00-00 00:00:00' ) {
|
309 |
$url = get_permalink($result);
|
310 |
+
if ( $result->post_title ) {
|
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 {
|
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($key) {
|
21 |
-
return $this->timberloader->get_cache($key, $this->cache_group,
|
22 |
}
|
23 |
|
24 |
-
public function save($key, $value, $expire = 0) {
|
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 Timber\Loader;
|
5 |
|
6 |
class WPObjectCacheAdapter implements CacheProviderInterface {
|
7 |
|
12 |
*/
|
13 |
private $timberloader;
|
14 |
|
15 |
+
public function __construct( Loader $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, Loader::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, Loader::CACHE_USE_DEFAULT);
|
26 |
}
|
27 |
|
28 |
}
|
lib/{timber-comment.php → Comment.php}
RENAMED
@@ -1,5 +1,11 @@
|
|
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,9 +25,9 @@
|
|
19 |
* <p class="comment-attribution">- Sullivan Ballou</p>
|
20 |
* ```
|
21 |
*/
|
22 |
-
class
|
23 |
|
24 |
-
public $PostClass = '
|
25 |
public $object_type = 'comment';
|
26 |
|
27 |
public static $representation = 'comment';
|
@@ -40,7 +46,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
40 |
/**
|
41 |
* @param int $cid
|
42 |
*/
|
43 |
-
function __construct($cid) {
|
44 |
$this->init($cid);
|
45 |
}
|
46 |
|
@@ -52,9 +58,9 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,14 +89,14 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
83 |
* <li>Rebecca Pearl, who is a author</li>
|
84 |
* </ol>
|
85 |
* ```
|
86 |
-
* @return
|
87 |
*/
|
88 |
public function author() {
|
89 |
-
if ($this->user_id) {
|
90 |
-
return new
|
91 |
} else {
|
92 |
-
$author = new
|
93 |
-
if (isset($this->comment_author) && $this->comment_author) {
|
94 |
$author->name = $this->comment_author;
|
95 |
} else {
|
96 |
$author->name = 'Anonymous';
|
@@ -113,22 +119,22 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,7 +187,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,7 +212,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,7 +220,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,15 +237,15 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,13 +254,14 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,7 +276,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
269 |
*/
|
270 |
public function reply_link( $reply_text = 'Reply' ) {
|
271 |
if ( is_singular() && comments_open() && get_option('thread_comments') ) {
|
272 |
-
wp_enqueue_script(
|
273 |
}
|
274 |
|
275 |
// Get the comments depth option from the admin panel
|
@@ -284,7 +291,7 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
284 |
'max_depth' => $max_depth,
|
285 |
);
|
286 |
|
287 |
-
return get_comment_reply_link(
|
288 |
}
|
289 |
|
290 |
/* AVATAR Stuff
|
@@ -295,9 +302,9 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,11 +317,11 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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,30 +339,30 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
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()
|
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
|
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
|
357 |
-
} else if (empty($email) && !strstr($default, 'http://')) {
|
358 |
-
$default = $host
|
359 |
}
|
360 |
return $default;
|
361 |
}
|
@@ -368,13 +375,13 @@ class TimberComment extends TimberCore implements TimberCoreInterface {
|
|
368 |
* @param string $size
|
369 |
* @return mixed
|
370 |
*/
|
371 |
-
protected function avatar_out($default, $host, $email_hash, $size) {
|
372 |
-
$out = $host
|
373 |
$rating = get_option('avatar_rating');
|
374 |
-
if (!empty($rating)) {
|
375 |
-
$out .= '&r='
|
376 |
}
|
377 |
return str_replace('&', '&', esc_url($out));
|
378 |
}
|
379 |
|
380 |
-
}
|
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 |
* <p class="comment-attribution">- Sullivan Ballou</p>
|
26 |
* ```
|
27 |
*/
|
28 |
+
class Comment extends Core implements CoreInterface {
|
29 |
|
30 |
+
public $PostClass = 'Post';
|
31 |
public $object_type = 'comment';
|
32 |
|
33 |
public static $representation = 'comment';
|
46 |
/**
|
47 |
* @param int $cid
|
48 |
*/
|
49 |
+
function __construct( $cid ) {
|
50 |
$this->init($cid);
|
51 |
}
|
52 |
|
58 |
* @internal
|
59 |
* @param integer $cid
|
60 |
*/
|
61 |
+
function init( $cid ) {
|
62 |
$comment_data = $cid;
|
63 |
+
if ( is_integer($cid) ) {
|
64 |
$comment_data = get_comment($cid);
|
65 |
}
|
66 |
$this->import($comment_data);
|
89 |
* <li>Rebecca Pearl, who is a author</li>
|
90 |
* </ol>
|
91 |
* ```
|
92 |
+
* @return User
|
93 |
*/
|
94 |
public function author() {
|
95 |
+
if ( $this->user_id ) {
|
96 |
+
return new User($this->user_id);
|
97 |
} else {
|
98 |
+
$author = new User(0);
|
99 |
+
if ( isset($this->comment_author) && $this->comment_author ) {
|
100 |
$author->name = $this->comment_author;
|
101 |
} else {
|
102 |
$author->name = 'Anonymous';
|
119 |
* @param string $default
|
120 |
* @return bool|mixed|string
|
121 |
*/
|
122 |
+
public function avatar( $size = 92, $default = '' ) {
|
123 |
+
if ( !get_option('show_avatars') ) {
|
124 |
return false;
|
125 |
}
|
126 |
+
if ( !is_numeric($size) ) {
|
127 |
$size = '92';
|
128 |
}
|
129 |
|
130 |
$email = $this->avatar_email();
|
131 |
$email_hash = '';
|
132 |
+
if ( !empty($email) ) {
|
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 ( !empty($email) ) {
|
138 |
$avatar = $this->avatar_out($default, $host, $email_hash, $size);
|
139 |
} else {
|
140 |
$avatar = $default;
|
187 |
*/
|
188 |
public function date( $date_format = '' ) {
|
189 |
$df = $date_format ? $date_format : get_option('date_format');
|
190 |
+
$the_date = (string) mysql2date($df, $this->comment_date);
|
191 |
return apply_filters('get_comment_date ', $the_date, $df);
|
192 |
}
|
193 |
|
212 |
*/
|
213 |
public function time( $time_format = '' ) {
|
214 |
$tf = $time_format ? $time_format : get_option('time_format');
|
215 |
+
$the_time = (string) mysql2date($tf, $this->comment_date);
|
216 |
return apply_filters('get_comment_time', $the_time, $tf);
|
217 |
}
|
218 |
|
220 |
* @param string $field_name
|
221 |
* @return mixed
|
222 |
*/
|
223 |
+
public function meta( $field_name ) {
|
224 |
return $this->get_meta_field($field_name);
|
225 |
}
|
226 |
|
237 |
* @param int $comment_id
|
238 |
* @return mixed
|
239 |
*/
|
240 |
+
protected function get_meta_fields( $comment_id = null ) {
|
241 |
+
if ( $comment_id === null ) {
|
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 ( $comment_metas as &$cm ) {
|
248 |
+
if ( is_array($cm) && count($cm) == 1 ) {
|
249 |
$cm = $cm[0];
|
250 |
}
|
251 |
}
|
254 |
}
|
255 |
|
256 |
/**
|
257 |
+
*
|
258 |
* @internal
|
259 |
* @param string $field_name
|
260 |
* @return mixed
|
261 |
*/
|
262 |
+
protected function get_meta_field( $field_name ) {
|
263 |
$value = apply_filters('timber_comment_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
264 |
+
if ( $value === null ) {
|
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 |
*/
|
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 |
'max_depth' => $max_depth,
|
292 |
);
|
293 |
|
294 |
+
return get_comment_reply_link($args, $this->ID, $this->post_id);
|
295 |
}
|
296 |
|
297 |
/* AVATAR Stuff
|
302 |
* @return string
|
303 |
*/
|
304 |
protected function avatar_email() {
|
305 |
+
$id = (int) $this->user_id;
|
306 |
$user = get_userdata($id);
|
307 |
+
if ( $user ) {
|
308 |
$email = $user->user_email;
|
309 |
} else {
|
310 |
$email = $this->comment_author_email;
|
317 |
* @param string $email_hash
|
318 |
* @return string
|
319 |
*/
|
320 |
+
protected function avatar_host( $email_hash ) {
|
321 |
+
if ( is_ssl() ) {
|
322 |
$host = 'https://secure.gravatar.com';
|
323 |
} else {
|
324 |
+
if ( !empty($email_hash) ) {
|
325 |
$host = sprintf("http://%d.gravatar.com", (hexdec($email_hash[0]) % 2));
|
326 |
} else {
|
327 |
$host = 'http://0.gravatar.com';
|
339 |
* @param string $host
|
340 |
* @return string
|
341 |
*/
|
342 |
+
protected function avatar_default( $default, $email, $size, $host ) {
|
343 |
+
if ( substr($default, 0, 1) == '/' ) {
|
344 |
+
$default = home_url().$default;
|
345 |
}
|
346 |
|
347 |
+
if ( empty($default) ) {
|
348 |
$avatar_default = get_option('avatar_default');
|
349 |
+
if ( empty($avatar_default) ) {
|
350 |
$default = 'mystery';
|
351 |
} else {
|
352 |
$default = $avatar_default;
|
353 |
}
|
354 |
}
|
355 |
+
if ( 'mystery' == $default ) {
|
356 |
+
$default = $host.'/avatar/ad516503a11cd5ca435acc9bb6523536?s='.$size;
|
357 |
// ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com')
|
358 |
+
} else if ( 'blank' == $default ) {
|
359 |
$default = $email ? 'blank' : includes_url('images/blank.gif');
|
360 |
+
} else if ( !empty($email) && 'gravatar_default' == $default ) {
|
361 |
$default = '';
|
362 |
+
} else if ( 'gravatar_default' == $default ) {
|
363 |
+
$default = $host.'/avatar/?s='.$size;
|
364 |
+
} else if ( empty($email) && !strstr($default, 'http://') ) {
|
365 |
+
$default = $host.'/avatar/?d='.$default.'&s='.$size;
|
366 |
}
|
367 |
return $default;
|
368 |
}
|
375 |
* @param string $size
|
376 |
* @return mixed
|
377 |
*/
|
378 |
+
protected function avatar_out( $default, $host, $email_hash, $size ) {
|
379 |
+
$out = $host.'/avatar/'.$email_hash.'?s='.$size.'&d='.urlencode($default);
|
380 |
$rating = get_option('avatar_rating');
|
381 |
+
if ( !empty($rating) ) {
|
382 |
+
$out .= '&r='.$rating;
|
383 |
}
|
384 |
return str_replace('&', '&', esc_url($out));
|
385 |
}
|
386 |
|
387 |
+
}
|
lib/Core.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{timber-core-interface.php → CoreInterface.php}
RENAMED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
public function __call( $field, $args );
|
6 |
|
1 |
<?php
|
2 |
|
3 |
+
namespace Timber;
|
4 |
+
|
5 |
+
interface CoreInterface {
|
6 |
|
7 |
public function __call( $field, $args );
|
8 |
|
lib/FunctionWrapper.php
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{timber-helper.php → Helper.php}
RENAMED
@@ -1,9 +1,14 @@
|
|
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
|
7 |
|
8 |
/**
|
9 |
* A utility for a one-stop shop for Transients
|
@@ -26,17 +31,17 @@ class TimberHelper {
|
|
26 |
* @return mixed
|
27 |
*/
|
28 |
public static function transient( $slug, $callback, $transient_time = 0, $lock_timeout = 5, $force = false ) {
|
29 |
-
$slug = apply_filters(
|
30 |
|
31 |
-
$enable_transients = (
|
32 |
-
$data = $enable_transients ? get_transient(
|
33 |
|
34 |
if ( false === $data ) {
|
35 |
|
36 |
-
if ( $enable_transients && self::_is_transient_locked(
|
37 |
|
38 |
-
$force = apply_filters(
|
39 |
-
$force = apply_filters(
|
40 |
|
41 |
if ( !$force ) {
|
42 |
//the server is currently executing the process.
|
@@ -49,14 +54,15 @@ class TimberHelper {
|
|
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 |
-
|
|
|
54 |
|
55 |
$data = $callback();
|
56 |
|
57 |
if ( $enable_transients ) {
|
58 |
-
set_transient(
|
59 |
-
self::_unlock_transient(
|
60 |
}
|
61 |
|
62 |
}
|
@@ -71,7 +77,7 @@ class TimberHelper {
|
|
71 |
* @param integer $lock_timeout
|
72 |
*/
|
73 |
static function _lock_transient( $slug, $lock_timeout ) {
|
74 |
-
set_transient(
|
75 |
}
|
76 |
|
77 |
/**
|
@@ -79,7 +85,7 @@ class TimberHelper {
|
|
79 |
* @param string $slug
|
80 |
*/
|
81 |
static function _unlock_transient( $slug ) {
|
82 |
-
delete_transient(
|
83 |
}
|
84 |
|
85 |
/**
|
@@ -87,7 +93,7 @@ class TimberHelper {
|
|
87 |
* @param string $slug
|
88 |
*/
|
89 |
static function _is_transient_locked( $slug ) {
|
90 |
-
return (bool)get_transient(
|
91 |
}
|
92 |
|
93 |
/* These are for measuring page render time */
|
@@ -99,7 +105,7 @@ class TimberHelper {
|
|
99 |
*/
|
100 |
public static function start_timer() {
|
101 |
$time = microtime();
|
102 |
-
$time = explode(
|
103 |
$time = $time[1] + $time[0];
|
104 |
return $time;
|
105 |
}
|
@@ -117,11 +123,11 @@ class TimberHelper {
|
|
117 |
*/
|
118 |
public static function stop_timer( $start ) {
|
119 |
$time = microtime();
|
120 |
-
$time = explode(
|
121 |
$time = $time[1] + $time[0];
|
122 |
$finish = $time;
|
123 |
-
$total_time = round(
|
124 |
-
return $total_time
|
125 |
}
|
126 |
|
127 |
/* Function Utilities
|
@@ -153,24 +159,22 @@ class TimberHelper {
|
|
153 |
* @param array $args
|
154 |
* @return string
|
155 |
*/
|
156 |
-
public static function ob_function( $function, $args = array(
|
157 |
ob_start();
|
158 |
-
call_user_func_array(
|
159 |
$data = ob_get_contents();
|
160 |
ob_end_clean();
|
161 |
return $data;
|
162 |
}
|
163 |
|
164 |
/**
|
165 |
-
*
|
166 |
-
*
|
167 |
-
* @param
|
168 |
-
* @
|
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
|
174 |
}
|
175 |
|
176 |
/**
|
@@ -183,12 +187,20 @@ class TimberHelper {
|
|
183 |
if ( !WP_DEBUG ) {
|
184 |
return;
|
185 |
}
|
186 |
-
if ( is_object(
|
187 |
-
$arg = print_r(
|
188 |
}
|
189 |
-
return error_log(
|
190 |
}
|
191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
/**
|
193 |
*
|
194 |
*
|
@@ -197,8 +209,8 @@ class TimberHelper {
|
|
197 |
* @return string
|
198 |
*/
|
199 |
public static function get_wp_title( $separator = ' ', $seplocation = 'left' ) {
|
200 |
-
$separator = apply_filters(
|
201 |
-
return trim(
|
202 |
}
|
203 |
|
204 |
/* Text Utilities
|
@@ -215,33 +227,33 @@ class TimberHelper {
|
|
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(
|
223 |
-
$allowed_tag_string .= '<'
|
224 |
}
|
225 |
-
$text = strip_tags(
|
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(
|
228 |
-
$text = trim(
|
229 |
-
preg_match_all(
|
230 |
-
$words_array = array_slice(
|
231 |
$sep = '';
|
232 |
} else {
|
233 |
-
$words_array = preg_split(
|
234 |
$sep = ' ';
|
235 |
}
|
236 |
-
if ( count(
|
237 |
-
array_pop(
|
238 |
-
$text = implode(
|
239 |
-
$text = $text
|
240 |
} else {
|
241 |
-
$text = implode(
|
242 |
}
|
243 |
-
$text = self::close_tags(
|
244 |
-
return apply_filters(
|
245 |
}
|
246 |
|
247 |
/**
|
@@ -252,87 +264,30 @@ class TimberHelper {
|
|
252 |
*/
|
253 |
public static function close_tags( $html ) {
|
254 |
//put all opened tags into an array
|
255 |
-
preg_match_all(
|
256 |
$openedtags = $result[1];
|
257 |
//put all closed tags into an array
|
258 |
-
preg_match_all(
|
259 |
$closedtags = $result[1];
|
260 |
-
$len_opened = count(
|
261 |
// all tags are closed
|
262 |
-
if ( count(
|
263 |
return $html;
|
264 |
}
|
265 |
-
$openedtags = array_reverse(
|
266 |
// close tags
|
267 |
for ( $i = 0; $i < $len_opened; $i++ ) {
|
268 |
-
if ( !in_array(
|
269 |
-
$html .= '</'
|
270 |
} else {
|
271 |
-
unset(
|
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,7 +299,7 @@ class TimberHelper {
|
|
344 |
* @return void
|
345 |
*/
|
346 |
public static function osort( &$array, $prop ) {
|
347 |
-
usort(
|
348 |
return $a->$prop > $b->$prop ? 1 : -1;
|
349 |
} );
|
350 |
}
|
@@ -356,10 +311,10 @@ class TimberHelper {
|
|
356 |
* @return bool
|
357 |
*/
|
358 |
public static function is_array_assoc( $arr ) {
|
359 |
-
if ( !is_array(
|
360 |
return false;
|
361 |
}
|
362 |
-
return (bool)count(
|
363 |
}
|
364 |
|
365 |
/**
|
@@ -369,10 +324,10 @@ class TimberHelper {
|
|
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(
|
375 |
-
$obj->{$k} = self::array_to_object(
|
376 |
} else {
|
377 |
$obj->{$k} = $v;
|
378 |
}
|
@@ -389,10 +344,10 @@ class TimberHelper {
|
|
389 |
* @return bool|int
|
390 |
*/
|
391 |
public static function get_object_index_by_property( $array, $key, $value ) {
|
392 |
-
if ( is_array(
|
393 |
$i = 0;
|
394 |
foreach ( $array as $arr ) {
|
395 |
-
if ( is_array(
|
396 |
if ( $arr[$key] == $value ) {
|
397 |
return $i;
|
398 |
}
|
@@ -417,15 +372,15 @@ class TimberHelper {
|
|
417 |
* @throws Exception
|
418 |
*/
|
419 |
public static function get_object_by_property( $array, $key, $value ) {
|
420 |
-
if ( is_array(
|
421 |
foreach ( $array as $arr ) {
|
422 |
if ( $arr->$key == $value ) {
|
423 |
return $arr;
|
424 |
}
|
425 |
}
|
426 |
} else {
|
427 |
-
throw new InvalidArgumentException(
|
428 |
-
|
429 |
}
|
430 |
}
|
431 |
|
@@ -437,8 +392,8 @@ class TimberHelper {
|
|
437 |
* @return array
|
438 |
*/
|
439 |
public static function array_truncate( $array, $len ) {
|
440 |
-
if ( sizeof(
|
441 |
-
$array = array_splice(
|
442 |
}
|
443 |
return $array;
|
444 |
}
|
@@ -453,11 +408,11 @@ class TimberHelper {
|
|
453 |
* @return bool
|
454 |
*/
|
455 |
public static function is_true( $value ) {
|
456 |
-
if ( isset(
|
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,7 +426,7 @@ class TimberHelper {
|
|
471 |
* @return bool
|
472 |
*/
|
473 |
public static function iseven( $i ) {
|
474 |
-
return (
|
475 |
}
|
476 |
|
477 |
/**
|
@@ -481,7 +436,7 @@ class TimberHelper {
|
|
481 |
* @return bool
|
482 |
*/
|
483 |
public static function isodd( $i ) {
|
484 |
-
return (
|
485 |
}
|
486 |
|
487 |
/* Links, Forms, Etc. Utilities
|
@@ -513,28 +468,28 @@ class TimberHelper {
|
|
513 |
'current' => 0,
|
514 |
'show_all' => false,
|
515 |
'prev_next' => false,
|
516 |
-
'prev_text' => __(
|
517 |
-
'next_text' => __(
|
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(
|
525 |
// Who knows what else people pass in $args
|
526 |
-
$args['total'] = intval(
|
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(
|
534 |
$page_links = array();
|
535 |
$dots = false;
|
536 |
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
537 |
-
$n_display = number_format_i18n(
|
538 |
if ( $n == $args['current'] ) {
|
539 |
$page_links[] = array(
|
540 |
'class' => 'page-number page-numbers current',
|
@@ -545,18 +500,18 @@ class TimberHelper {
|
|
545 |
);
|
546 |
$dots = true;
|
547 |
} else {
|
548 |
-
if ( $args['show_all'] || (
|
549 |
-
$link = str_replace(
|
550 |
-
$link = str_replace(
|
551 |
-
$link = trailingslashit(
|
552 |
if ( $args['add_args'] ) {
|
553 |
-
$link = rtrim(
|
554 |
}
|
555 |
$link = str_replace(' ', '+', $link);
|
556 |
-
$link = untrailingslashit(
|
557 |
$page_links[] = array(
|
558 |
'class' => 'page-number page-numbers',
|
559 |
-
'link' => esc_url(
|
560 |
'title' => $n_display,
|
561 |
'name' => $n_display,
|
562 |
'current' => $args['current'] == $n
|
@@ -565,7 +520,7 @@ class TimberHelper {
|
|
565 |
} elseif ( $dots && !$args['show_all'] ) {
|
566 |
$page_links[] = array(
|
567 |
'class' => 'dots',
|
568 |
-
'title' => __(
|
569 |
);
|
570 |
$dots = false;
|
571 |
}
|
@@ -575,94 +530,10 @@ class TimberHelper {
|
|
575 |
}
|
576 |
|
577 |
/**
|
578 |
-
*
|
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 |
-
|
665 |
-
|
|
|
666 |
}
|
667 |
-
|
668 |
-
}
|
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 Helper {
|
12 |
|
13 |
/**
|
14 |
* A utility for a one-stop shop for Transients
|
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_'.$slug, $force);
|
45 |
|
46 |
if ( !$force ) {
|
47 |
//the server is currently executing the process.
|
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 |
+
self::_lock_transient($slug, $lock_timeout);
|
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 |
* @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 |
* @param string $slug
|
86 |
*/
|
87 |
static function _unlock_transient( $slug ) {
|
88 |
+
delete_transient($slug.'_lock', true);
|
89 |
}
|
90 |
|
91 |
/**
|
93 |
* @param string $slug
|
94 |
*/
|
95 |
static function _is_transient_locked( $slug ) {
|
96 |
+
return (bool) get_transient($slug.'_lock');
|
97 |
}
|
98 |
|
99 |
/* These are for measuring page render time */
|
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 |
*/
|
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 |
* @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 |
+
* @param mixed $function_name or array( $class( string|object ), $function_name )
|
172 |
+
* @param array (optional) $defaults
|
173 |
+
* @param bool (optional) $return_output_buffer Return function output instead of return value (default: false)
|
174 |
+
* @return \TimberFunctionWrapper
|
|
|
|
|
175 |
*/
|
176 |
public static function function_wrapper( $function_name, $defaults = array(), $return_output_buffer = false ) {
|
177 |
+
return new FunctionWrapper($function_name, $defaults, $return_output_buffer);
|
178 |
}
|
179 |
|
180 |
/**
|
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 |
* @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 |
*/
|
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 .= '<'.$tag.'>';
|
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.$more;
|
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 |
*/
|
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 .= '</'.$openedtags[$i].'>';
|
282 |
} else {
|
283 |
+
unset($closedtags[array_search($openedtags[$i], $closedtags)]);
|
284 |
}
|
285 |
}
|
286 |
+
$html = str_replace(array('</br>', '</hr>', '</wbr>'), '', $html);
|
287 |
+
$html = str_replace(array('<br>', '<hr>', '<wbr>'), array('<br />', '<hr />', '<wbr />'), $html);
|
288 |
return $html;
|
289 |
}
|
290 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
/* Object Utilities
|
292 |
======================== */
|
293 |
|
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 |
* @return bool
|
312 |
*/
|
313 |
public static function is_array_assoc( $arr ) {
|
314 |
+
if ( !is_array($arr) ) {
|
315 |
return false;
|
316 |
}
|
317 |
+
return (bool) count(array_filter(array_keys($arr), 'is_string'));
|
318 |
}
|
319 |
|
320 |
/**
|
324 |
* @return stdClass
|
325 |
*/
|
326 |
public static function array_to_object( $array ) {
|
327 |
+
$obj = new \stdClass;
|
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 |
* @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 |
* @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 \InvalidArgumentException('$array is not an array, got:');
|
383 |
+
Helper::error_log($array);
|
384 |
}
|
385 |
}
|
386 |
|
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 |
* @return bool
|
409 |
*/
|
410 |
public static function is_true( $value ) {
|
411 |
+
if ( isset($value) ) {
|
412 |
+
if ( is_string($value) ) {
|
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 |
* @return bool
|
427 |
*/
|
428 |
public static function iseven( $i ) {
|
429 |
+
return ($i % 2) == 0;
|
430 |
}
|
431 |
|
432 |
/**
|
436 |
* @return bool
|
437 |
*/
|
438 |
public static function isodd( $i ) {
|
439 |
+
return ($i % 2) != 0;
|
440 |
}
|
441 |
|
442 |
/* Links, Forms, Etc. Utilities
|
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) $args['total']);
|
482 |
if ( $args['total'] < 2 ) {
|
483 |
return array();
|
484 |
}
|
485 |
+
$args['current'] = (int) $args['current'];
|
486 |
+
$args['end_size'] = 0 < (int) $args['end_size'] ? (int) $args['end_size'] : 1; // Out of bounds? Make it the default.
|
487 |
+
$args['mid_size'] = 0 <= (int) $args['mid_size'] ? (int) $args['mid_size'] : 2;
|
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 |
);
|
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 |
} elseif ( $dots && !$args['show_all'] ) {
|
521 |
$page_links[] = array(
|
522 |
'class' => 'dots',
|
523 |
+
'title' => __('…')
|
524 |
);
|
525 |
$dots = false;
|
526 |
}
|
530 |
}
|
531 |
|
532 |
/**
|
533 |
+
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
*/
|
535 |
+
function get_current_url() {
|
536 |
+
Helper::warn('TimberHelper::get_current_url() is deprecated and will be removed in future versions, use Timber\URLHelper::get_current_url()');
|
537 |
+
return URLHelper::get_current_url();
|
538 |
}
|
539 |
+
}
|
|
lib/{timber-image.php → Image.php}
RENAMED
@@ -1,5 +1,13 @@
|
|
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,7 +45,7 @@
|
|
37 |
* </article>
|
38 |
* ```
|
39 |
*/
|
40 |
-
class
|
41 |
|
42 |
protected $_can_edit;
|
43 |
protected $_dimensions;
|
@@ -88,7 +96,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
88 |
* ```
|
89 |
* @param int|string $iid
|
90 |
*/
|
91 |
-
public function __construct($iid) {
|
92 |
$this->init($iid);
|
93 |
}
|
94 |
|
@@ -96,8 +104,8 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
96 |
* @return string the src of the file
|
97 |
*/
|
98 |
public function __toString() {
|
99 |
-
if ( $this->
|
100 |
-
return $this->
|
101 |
}
|
102 |
return '';
|
103 |
}
|
@@ -115,7 +123,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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,7 +141,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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,31 +154,42 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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,9 +200,9 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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'
|
187 |
}
|
188 |
return $url;
|
189 |
}
|
@@ -203,8 +222,12 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
203 |
* @param int $iid
|
204 |
*/
|
205 |
function init( $iid = false ) {
|
206 |
-
if (
|
207 |
-
|
|
|
|
|
|
|
|
|
208 |
$this->init_with_url($iid);
|
209 |
return;
|
210 |
}
|
@@ -215,23 +238,23 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
215 |
|
216 |
$relative = false;
|
217 |
$iid_lower = strtolower($iid);
|
218 |
-
foreach( $this->file_types as $type ) { if( strstr(
|
219 |
if ( $relative ) {
|
220 |
-
$this->init_with_relative_path(
|
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
|
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/
|
235 |
*/
|
236 |
$iid = (int) $iid->_thumbnail_id;
|
237 |
}
|
@@ -242,10 +265,10 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
242 |
$basedir = self::wp_upload_dir();
|
243 |
$basedir = $basedir['basedir'];
|
244 |
if ( isset($this->file) ) {
|
245 |
-
$this->file_loc = $basedir
|
246 |
} else if ( isset($this->_wp_attached_file) ) {
|
247 |
$this->file = reset($this->_wp_attached_file);
|
248 |
-
$this->file_loc = $basedir
|
249 |
}
|
250 |
if ( isset($image_info['id']) ) {
|
251 |
$this->ID = $image_info['id'];
|
@@ -253,17 +276,17 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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 |
-
|
264 |
-
|
265 |
} else {
|
266 |
-
|
267 |
}
|
268 |
}
|
269 |
}
|
@@ -273,8 +296,8 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
273 |
* @param string $relative_path
|
274 |
*/
|
275 |
protected function init_with_relative_path( $relative_path ) {
|
276 |
-
$this->abs_url = home_url(
|
277 |
-
$file_path =
|
278 |
$this->file_loc = $file_path;
|
279 |
$this->file = $file_path;
|
280 |
}
|
@@ -284,7 +307,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
284 |
* @param string $file_path
|
285 |
*/
|
286 |
protected function init_with_file_path( $file_path ) {
|
287 |
-
$url =
|
288 |
$this->abs_url = $url;
|
289 |
$this->file_loc = $file_path;
|
290 |
$this->file = $file_path;
|
@@ -294,11 +317,11 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
294 |
* @internal
|
295 |
* @param string $url
|
296 |
*/
|
297 |
-
protected function init_with_url($url) {
|
298 |
$this->abs_url = $url;
|
299 |
-
if (
|
300 |
-
$this->file = ABSPATH
|
301 |
-
$this->file_loc = ABSPATH
|
302 |
}
|
303 |
}
|
304 |
|
@@ -393,7 +416,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
393 |
* @return string the /relative/path/to/the/file
|
394 |
*/
|
395 |
public function path() {
|
396 |
-
return
|
397 |
}
|
398 |
|
399 |
/**
|
@@ -409,7 +432,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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,19 +453,11 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
430 |
$dir = self::wp_upload_dir();
|
431 |
$base = $dir['baseurl'];
|
432 |
|
433 |
-
$src = trailingslashit($this->_maybe_secure_url($base))
|
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,69 +473,34 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
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 |
-
|
|
|
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
|
504 |
-
|
|
|
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 |
-
* @
|
518 |
-
* @deprecated 0.21.9
|
519 |
-
* @see TimberImage::alt
|
520 |
* @return string
|
521 |
*/
|
522 |
-
function
|
523 |
-
|
|
|
524 |
}
|
525 |
-
|
526 |
-
}
|
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 |
* </article>
|
46 |
* ```
|
47 |
*/
|
48 |
+
class Image extends Post implements CoreInterface {
|
49 |
|
50 |
protected $_can_edit;
|
51 |
protected $_dimensions;
|
96 |
* ```
|
97 |
* @param int|string $iid
|
98 |
*/
|
99 |
+
public function __construct( $iid ) {
|
100 |
$this->init($iid);
|
101 |
}
|
102 |
|
104 |
* @return string the src of the file
|
105 |
*/
|
106 |
public function __toString() {
|
107 |
+
if ( $this->src() ) {
|
108 |
+
return $this->src();
|
109 |
}
|
110 |
return '';
|
111 |
}
|
123 |
* @param string $dim
|
124 |
* @return array|int
|
125 |
*/
|
126 |
+
protected function get_dimensions( $dim = null ) {
|
127 |
if ( isset($this->_dimensions) ) {
|
128 |
return $this->get_dimensions_loaded($dim);
|
129 |
}
|
141 |
* @param string|null $dim
|
142 |
* @return array|int
|
143 |
*/
|
144 |
+
protected function get_dimensions_loaded( $dim ) {
|
145 |
if ( $dim === null ) {
|
146 |
return $this->_dimensions;
|
147 |
}
|
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 ( is_numeric($iid) ) {
|
175 |
$image_info = wp_get_attachment_metadata($iid);
|
176 |
+
if ( !is_array($image_info) ) {
|
177 |
$image_info = array();
|
178 |
}
|
179 |
+
$image_custom = self::get_post_custom($iid);
|
180 |
$basic = get_post($iid);
|
181 |
+
if ( $basic ) {
|
182 |
+
if ( isset($basic->post_excerpt) ) {
|
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 ( is_array($image_info) && isset($image_info['image']) ) {
|
190 |
return $image_info['image'];
|
191 |
}
|
192 |
+
if ( is_object($image_info) ) {
|
193 |
return get_object_vars($image_info);
|
194 |
}
|
195 |
return $iid;
|
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( $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 |
* @param int $iid
|
223 |
*/
|
224 |
function init( $iid = false ) {
|
225 |
+
if ( !$iid ) { Helper::error_log('Initalized TimberImage without providing first parameter.'); return; }
|
226 |
+
if ( $iid instanceof self ) {
|
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 |
|
239 |
$relative = false;
|
240 |
$iid_lower = strtolower($iid);
|
241 |
+
foreach ( $this->file_types as $type ) { if ( strstr($iid_lower, $type) ) { $relative = true; break; } };
|
242 |
if ( $relative ) {
|
243 |
+
$this->init_with_relative_path($iid);
|
244 |
return;
|
245 |
}
|
246 |
+
} else if ( $iid instanceof \WP_Post ) {
|
247 |
+
$ref = new \ReflectionClass($this);
|
248 |
$post = $ref->getParentClass()->newInstance($iid->ID);
|
249 |
+
if ( isset($post->_thumbnail_id) && $post->_thumbnail_id ) {
|
250 |
return $this->init((int) $post->_thumbnail_id);
|
251 |
}
|
252 |
return $this->init($iid->ID);
|
253 |
+
} else if ( $iid instanceof Post ) {
|
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/timber/timber/wiki/Extending-Timber
|
258 |
*/
|
259 |
$iid = (int) $iid->_thumbnail_id;
|
260 |
}
|
265 |
$basedir = self::wp_upload_dir();
|
266 |
$basedir = $basedir['basedir'];
|
267 |
if ( isset($this->file) ) {
|
268 |
+
$this->file_loc = $basedir.DIRECTORY_SEPARATOR.$this->file;
|
269 |
} else if ( isset($this->_wp_attached_file) ) {
|
270 |
$this->file = reset($this->_wp_attached_file);
|
271 |
+
$this->file_loc = $basedir.DIRECTORY_SEPARATOR.$this->file;
|
272 |
}
|
273 |
if ( isset($image_info['id']) ) {
|
274 |
$this->ID = $image_info['id'];
|
276 |
$this->ID = $iid;
|
277 |
}
|
278 |
if ( isset($this->ID) ) {
|
279 |
+
$custom = self::get_post_custom($this->ID);
|
280 |
+
foreach ( $custom as $key => $value ) {
|
281 |
$this->$key = $value[0];
|
282 |
}
|
283 |
$this->id = $this->ID;
|
284 |
} else {
|
285 |
if ( is_array($iid) || is_object($iid) ) {
|
286 |
+
Helper::error_log('Not able to init in TimberImage with iid=');
|
287 |
+
Helper::error_log($iid);
|
288 |
} else {
|
289 |
+
Helper::error_log('Not able to init in TimberImage with iid='.$iid);
|
290 |
}
|
291 |
}
|
292 |
}
|
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 = URLHelper::get_full_path($relative_path);
|
301 |
$this->file_loc = $file_path;
|
302 |
$this->file = $file_path;
|
303 |
}
|
307 |
* @param string $file_path
|
308 |
*/
|
309 |
protected function init_with_file_path( $file_path ) {
|
310 |
+
$url = URLHelper::file_system_to_url($file_path);
|
311 |
$this->abs_url = $url;
|
312 |
$this->file_loc = $file_path;
|
313 |
$this->file = $file_path;
|
317 |
* @internal
|
318 |
* @param string $url
|
319 |
*/
|
320 |
+
protected function init_with_url( $url ) {
|
321 |
$this->abs_url = $url;
|
322 |
+
if ( URLHelper::is_local($url) ) {
|
323 |
+
$this->file = URLHelper::remove_double_slashes(ABSPATH.URLHelper::get_rel_url($url));
|
324 |
+
$this->file_loc = URLHelper::remove_double_slashes(ABSPATH.URLHelper::get_rel_url($url));
|
325 |
}
|
326 |
}
|
327 |
|
416 |
* @return string the /relative/path/to/the/file
|
417 |
*/
|
418 |
public function path() {
|
419 |
+
return URLHelper::get_rel_path($this->src());
|
420 |
}
|
421 |
|
422 |
/**
|
432 |
* ```
|
433 |
* @return bool|string
|
434 |
*/
|
435 |
+
public function src( $size = '' ) {
|
436 |
if ( isset($this->abs_url) ) {
|
437 |
return $this->_maybe_secure_url($this->abs_url);
|
438 |
}
|
453 |
$dir = self::wp_upload_dir();
|
454 |
$base = $dir['baseurl'];
|
455 |
|
456 |
+
$src = trailingslashit($this->_maybe_secure_url($base)).$this->file;
|
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 |
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 |
+
public function get_src( $size = '' ) {
|
483 |
+
Helper::warn('{{image.get_src}} is deprecated and will be removed in 1.1; use {{image.src}}');
|
484 |
+
return $this->src($size);
|
485 |
}
|
486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
|
488 |
/**
|
489 |
+
* @deprecated since 0.21.9 use src() instead
|
490 |
* @return string
|
491 |
*/
|
492 |
+
public function url( $size = '' ) {
|
493 |
+
Helper::warn('{{image.url}} is deprecated and will be removed in 1.1; use {{image.src}}');
|
494 |
+
return $this->src($size);
|
495 |
}
|
496 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
497 |
|
498 |
/**
|
499 |
+
* @deprecated since 0.21.9 use src() instead
|
|
|
|
|
500 |
* @return string
|
501 |
*/
|
502 |
+
public function get_url( $size = '' ) {
|
503 |
+
Helper::warn('{{image.get_url}} is deprecated and will be removed in 1.1; use {{image.src}}');
|
504 |
+
return $this->src($size);
|
505 |
}
|
506 |
+
}
|
|
lib/{image/timber-image-operation.php → Image/Operation.php}
RENAMED
@@ -1,4 +1,7 @@
|
|
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,8 +11,9 @@
|
|
8 |
* - filename
|
9 |
* - run
|
10 |
*/
|
11 |
-
abstract class
|
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,7 +21,7 @@ abstract class TimberImageOperation {
|
|
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,7 +31,7 @@ abstract class TimberImageOperation {
|
|
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,13 +41,13 @@ abstract class TimberImageOperation {
|
|
37 |
* ex: array('red' => 255, 'green' => 20, 'blue' => 85);
|
38 |
*/
|
39 |
public static function hexrgb( $hexstr ) {
|
40 |
-
if ( !strstr(
|
41 |
-
$hexstr = '#'
|
42 |
}
|
43 |
-
if ( strlen(
|
44 |
-
$hexstr = '#'
|
45 |
}
|
46 |
-
$int = hexdec(
|
47 |
-
return array(
|
48 |
}
|
49 |
}
|
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 |
* - filename
|
12 |
* - run
|
13 |
*/
|
14 |
+
abstract class Operation {
|
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 |
* @return string resulting filename (including extension but excluding path)
|
22 |
* ex: my-awesome-file.jpg
|
23 |
*/
|
24 |
+
public abstract function filename( $src_filename, $src_extension );
|
25 |
|
26 |
/**
|
27 |
* Performs the actual image manipulation,
|
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( $load_filename, $save_filename );
|
35 |
|
36 |
/**
|
37 |
* Helper method to convert hex string to rgb array
|
41 |
* ex: array('red' => 255, 'green' => 20, 'blue' => 85);
|
42 |
*/
|
43 |
public static function hexrgb( $hexstr ) {
|
44 |
+
if ( !strstr($hexstr, '#') ) {
|
45 |
+
$hexstr = '#'.$hexstr;
|
46 |
}
|
47 |
+
if ( strlen($hexstr) == 4 ) {
|
48 |
+
$hexstr = '#'.$hexstr[1].$hexstr[1].$hexstr[2].$hexstr[2].$hexstr[3].$hexstr[3];
|
49 |
}
|
50 |
+
$int = hexdec($hexstr);
|
51 |
+
return array("red" => 0xFF & ($int >> 0x10), "green" => 0xFF & ($int >> 0x8), "blue" => 0xFF & $int);
|
52 |
}
|
53 |
}
|
lib/{image/timber-image-operation-letterbox.php → Image/Operation/Letterbox.php}
RENAMED
@@ -1,4 +1,10 @@
|
|
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,7 +14,7 @@
|
|
8 |
* - height of new image
|
9 |
* - color of padding
|
10 |
*/
|
11 |
-
class
|
12 |
|
13 |
private $w, $h, $color;
|
14 |
|
@@ -17,7 +23,7 @@ class TimberImageOperationLetterbox extends TimberImageOperation {
|
|
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,10 +35,10 @@ class TimberImageOperationLetterbox extends TimberImageOperation {
|
|
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(
|
34 |
-
$newbase = $src_filename
|
35 |
-
$new_name = $newbase
|
36 |
return $new_name;
|
37 |
}
|
38 |
|
@@ -46,16 +52,16 @@ class TimberImageOperationLetterbox extends TimberImageOperation {
|
|
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(
|
54 |
-
$c = self::hexrgb(
|
55 |
-
$bgColor = imagecolorallocate(
|
56 |
-
imagefill(
|
57 |
-
$image = wp_get_image_editor(
|
58 |
-
if ( !is_wp_error(
|
59 |
$current_size = $image->get_size();
|
60 |
$quality = $image->get_quality();
|
61 |
$ow = $current_size['width'];
|
@@ -69,38 +75,38 @@ class TimberImageOperationLetterbox extends TimberImageOperation {
|
|
69 |
$y = 0;
|
70 |
$x = $w / 2 - $owt / 2;
|
71 |
$oht = $h;
|
72 |
-
$image->crop(
|
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(
|
80 |
}
|
81 |
-
$result = $image->save(
|
82 |
$func = 'imagecreatefromjpeg';
|
83 |
$save_func = 'imagejpeg';
|
84 |
-
$ext = pathinfo(
|
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(
|
97 |
-
imagecopy(
|
98 |
-
if ($save_func === 'imagegif') {
|
99 |
-
return $save_func(
|
100 |
}
|
101 |
-
return $save_func(
|
102 |
} else {
|
103 |
-
|
104 |
}
|
105 |
return false;
|
106 |
}
|
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 |
* - height of new image
|
15 |
* - color of padding
|
16 |
*/
|
17 |
+
class Letterbox extends ImageOperation {
|
18 |
|
19 |
private $w, $h, $color;
|
20 |
|
23 |
* @param int $h height
|
24 |
* @param string $color hex string, for color of padding bands
|
25 |
*/
|
26 |
+
function __construct( $w, $h, $color ) {
|
27 |
$this->w = $w;
|
28 |
$this->h = $h;
|
29 |
$this->color = $color;
|
35 |
* @return string the final filename to be used
|
36 |
* (ex: my-awesome-pic-lbox-300x200-FF3366.jpg)
|
37 |
*/
|
38 |
+
public function filename( $src_filename, $src_extension ) {
|
39 |
+
$color = str_replace('#', '', $this->color);
|
40 |
+
$newbase = $src_filename.'-lbox-'.$this->w.'x'.$this->h.'-'.$color;
|
41 |
+
$new_name = $newbase.'.'.$src_extension;
|
42 |
return $new_name;
|
43 |
}
|
44 |
|
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( $load_filename, $save_filename ) {
|
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 |
$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 ( $quality > 9 ) {
|
98 |
+
$quality = $quality / 10;
|
99 |
$quality = round(10 - $quality);
|
100 |
}
|
101 |
}
|
102 |
+
$image = $func($save_filename);
|
103 |
+
imagecopy($bg, $image, $x, $y, 0, 0, $owt, $oht);
|
104 |
+
if ( $save_func === 'imagegif' ) {
|
105 |
+
return $save_func($bg, $save_filename);
|
106 |
}
|
107 |
+
return $save_func($bg, $save_filename, $quality);
|
108 |
} else {
|
109 |
+
Helper::error_log($image);
|
110 |
}
|
111 |
return false;
|
112 |
}
|
lib/{image/timber-image-operation-resize.php → Image/Operation/Resize.php}
RENAMED
@@ -1,4 +1,10 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* Changes image to new size, by shrinking/enlarging
|
4 |
* then cropping to respect new ratio.
|
@@ -8,7 +14,7 @@
|
|
8 |
* - height of new image
|
9 |
* - crop method
|
10 |
*/
|
11 |
-
class
|
12 |
|
13 |
private $w, $h, $crop;
|
14 |
|
@@ -17,12 +23,12 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
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(
|
25 |
-
if ( $crop !== false && !in_array(
|
26 |
$crop = $allowed_crop_positions[0];
|
27 |
}
|
28 |
$this->crop = $crop;
|
@@ -33,7 +39,7 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
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,8 +48,8 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
42 |
if ( $this->h ) {
|
43 |
$h = $this->h;
|
44 |
}
|
45 |
-
$result = $src_filename
|
46 |
-
if($src_extension) {
|
47 |
$result .= '.'.$src_extension;
|
48 |
}
|
49 |
return $result;
|
@@ -54,7 +60,7 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
54 |
* @param string $save_filename
|
55 |
*/
|
56 |
protected function run_animated_gif( $load_filename, $save_filename ) {
|
57 |
-
$image = wp_get_image_editor(
|
58 |
$current_size = $image->get_size();
|
59 |
$src_w = $current_size['width'];
|
60 |
$src_h = $current_size['height'];
|
@@ -63,10 +69,10 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
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(
|
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,8 +81,11 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
75 |
return $image->writeImages($save_filename, true);
|
76 |
}
|
77 |
|
|
|
|
|
|
|
78 |
protected function get_target_sizes( $load_filename ) {
|
79 |
-
$image = wp_get_image_editor(
|
80 |
$w = $this->w;
|
81 |
$h = $this->h;
|
82 |
$crop = $this->crop;
|
@@ -86,11 +95,11 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
86 |
$src_h = $current_size['height'];
|
87 |
$src_ratio = $src_w / $src_h;
|
88 |
if ( !$h ) {
|
89 |
-
$h = round(
|
90 |
}
|
91 |
if ( !$w ) {
|
92 |
//the user wants to resize based on constant height
|
93 |
-
$w = round(
|
94 |
}
|
95 |
if ( !$crop ) {
|
96 |
return array(
|
@@ -104,13 +113,13 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
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 = (
|
108 |
//now specific overrides based on options:
|
109 |
switch ( $crop ) {
|
110 |
case 'center':
|
111 |
// Get source x and y
|
112 |
-
$src_x = round(
|
113 |
-
$src_y = round(
|
114 |
break;
|
115 |
|
116 |
case 'top':
|
@@ -122,11 +131,11 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
122 |
break;
|
123 |
|
124 |
case 'top-center':
|
125 |
-
$src_y = round(
|
126 |
break;
|
127 |
|
128 |
case 'bottom-center':
|
129 |
-
$src_y = $src_h - $src_ht - round(
|
130 |
break;
|
131 |
|
132 |
case 'left':
|
@@ -138,7 +147,7 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
138 |
break;
|
139 |
}
|
140 |
// Crop the image
|
141 |
-
return (
|
142 |
? array(
|
143 |
'x' => 0, 'y' => $src_y,
|
144 |
'src_w' => $src_w, 'src_h' => $src_ht,
|
@@ -159,44 +168,44 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
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
|
163 |
*/
|
164 |
-
public function run($load_filename, $save_filename) {
|
165 |
//should be resized by gif resizer
|
166 |
-
if (
|
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(
|
176 |
-
if ( !is_wp_error(
|
177 |
-
$crop = self::get_target_sizes(
|
178 |
-
$image->crop(
|
179 |
$crop['y'],
|
180 |
$crop['src_w'],
|
181 |
$crop['src_h'],
|
182 |
$crop['target_w'],
|
183 |
$crop['target_h']
|
184 |
);
|
185 |
-
$result = $image->save(
|
186 |
-
if ( is_wp_error(
|
187 |
// @codeCoverageIgnoreStart
|
188 |
-
|
189 |
-
|
190 |
return false;
|
191 |
// @codeCoverageIgnoreEnd
|
192 |
} else {
|
193 |
return true;
|
194 |
}
|
195 |
-
} else if ( isset(
|
196 |
// @codeCoverageIgnoreStart
|
197 |
-
|
198 |
} else {
|
199 |
-
|
200 |
// @codeCoverageIgnoreEnd
|
201 |
}
|
202 |
}
|
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 |
* - height of new image
|
15 |
* - crop method
|
16 |
*/
|
17 |
+
class Resize extends ImageOperation {
|
18 |
|
19 |
private $w, $h, $crop;
|
20 |
|
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( $w, $h, $crop ) {
|
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 |
* @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( $src_filename, $src_extension ) {
|
43 |
$w = 0;
|
44 |
$h = 0;
|
45 |
if ( $this->w ) {
|
48 |
if ( $this->h ) {
|
49 |
$h = $this->h;
|
50 |
}
|
51 |
+
$result = $src_filename.'-'.$w.'x'.$h.'-c-'.($this->crop ? $this->crop : 'f'); // Crop will be either user named or f (false)
|
52 |
+
if ( $src_extension ) {
|
53 |
$result .= '.'.$src_extension;
|
54 |
}
|
55 |
return $result;
|
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 |
if ( !class_exists('Imagick') ) {
|
70 |
return false;
|
71 |
}
|
72 |
+
$image = new \Imagick($load_filename);
|
73 |
$image = $image->coalesceImages();
|
74 |
+
$crop = self::get_target_sizes($load_filename);
|
75 |
+
foreach ( $image as $frame ) {
|
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 |
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 |
$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 |
$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 |
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 |
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 |
* (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 boolean|null true if everything went fine, false otherwise
|
172 |
*/
|
173 |
+
public function run( $load_filename, $save_filename ) {
|
174 |
//should be resized by gif resizer
|
175 |
+
if ( \Timber\ImageHelper::is_animated_gif($load_filename) ) {
|
176 |
//attempt to resize
|
177 |
//return if successful
|
178 |
//proceed if not
|
179 |
$gif = self::run_animated_gif($load_filename, $save_filename);
|
180 |
+
if ( $gif ) {
|
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 |
+
Helper::error_log('Error resizing image');
|
198 |
+
Helper::error_log($result);
|
199 |
return false;
|
200 |
// @codeCoverageIgnoreEnd
|
201 |
} else {
|
202 |
return true;
|
203 |
}
|
204 |
+
} else if ( isset($image->error_data['error_loading_image']) ) {
|
205 |
// @codeCoverageIgnoreStart
|
206 |
+
Helper::error_log('Error loading '.$image->error_data['error_loading_image']);
|
207 |
} else {
|
208 |
+
Helper::error_log($image);
|
209 |
// @codeCoverageIgnoreEnd
|
210 |
}
|
211 |
}
|
lib/Image/Operation/Retina.php
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{image/timber-image-operation-tojpg.php → Image/Operation/ToJpg.php}
RENAMED
@@ -1,18 +1,22 @@
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Implements converting a PNG file to JPG.
|
5 |
* Argument:
|
6 |
* - color to fill transparent zones
|
7 |
*/
|
8 |
-
class
|
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,8 +25,8 @@ class TimberImageOperationToJpg extends TimberImageOperation {
|
|
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
|
26 |
return $new_name;
|
27 |
}
|
28 |
|
@@ -35,15 +39,15 @@ class TimberImageOperationToJpg extends TimberImageOperation {
|
|
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(
|
40 |
-
list(
|
41 |
-
$output = imagecreatetruecolor(
|
42 |
-
$c = self::hexrgb(
|
43 |
-
$color = imagecolorallocate(
|
44 |
-
imagefilledrectangle(
|
45 |
-
imagecopy(
|
46 |
-
imagejpeg(
|
47 |
return true;
|
48 |
}
|
49 |
|
@@ -55,7 +59,7 @@ class TimberImageOperationToJpg extends TimberImageOperation {
|
|
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,6 +73,6 @@ class TimberImageOperationToJpg extends TimberImageOperation {
|
|
69 |
if ( $ext == 'jpg' || $ext == 'jpeg' ) {
|
70 |
return imagecreatefromjpeg($filename);
|
71 |
}
|
72 |
-
throw new InvalidArgumentException(
|
73 |
}
|
74 |
}
|
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 ToJpg extends ImageOperation {
|
13 |
|
14 |
private $color;
|
15 |
|
16 |
/**
|
17 |
* @param string $color hex string of color to use for transparent zones
|
18 |
*/
|
19 |
+
function __construct( $color ) {
|
20 |
$this->color = $color;
|
21 |
}
|
22 |
|
25 |
* @param string $src_extension ignored
|
26 |
* @return string the final filename to be used (ex: my-awesome-pic.jpg)
|
27 |
*/
|
28 |
+
function filename( $src_filename, $src_extension = 'jpg' ) {
|
29 |
+
$new_name = $src_filename.'.jpg';
|
30 |
return $new_name;
|
31 |
}
|
32 |
|
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( $load_filename, $save_filename ) {
|
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 |
function image_create( $filename, $ext = 'auto' ) {
|
60 |
if ( $ext == 'auto' ) {
|
61 |
$ext = wp_check_filetype($filename);
|
62 |
+
if ( isset($ext['ext']) ) {
|
63 |
$ext = $ext['ext'];
|
64 |
}
|
65 |
}
|
73 |
if ( $ext == 'jpg' || $ext == 'jpeg' ) {
|
74 |
return imagecreatefromjpeg($filename);
|
75 |
}
|
76 |
+
throw new \InvalidArgumentException('image_create only accepts PNG, GIF and JPGs. File extension was: '.$ext);
|
77 |
}
|
78 |
}
|
lib/{timber-image-helper.php → ImageHelper.php}
RENAMED
@@ -1,8 +1,18 @@
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Implements the Twig image filters:
|
5 |
-
* https://github.com/
|
6 |
* - resize
|
7 |
* - retina
|
8 |
* - letterbox
|
@@ -13,7 +23,7 @@
|
|
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
|
17 |
|
18 |
const BASE_UPLOADS = 1;
|
19 |
const BASE_CONTENT = 2;
|
@@ -52,7 +62,7 @@ class TimberImageHelper {
|
|
52 |
return $src;
|
53 |
}
|
54 |
}
|
55 |
-
$op = new
|
56 |
return self::_operate($src, $op, $force);
|
57 |
}
|
58 |
|
@@ -91,7 +101,7 @@ class TimberImageHelper {
|
|
91 |
* @return string url to the new image
|
92 |
*/
|
93 |
public static function retina_resize( $src, $multiplier = 2, $force = false ) {
|
94 |
-
$op = new
|
95 |
return self::_operate($src, $op, $force);
|
96 |
}
|
97 |
|
@@ -106,7 +116,7 @@ class TimberImageHelper {
|
|
106 |
return false;
|
107 |
}
|
108 |
//its a gif so test
|
109 |
-
if( !($fh = @fopen($file, 'rb')) ) {
|
110 |
return false;
|
111 |
}
|
112 |
$count = 0;
|
@@ -118,13 +128,13 @@ class TimberImageHelper {
|
|
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 |
-
|
127 |
-
|
128 |
}
|
129 |
|
130 |
/**
|
@@ -139,7 +149,7 @@ class TimberImageHelper {
|
|
139 |
* @return mixed|null|string
|
140 |
*/
|
141 |
public static function letterbox( $src, $w, $h, $color = '#000000', $force = false ) {
|
142 |
-
$op = new
|
143 |
return self::_operate($src, $op, $force);
|
144 |
}
|
145 |
|
@@ -151,7 +161,7 @@ class TimberImageHelper {
|
|
151 |
* @return string
|
152 |
*/
|
153 |
public static function img_to_jpg( $src, $bghex = '#FFFFFF', $force = false ) {
|
154 |
-
$op = new
|
155 |
return self::_operate($src, $op, $force);
|
156 |
}
|
157 |
|
@@ -159,13 +169,13 @@ class TimberImageHelper {
|
|
159 |
* Deletes all resized versions of an image when the source is deleted
|
160 |
*/
|
161 |
protected static function add_actions() {
|
162 |
-
add_action(
|
163 |
-
$post = get_post(
|
164 |
-
$image_types = array(
|
165 |
-
if ( in_array(
|
166 |
-
$attachment = new
|
167 |
if ( $attachment->file_loc ) {
|
168 |
-
|
169 |
}
|
170 |
}
|
171 |
} );
|
@@ -176,9 +186,9 @@ class TimberImageHelper {
|
|
176 |
* for example /wp-content or /content
|
177 |
*/
|
178 |
protected static function add_constants() {
|
179 |
-
if ( !defined(
|
180 |
-
$wp_content_path = str_replace(
|
181 |
-
define(
|
182 |
}
|
183 |
}
|
184 |
|
@@ -188,8 +198,8 @@ class TimberImageHelper {
|
|
188 |
* @return void
|
189 |
*/
|
190 |
static function add_filters() {
|
191 |
-
add_filter(
|
192 |
-
$arr['relative'] = str_replace(
|
193 |
return $arr;
|
194 |
} );
|
195 |
}
|
@@ -201,17 +211,17 @@ class TimberImageHelper {
|
|
201 |
* or: http://example.org/wp-content/uploads/2015/my-pic.jpg
|
202 |
*/
|
203 |
static function delete_generated_files( $local_file ) {
|
204 |
-
if (
|
205 |
-
$local_file =
|
206 |
}
|
207 |
-
$info = pathinfo(
|
208 |
$dir = $info['dirname'];
|
209 |
$ext = $info['extension'];
|
210 |
$filename = $info['filename'];
|
211 |
-
self::process_delete_generated_files(
|
212 |
-
self::process_delete_generated_files(
|
213 |
-
self::process_delete_generated_files(
|
214 |
-
self::process_delete_generated_files(
|
215 |
}
|
216 |
|
217 |
/**
|
@@ -229,18 +239,17 @@ class TimberImageHelper {
|
|
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 = '/'
|
233 |
-
foreach ( glob(
|
234 |
-
$regexdir = str_replace(
|
235 |
-
$pattern = '/'
|
236 |
-
$match = preg_match(
|
237 |
-
if (
|
238 |
-
unlink(
|
239 |
}
|
240 |
}
|
241 |
}
|
242 |
|
243 |
-
|
244 |
/**
|
245 |
* Determines the filepath corresponding to a given URL
|
246 |
*
|
@@ -249,7 +258,7 @@ class TimberImageHelper {
|
|
249 |
*/
|
250 |
public static function get_server_location( $url ) {
|
251 |
// if we're already an absolute dir, just return
|
252 |
-
if ( 0 === strpos(
|
253 |
return $url;
|
254 |
}
|
255 |
// otherwise, analyze URL then build mapping path
|
@@ -268,14 +277,14 @@ class TimberImageHelper {
|
|
268 |
$upload = wp_upload_dir();
|
269 |
$dir = $upload['path'];
|
270 |
$filename = $file;
|
271 |
-
$file = parse_url(
|
272 |
-
$path_parts = pathinfo(
|
273 |
-
$basename = md5(
|
274 |
$ext = 'jpg';
|
275 |
-
if ( isset(
|
276 |
$ext = $path_parts['extension'];
|
277 |
}
|
278 |
-
return $dir
|
279 |
}
|
280 |
|
281 |
/**
|
@@ -285,27 +294,27 @@ class TimberImageHelper {
|
|
285 |
* @return string the URL to the downloaded file
|
286 |
*/
|
287 |
public static function sideload_image( $file ) {
|
288 |
-
$loc = self::get_sideloaded_file_loc(
|
289 |
-
if ( file_exists(
|
290 |
-
return
|
291 |
}
|
292 |
// Download file to temp location
|
293 |
-
if ( !function_exists(
|
294 |
-
require_once ABSPATH
|
295 |
}
|
296 |
-
$tmp = download_url(
|
297 |
-
preg_match(
|
298 |
$file_array = array();
|
299 |
-
$file_array['name'] = basename(
|
300 |
$file_array['tmp_name'] = $tmp;
|
301 |
// If error storing temporarily, unlink
|
302 |
-
if ( is_wp_error(
|
303 |
-
@unlink(
|
304 |
$file_array['tmp_name'] = '';
|
305 |
}
|
306 |
// do the validation and storage stuff
|
307 |
-
$locinfo = pathinfo(
|
308 |
-
$file = wp_upload_bits(
|
309 |
return $file['url'];
|
310 |
}
|
311 |
|
@@ -317,10 +326,10 @@ class TimberImageHelper {
|
|
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' =>
|
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,31 +338,32 @@ class TimberImageHelper {
|
|
329 |
);
|
330 |
$upload_dir = wp_upload_dir();
|
331 |
$tmp = $url;
|
332 |
-
if ( 0 === strpos($tmp, ABSPATH) ) {
|
|
|
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,20 +380,20 @@ class TimberImageHelper {
|
|
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,16 +408,16 @@ class TimberImageHelper {
|
|
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,14 +439,14 @@ class TimberImageHelper {
|
|
429 |
*
|
430 |
*/
|
431 |
private static function _operate( $src, $op, $force = false ) {
|
432 |
-
if ( empty(
|
433 |
return '';
|
434 |
}
|
435 |
$external = false;
|
436 |
|
437 |
// if external image, load it first
|
438 |
-
if (
|
439 |
-
$src = self::sideload_image(
|
440 |
$external = true;
|
441 |
}
|
442 |
// break down URL into components
|
@@ -458,20 +468,24 @@ class TimberImageHelper {
|
|
458 |
$au['subdir'],
|
459 |
$au['basename']
|
460 |
);
|
|
|
|
|
|
|
|
|
461 |
// if already exists...
|
462 |
-
if ( file_exists(
|
463 |
if ( $force ) {
|
464 |
// Force operation - warning: will regenerate the image on every pageload, use for testing purposes only!
|
465 |
-
unlink(
|
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(
|
474 |
-
$new_url = strtolower(
|
475 |
}
|
476 |
return $new_url;
|
477 |
} else {
|
@@ -483,9 +497,9 @@ class TimberImageHelper {
|
|
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
|
489 |
$new_url = self::_get_file_url(
|
490 |
$au['base'],
|
491 |
$au['subdir'],
|
@@ -494,9 +508,9 @@ class TimberImageHelper {
|
|
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
|
500 |
$new_path = self::_get_file_path(
|
501 |
$au['base'],
|
502 |
$au['subdir'],
|
@@ -504,9 +518,9 @@ class TimberImageHelper {
|
|
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
|
510 |
$new_url = self::_get_file_url(
|
511 |
$au['base'],
|
512 |
$au['subdir'],
|
@@ -515,9 +529,9 @@ class TimberImageHelper {
|
|
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
|
521 |
$new_path = self::_get_file_path(
|
522 |
$au['base'],
|
523 |
$au['subdir'],
|
@@ -525,6 +539,4 @@ class TimberImageHelper {
|
|
525 |
);
|
526 |
return $new_path;
|
527 |
}
|
528 |
-
|
529 |
-
|
530 |
-
}
|
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/timber/timber/wiki/Image-cookbook#arbitrary-resizing-of-images
|
16 |
* - resize
|
17 |
* - retina
|
18 |
* - letterbox
|
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 ImageHelper {
|
27 |
|
28 |
const BASE_UPLOADS = 1;
|
29 |
const BASE_CONTENT = 2;
|
62 |
return $src;
|
63 |
}
|
64 |
}
|
65 |
+
$op = new Image\Operation\Resize($w, $h, $crop);
|
66 |
return self::_operate($src, $op, $force);
|
67 |
}
|
68 |
|
101 |
* @return string url to the new image
|
102 |
*/
|
103 |
public static function retina_resize( $src, $multiplier = 2, $force = false ) {
|
104 |
+
$op = new Image\Operation\Retina($multiplier);
|
105 |
return self::_operate($src, $op, $force);
|
106 |
}
|
107 |
|
116 |
return false;
|
117 |
}
|
118 |
//its a gif so test
|
119 |
+
if ( !($fh = @fopen($file, 'rb')) ) {
|
120 |
return false;
|
121 |
}
|
122 |
$count = 0;
|
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 ( !feof($fh) && $count < 2 ) {
|
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 |
+
fclose($fh);
|
137 |
+
return $count > 1;
|
138 |
}
|
139 |
|
140 |
/**
|
149 |
* @return mixed|null|string
|
150 |
*/
|
151 |
public static function letterbox( $src, $w, $h, $color = '#000000', $force = false ) {
|
152 |
+
$op = new Letterbox($w, $h, $color);
|
153 |
return self::_operate($src, $op, $force);
|
154 |
}
|
155 |
|
161 |
* @return string
|
162 |
*/
|
163 |
public static function img_to_jpg( $src, $bghex = '#FFFFFF', $force = false ) {
|
164 |
+
$op = new Image\Operation\ToJpg($bghex);
|
165 |
return self::_operate($src, $op, $force);
|
166 |
}
|
167 |
|
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 Image($post_id);
|
177 |
if ( $attachment->file_loc ) {
|
178 |
+
ImageHelper::delete_generated_files($attachment->file_loc);
|
179 |
}
|
180 |
}
|
181 |
} );
|
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 |
* @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 |
* or: http://example.org/wp-content/uploads/2015/my-pic.jpg
|
212 |
*/
|
213 |
static function delete_generated_files( $local_file ) {
|
214 |
+
if ( URLHelper::is_absolute($local_file) ) {
|
215 |
+
$local_file = URLHelper::url_to_file_system($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 |
* @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 = '/'.$filename.$search_pattern;
|
243 |
+
foreach ( glob($dir.$searcher) as $found_file ) {
|
244 |
+
$regexdir = str_replace('/', '\/', $dir);
|
245 |
+
$pattern = '/'.($regexdir).'\/'.$filename.$match_pattern.$ext.'/';
|
246 |
+
$match = preg_match($pattern, $found_file);
|
247 |
+
if ( !$match_pattern || $match ) {
|
248 |
+
unlink($found_file);
|
249 |
}
|
250 |
}
|
251 |
}
|
252 |
|
|
|
253 |
/**
|
254 |
* Determines the filepath corresponding to a given URL
|
255 |
*
|
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 |
$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.'/'.$basename.'.'.$ext;
|
288 |
}
|
289 |
|
290 |
/**
|
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 URLHelper::preslashit(URLHelper::get_rel_path($loc));
|
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 |
* @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( $url ) {
|
330 |
$result = array(
|
331 |
'url' => $url, // the initial url
|
332 |
+
'absolute' => URLHelper::is_absolute($url), // is the url absolute or relative (to home_url)
|
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 |
);
|
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'] = self::BASE_UPLOADS; // upload based
|
346 |
$tmp = str_replace($upload_dir['basedir'], '', $tmp);
|
347 |
}
|
348 |
if ( 0 === strpos($tmp, WP_CONTENT_DIR) ) {
|
349 |
+
$result['base'] = self::BASE_CONTENT; // content based
|
350 |
$tmp = str_replace(WP_CONTENT_DIR, '', $tmp);
|
351 |
}
|
352 |
} else {
|
353 |
+
if ( !$result['absolute'] ) {
|
354 |
$tmp = home_url().$tmp;
|
355 |
}
|
356 |
+
if ( 0 === strpos($tmp, $upload_dir['baseurl']) ) {
|
357 |
+
$result['base'] = self::BASE_UPLOADS; // upload based
|
358 |
$tmp = str_replace($upload_dir['baseurl'], '', $tmp);
|
359 |
}
|
360 |
+
if ( 0 === strpos($tmp, content_url()) ) {
|
361 |
+
$result['base'] = self::BASE_CONTENT; // content-based
|
362 |
$tmp = str_replace(content_url(), '', $tmp);
|
363 |
}
|
364 |
}
|
365 |
$parts = pathinfo($tmp);
|
366 |
+
$result['subdir'] = ($parts['dirname'] === '/') ? '' : $parts['dirname'];
|
367 |
$result['filename'] = $parts['filename'];
|
368 |
$result['extension'] = $parts['extension'];
|
369 |
$result['basename'] = $parts['basename'];
|
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( $base, $subdir, $filename, $absolute ) {
|
384 |
$url = '';
|
385 |
+
if ( self::BASE_UPLOADS == $base ) {
|
386 |
$upload_dir = wp_upload_dir();
|
387 |
$url = $upload_dir['baseurl'];
|
388 |
}
|
389 |
+
if ( self::BASE_CONTENT == $base ) {
|
390 |
$url = content_url();
|
391 |
}
|
392 |
+
if ( !empty($subdir) ) {
|
393 |
$url .= $subdir;
|
394 |
}
|
395 |
$url .= '/'.$filename;
|
396 |
+
if ( !$absolute ) {
|
397 |
$url = str_replace(home_url(), '', $url);
|
398 |
}
|
399 |
// $url = TimberURLHelper::remove_double_slashes( $url);
|
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( $base, $subdir, $filename ) {
|
412 |
$path = '';
|
413 |
+
if ( self::BASE_UPLOADS == $base ) {
|
414 |
$upload_dir = wp_upload_dir();
|
415 |
$path = $upload_dir['basedir'];
|
416 |
}
|
417 |
+
if ( self::BASE_CONTENT == $base ) {
|
418 |
$path = WP_CONTENT_DIR;
|
419 |
}
|
420 |
+
if ( !empty($subdir) ) {
|
421 |
$path .= $subdir;
|
422 |
}
|
423 |
$path .= '/'.$filename;
|
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 ( URLHelper::is_external_content($src) ) {
|
449 |
+
$src = self::sideload_image($src);
|
450 |
$external = true;
|
451 |
}
|
452 |
// break down URL into components
|
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 ( $op->run($old_server_path, $new_server_path) ) {
|
487 |
+
if ( get_class($op) === 'TimberImageOperationResize' && $external ) {
|
488 |
+
$new_url = strtolower($new_url);
|
489 |
}
|
490 |
return $new_url;
|
491 |
} else {
|
497 |
|
498 |
// -- the below methods are just used for unit testing the URL generation code
|
499 |
//
|
500 |
+
static function get_letterbox_file_url( $url, $w, $h, $color ) {
|
501 |
$au = self::analyze_url($url);
|
502 |
+
$op = new Image\Operation\Letterbox($w, $h, $color);
|
503 |
$new_url = self::_get_file_url(
|
504 |
$au['base'],
|
505 |
$au['subdir'],
|
508 |
);
|
509 |
return $new_url;
|
510 |
}
|
511 |
+
public static function get_letterbox_file_path( $url, $w, $h, $color ) {
|
512 |
$au = self::analyze_url($url);
|
513 |
+
$op = new Image\Operation\Letterbox($w, $h, $color);
|
514 |
$new_path = self::_get_file_path(
|
515 |
$au['base'],
|
516 |
$au['subdir'],
|
518 |
);
|
519 |
return $new_path;
|
520 |
}
|
521 |
+
static function get_resize_file_url( $url, $w, $h, $crop ) {
|
522 |
$au = self::analyze_url($url);
|
523 |
+
$op = new Image\Operation\Resize($w, $h, $crop);
|
524 |
$new_url = self::_get_file_url(
|
525 |
$au['base'],
|
526 |
$au['subdir'],
|
529 |
);
|
530 |
return $new_url;
|
531 |
}
|
532 |
+
static function get_resize_file_path( $url, $w, $h, $crop ) {
|
533 |
$au = self::analyze_url($url);
|
534 |
+
$op = new Image\Operation\Resize($w, $h, $crop);
|
535 |
$new_path = self::_get_file_path(
|
536 |
$au['base'],
|
537 |
$au['subdir'],
|
539 |
);
|
540 |
return $new_path;
|
541 |
}
|
542 |
+
}
|
|
|
|
lib/Integrations.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{timber-loader.php → Loader.php}
RENAMED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
const CACHEGROUP = 'timberloader';
|
6 |
|
@@ -26,7 +28,7 @@ class TimberLoader {
|
|
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,10 +41,10 @@ class TimberLoader {
|
|
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,15 +53,15 @@ class TimberLoader {
|
|
51 |
|
52 |
$key = null;
|
53 |
$output = false;
|
54 |
-
if (false !== $expires) {
|
55 |
ksort($data);
|
56 |
-
$key = md5($file
|
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,7 +71,7 @@ class TimberLoader {
|
|
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,11 +82,11 @@ class TimberLoader {
|
|
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,10 +99,10 @@ class TimberLoader {
|
|
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)
|
103 |
-
if (file_exists($look_for)) {
|
104 |
return true;
|
105 |
}
|
106 |
}
|
@@ -114,18 +116,18 @@ class TimberLoader {
|
|
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)
|
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)
|
129 |
}
|
130 |
}
|
131 |
//now make sure theres a trailing slash on everything
|
@@ -138,24 +140,25 @@ class TimberLoader {
|
|
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,16 +170,16 @@ class TimberLoader {
|
|
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
|
179 |
-
if (is_dir($caller_sub)) {
|
180 |
$locs[] = $caller_sub;
|
181 |
}
|
182 |
}
|
@@ -188,7 +191,7 @@ class TimberLoader {
|
|
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,26 +207,26 @@ class TimberLoader {
|
|
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,22 +236,22 @@ class TimberLoader {
|
|
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(
|
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,26 +261,26 @@ class TimberLoader {
|
|
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(
|
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(
|
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,7 +292,7 @@ class TimberLoader {
|
|
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,16 +302,16 @@ class TimberLoader {
|
|
299 |
/**
|
300 |
* @param string|false $dirPath
|
301 |
*/
|
302 |
-
public static function rrmdir($dirPath) {
|
303 |
-
if (!
|
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
|
310 |
-
foreach ($files as $file) {
|
311 |
-
if (is_dir($file)) {
|
312 |
self::rrmdir($file);
|
313 |
} else {
|
314 |
unlink($file);
|
@@ -323,9 +326,9 @@ class TimberLoader {
|
|
323 |
private function _get_cache_extension() {
|
324 |
|
325 |
$key_generator = new \Timber\Cache\KeyGenerator();
|
326 |
-
$cache_provider = new \Timber\Cache\WPObjectCacheAdapter(
|
327 |
-
$cache_strategy = new \Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy(
|
328 |
-
$cache_extension = new \Asm89\Twig\CacheExtension\Extension(
|
329 |
|
330 |
return $cache_extension;
|
331 |
}
|
@@ -336,10 +339,10 @@ class TimberLoader {
|
|
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,15 +350,14 @@ class TimberLoader {
|
|
347 |
|
348 |
$value = false;
|
349 |
|
350 |
-
$trans_key = substr($group
|
351 |
-
if (self::CACHE_TRANSIENT === $cache_mode)
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
$value = wp_cache_get($key, $group);
|
359 |
|
360 |
return $value;
|
361 |
}
|
@@ -368,27 +370,27 @@ class TimberLoader {
|
|
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 |
-
|
|
|
380 |
|
381 |
$cache_mode = self::_get_cache_mode($cache_mode);
|
382 |
-
$trans_key = substr($group
|
383 |
-
|
384 |
-
if (self::CACHE_TRANSIENT === $cache_mode)
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
wp_cache_set($key, $value, $group, $expires);
|
392 |
|
393 |
return $value;
|
394 |
}
|
@@ -397,13 +399,13 @@ class TimberLoader {
|
|
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 |
|
1 |
<?php
|
2 |
|
3 |
+
namespace Timber;
|
4 |
+
|
5 |
+
class Loader {
|
6 |
|
7 |
const CACHEGROUP = 'timberloader';
|
8 |
|
28 |
/**
|
29 |
* @param bool|string $caller the calling directory or false
|
30 |
*/
|
31 |
+
function __construct( $caller = false ) {
|
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 |
* @param string $cache_mode
|
42 |
* @return bool|string
|
43 |
*/
|
44 |
+
function render( $file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT ) {
|
45 |
// Different $expires if user is anonymous or logged in
|
46 |
+
if ( is_array($expires) ) {
|
47 |
+
if ( is_user_logged_in() && isset($expires[1]) ) {
|
48 |
$expires = $expires[1];
|
49 |
} else {
|
50 |
$expires = $expires[0];
|
53 |
|
54 |
$key = null;
|
55 |
$output = false;
|
56 |
+
if ( false !== $expires ) {
|
57 |
ksort($data);
|
58 |
+
$key = md5($file.json_encode($data));
|
59 |
$output = $this->get_cache($key, self::CACHEGROUP, $cache_mode);
|
60 |
}
|
61 |
|
62 |
+
if ( false === $output || null === $output ) {
|
63 |
$twig = $this->get_twig();
|
64 |
+
if ( strlen($file) ) {
|
65 |
$loader = $this->get_loader();
|
66 |
$result = $loader->getCacheKey($file);
|
67 |
do_action('timber_loader_render_file', $result);
|
71 |
$output = $twig->render($file, $data);
|
72 |
}
|
73 |
|
74 |
+
if ( false !== $output && false !== $expires && null !== $key ) {
|
75 |
$this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode);
|
76 |
}
|
77 |
$output = apply_filters('timber_output', $output);
|
82 |
* @param array $filenames
|
83 |
* @return bool
|
84 |
*/
|
85 |
+
public function choose_template( $filenames ) {
|
86 |
+
if ( is_array($filenames) ) {
|
87 |
/* its an array so we have to figure out which one the dev wants */
|
88 |
+
foreach ( $filenames as $filename ) {
|
89 |
+
if ( self::template_exists($filename) ) {
|
90 |
return $filename;
|
91 |
}
|
92 |
}
|
99 |
* @param string $file
|
100 |
* @return bool
|
101 |
*/
|
102 |
+
protected function template_exists( $file ) {
|
103 |
+
foreach ( $this->locations as $dir ) {
|
104 |
+
$look_for = trailingslashit($dir).$file;
|
105 |
+
if ( file_exists($look_for) ) {
|
106 |
return true;
|
107 |
}
|
108 |
}
|
116 |
$theme_locs = array();
|
117 |
$child_loc = get_stylesheet_directory();
|
118 |
$parent_loc = get_template_directory();
|
119 |
+
if ( DIRECTORY_SEPARATOR == '\\' ) {
|
120 |
$child_loc = str_replace('/', '\\', $child_loc);
|
121 |
$parent_loc = str_replace('/', '\\', $parent_loc);
|
122 |
}
|
123 |
$theme_locs[] = $child_loc;
|
124 |
+
foreach ( $this->get_locations_theme_dir() as $dirname ) {
|
125 |
+
$theme_locs[] = trailingslashit($child_loc).trailingslashit($dirname);
|
126 |
}
|
127 |
+
if ( $child_loc != $parent_loc ) {
|
128 |
$theme_locs[] = $parent_loc;
|
129 |
+
foreach ( $this->get_locations_theme_dir() as $dirname ) {
|
130 |
+
$theme_locs[] = trailingslashit($parent_loc).trailingslashit($dirname);
|
131 |
}
|
132 |
}
|
133 |
//now make sure theres a trailing slash on everything
|
140 |
* @return string[] the names of directores, ie: array('templats', 'views');
|
141 |
*/
|
142 |
private function get_locations_theme_dir() {
|
143 |
+
if ( is_string(Timber::$dirname) ) {
|
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 ( isset(Timber::$locations) ) {
|
156 |
+
if ( is_string(Timber::$locations) ) {
|
157 |
Timber::$locations = array(Timber::$locations);
|
158 |
}
|
159 |
+
foreach ( Timber::$locations as $tloc ) {
|
160 |
$tloc = realpath($tloc);
|
161 |
+
if ( is_dir($tloc) ) {
|
162 |
$locs[] = $tloc;
|
163 |
}
|
164 |
}
|
170 |
* @param bool|string $caller the calling directory
|
171 |
* @return array
|
172 |
*/
|
173 |
+
function get_locations_caller( $caller = false ) {
|
174 |
$locs = array();
|
175 |
+
if ( $caller && is_string($caller) ) {
|
176 |
$caller = trailingslashit($caller);
|
177 |
+
if ( is_dir($caller) ) {
|
178 |
$locs[] = $caller;
|
179 |
}
|
180 |
+
foreach ( $this->get_locations_theme_dir() as $dirname ) {
|
181 |
+
$caller_sub = $caller.trailingslashit($dirname);
|
182 |
+
if ( is_dir($caller_sub) ) {
|
183 |
$locs[] = $caller_sub;
|
184 |
}
|
185 |
}
|
191 |
* @param bool|string $caller the calling directory (or false)
|
192 |
* @return array
|
193 |
*/
|
194 |
+
function get_locations( $caller = false ) {
|
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 |
}
|
208 |
|
209 |
/**
|
210 |
+
* @return \Twig_Loader_Filesystem
|
211 |
*/
|
212 |
function get_loader() {
|
213 |
$paths = array();
|
214 |
+
foreach ( $this->locations as $loc ) {
|
215 |
$loc = realpath($loc);
|
216 |
+
if ( is_dir($loc) ) {
|
217 |
$loc = realpath($loc);
|
218 |
$paths[] = $loc;
|
219 |
} else {
|
220 |
//error_log($loc.' is not a directory');
|
221 |
}
|
222 |
}
|
223 |
+
if ( !ini_get('open_basedir') ) {
|
224 |
$paths[] = '/';
|
225 |
} else {
|
226 |
$paths[] = ABSPATH;
|
227 |
}
|
228 |
$paths = apply_filters('timber/loader/paths', $paths);
|
229 |
+
$loader = new \Twig_Loader_Filesystem($paths);
|
230 |
return $loader;
|
231 |
}
|
232 |
|
236 |
function get_twig() {
|
237 |
$loader = $this->get_loader();
|
238 |
$params = array('debug' => WP_DEBUG, 'autoescape' => false);
|
239 |
+
if ( isset(Timber::$autoescape) ) {
|
240 |
$params['autoescape'] = Timber::$autoescape;
|
241 |
}
|
242 |
+
if ( Timber::$cache === true ) {
|
243 |
Timber::$twig_cache = true;
|
244 |
}
|
245 |
+
if ( Timber::$twig_cache ) {
|
246 |
+
$twig_cache_loc = apply_filters('timber/cache/location', TIMBER_LOC.'/cache/twig');
|
247 |
+
if ( !file_exists($twig_cache_loc) ) {
|
248 |
mkdir($twig_cache_loc, 0777, true);
|
249 |
}
|
250 |
$params['cache'] = $twig_cache_loc;
|
251 |
}
|
252 |
+
$twig = new \Twig_Environment($loader, $params);
|
253 |
if ( WP_DEBUG ) {
|
254 |
+
$twig->addExtension(new \Twig_Extension_Debug());
|
255 |
}
|
256 |
$twig->addExtension($this->_get_cache_extension());
|
257 |
|
261 |
return $twig;
|
262 |
}
|
263 |
|
264 |
+
public function clear_cache_timber( $cache_mode = self::CACHE_USE_DEFAULT ) {
|
265 |
//_transient_timberloader
|
266 |
$object_cache = false;
|
267 |
+
if ( isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache']) ) {
|
268 |
$object_cache = true;
|
269 |
}
|
270 |
$cache_mode = $this->_get_cache_mode($cache_mode);
|
271 |
+
if ( self::CACHE_TRANSIENT === $cache_mode ) {
|
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 ( self::CACHE_SITE_TRANSIENT === $cache_mode ) {
|
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 ( self::CACHE_OBJECT === $cache_mode && $object_cache ) {
|
282 |
global $wp_object_cache;
|
283 |
+
if ( isset($wp_object_cache->cache[self::CACHEGROUP]) ) {
|
284 |
unset($wp_object_cache->cache[self::CACHEGROUP]);
|
285 |
return true;
|
286 |
}
|
292 |
$twig = $this->get_twig();
|
293 |
$twig->clearCacheFiles();
|
294 |
$cache = $twig->getCache();
|
295 |
+
if ( $cache ) {
|
296 |
self::rrmdir($twig->getCache());
|
297 |
return true;
|
298 |
}
|
302 |
/**
|
303 |
* @param string|false $dirPath
|
304 |
*/
|
305 |
+
public static function rrmdir( $dirPath ) {
|
306 |
+
if ( !is_dir($dirPath) ) {
|
307 |
+
throw new \InvalidArgumentException("$dirPath must be a directory");
|
308 |
}
|
309 |
+
if ( substr($dirPath, strlen($dirPath) - 1, 1) != '/' ) {
|
310 |
$dirPath .= '/';
|
311 |
}
|
312 |
+
$files = glob($dirPath.'*', GLOB_MARK);
|
313 |
+
foreach ( $files as $file ) {
|
314 |
+
if ( is_dir($file) ) {
|
315 |
self::rrmdir($file);
|
316 |
} else {
|
317 |
unlink($file);
|
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 |
* @param string $cache_mode
|
340 |
* @return bool
|
341 |
*/
|
342 |
+
public function get_cache( $key, $group = self::CACHEGROUP, $cache_mode = self::CACHE_USE_DEFAULT ) {
|
343 |
$object_cache = false;
|
344 |
|
345 |
+
if ( isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache']) ) {
|
346 |
$object_cache = true;
|
347 |
}
|
348 |
|
350 |
|
351 |
$value = false;
|
352 |
|
353 |
+
$trans_key = substr($group.'_'.$key, 0, self::TRANS_KEY_LEN);
|
354 |
+
if ( self::CACHE_TRANSIENT === $cache_mode ) {
|
355 |
+
$value = get_transient($trans_key);
|
356 |
+
} elseif ( self::CACHE_SITE_TRANSIENT === $cache_mode ) {
|
357 |
+
$value = get_site_transient($trans_key);
|
358 |
+
} elseif ( self::CACHE_OBJECT === $cache_mode && $object_cache ) {
|
359 |
+
$value = wp_cache_get($key, $group);
|
360 |
+
}
|
|
|
361 |
|
362 |
return $value;
|
363 |
}
|
370 |
* @param string $cache_mode
|
371 |
* @return string|boolean
|
372 |
*/
|
373 |
+
public function set_cache( $key, $value, $group = self::CACHEGROUP, $expires = 0, $cache_mode = self::CACHE_USE_DEFAULT ) {
|
374 |
$object_cache = false;
|
375 |
|
376 |
+
if ( isset($GLOBALS['wp_object_cache']) && is_object($GLOBALS['wp_object_cache']) ) {
|
377 |
$object_cache = true;
|
378 |
}
|
379 |
|
380 |
+
if ( (int) $expires < 1 ) {
|
381 |
+
$expires = 0;
|
382 |
+
}
|
383 |
|
384 |
$cache_mode = self::_get_cache_mode($cache_mode);
|
385 |
+
$trans_key = substr($group.'_'.$key, 0, self::TRANS_KEY_LEN);
|
386 |
+
|
387 |
+
if ( self::CACHE_TRANSIENT === $cache_mode ) {
|
388 |
+
set_transient($trans_key, $value, $expires);
|
389 |
+
} elseif ( self::CACHE_SITE_TRANSIENT === $cache_mode ) {
|
390 |
+
set_site_transient($trans_key, $value, $expires);
|
391 |
+
} elseif ( self::CACHE_OBJECT === $cache_mode && $object_cache ) {
|
392 |
+
wp_cache_set($key, $value, $group, $expires);
|
393 |
+
}
|
|
|
394 |
|
395 |
return $value;
|
396 |
}
|
399 |
* @param string $cache_mode
|
400 |
* @return string
|
401 |
*/
|
402 |
+
private function _get_cache_mode( $cache_mode ) {
|
403 |
+
if ( empty($cache_mode) || self::CACHE_USE_DEFAULT === $cache_mode ) {
|
404 |
$cache_mode = $this->cache_mode;
|
405 |
}
|
406 |
|
407 |
// Fallback if self::$cache_mode did not get a valid value
|
408 |
+
if ( !in_array($cache_mode, self::$cache_modes) ) {
|
409 |
$cache_mode = self::CACHE_OBJECT;
|
410 |
}
|
411 |
|
lib/{timber-menu.php → Menu.php}
RENAMED
@@ -1,5 +1,10 @@
|
|
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,11 +32,11 @@
|
|
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.
|
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.
|
35 |
* {% endfor %}
|
36 |
* </ul>
|
37 |
* {% endif %}
|
@@ -41,10 +46,10 @@
|
|
41 |
* </nav>
|
42 |
* ```
|
43 |
*/
|
44 |
-
class
|
45 |
|
46 |
-
public $MenuItemClass = '
|
47 |
-
public $PostClass = '
|
48 |
|
49 |
/**
|
50 |
* @api
|
@@ -75,18 +80,18 @@ class TimberMenu extends TimberCore {
|
|
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,11 +102,11 @@ class TimberMenu extends TimberCore {
|
|
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,12 +123,12 @@ class TimberMenu extends TimberCore {
|
|
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,14 +141,14 @@ class TimberMenu extends TimberCore {
|
|
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,21 +159,21 @@ class TimberMenu extends TimberCore {
|
|
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,9 +185,9 @@ class TimberMenu extends TimberCore {
|
|
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,29 +198,29 @@ class TimberMenu extends TimberCore {
|
|
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,7 +233,7 @@ class TimberMenu extends TimberCore {
|
|
228 |
* @return array
|
229 |
*/
|
230 |
function get_items() {
|
231 |
-
if (is_array($this->items)) {
|
232 |
return $this->items;
|
233 |
}
|
234 |
return array();
|
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 |
* <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.link}}">{{item.title}}</a>
|
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.link}}">{{child.title}}</a></li>
|
40 |
* {% endfor %}
|
41 |
* </ul>
|
42 |
* {% endif %}
|
46 |
* </nav>
|
47 |
* ```
|
48 |
*/
|
49 |
+
class Menu extends Core {
|
50 |
|
51 |
+
public $MenuItemClass = 'Timber\MenuItem';
|
52 |
+
public $PostClass = 'Timber\Post';
|
53 |
|
54 |
/**
|
55 |
* @api
|
80 |
/**
|
81 |
* @param int|string $slug
|
82 |
*/
|
83 |
+
function __construct( $slug = 0 ) {
|
84 |
$locations = get_nav_menu_locations();
|
85 |
+
if ( $slug != 0 && is_numeric($slug) ) {
|
86 |
$menu_id = $slug;
|
87 |
+
} else if ( is_array($locations) && count($locations) ) {
|
88 |
$menu_id = $this->get_menu_id_from_locations($slug, $locations);
|
89 |
+
} else if ( $slug === false ) {
|
90 |
$menu_id = false;
|
91 |
} else {
|
92 |
$menu_id = $this->get_menu_id_from_terms($slug);
|
93 |
}
|
94 |
+
if ( $menu_id ) {
|
95 |
$this->init($menu_id);
|
96 |
} else {
|
97 |
$this->init_as_page_menu();
|
102 |
* @internal
|
103 |
* @param int $menu_id
|
104 |
*/
|
105 |
+
protected function init( $menu_id ) {
|
106 |
$menu = wp_get_nav_menu_items($menu_id);
|
107 |
+
if ( $menu ) {
|
108 |
_wp_menu_item_classes_by_context($menu);
|
109 |
+
if ( is_array($menu) ) {
|
110 |
$menu = self::order_children($menu);
|
111 |
}
|
112 |
$this->items = $menu;
|
123 |
*/
|
124 |
protected function init_as_page_menu() {
|
125 |
$menu = get_pages();
|
126 |
+
if ( $menu ) {
|
127 |
+
foreach ( $menu as $mi ) {
|
128 |
$mi->__title = $mi->post_title;
|
129 |
}
|
130 |
_wp_menu_item_classes_by_context($menu);
|
131 |
+
if ( is_array($menu) ) {
|
132 |
$menu = self::order_children($menu);
|
133 |
}
|
134 |
$this->items = $menu;
|
141 |
* @param array $locations
|
142 |
* @return integer
|
143 |
*/
|
144 |
+
protected function get_menu_id_from_locations( $slug, $locations ) {
|
145 |
+
if ( $slug === 0 ) {
|
146 |
$slug = $this->get_menu_id_from_terms($slug);
|
147 |
}
|
148 |
+
if ( is_numeric($slug) ) {
|
149 |
$slug = array_search($slug, $locations);
|
150 |
}
|
151 |
+
if ( isset($locations[$slug]) ) {
|
152 |
$menu_id = $locations[$slug];
|
153 |
return $menu_id;
|
154 |
}
|
159 |
* @param int $slug
|
160 |
* @return int
|
161 |
*/
|
162 |
+
protected function get_menu_id_from_terms( $slug = 0 ) {
|
163 |
+
if ( !is_numeric($slug) && is_string($slug) ) {
|
164 |
//we have a string so lets search for that
|
165 |
$menu_id = get_term_by('slug', $slug, 'nav_menu');
|
166 |
+
if ( $menu_id ) {
|
167 |
return $menu_id;
|
168 |
}
|
169 |
$menu_id = get_term_by('name', $slug, 'nav_menu');
|
170 |
+
if ( $menu_id ) {
|
171 |
return $menu_id;
|
172 |
}
|
173 |
}
|
174 |
$menus = get_terms('nav_menu', array('hide_empty' => true));
|
175 |
+
if ( is_array($menus) && count($menus) ) {
|
176 |
+
if ( isset($menus[0]->term_id) ) {
|
177 |
return $menus[0]->term_id;
|
178 |
}
|
179 |
}
|
185 |
* @param int $parent_id
|
186 |
* @return TimberMenuItem|null
|
187 |
*/
|
188 |
+
function find_parent_item_in_menu( $menu_items, $parent_id ) {
|
189 |
+
foreach ( $menu_items as &$item ) {
|
190 |
+
if ( $item->ID == $parent_id ) {
|
191 |
return $item;
|
192 |
}
|
193 |
}
|
198 |
* @param array $items
|
199 |
* @return array
|
200 |
*/
|
201 |
+
protected function order_children( $items ) {
|
202 |
$index = array();
|
203 |
$menu = array();
|
204 |
+
foreach ( $items as $item ) {
|
205 |
+
if ( isset($item->title) ) {
|
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 ( isset($item->ID) ) {
|
211 |
+
if ( is_object($item) && get_class($item) == 'WP_Post' ) {
|
212 |
$old_menu_item = $item;
|
213 |
$item = new $this->PostClass($item);
|
214 |
}
|
215 |
$menu_item = new $this->MenuItemClass($item);
|
216 |
+
if ( isset($old_menu_item) ) {
|
217 |
$menu_item->import_classes($old_menu_item);
|
218 |
}
|
219 |
$index[$item->ID] = $menu_item;
|
220 |
}
|
221 |
}
|
222 |
+
foreach ( $index as $item ) {
|
223 |
+
if ( isset($item->menu_item_parent) && $item->menu_item_parent && isset($index[$item->menu_item_parent]) ) {
|
224 |
$index[$item->menu_item_parent]->add_child($item);
|
225 |
} else {
|
226 |
$menu[] = $item;
|
233 |
* @return array
|
234 |
*/
|
235 |
function get_items() {
|
236 |
+
if ( is_array($this->items) ) {
|
237 |
return $this->items;
|
238 |
}
|
239 |
return array();
|
lib/{timber-menu-item.php → MenuItem.php}
RENAMED
@@ -1,6 +1,13 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
public $children;
|
6 |
public $has_child_class = false;
|
@@ -26,13 +33,13 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
26 |
*/
|
27 |
public function __construct( $data ) {
|
28 |
$data = (object) $data;
|
29 |
-
$this->import(
|
30 |
-
$this->import_classes(
|
31 |
-
if ( isset(
|
32 |
$this->_name = $this->name;
|
33 |
}
|
34 |
$this->name = $this->name();
|
35 |
-
$this->add_class(
|
36 |
$this->menu_object = $data;
|
37 |
}
|
38 |
|
@@ -49,7 +56,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
49 |
*/
|
50 |
public function add_class( $class_name ) {
|
51 |
$this->classes[] = $class_name;
|
52 |
-
$this->class .= ' '
|
53 |
}
|
54 |
|
55 |
/**
|
@@ -61,7 +68,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
61 |
if ( $title = $this->title() ) {
|
62 |
return $title;
|
63 |
}
|
64 |
-
if ( isset(
|
65 |
return $this->_name;
|
66 |
}
|
67 |
return '';
|
@@ -82,10 +89,10 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
82 |
* @return string the slug of the menu item kinda-like-this
|
83 |
*/
|
84 |
public function slug() {
|
85 |
-
if ( !isset(
|
86 |
$this->master_object = $this->get_master_object();
|
87 |
}
|
88 |
-
if ( isset(
|
89 |
return $this->master_object->post_name;
|
90 |
}
|
91 |
return $this->post_name;
|
@@ -96,34 +103,29 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
96 |
* @return mixed whatever object (Post, Term, etc.) the menu item represents
|
97 |
*/
|
98 |
protected function get_master_object() {
|
99 |
-
if ( isset(
|
100 |
-
return new $this->PostClass(
|
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 |
-
|
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
|
127 |
}
|
128 |
|
129 |
/**
|
@@ -133,15 +135,15 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
133 |
*/
|
134 |
function add_child( $item ) {
|
135 |
if ( !$this->has_child_class ) {
|
136 |
-
$this->add_class(
|
137 |
$this->has_child_class = true;
|
138 |
}
|
139 |
-
if ( !isset(
|
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,8 +154,8 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
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,10 +172,10 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
170 |
if ( is_array($data) ) {
|
171 |
$data = (object) $data;
|
172 |
}
|
173 |
-
$this->classes = array_merge(
|
174 |
-
$this->classes = array_unique(
|
175 |
-
$this->classes = apply_filters(
|
176 |
-
$this->class = trim(
|
177 |
}
|
178 |
|
179 |
/**
|
@@ -182,7 +184,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
182 |
* @return array|bool
|
183 |
*/
|
184 |
function get_children() {
|
185 |
-
if ( isset(
|
186 |
return $this->children;
|
187 |
}
|
188 |
return false;
|
@@ -201,7 +203,7 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
201 |
if ( $this->type != 'custom' ) {
|
202 |
return false;
|
203 |
}
|
204 |
-
return
|
205 |
}
|
206 |
|
207 |
/**
|
@@ -209,10 +211,10 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
209 |
* @return mixed whatever value is storied in the database
|
210 |
*/
|
211 |
public function meta( $key ) {
|
212 |
-
if ( is_object(
|
213 |
-
return $this->menu_object->meta(
|
214 |
}
|
215 |
-
if ( isset(
|
216 |
return $this->$key;
|
217 |
}
|
218 |
}
|
@@ -249,22 +251,14 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
249 |
* @return string a full URL like http://mysite.com/thing/
|
250 |
*/
|
251 |
public function link() {
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
* <li><a href="{{ item.path }}">{{ item.title }}</a></li>
|
261 |
-
* {% endfor %}
|
262 |
-
* ```
|
263 |
-
* @see get_path()
|
264 |
-
* @return string the path of a URL like /foo
|
265 |
-
*/
|
266 |
-
public function path() {
|
267 |
-
return $this->get_path();
|
268 |
}
|
269 |
|
270 |
/**
|
@@ -275,17 +269,23 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
275 |
* @return string a full URL like http://mysite.com/thing/
|
276 |
*/
|
277 |
public function permalink() {
|
278 |
-
|
|
|
279 |
}
|
280 |
|
281 |
/**
|
282 |
-
*
|
283 |
-
* @
|
284 |
-
*
|
285 |
-
*
|
|
|
|
|
|
|
|
|
|
|
286 |
*/
|
287 |
-
public function
|
288 |
-
return $this->
|
289 |
}
|
290 |
|
291 |
/**
|
@@ -299,9 +299,8 @@ class TimberMenuItem extends TimberCore implements TimberCoreInterface {
|
|
299 |
* @return string the public label like Foo
|
300 |
*/
|
301 |
public function title() {
|
302 |
-
if ( isset(
|
303 |
return $this->__title;
|
304 |
}
|
305 |
}
|
306 |
-
|
307 |
-
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace Timber;
|
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 |
*/
|
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-'.$this->ID);
|
43 |
$this->menu_object = $data;
|
44 |
}
|
45 |
|
56 |
*/
|
57 |
public function add_class( $class_name ) {
|
58 |
$this->classes[] = $class_name;
|
59 |
+
$this->class .= ' '.$class_name;
|
60 |
}
|
61 |
|
62 |
/**
|
68 |
if ( $title = $this->title() ) {
|
69 |
return $title;
|
70 |
}
|
71 |
+
if ( isset($this->_name) ) {
|
72 |
return $this->_name;
|
73 |
}
|
74 |
return '';
|
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 |
* @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 |
+
return $this->link();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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->path();
|
129 |
}
|
130 |
|
131 |
/**
|
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 ( $item->children ) {
|
147 |
$this->update_child_levels();
|
148 |
}
|
149 |
}
|
154 |
* @return bool
|
155 |
*/
|
156 |
function update_child_levels() {
|
157 |
+
if ( is_array($this->children) ) {
|
158 |
+
foreach ( $this->children as $child ) {
|
159 |
$child->level = $this->level + 1;
|
160 |
$child->update_child_levels();
|
161 |
}
|
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 |
* @return array|bool
|
185 |
*/
|
186 |
function get_children() {
|
187 |
+
if ( isset($this->children) ) {
|
188 |
return $this->children;
|
189 |
}
|
190 |
return false;
|
203 |
if ( $this->type != 'custom' ) {
|
204 |
return false;
|
205 |
}
|
206 |
+
return URLHelper::is_external($this->url);
|
207 |
}
|
208 |
|
209 |
/**
|
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 |
* @return string a full URL like http://mysite.com/thing/
|
252 |
*/
|
253 |
public function link() {
|
254 |
+
if ( !isset($this->url) || !$this->url ) {
|
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 |
/**
|
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 |
/**
|
277 |
+
* Return the relative path of a Menu Item's link
|
278 |
+
* @example
|
279 |
+
* ```twig
|
280 |
+
* {% for item in menu.items %}
|
281 |
+
* <li><a href="{{ item.path }}">{{ item.title }}</a></li>
|
282 |
+
* {% endfor %}
|
283 |
+
* ```
|
284 |
+
* @see get_path()
|
285 |
+
* @return string the path of a URL like /foo
|
286 |
*/
|
287 |
+
public function path() {
|
288 |
+
return URLHelper::get_rel_url($this->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 |
+
}
|
|
lib/{timber-post.php → Post.php}
RENAMED
@@ -1,5 +1,17 @@
|
|
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,7 +19,7 @@
|
|
7 |
* <?php
|
8 |
* // single.php, see connected twig example
|
9 |
* $context = Timber::get_context();
|
10 |
-
* $context['post'] = new
|
11 |
* Timber::render('single.twig', $context);
|
12 |
* ?>
|
13 |
* ```
|
@@ -32,22 +44,22 @@
|
|
32 |
*
|
33 |
* @package Timber
|
34 |
*/
|
35 |
-
class
|
36 |
-
|
37 |
/**
|
38 |
* @var string $ImageClass the name of the class to handle images by default
|
39 |
*/
|
40 |
-
public $ImageClass = '
|
41 |
|
42 |
/**
|
43 |
* @var string $PostClass the name of the class to handle posts by default
|
44 |
*/
|
45 |
-
public $PostClass = '
|
46 |
|
47 |
/**
|
48 |
* @var string $TermClass the name of the class to handle terms by default
|
49 |
*/
|
50 |
-
public $TermClass = '
|
51 |
|
52 |
/**
|
53 |
* @var string $object_type what does this class represent in WordPress terms?
|
@@ -65,25 +77,18 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
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
|
82 |
*/
|
83 |
protected $_next = array();
|
84 |
|
85 |
/**
|
86 |
-
* @var array $_prev stores the results of the previous
|
87 |
*/
|
88 |
protected $_prev = array();
|
89 |
|
@@ -156,13 +161,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
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
|
160 |
-
* $other_post = new
|
161 |
* ```
|
162 |
* @param mixed $pid
|
163 |
*/
|
164 |
-
public function __construct($pid = null) {
|
165 |
-
$pid = $this->determine_id(
|
166 |
$this->init($pid);
|
167 |
}
|
168 |
|
@@ -172,7 +177,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
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,18 +186,18 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
181 |
&& is_object($wp_query->queried_object)
|
182 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
183 |
) {
|
184 |
-
if( isset(
|
185 |
-
$pid = $this->get_post_preview_id(
|
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,7 +210,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
205 |
}
|
206 |
}
|
207 |
}
|
208 |
-
if ( $pid === null && ($pid_from_loop =
|
209 |
$pid = $pid_from_loop;
|
210 |
}
|
211 |
return $pid;
|
@@ -221,28 +226,28 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
221 |
|
222 |
protected function get_post_preview_id( $query ) {
|
223 |
$can = array(
|
224 |
-
'edit_'
|
225 |
);
|
226 |
|
227 |
if ( $query->queried_object->author_id !== get_current_user_id() ) {
|
228 |
-
$can[] = 'edit_others_'
|
229 |
}
|
230 |
|
231 |
$can_preview = array();
|
232 |
|
233 |
-
foreach( $can as $type ) {
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
}
|
238 |
|
239 |
-
if ( count(
|
240 |
-
|
241 |
}
|
242 |
|
243 |
-
$revisions = wp_get_post_revisions(
|
244 |
|
245 |
-
if( !empty(
|
246 |
$last = end($revisions);
|
247 |
return $last->ID;
|
248 |
}
|
@@ -251,11 +256,11 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
-
* Initializes a
|
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,13 +277,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
272 |
/**
|
273 |
* Get the URL that will edit the current post/object
|
274 |
* @internal
|
275 |
-
* @
|
|
|
|
|
276 |
* @return bool|string
|
277 |
*/
|
278 |
function get_edit_url() {
|
279 |
-
|
280 |
-
return get_edit_post_link($this->ID);
|
281 |
-
}
|
282 |
}
|
283 |
|
284 |
/**
|
@@ -342,11 +347,11 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
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,12 +373,12 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
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 =
|
377 |
$trimmed = true;
|
378 |
} else {
|
379 |
$text = $this->post_excerpt;
|
@@ -383,13 +388,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
383 |
$pieces = explode($readmore_matches[0], $this->post_content);
|
384 |
$text = $pieces[0];
|
385 |
if ( $force ) {
|
386 |
-
$text =
|
387 |
$trimmed = true;
|
388 |
}
|
389 |
-
$text = do_shortcode(
|
390 |
}
|
391 |
if ( !strlen($text) ) {
|
392 |
-
$text =
|
393 |
$trimmed = true;
|
394 |
}
|
395 |
if ( !strlen(trim($text)) ) {
|
@@ -411,16 +416,16 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
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="'
|
420 |
} elseif ( $readmore ) {
|
421 |
-
$text .= ' <a href="'
|
422 |
}
|
423 |
-
if ( !$strip && $last_p_tag && (
|
424 |
$text .= '</p>';
|
425 |
}
|
426 |
}
|
@@ -464,252 +469,326 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
464 |
}
|
465 |
|
466 |
/**
|
467 |
-
* @
|
468 |
-
* @
|
469 |
-
* @return null|TimberImage
|
470 |
*/
|
471 |
-
function
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
}
|
477 |
}
|
|
|
478 |
}
|
479 |
|
480 |
/**
|
|
|
481 |
* @internal
|
482 |
-
* @
|
483 |
-
* @return
|
484 |
*/
|
485 |
-
function
|
486 |
-
|
487 |
-
|
|
|
488 |
}
|
489 |
-
|
490 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
491 |
}
|
492 |
|
493 |
/**
|
494 |
-
*
|
495 |
-
*
|
496 |
-
*
|
497 |
-
* @
|
498 |
-
* @return string
|
499 |
*/
|
500 |
-
function
|
501 |
-
return $this->
|
502 |
}
|
503 |
|
|
|
504 |
/**
|
505 |
-
* Get the
|
506 |
-
*
|
507 |
-
* @
|
508 |
-
* @
|
|
|
|
|
509 |
*/
|
510 |
-
function
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
$
|
516 |
-
|
517 |
-
|
|
|
|
|
|
|
|
|
|
|
518 |
} else {
|
519 |
-
$
|
520 |
}
|
|
|
521 |
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
526 |
}
|
527 |
-
$post = $old_global;
|
528 |
}
|
529 |
-
return $
|
530 |
}
|
531 |
|
532 |
/**
|
533 |
-
*
|
534 |
-
* @
|
|
|
535 |
*/
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
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 $
|
561 |
}
|
562 |
|
563 |
/**
|
564 |
-
* @param int $i
|
565 |
* @return string
|
566 |
*/
|
567 |
-
|
568 |
-
$
|
569 |
-
$link = new SimpleXMLElement($link . '</a>');
|
570 |
-
if ( isset($link['href']) ) {
|
571 |
-
return $link['href'];
|
572 |
-
}
|
573 |
-
return '';
|
574 |
}
|
575 |
-
|
576 |
/**
|
577 |
-
*
|
578 |
-
*
|
579 |
-
*
|
580 |
-
*
|
581 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
*/
|
583 |
-
function
|
584 |
-
return
|
585 |
}
|
586 |
|
587 |
/**
|
588 |
-
*
|
589 |
-
* @internal
|
590 |
-
* @param bool $taxonomy
|
591 |
-
* @return TimberPost|boolean
|
592 |
*/
|
593 |
-
function
|
594 |
-
|
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 |
-
*
|
613 |
-
* @
|
614 |
-
* @return bool|TimberPost
|
615 |
*/
|
616 |
-
function
|
617 |
-
|
618 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
619 |
}
|
620 |
-
|
|
|
|
|
621 |
}
|
622 |
|
623 |
/**
|
624 |
-
*
|
625 |
-
* @internal
|
626 |
-
* @see TimberPost::author
|
627 |
-
* @return bool|TimberUser
|
628 |
*/
|
629 |
-
function
|
630 |
-
|
631 |
-
return new TimberUser($this->post_author);
|
632 |
-
}
|
633 |
}
|
634 |
|
635 |
/**
|
|
|
636 |
* @internal
|
637 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
638 |
*/
|
639 |
-
function
|
640 |
-
|
641 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
642 |
}
|
643 |
|
|
|
|
|
644 |
/**
|
645 |
-
*
|
646 |
-
* @
|
647 |
-
* @param int $pid
|
648 |
-
* @return null|object|WP_Post
|
649 |
*/
|
650 |
-
|
651 |
-
$
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
$
|
656 |
-
$
|
657 |
-
$
|
658 |
-
$
|
659 |
-
$
|
660 |
-
$
|
661 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
662 |
}
|
663 |
|
664 |
/**
|
665 |
-
*
|
666 |
-
* @
|
667 |
-
* @
|
668 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
669 |
*/
|
670 |
-
function
|
671 |
-
|
672 |
-
$the_date = (string)mysql2date($df, $this->post_date);
|
673 |
-
return apply_filters('get_the_date', $the_date, $df);
|
674 |
}
|
675 |
|
676 |
/**
|
677 |
-
*
|
678 |
-
* @
|
679 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
680 |
*/
|
681 |
-
function
|
682 |
-
$
|
683 |
-
$
|
684 |
-
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
685 |
}
|
686 |
|
687 |
/**
|
688 |
-
*
|
689 |
-
* @
|
690 |
-
* @return
|
691 |
*/
|
692 |
-
function
|
693 |
-
|
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 |
-
*
|
700 |
-
* @
|
701 |
-
*
|
702 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
703 |
* @return array
|
704 |
*/
|
705 |
-
function
|
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='
|
713 |
foreach ( $children as &$child ) {
|
714 |
$child = new $childPostClass($child->ID);
|
715 |
}
|
@@ -717,21 +796,28 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
717 |
return $children;
|
718 |
}
|
719 |
|
720 |
-
|
721 |
/**
|
722 |
-
*
|
723 |
-
* @
|
724 |
-
* @
|
725 |
-
* @param
|
726 |
-
* @param string $
|
727 |
-
* @param string $
|
728 |
-
* @param string $
|
729 |
-
* @
|
730 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,50 +825,50 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
739 |
$comment_author_email = $commenter['comment_author_email'];
|
740 |
|
741 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
742 |
-
if ( $
|
743 |
-
$args['number'] = $
|
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(
|
751 |
-
} elseif ( !
|
752 |
-
$args['include_unapproved'] = array(
|
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(
|
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 (
|
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,649 +880,664 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
794 |
}
|
795 |
|
796 |
/**
|
797 |
-
*
|
798 |
-
* @
|
799 |
-
* @
|
800 |
-
*
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
* @
|
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
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
if ( is_string($merge) && class_exists($merge) ) {
|
830 |
-
$TermClass = $merge;
|
831 |
-
}
|
832 |
-
if ( is_array($tax) ) {
|
833 |
-
$taxonomies = $tax;
|
834 |
}
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
} else {
|
839 |
-
$taxonomies = array($tax);
|
840 |
-
}
|
841 |
}
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
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 |
-
|
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
|
896 |
}
|
897 |
|
898 |
/**
|
899 |
-
* @
|
900 |
-
* @return TimberImage
|
901 |
*/
|
902 |
-
function
|
903 |
-
|
|
|
904 |
}
|
905 |
|
906 |
/**
|
907 |
-
*
|
908 |
-
* @
|
909 |
* @example
|
910 |
* ```twig
|
911 |
-
*
|
912 |
-
*
|
913 |
-
*
|
914 |
-
* {% endfor %}
|
915 |
-
* </ul>
|
916 |
* ```
|
917 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
918 |
*/
|
919 |
-
function
|
920 |
-
|
|
|
|
|
921 |
}
|
922 |
|
923 |
/**
|
924 |
-
*
|
925 |
-
* @
|
926 |
* @example
|
927 |
* ```twig
|
928 |
-
*
|
|
|
|
|
929 |
* ```
|
|
|
930 |
* ```html
|
931 |
-
*
|
|
|
|
|
932 |
* ```
|
|
|
933 |
* @return string
|
934 |
*/
|
935 |
-
function
|
936 |
-
|
|
|
|
|
937 |
}
|
938 |
|
939 |
/**
|
940 |
-
*
|
941 |
-
* @
|
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
|
953 |
-
if ( $
|
954 |
-
return $this->
|
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 |
-
* @
|
|
|
976 |
*/
|
977 |
-
function
|
978 |
-
|
979 |
-
return $this->get_content(0, $page);
|
980 |
}
|
|
|
981 |
/**
|
982 |
-
*
|
983 |
-
*
|
984 |
* @example
|
985 |
* ```twig
|
986 |
-
*
|
987 |
-
* ```
|
988 |
-
*
|
989 |
-
* ```html
|
990 |
-
* This post is from <span>Recipes</span>
|
991 |
* ```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
992 |
* @return mixed
|
993 |
*/
|
994 |
-
public function
|
995 |
-
|
|
|
|
|
|
|
|
|
996 |
}
|
997 |
|
998 |
/**
|
999 |
-
* @return
|
1000 |
*/
|
1001 |
-
public function
|
1002 |
-
return
|
1003 |
}
|
1004 |
|
1005 |
/**
|
1006 |
-
* @param string $
|
1007 |
-
* @return
|
1008 |
*/
|
1009 |
-
public function
|
1010 |
-
$
|
1011 |
-
|
1012 |
-
|
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 $
|
|
|
1026 |
*/
|
1027 |
-
function
|
1028 |
-
|
1029 |
}
|
1030 |
|
1031 |
/**
|
1032 |
-
* @
|
|
|
1033 |
* @return mixed
|
1034 |
*/
|
1035 |
-
function
|
1036 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1037 |
}
|
1038 |
|
1039 |
/**
|
1040 |
-
* Get
|
1041 |
-
* @
|
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
|
1059 |
-
global $post;
|
1060 |
-
$old_global_post = $post;
|
1061 |
$post = $this;
|
1062 |
-
$
|
1063 |
-
$
|
1064 |
-
|
1065 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1066 |
}
|
1067 |
-
return $
|
1068 |
}
|
1069 |
|
1070 |
-
|
1071 |
|
1072 |
/**
|
1073 |
-
*
|
1074 |
-
* @
|
1075 |
*/
|
1076 |
-
public function
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
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 |
-
*
|
1101 |
* @api
|
1102 |
* @example
|
1103 |
* ```twig
|
1104 |
-
* <
|
1105 |
-
* <p class="byline">
|
1106 |
-
* <a href="{{post.author.link}}">{{post.author.name}}</a>
|
1107 |
-
* </p>
|
1108 |
* ```
|
1109 |
-
* @return
|
|
|
1110 |
*/
|
1111 |
-
public function
|
1112 |
-
|
|
|
|
|
|
|
1113 |
}
|
1114 |
|
1115 |
/**
|
1116 |
-
*
|
|
|
|
|
1117 |
* @example
|
1118 |
* ```twig
|
1119 |
-
*
|
1120 |
-
* ```
|
1121 |
-
* ```html
|
1122 |
-
* Last updated by Harper Lee
|
1123 |
* ```
|
1124 |
-
* @return
|
1125 |
*/
|
1126 |
-
public function
|
1127 |
-
return $this->
|
1128 |
}
|
1129 |
|
1130 |
/**
|
1131 |
-
* Get the
|
1132 |
* @api
|
1133 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1134 |
*/
|
1135 |
-
public function
|
1136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1137 |
}
|
1138 |
|
1139 |
/**
|
1140 |
-
*
|
1141 |
* @api
|
1142 |
-
*
|
1143 |
-
* @return TimberTerm|null
|
1144 |
*/
|
1145 |
-
public function
|
1146 |
-
return $this->
|
1147 |
}
|
1148 |
|
1149 |
/**
|
1150 |
-
*
|
1151 |
-
* (or other claass as you define).
|
1152 |
* @api
|
1153 |
* @example
|
1154 |
* ```twig
|
1155 |
-
* {
|
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 |
-
* @
|
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
|
1167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1168 |
}
|
1169 |
|
1170 |
/**
|
1171 |
-
*
|
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 |
-
* {
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1190 |
*/
|
1191 |
-
|
1192 |
-
return $this->
|
1193 |
}
|
1194 |
|
1195 |
/**
|
1196 |
-
*
|
1197 |
-
* @
|
1198 |
-
* @
|
1199 |
-
*
|
1200 |
-
*
|
1201 |
-
* <h2>{{post.title}}</h2>
|
1202 |
-
* <div class="content">{{ post.content }}</div>
|
1203 |
-
* </div>
|
1204 |
-
* ```
|
1205 |
-
* @param int $page
|
1206 |
-
* @return string
|
1207 |
*/
|
1208 |
-
|
1209 |
-
|
|
|
|
|
|
|
1210 |
}
|
1211 |
|
1212 |
/**
|
1213 |
-
* @
|
|
|
1214 |
*/
|
1215 |
-
|
1216 |
-
return $this->
|
1217 |
}
|
1218 |
|
1219 |
/**
|
1220 |
-
*
|
1221 |
-
* @
|
|
|
|
|
1222 |
* @example
|
1223 |
* ```twig
|
1224 |
-
*
|
1225 |
-
*
|
1226 |
-
*
|
1227 |
-
*
|
1228 |
-
*
|
1229 |
-
* ```html
|
1230 |
-
* Published on January 12, 2015
|
1231 |
-
* OR
|
1232 |
-
* Published on Jan 12th
|
1233 |
* ```
|
1234 |
-
* @
|
1235 |
-
* @return string
|
1236 |
*/
|
1237 |
-
|
1238 |
-
return $this->
|
1239 |
}
|
1240 |
|
1241 |
/**
|
1242 |
-
*
|
1243 |
-
* @
|
|
|
|
|
1244 |
* @example
|
1245 |
* ```twig
|
1246 |
-
*
|
1247 |
-
* OR
|
1248 |
-
* Published at {{ post.time | time('G:i') }} // 13:25
|
1249 |
* ```
|
1250 |
-
*
|
1251 |
* ```html
|
1252 |
-
*
|
1253 |
-
* OR
|
1254 |
-
* Published at 13:25
|
1255 |
* ```
|
1256 |
-
* @param string $time_format
|
1257 |
* @return string
|
1258 |
*/
|
1259 |
-
|
1260 |
-
|
1261 |
-
$the_time = (string)mysql2date($tf, $this->post_date);
|
1262 |
-
return apply_filters('get_the_time', $the_time, $tf);
|
1263 |
}
|
1264 |
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1270 |
}
|
1271 |
|
1272 |
/**
|
1273 |
-
* @
|
|
|
1274 |
* @return mixed
|
1275 |
*/
|
1276 |
-
|
1277 |
-
return $this->
|
1278 |
}
|
1279 |
|
1280 |
/**
|
1281 |
-
*
|
1282 |
-
*
|
1283 |
-
* @
|
1284 |
-
*
|
1285 |
-
*
|
1286 |
-
*
|
1287 |
-
* @
|
|
|
1288 |
*/
|
1289 |
-
public function
|
1290 |
-
return $this->
|
1291 |
}
|
1292 |
|
1293 |
/**
|
1294 |
-
* @
|
1295 |
-
* @
|
|
|
1296 |
*/
|
1297 |
-
public function
|
1298 |
-
|
1299 |
-
|
1300 |
-
|
1301 |
-
|
1302 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1303 |
}
|
1304 |
|
1305 |
/**
|
|
|
|
|
|
|
|
|
|
|
1306 |
* @return string
|
1307 |
*/
|
1308 |
-
|
1309 |
-
return $this->
|
1310 |
}
|
1311 |
|
1312 |
/**
|
1313 |
-
* @
|
|
|
1314 |
* @return string
|
1315 |
*/
|
1316 |
-
|
1317 |
-
|
|
|
|
|
1318 |
}
|
1319 |
|
1320 |
/**
|
1321 |
-
* @
|
1322 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
1323 |
*/
|
1324 |
-
|
1325 |
-
return $this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1326 |
}
|
1327 |
|
1328 |
/**
|
1329 |
-
*
|
1330 |
-
* @
|
1331 |
-
* @
|
|
|
|
|
|
|
1332 |
*/
|
1333 |
-
|
1334 |
-
return $this->
|
1335 |
}
|
1336 |
|
1337 |
/**
|
1338 |
-
*
|
|
|
|
|
|
|
|
|
1339 |
*/
|
1340 |
-
|
1341 |
-
return $this->
|
1342 |
}
|
1343 |
|
1344 |
/**
|
1345 |
-
* Gets
|
1346 |
-
* @
|
1347 |
-
* @
|
1348 |
-
*
|
1349 |
-
*
|
1350 |
-
*
|
1351 |
-
* @return bool|TimberPost
|
1352 |
*/
|
1353 |
-
|
1354 |
-
|
|
|
|
|
1355 |
}
|
1356 |
|
1357 |
/**
|
1358 |
-
*
|
1359 |
-
*
|
1360 |
-
* @
|
1361 |
-
* @
|
1362 |
-
* ```twig
|
1363 |
-
* <a href="{{post.path}}">{{post.title}}</a>
|
1364 |
-
* ```
|
1365 |
-
* @return string
|
1366 |
*/
|
1367 |
-
|
1368 |
-
return $this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1369 |
}
|
1370 |
|
1371 |
/**
|
1372 |
-
* @
|
|
|
|
|
|
|
1373 |
* @return string
|
1374 |
*/
|
1375 |
-
|
1376 |
-
return $this->
|
1377 |
}
|
1378 |
|
1379 |
/**
|
1380 |
-
*
|
1381 |
-
*
|
1382 |
-
*
|
1383 |
-
*
|
1384 |
-
*
|
1385 |
-
*
|
1386 |
-
*
|
1387 |
-
* ```
|
1388 |
-
* @param bool $in_same_cat
|
1389 |
-
* @return mixed
|
1390 |
*/
|
1391 |
-
|
1392 |
-
return $this->
|
1393 |
}
|
1394 |
|
1395 |
/**
|
1396 |
-
* Get the
|
1397 |
-
*
|
1398 |
-
* @
|
1399 |
-
* @
|
1400 |
-
* @param bool $
|
1401 |
-
* @return
|
1402 |
*/
|
1403 |
-
|
1404 |
-
return $this->
|
1405 |
}
|
1406 |
|
1407 |
/**
|
1408 |
-
*
|
1409 |
-
* @
|
|
|
|
|
|
|
1410 |
* @return array
|
1411 |
*/
|
1412 |
-
public function
|
1413 |
-
return $this->
|
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 |
-
*
|
1431 |
-
* @
|
1432 |
-
* @
|
1433 |
-
*
|
1434 |
-
*
|
1435 |
-
*
|
1436 |
-
* @
|
|
|
|
|
1437 |
*/
|
1438 |
-
|
1439 |
-
return $this->
|
1440 |
}
|
1441 |
|
1442 |
}
|
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 |
* <?php
|
20 |
* // single.php, see connected twig example
|
21 |
* $context = Timber::get_context();
|
22 |
+
* $context['post'] = new Timber\Post(); // It's a new Timber\Post object, but an existing post from WordPress.
|
23 |
* Timber::render('single.twig', $context);
|
24 |
* ?>
|
25 |
* ```
|
44 |
*
|
45 |
* @package Timber
|
46 |
*/
|
47 |
+
class Post extends Core implements CoreInterface {
|
48 |
+
|
49 |
/**
|
50 |
* @var string $ImageClass the name of the class to handle images by default
|
51 |
*/
|
52 |
+
public $ImageClass = 'Timber\Image';
|
53 |
|
54 |
/**
|
55 |
* @var string $PostClass the name of the class to handle posts by default
|
56 |
*/
|
57 |
+
public $PostClass = 'Timber\Post';
|
58 |
|
59 |
/**
|
60 |
* @var string $TermClass the name of the class to handle terms by default
|
61 |
*/
|
62 |
+
public $TermClass = 'Timber\Term';
|
63 |
|
64 |
/**
|
65 |
* @var string $object_type what does this class represent in WordPress terms?
|
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 Timber\Post in a set inside an array (in order to manage by-taxonomy)
|
87 |
*/
|
88 |
protected $_next = array();
|
89 |
|
90 |
/**
|
91 |
+
* @var array $_prev stores the results of the previous Timber\Post in a set inside an array (in order to manage by-taxonomy)
|
92 |
*/
|
93 |
protected $_prev = array();
|
94 |
|
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 Timber\Post();
|
165 |
+
* $other_post = new Timber\Post($random_post_id);
|
166 |
* ```
|
167 |
* @param mixed $pid
|
168 |
*/
|
169 |
+
public function __construct( $pid = null ) {
|
170 |
+
$pid = $this->determine_id($pid);
|
171 |
$this->init($pid);
|
172 |
}
|
173 |
|
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( $pid ) {
|
181 |
global $wp_query;
|
182 |
if ( $pid === null &&
|
183 |
isset($wp_query->queried_object_id)
|
186 |
&& is_object($wp_query->queried_object)
|
187 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
188 |
) {
|
189 |
+
if ( isset($_GET['preview']) && isset($_GET['preview_nonce']) && wp_verify_nonce($_GET['preview_nonce'], 'post_preview_'.$wp_query->queried_object_id) ) {
|
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 |
}
|
211 |
}
|
212 |
}
|
213 |
+
if ( $pid === null && ($pid_from_loop = PostGetter::loop_to_id()) ) {
|
214 |
$pid = $pid_from_loop;
|
215 |
}
|
216 |
return $pid;
|
226 |
|
227 |
protected function get_post_preview_id( $query ) {
|
228 |
$can = array(
|
229 |
+
'edit_'.$query->queried_object->post_type.'s',
|
230 |
);
|
231 |
|
232 |
if ( $query->queried_object->author_id !== get_current_user_id() ) {
|
233 |
+
$can[] = 'edit_others_'.$query->queried_object->post_type.'s';
|
234 |
}
|
235 |
|
236 |
$can_preview = array();
|
237 |
|
238 |
+
foreach ( $can as $type ) {
|
239 |
+
if ( current_user_can($type) ) {
|
240 |
+
$can_preview[] = true;
|
241 |
+
}
|
242 |
}
|
243 |
|
244 |
+
if ( count($can_preview) !== count($can) ) {
|
245 |
+
return;
|
246 |
}
|
247 |
|
248 |
+
$revisions = wp_get_post_revisions($query->queried_object_id);
|
249 |
|
250 |
+
if ( !empty($revisions) ) {
|
251 |
$last = end($revisions);
|
252 |
return $last->ID;
|
253 |
}
|
256 |
}
|
257 |
|
258 |
/**
|
259 |
+
* Initializes a Post
|
260 |
* @internal
|
261 |
* @param int|bool $pid
|
262 |
*/
|
263 |
+
protected function init( $pid = false ) {
|
264 |
if ( $pid === false ) {
|
265 |
$pid = get_the_ID();
|
266 |
}
|
277 |
/**
|
278 |
* Get the URL that will edit the current post/object
|
279 |
* @internal
|
280 |
+
* @deprecated since 1.0
|
281 |
+
* @codeCoverageIgnore
|
282 |
+
* @see Timber\Post::edit_link
|
283 |
* @return bool|string
|
284 |
*/
|
285 |
function get_edit_url() {
|
286 |
+
return $this->edit_link();
|
|
|
|
|
287 |
}
|
288 |
|
289 |
/**
|
347 |
* @param string $post_name
|
348 |
* @return int
|
349 |
*/
|
350 |
+
static function get_post_id_by_name( $post_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 ( !$result ) {
|
355 |
return null;
|
356 |
}
|
357 |
return $result->ID;
|
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( $len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '…' ) {
|
377 |
$text = '';
|
378 |
$trimmed = false;
|
379 |
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
380 |
if ( $force ) {
|
381 |
+
$text = Helper::trim_words($this->post_excerpt, $len, false);
|
382 |
$trimmed = true;
|
383 |
} else {
|
384 |
$text = $this->post_excerpt;
|
388 |
$pieces = explode($readmore_matches[0], $this->post_content);
|
389 |
$text = $pieces[0];
|
390 |
if ( $force ) {
|
391 |
+
$text = Helper::trim_words($text, $len, false);
|
392 |
$trimmed = true;
|
393 |
}
|
394 |
+
$text = do_shortcode($text);
|
395 |
}
|
396 |
if ( !strlen($text) ) {
|
397 |
+
$text = Helper::trim_words($this->get_content(), $len, false);
|
398 |
$trimmed = true;
|
399 |
}
|
400 |
if ( !strlen(trim($text)) ) {
|
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="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore_matches[1]).'</a>';
|
425 |
} elseif ( $readmore ) {
|
426 |
+
$text .= ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore).'</a>';
|
427 |
}
|
428 |
+
if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
|
429 |
$text .= '</p>';
|
430 |
}
|
431 |
}
|
469 |
}
|
470 |
|
471 |
/**
|
472 |
+
* @param int $i
|
473 |
+
* @return string
|
|
|
474 |
*/
|
475 |
+
protected static function get_wp_link_page( $i ) {
|
476 |
+
$link = _wp_link_page($i);
|
477 |
+
$link = new \SimpleXMLElement($link.'</a>');
|
478 |
+
if ( isset($link['href']) ) {
|
479 |
+
return $link['href'];
|
|
|
480 |
}
|
481 |
+
return '';
|
482 |
}
|
483 |
|
484 |
/**
|
485 |
+
* Used internally by init, etc. to build TimberPost object
|
486 |
* @internal
|
487 |
+
* @param int $pid
|
488 |
+
* @return null|object|WP_Post
|
489 |
*/
|
490 |
+
protected function get_info( $pid ) {
|
491 |
+
$post = $this->prepare_post_info($pid);
|
492 |
+
if ( !isset($post->post_status) ) {
|
493 |
+
return null;
|
494 |
}
|
495 |
+
|
496 |
+
do_action_ref_array( 'the_post', array( &$post, &$GLOBALS['wp_query'] ) );
|
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 |
+
* Gets the comment form for use on a single article page
|
510 |
+
* @param array $args this $args thing is a fucking mess, [fix at some point](http://codex.wordpress.org/Function_Reference/comment_form)
|
511 |
+
* @return string of HTML for the form
|
|
|
512 |
*/
|
513 |
+
public function comment_form( $args = array() ) {
|
514 |
+
return Helper::get_comment_form( $this->ID, $args );
|
515 |
}
|
516 |
|
517 |
+
|
518 |
/**
|
519 |
+
* Get the terms associated with the post
|
520 |
+
* This goes across all taxonomies by default
|
521 |
+
* @api
|
522 |
+
* @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.
|
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 |
+
public function terms( $tax = '', $merge = true, $TermClass = '' ) {
|
527 |
+
|
528 |
+
$TermClass = $TermClass ?: $this->TermClass;
|
529 |
+
|
530 |
+
if ( is_string($merge) && class_exists($merge) ) {
|
531 |
+
$TermClass = $merge;
|
532 |
+
}
|
533 |
+
if ( is_array($tax) ) {
|
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 |
+
$taxonomies = array($tax);
|
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 |
+
// map over array of wordpress terms, and transform them into instances of the TermClass
|
566 |
+
$terms = array_map(function( $term ) use ($TermClass, $taxonomy) {
|
567 |
+
return call_user_func(array($TermClass, 'from'), $term->term_id, $taxonomy);
|
568 |
+
}, $terms);
|
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 $term_class_objects;
|
577 |
}
|
578 |
|
579 |
/**
|
580 |
+
* @param string|int $term_name_or_id
|
581 |
+
* @param string $taxonomy
|
582 |
+
* @return bool
|
583 |
*/
|
584 |
+
function has_term( $term_name_or_id, $taxonomy = 'all' ) {
|
585 |
+
if ( $taxonomy == 'all' || $taxonomy == 'any' ) {
|
586 |
+
$taxes = get_object_taxonomies($this->post_type, 'names');
|
587 |
+
$ret = false;
|
588 |
+
foreach ( $taxes as $tax ) {
|
589 |
+
if ( has_term($term_name_or_id, $tax, $this->ID) ) {
|
590 |
+
$ret = true;
|
591 |
+
break;
|
|
|
|
|
592 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
593 |
}
|
594 |
+
return $ret;
|
595 |
}
|
596 |
+
return has_term($term_name_or_id, $taxonomy, $this->ID);
|
597 |
}
|
598 |
|
599 |
/**
|
|
|
600 |
* @return string
|
601 |
*/
|
602 |
+
function get_paged_content() {
|
603 |
+
return $this->paged_content();
|
|
|
|
|
|
|
|
|
|
|
604 |
}
|
|
|
605 |
/**
|
606 |
+
*
|
607 |
+
* Here is my summary
|
608 |
+
* @example
|
609 |
+
* ```twig
|
610 |
+
* This post is from <span>{{ post.get_post_type.labels.plural }}</span>
|
611 |
+
* ```
|
612 |
+
*
|
613 |
+
* ```html
|
614 |
+
* This post is from <span>Recipes</span>
|
615 |
+
* ```
|
616 |
+
* @return mixed
|
617 |
*/
|
618 |
+
public function get_post_type() {
|
619 |
+
return get_post_type_object($this->post_type);
|
620 |
}
|
621 |
|
622 |
/**
|
623 |
+
* @return int the number of comments on a post
|
|
|
|
|
|
|
624 |
*/
|
625 |
+
public function get_comment_count() {
|
626 |
+
return get_comments_number($this->ID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
627 |
}
|
628 |
|
629 |
/**
|
630 |
+
* @param string $field_name
|
631 |
+
* @return mixed
|
|
|
632 |
*/
|
633 |
+
public function get_field( $field_name ) {
|
634 |
+
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
635 |
+
if ( $value === null ) {
|
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 |
+
$value = apply_filters('timber_post_get_meta_field', $value, $this->ID, $field_name, $this);
|
645 |
+
$value = $this->convert($value, __CLASS__);
|
646 |
+
return $value;
|
647 |
}
|
648 |
|
649 |
/**
|
650 |
+
* @param string $field_name
|
|
|
|
|
|
|
651 |
*/
|
652 |
+
function import_field( $field_name ) {
|
653 |
+
$this->$field_name = $this->get_field($field_name);
|
|
|
|
|
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 |
+
* @param string $class additional classes you want to add
|
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 |
+
public function post_class( $class = '' ) {
|
676 |
+
global $post;
|
677 |
+
$old_global_post = $post;
|
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 |
+
* @return array
|
691 |
+
* @codeCoverageIgnore
|
|
|
|
|
692 |
*/
|
693 |
+
public function get_method_values() {
|
694 |
+
$ret = parent::get_method_values();
|
695 |
+
$ret['author'] = $this->author();
|
696 |
+
$ret['categories'] = $this->categories();
|
697 |
+
$ret['category'] = $this->category();
|
698 |
+
$ret['children'] = $this->children();
|
699 |
+
$ret['comments'] = $this->comments();
|
700 |
+
$ret['content'] = $this->content();
|
701 |
+
$ret['edit_link'] = $this->edit_link();
|
702 |
+
$ret['format'] = $this->format();
|
703 |
+
$ret['link'] = $this->link();
|
704 |
+
$ret['next'] = $this->next();
|
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 |
+
* Get the author (WordPress user) who last modified the post
|
734 |
+
* @example
|
735 |
+
* ```twig
|
736 |
+
* Last updated by {{ post.modified_author.name }}
|
737 |
+
* ```
|
738 |
+
* ```html
|
739 |
+
* Last updated by Harper Lee
|
740 |
+
* ```
|
741 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
742 |
*/
|
743 |
+
public function modified_author() {
|
744 |
+
$user_id = get_post_meta($this->ID, '_edit_last', true);
|
745 |
+
return ($user_id ? new User($user_id) : $this->get_author());
|
|
|
746 |
}
|
747 |
|
748 |
/**
|
749 |
+
* Get the categoires on a particular post
|
750 |
+
* @api
|
751 |
+
* @return array of TimberTerms
|
752 |
*/
|
753 |
+
public function categories() {
|
754 |
+
return $this->get_terms('category');
|
|
|
|
|
755 |
}
|
756 |
|
757 |
/**
|
758 |
+
* Returns a category attached to a post
|
759 |
+
* @api
|
760 |
+
* If mulitpuile categories are set, it will return just the first one
|
761 |
+
* @return TimberTerm|null
|
762 |
+
*/
|
763 |
+
public function category() {
|
764 |
+
return $this->get_category();
|
765 |
+
}
|
766 |
+
|
767 |
+
/**
|
768 |
+
* Returns an array of children on the post as Timber\Posts
|
769 |
+
* (or other claass as you define).
|
770 |
+
* @api
|
771 |
+
* @example
|
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 |
+
public function children( $post_type = 'any', $childPostClass = false ) {
|
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='.$this->ID.'&post_type='.$post_type.'&numberposts=-1&orderby=menu_order title&order=ASC&post_status=publish');
|
792 |
foreach ( $children as &$child ) {
|
793 |
$child = new $childPostClass($child->ID);
|
794 |
}
|
796 |
return $children;
|
797 |
}
|
798 |
|
|
|
799 |
/**
|
800 |
+
* Gets the comments on a Timber\Post and returns them as an array of [TimberComments](#TimberComment) (or whatever comment class you set).
|
801 |
+
* @api
|
802 |
+
* @param int $count Set the number of comments you want to get. `0` is analogous to "all"
|
803 |
+
* @param string $order use ordering set in WordPress admin, or a different scheme
|
804 |
+
* @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
|
805 |
+
* @param string $status Could be 'pending', etc.
|
806 |
+
* @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)
|
807 |
+
* @example
|
808 |
+
* ```twig
|
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 |
+
public function comments( $count = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment' ) {
|
|
|
|
|
821 |
global $overridden_cpage, $user_ID;
|
822 |
$overridden_cpage = false;
|
823 |
|
825 |
$comment_author_email = $commenter['comment_author_email'];
|
826 |
|
827 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
828 |
+
if ( $count > 0 ) {
|
829 |
+
$args['number'] = $count;
|
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 ( $comments as $key => &$comment ) {
|
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 ( $timber_comments as $key => $comment ) {
|
857 |
+
if ( !$comment->is_child() ) {
|
858 |
continue;
|
859 |
}
|
860 |
|
861 |
$tree_element = $comment;
|
862 |
do {
|
863 |
$tree_element = $timber_comments[$tree_element->comment_parent];
|
864 |
+
} while ( $tree_element->is_child() );
|
865 |
|
866 |
$comments_tree[$tree_element->id][] = $comment->id;
|
867 |
}
|
868 |
|
869 |
// Add child comments to the relative "super parents"
|
870 |
+
foreach ( $comments_tree as $comment_parent => $comment_children ) {
|
871 |
+
foreach ( $comment_children as $comment_child ) {
|
872 |
$timber_comments[$comment_parent]->children[] = $timber_comments[$comment_child];
|
873 |
unset($timber_comments[$comment_child]);
|
874 |
}
|
880 |
}
|
881 |
|
882 |
/**
|
883 |
+
* 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).
|
884 |
+
* @api
|
885 |
+
* @example
|
886 |
+
* ```twig
|
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 |
+
public function content( $page = 0, $len = -1 ) {
|
896 |
+
if ( $len == -1 && $page == 0 && $this->_content ) {
|
897 |
+
return $this->_content;
|
|
|
|
|
|
|
|
|
|
|
|
|
898 |
}
|
899 |
+
$content = $this->post_content;
|
900 |
+
if ( $len > 0 ) {
|
901 |
+
$content = wp_trim_words($content, $len);
|
|
|
|
|
|
|
902 |
}
|
903 |
+
if ( $page ) {
|
904 |
+
$contents = explode('<!--nextpage-->', $content);
|
905 |
+
$page--;
|
906 |
+
if ( count($contents) > $page ) {
|
907 |
+
$content = $contents[$page];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
908 |
}
|
909 |
}
|
910 |
+
$content = apply_filters('the_content', ($content));
|
911 |
+
if ( $len == -1 && $page == 0 ) {
|
912 |
+
$this->_content = $content;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
913 |
}
|
914 |
+
return $content;
|
915 |
}
|
916 |
|
917 |
/**
|
918 |
+
* @return string
|
|
|
919 |
*/
|
920 |
+
public function paged_content() {
|
921 |
+
global $page;
|
922 |
+
return $this->content($page, -1);
|
923 |
}
|
924 |
|
925 |
/**
|
926 |
+
* Get the date to use in your template!
|
927 |
+
* @api
|
928 |
* @example
|
929 |
* ```twig
|
930 |
+
* Published on {{ post.date }} // Uses WP's formatting set in Admin
|
931 |
+
* OR
|
932 |
+
* Published on {{ post.date | date('F jS') }} // Jan 12th
|
|
|
|
|
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 |
+
public function date( $date_format = '' ) {
|
944 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
945 |
+
$the_date = (string) mysql2date($df, $this->post_date);
|
946 |
+
return apply_filters('get_the_date', $the_date, $df);
|
947 |
}
|
948 |
|
949 |
/**
|
950 |
+
* Get the time to use in your template
|
951 |
+
* @api
|
952 |
* @example
|
953 |
* ```twig
|
954 |
+
* Published at {{ post.time }} // Uses WP's formatting set in Admin
|
955 |
+
* OR
|
956 |
+
* Published at {{ post.time | time('G:i') }} // 13:25
|
957 |
* ```
|
958 |
+
*
|
959 |
* ```html
|
960 |
+
* Published at 1:25 pm
|
961 |
+
* OR
|
962 |
+
* Published at 13:25
|
963 |
* ```
|
964 |
+
* @param string $time_format
|
965 |
* @return string
|
966 |
*/
|
967 |
+
public function time( $time_format = '' ) {
|
968 |
+
$tf = $time_format ? $time_format : get_option('time_format');
|
969 |
+
$the_time = (string) mysql2date($tf, $this->post_date);
|
970 |
+
return apply_filters('get_the_time', $the_time, $tf);
|
971 |
}
|
972 |
|
973 |
/**
|
974 |
+
* Returns the edit URL of a post if the user has access to it
|
975 |
+
* @return bool|string the edit URL of a post in the WordPress admin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
976 |
*/
|
977 |
+
public function edit_link() {
|
978 |
+
if ( $this->can_edit() ) {
|
979 |
+
return get_edit_post_link($this->ID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
980 |
}
|
|
|
981 |
}
|
982 |
|
983 |
/**
|
984 |
+
* @api
|
985 |
+
* @return mixed
|
986 |
*/
|
987 |
+
public function format() {
|
988 |
+
return get_post_format($this->ID);
|
|
|
989 |
}
|
990 |
+
|
991 |
/**
|
992 |
+
* get the permalink for a post object
|
993 |
+
* @api
|
994 |
* @example
|
995 |
* ```twig
|
996 |
+
* <a href="{{post.link}}">Read my post</a>
|
|
|
|
|
|
|
|
|
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 meta( $field_name = null ) {
|
1013 |
+
if ( $field_name === null ) {
|
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 string
|
1022 |
*/
|
1023 |
+
public function name() {
|
1024 |
+
return $this->title();
|
1025 |
}
|
1026 |
|
1027 |
/**
|
1028 |
+
* @param string $date_format
|
1029 |
+
* @return string
|
1030 |
*/
|
1031 |
+
public function modified_date( $date_format = '' ) {
|
1032 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
1033 |
+
$the_time = $this->get_modified_time($df);
|
1034 |
+
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1035 |
}
|
1036 |
|
1037 |
/**
|
1038 |
+
* @param string $time_format
|
1039 |
+
* @return string
|
1040 |
*/
|
1041 |
+
public function modified_time( $time_format = '' ) {
|
1042 |
+
return $this->get_modified_time($time_format);
|
1043 |
}
|
1044 |
|
1045 |
/**
|
1046 |
+
* @api
|
1047 |
+
* @param bool $in_same_cat
|
1048 |
* @return mixed
|
1049 |
*/
|
1050 |
+
public function next( $in_same_term = false ) {
|
1051 |
+
if ( !isset($this->_next) || !isset($this->_next[$in_same_term]) ) {
|
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 a data array of pagination so you can navigate to the previous/next for a paginated post
|
1074 |
+
* @return array
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1075 |
*/
|
1076 |
+
public function pagination() {
|
1077 |
+
global $post, $page, $numpages, $multipage;
|
|
|
1078 |
$post = $this;
|
1079 |
+
$ret = array();
|
1080 |
+
if ( $multipage ) {
|
1081 |
+
for ( $i = 1; $i <= $numpages; $i++ ) {
|
1082 |
+
$link = self::get_wp_link_page($i);
|
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 $ret;
|
1101 |
}
|
1102 |
|
1103 |
+
|
1104 |
|
1105 |
/**
|
1106 |
+
* Finds any WP_Post objects and converts them to Timber\Posts
|
1107 |
+
* @param array $data
|
1108 |
*/
|
1109 |
+
public function convert( $data, $class ) {
|
1110 |
+
if ( is_array($data) ) {
|
1111 |
+
$func = __FUNCTION__;
|
1112 |
+
foreach ( $data as &$ele ) {
|
1113 |
+
if ( gettype($ele) === 'array' ) {
|
1114 |
+
$ele = $this->$func($ele, $class);
|
1115 |
+
} else {
|
1116 |
+
if ( $ele instanceof WP_Post ) {
|
1117 |
+
$ele = new $class($ele);
|
1118 |
+
}
|
1119 |
+
}
|
1120 |
+
}
|
1121 |
+
}
|
1122 |
+
|
1123 |
+
return $data;
|
|
|
|
|
|
|
|
|
|
|
|
|
1124 |
}
|
1125 |
|
1126 |
/**
|
1127 |
+
* Gets the parent (if one exists) from a post as a Timber\Post object (or whatever is set in Timber\Post::$PostClass)
|
1128 |
* @api
|
1129 |
* @example
|
1130 |
* ```twig
|
1131 |
+
* Parent page: <a href="{{ post.parent.link }}">{{ post.parent.title }}</a>
|
|
|
|
|
|
|
1132 |
* ```
|
1133 |
+
* @return bool|Timber\Post
|
1134 |
+
* @param string $field_name
|
1135 |
*/
|
1136 |
+
public function parent() {
|
1137 |
+
if ( !$this->post_parent ) {
|
1138 |
+
return false;
|
1139 |
+
}
|
1140 |
+
return new $this->PostClass($this->post_parent);
|
1141 |
}
|
1142 |
|
1143 |
/**
|
1144 |
+
* Gets the relative path of a WP Post, so while link() will return http://example.org/2015/07/my-cool-post
|
1145 |
+
* this will return just /2015/07/my-cool-post
|
1146 |
+
* @api
|
1147 |
* @example
|
1148 |
* ```twig
|
1149 |
+
* <a href="{{post.path}}">{{post.title}}</a>
|
|
|
|
|
|
|
1150 |
* ```
|
1151 |
+
* @return string
|
1152 |
*/
|
1153 |
+
public function path() {
|
1154 |
+
return URLHelper::get_rel_url($this->get_link());
|
1155 |
}
|
1156 |
|
1157 |
/**
|
1158 |
+
* Get the previous post in a set
|
1159 |
* @api
|
1160 |
+
* @example
|
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 prev( $in_same_term = false ) {
|
1170 |
+
if ( isset($this->_prev) && isset($this->_prev[$in_same_term]) ) {
|
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 |
+
* Gets the tags on a post, uses WP's post_tag taxonomy
|
1189 |
* @api
|
1190 |
+
* @return array
|
|
|
1191 |
*/
|
1192 |
+
public function tags() {
|
1193 |
+
return $this->get_tags();
|
1194 |
}
|
1195 |
|
1196 |
/**
|
1197 |
+
* get the featured image as a TimberImage
|
|
|
1198 |
* @api
|
1199 |
* @example
|
1200 |
* ```twig
|
1201 |
+
* <img src="{{post.thumbnail.src}}" />
|
|
|
|
|
|
|
|
|
|
|
1202 |
* ```
|
1203 |
+
* @return TimberImage|null of your thumbnail
|
|
|
|
|
1204 |
*/
|
1205 |
+
public function thumbnail() {
|
1206 |
+
if ( function_exists('get_post_thumbnail_id') ) {
|
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 |
+
* 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.
|
1217 |
* @api
|
|
|
|
|
|
|
|
|
|
|
1218 |
* @example
|
1219 |
* ```twig
|
1220 |
+
* <h1>{{ post.title }}</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1221 |
* ```
|
1222 |
+
* @return string
|
1223 |
+
*/
|
1224 |
+
public function title() {
|
1225 |
+
return apply_filters('the_title', $this->post_title, $this->ID);
|
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 get_categories() {
|
1245 |
+
return $this->get_terms('category');
|
1246 |
}
|
1247 |
|
1248 |
/**
|
1249 |
+
* @internal
|
1250 |
+
* @deprecated since 1.0
|
1251 |
+
* @codeCoverageIgnore
|
1252 |
+
* @see Timber\Post::category
|
1253 |
+
* @return mixed
|
|
|
|
|
|
|
|
|
|
|
|
|
1254 |
*/
|
1255 |
+
function get_category( ) {
|
1256 |
+
$cats = $this->get_categories();
|
1257 |
+
if ( count($cats) && isset($cats[0]) ) {
|
1258 |
+
return $cats[0];
|
1259 |
+
}
|
1260 |
}
|
1261 |
|
1262 |
/**
|
1263 |
+
* @param string $field
|
1264 |
+
* @return TimberImage
|
1265 |
*/
|
1266 |
+
function get_image( $field ) {
|
1267 |
+
return new $this->ImageClass($this->$field);
|
1268 |
}
|
1269 |
|
1270 |
/**
|
1271 |
+
* Gets an array of tags for you to use
|
1272 |
+
* @internal
|
1273 |
+
* @deprecated since 1.0
|
1274 |
+
* @codeCoverageIgnore
|
1275 |
* @example
|
1276 |
* ```twig
|
1277 |
+
* <ul class="tags">
|
1278 |
+
* {% for tag in post.tags %}
|
1279 |
+
* <li>{{tag.name}}</li>
|
1280 |
+
* {% endfor %}
|
1281 |
+
* </ul>
|
|
|
|
|
|
|
|
|
1282 |
* ```
|
1283 |
+
* @return array
|
|
|
1284 |
*/
|
1285 |
+
function get_tags() {
|
1286 |
+
return $this->get_terms('post_tag');
|
1287 |
}
|
1288 |
|
1289 |
/**
|
1290 |
+
* Outputs the title with filters applied
|
1291 |
+
* @internal
|
1292 |
+
* @deprecated since 1.0
|
1293 |
+
* @codeCoverageIgnore
|
1294 |
* @example
|
1295 |
* ```twig
|
1296 |
+
* <h1>{{post.get_title}}</h1>
|
|
|
|
|
1297 |
* ```
|
|
|
1298 |
* ```html
|
1299 |
+
* <h1>Hello World!</h1>
|
|
|
|
|
1300 |
* ```
|
|
|
1301 |
* @return string
|
1302 |
*/
|
1303 |
+
function get_title() {
|
1304 |
+
return $this->title();
|
|
|
|
|
1305 |
}
|
1306 |
|
1307 |
+
/**
|
1308 |
+
* Displays the content of the post with filters, shortcodes and wpautop applied
|
1309 |
+
* @example
|
1310 |
+
* ```twig
|
1311 |
+
* <div class="article-text">{{post.get_content}}</div>
|
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 |
+
* @internal
|
1329 |
+
* @deprecated since 1.0
|
1330 |
* @return mixed
|
1331 |
*/
|
1332 |
+
function get_format() {
|
1333 |
+
return $this->format();
|
1334 |
}
|
1335 |
|
1336 |
/**
|
1337 |
+
* Get the terms associated with the post
|
1338 |
+
* This goes across all taxonomies by default
|
1339 |
+
* @internal
|
1340 |
+
* @deprecated since 1.0
|
1341 |
+
* @codeCoverageIgnore
|
1342 |
+
* @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.
|
1343 |
+
* @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)?
|
1344 |
+
* @return array
|
1345 |
*/
|
1346 |
+
public function get_terms( $tax = '', $merge = true ) {
|
1347 |
+
return $this->terms($tax, $merge);
|
1348 |
}
|
1349 |
|
1350 |
/**
|
1351 |
+
* @deprecated 0.20.0 use link() instead
|
1352 |
+
* @codeCoverageIgnore
|
1353 |
+
* @return string
|
1354 |
*/
|
1355 |
+
public function permalink() {
|
1356 |
+
Helper::warn('post.permalink has been removed, please use post.link');
|
1357 |
+
return $this->link();
|
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 get_modified_date( $date_format = '' ) {
|
1381 |
+
return $this->modified_date($date_format);
|
1382 |
}
|
1383 |
|
1384 |
/**
|
1385 |
+
* @internal
|
1386 |
+
* @param string $time_format
|
1387 |
* @return string
|
1388 |
*/
|
1389 |
+
function get_modified_time( $time_format = '' ) {
|
1390 |
+
$tf = $time_format ? $time_format : get_option('time_format');
|
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 |
+
* @internal
|
1397 |
+
* @see Timber\Post::children
|
1398 |
+
* @deprecated since 1.0
|
1399 |
+
* @codeCoverageIgnore
|
1400 |
+
* @param string $post_type
|
1401 |
+
* @param bool|string $childPostClass
|
1402 |
+
* @return array
|
1403 |
*/
|
1404 |
+
function get_children( $post_type = 'any', $childPostClass = false ) {
|
1405 |
+
return $this->children($post_type, $childPostClass);
|
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 |
+
* Get the next post in WordPress's ordering
|
1423 |
+
* @internal
|
1424 |
+
* @deprecated since 1.0
|
1425 |
+
* @codeCoverageIgnore
|
1426 |
+
* @param bool $taxonomy
|
1427 |
+
* @return TimberPost|boolean
|
1428 |
*/
|
1429 |
+
function get_prev( $in_same_term = false ) {
|
1430 |
+
return $this->prev($in_same_term);
|
1431 |
}
|
1432 |
|
1433 |
/**
|
1434 |
+
* Get the parent post of the post
|
1435 |
+
* @internal
|
1436 |
+
* @deprecated since 1.0
|
1437 |
+
* @codeCoverageIgnore
|
1438 |
+
* @return bool|TimberPost
|
1439 |
*/
|
1440 |
+
function get_parent() {
|
1441 |
+
return $this->parent();
|
1442 |
}
|
1443 |
|
1444 |
/**
|
1445 |
+
* Gets a User object from the author of the post
|
1446 |
+
* @internal
|
1447 |
+
* @deprecated since 1.0
|
1448 |
+
* @codeCoverageIgnore
|
1449 |
+
* @see TimberPost::author
|
1450 |
+
* @return bool|TimberUser
|
|
|
1451 |
*/
|
1452 |
+
function get_author() {
|
1453 |
+
if ( isset($this->post_author) ) {
|
1454 |
+
return new User($this->post_author);
|
1455 |
+
}
|
1456 |
}
|
1457 |
|
1458 |
/**
|
1459 |
+
* @internal
|
1460 |
+
* @deprecated since 1.0
|
1461 |
+
* @codeCoverageIgnore
|
1462 |
+
* @return bool|TimberUser
|
|
|
|
|
|
|
|
|
1463 |
*/
|
1464 |
+
function get_modified_author() {
|
1465 |
+
return $this->modified_author();
|
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 |
+
* @internal
|
1481 |
+
* @see TimberPost::link
|
1482 |
+
* @deprecated since 1.0
|
1483 |
+
* @codeCoverageIgnore
|
1484 |
* @return string
|
1485 |
*/
|
1486 |
+
function get_permalink() {
|
1487 |
+
return $this->link();
|
1488 |
}
|
1489 |
|
1490 |
/**
|
1491 |
+
* get the permalink for a post object
|
1492 |
+
* In your templates you should use link:
|
1493 |
+
* <a href="{{post.link}}">Read my post</a>
|
1494 |
+
* @internal
|
1495 |
+
* @deprecated since 1.0
|
1496 |
+
* @codeCoverageIgnore
|
1497 |
+
* @return string
|
|
|
|
|
|
|
1498 |
*/
|
1499 |
+
function get_link() {
|
1500 |
+
return $this->get_permalink();
|
1501 |
}
|
1502 |
|
1503 |
/**
|
1504 |
+
* Get the next post in WordPress's ordering
|
1505 |
+
* @internal
|
1506 |
+
* @deprecated since 1.0
|
1507 |
+
* @codeCoverageIgnore
|
1508 |
+
* @param bool $taxonomy
|
1509 |
+
* @return TimberPost|boolean
|
1510 |
*/
|
1511 |
+
function get_next( $taxonomy = false ) {
|
1512 |
+
return $this->next($taxonomy);
|
1513 |
}
|
1514 |
|
1515 |
/**
|
1516 |
+
* Get a data array of pagination so you can navigate to the previous/next for a paginated post
|
1517 |
+
* @internal
|
1518 |
+
* @see Timber\Post::pagination();
|
1519 |
+
* @deprecated since 1.0
|
1520 |
+
* @codeCoverageIgnore
|
1521 |
* @return array
|
1522 |
*/
|
1523 |
+
public function get_pagination() {
|
1524 |
+
return $this->pagination();
|
1525 |
}
|
1526 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1527 |
|
1528 |
/**
|
1529 |
+
* Get the comments for a post
|
1530 |
+
* @internal
|
1531 |
+
* @see Timber\Post::comments
|
1532 |
+
* @param int $count
|
1533 |
+
* @param string $order
|
1534 |
+
* @param string $type
|
1535 |
+
* @param string $status
|
1536 |
+
* @param string $CommentClass
|
1537 |
+
* @return array|mixed
|
1538 |
*/
|
1539 |
+
function get_comments( $count = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment' ) {
|
1540 |
+
return $this->comments($count, $order, $type, $status, $CommentClass);
|
1541 |
}
|
1542 |
|
1543 |
}
|
lib/PostGetter.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{timber-request.php → Request.php}
RENAMED
@@ -1,8 +1,15 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
/**
|
3 |
* TimberRequest exposes $_GET and $_POST to the context
|
4 |
*/
|
5 |
-
|
|
|
6 |
public $post = array();
|
7 |
public $get = array();
|
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 |
|
lib/{timber-site.php → Site.php}
RENAMED
@@ -1,5 +1,13 @@
|
|
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,7 +24,7 @@
|
|
16 |
* My site is called Jared's blog, another site on my network is Upstatement.com
|
17 |
* ```
|
18 |
*/
|
19 |
-
class
|
20 |
|
21 |
/**
|
22 |
* @api
|
@@ -64,7 +72,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
64 |
|
65 |
/** @api
|
66 |
* @var string for people who like trackback spam
|
67 |
-
|
68 |
public $pingback_url;
|
69 |
public $siteurl;
|
70 |
/**
|
@@ -104,7 +112,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
104 |
function __construct( $site_name_or_id = null ) {
|
105 |
$this->init();
|
106 |
if ( is_multisite() ) {
|
107 |
-
$this->init_as_multisite(
|
108 |
} else {
|
109 |
$this->init_as_singlesite();
|
110 |
}
|
@@ -122,17 +130,17 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
122 |
$site_name_or_id = get_current_blog_id();
|
123 |
}
|
124 |
}
|
125 |
-
$info = get_blog_details(
|
126 |
-
$this->import(
|
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(
|
133 |
-
$this->theme = new
|
134 |
-
$this->description = get_blog_option(
|
135 |
-
$this->admin_email = get_blog_option(
|
136 |
$this->multisite = true;
|
137 |
}
|
138 |
|
@@ -141,13 +149,13 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
141 |
* @internal
|
142 |
*/
|
143 |
protected function init_as_singlesite() {
|
144 |
-
$this->admin_email = get_bloginfo(
|
145 |
-
$this->name = get_bloginfo(
|
146 |
$this->title = $this->name;
|
147 |
-
$this->description = get_bloginfo(
|
148 |
-
$this->url = get_bloginfo(
|
149 |
-
$this->theme = new
|
150 |
-
$this->language_attributes =
|
151 |
$this->multisite = false;
|
152 |
}
|
153 |
|
@@ -156,16 +164,14 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
156 |
* @internal
|
157 |
*/
|
158 |
protected function init() {
|
159 |
-
$this->rdf = get_bloginfo(
|
160 |
-
$this->rss = get_bloginfo(
|
161 |
-
$this->rss2 = get_bloginfo(
|
162 |
-
$this->atom = get_bloginfo(
|
163 |
-
$this->language = get_bloginfo(
|
164 |
-
$this->charset = get_bloginfo(
|
165 |
-
$this->pingback = get_bloginfo(
|
166 |
-
$this->language_attributes =
|
167 |
-
/* deprecated benath this comment */
|
168 |
-
$this->pingback_url = get_bloginfo( 'pingback_url' );
|
169 |
}
|
170 |
|
171 |
/**
|
@@ -175,34 +181,16 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
175 |
* @return mixed
|
176 |
*/
|
177 |
function __get( $field ) {
|
178 |
-
if ( !isset(
|
179 |
if ( is_multisite() ) {
|
180 |
-
$this->$field = get_blog_option(
|
181 |
} else {
|
182 |
-
$this->$field = get_option(
|
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,11 +211,22 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
223 |
return $this->url;
|
224 |
}
|
225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
/**
|
227 |
* @ignore
|
228 |
*/
|
229 |
public function meta( $field ) {
|
230 |
-
return $this->__get(
|
231 |
}
|
232 |
|
233 |
/**
|
@@ -237,11 +236,11 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
237 |
* @param mixed $value
|
238 |
*/
|
239 |
public function update( $key, $value ) {
|
240 |
-
$value = apply_filters(
|
241 |
if ( is_multisite() ) {
|
242 |
-
update_blog_option(
|
243 |
} else {
|
244 |
-
update_option(
|
245 |
}
|
246 |
$this->$key = $value;
|
247 |
}
|
@@ -253,7 +252,17 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
253 |
* @return string
|
254 |
*/
|
255 |
function url() {
|
256 |
-
return $this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
}
|
258 |
|
259 |
}
|
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 |
* My site is called Jared's blog, another site on my network is Upstatement.com
|
25 |
* ```
|
26 |
*/
|
27 |
+
class Site extends Core implements CoreInterface {
|
28 |
|
29 |
/**
|
30 |
* @api
|
72 |
|
73 |
/** @api
|
74 |
* @var string for people who like trackback spam
|
75 |
+
*/
|
76 |
public $pingback_url;
|
77 |
public $siteurl;
|
78 |
/**
|
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 |
$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 Theme($theme_slug);
|
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 |
* @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 Theme();
|
158 |
+
$this->language_attributes = Helper::function_wrapper('language_attributes');
|
159 |
$this->multisite = false;
|
160 |
}
|
161 |
|
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 = Helper::function_wrapper('language_attributes');
|
|
|
|
|
175 |
}
|
176 |
|
177 |
/**
|
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 |
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 |
* @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 |
* @return string
|
253 |
*/
|
254 |
function url() {
|
255 |
+
return $this->link();
|
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 |
}
|
lib/{timber-term.php → Term.php}
RENAMED
@@ -1,4 +1,14 @@
|
|
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,10 +40,10 @@
|
|
30 |
* </ul>
|
31 |
* ```
|
32 |
*/
|
33 |
-
class
|
34 |
|
35 |
-
public $PostClass = '
|
36 |
-
public $TermClass = '
|
37 |
|
38 |
public $object_type = 'term';
|
39 |
public static $representation = 'term';
|
@@ -55,10 +65,10 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,7 +103,7 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,9 +124,9 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
114 |
$term->ID = $term->term_id;
|
115 |
} else if ( is_string($tid) ) {
|
116 |
//echo 'bad call using '.$tid;
|
117 |
-
//
|
118 |
}
|
119 |
-
if ( isset($term->ID) ){
|
120 |
$term->id = $term->ID;
|
121 |
$this->import($term);
|
122 |
if ( isset($term->term_id) ) {
|
@@ -131,7 +141,7 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,7 +164,7 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,7 +216,7 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,23 +227,20 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
217 |
|
218 |
/**
|
219 |
* @internal
|
|
|
220 |
* @return string
|
221 |
*/
|
222 |
public function get_path() {
|
223 |
-
|
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
|
235 |
-
$link = apply_filters('timber_term_link', $link, $this);
|
236 |
-
return apply_filters('timber/term/link', $link, $this);
|
237 |
}
|
238 |
|
239 |
/**
|
@@ -245,7 +252,7 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,10 +266,10 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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,8 +301,8 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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
|
299 |
}
|
300 |
$this->_children = $children;
|
301 |
}
|
@@ -309,7 +316,7 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
309 |
* @param mixed $value
|
310 |
*/
|
311 |
function update( $key, $value ) {
|
312 |
-
$value = apply_filters(
|
313 |
$this->$key = $value;
|
314 |
}
|
315 |
|
@@ -331,11 +338,11 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
331 |
public function description() {
|
332 |
$prefix = '<p>';
|
333 |
$suffix = '</p>';
|
334 |
-
$desc = term_description(
|
335 |
-
if (substr($desc, 0, strlen($prefix)) == $prefix) {
|
336 |
$desc = substr($desc, strlen($prefix));
|
337 |
}
|
338 |
-
$desc = preg_replace('/'.
|
339 |
return trim($desc);
|
340 |
}
|
341 |
|
@@ -347,21 +354,15 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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 |
-
|
|
|
|
|
365 |
}
|
366 |
|
367 |
/**
|
@@ -378,7 +379,10 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
378 |
* @return string
|
379 |
*/
|
380 |
public function path() {
|
381 |
-
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
/**
|
@@ -408,22 +412,4 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
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 |
}
|
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 |
* </ul>
|
41 |
* ```
|
42 |
*/
|
43 |
+
class Term extends Core implements CoreInterface {
|
44 |
|
45 |
+
public $PostClass = 'Timber\Post';
|
46 |
+
public $TermClass = 'Term';
|
47 |
|
48 |
public $object_type = 'term';
|
49 |
public static $representation = 'term';
|
65 |
* @param string $tax
|
66 |
*/
|
67 |
public function __construct( $tid = null, $tax = '' ) {
|
68 |
+
if ( $tid === null ) {
|
69 |
$tid = $this->get_term_from_query();
|
70 |
}
|
71 |
+
if ( strlen($tax) ) {
|
72 |
$this->taxonomy = $tax;
|
73 |
}
|
74 |
$this->init($tid);
|
103 |
global $wp_query;
|
104 |
if ( isset($wp_query->queried_object) ) {
|
105 |
$qo = $wp_query->queried_object;
|
106 |
+
if ( isset($qo->term_id) ) {
|
107 |
return $qo->term_id;
|
108 |
}
|
109 |
}
|
124 |
$term->ID = $term->term_id;
|
125 |
} else if ( is_string($tid) ) {
|
126 |
//echo 'bad call using '.$tid;
|
127 |
+
//Helper::error_log(debug_backtrace());
|
128 |
}
|
129 |
+
if ( isset($term->ID) ) {
|
130 |
$term->id = $term->ID;
|
131 |
$this->import($term);
|
132 |
if ( isset($term->term_id) ) {
|
141 |
* @param int $tid
|
142 |
* @return array
|
143 |
*/
|
144 |
+
protected function get_term_meta( $tid ) {
|
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 |
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 ( isset($tax) && strlen($tax) ) {
|
168 |
$this->taxonomy = $tax;
|
169 |
return get_term($tid, $tax);
|
170 |
}
|
216 |
* @return string
|
217 |
*/
|
218 |
public function get_meta_field( $field_name ) {
|
219 |
+
if ( !isset($this->$field_name) ) {
|
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 |
|
228 |
/**
|
229 |
* @internal
|
230 |
+
* @deprecated since 1.0
|
231 |
* @return string
|
232 |
*/
|
233 |
public function get_path() {
|
234 |
+
return $this->path();
|
|
|
|
|
|
|
235 |
}
|
236 |
|
237 |
/**
|
238 |
* @internal
|
239 |
+
* @deprecated since 1.0
|
240 |
* @return string
|
241 |
*/
|
242 |
public function get_link() {
|
243 |
+
return $this->link();
|
|
|
|
|
244 |
}
|
245 |
|
246 |
/**
|
252 |
* @return array|bool|null
|
253 |
*/
|
254 |
public function get_posts( $numberposts = 10, $post_type = 'any', $PostClass = '' ) {
|
255 |
+
if ( !strlen($PostClass) ) {
|
256 |
$PostClass = $this->PostClass;
|
257 |
}
|
258 |
$default_tax_query = array(array(
|
266 |
parse_str($args, $new_args);
|
267 |
$args = $new_args;
|
268 |
$args['tax_query'] = $default_tax_query;
|
269 |
+
if ( !isset($args['post_type']) ) {
|
270 |
$args['post_type'] = 'any';
|
271 |
}
|
272 |
+
if ( class_exists($post_type) ) {
|
273 |
$PostClass = $post_type;
|
274 |
}
|
275 |
} else if ( is_array($numberposts) ) {
|
301 |
public function get_children() {
|
302 |
if ( !isset($this->_children) ) {
|
303 |
$children = get_term_children($this->ID, $this->taxonomy);
|
304 |
+
foreach ( $children as &$child ) {
|
305 |
+
$child = new Term($child);
|
306 |
}
|
307 |
$this->_children = $children;
|
308 |
}
|
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 |
public function description() {
|
339 |
$prefix = '<p>';
|
340 |
$suffix = '</p>';
|
341 |
+
$desc = term_description($this->ID, $this->taxonomy);
|
342 |
+
if ( substr($desc, 0, strlen($prefix)) == $prefix ) {
|
343 |
$desc = substr($desc, strlen($prefix));
|
344 |
}
|
345 |
+
$desc = preg_replace('/'.preg_quote('</p>', '/').'$/', '', $desc);
|
346 |
return trim($desc);
|
347 |
}
|
348 |
|
354 |
return $this->get_edit_url();
|
355 |
}
|
356 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
|
358 |
/**
|
359 |
* @api
|
360 |
* @return string
|
361 |
*/
|
362 |
public function link() {
|
363 |
+
$link = get_term_link($this);
|
364 |
+
$link = apply_filters('timber_term_link', $link, $this);
|
365 |
+
return apply_filters('timber/term/link', $link, $this);
|
366 |
}
|
367 |
|
368 |
/**
|
379 |
* @return string
|
380 |
*/
|
381 |
public function path() {
|
382 |
+
$link = $this->get_link();
|
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 |
public function title() {
|
413 |
return $this->name;
|
414 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
415 |
}
|
lib/{timber-term-getter.php → TermGetter.php}
RENAMED
@@ -1,6 +1,11 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
* @param string|array $args
|
@@ -8,7 +13,7 @@ class TimberTermGetter {
|
|
8 |
* @param string $TermClass
|
9 |
* @return mixed
|
10 |
*/
|
11 |
-
public static function get_terms($args = null, $maybe_args = array(), $TermClass = '
|
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,7 +35,7 @@ class TimberTermGetter {
|
|
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) &&
|
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,7 +58,7 @@ class TimberTermGetter {
|
|
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,7 +69,7 @@ class TimberTermGetter {
|
|
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,7 +79,7 @@ class TimberTermGetter {
|
|
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,8 +90,8 @@ class TimberTermGetter {
|
|
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,8 +104,8 @@ class TimberTermGetter {
|
|
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,7 +131,7 @@ class TimberTermGetter {
|
|
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,8 +147,8 @@ class TimberTermGetter {
|
|
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,8 +158,8 @@ class TimberTermGetter {
|
|
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,11 +169,11 @@ class TimberTermGetter {
|
|
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' ) {
|
1 |
<?php
|
2 |
|
3 |
+
namespace Timber;
|
4 |
+
|
5 |
+
use Timber\Term;
|
6 |
+
use Timber\Helper;
|
7 |
+
|
8 |
+
class TermGetter {
|
9 |
|
10 |
/**
|
11 |
* @param string|array $args
|
13 |
* @param string $TermClass
|
14 |
* @return mixed
|
15 |
*/
|
16 |
+
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'Term' ) {
|
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 |
$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) && Helper::is_array_assoc($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 |
* @param string $TermClass
|
59 |
* @return mixed
|
60 |
*/
|
61 |
+
public static function handle_term_query( $taxonomies, $args, $TermClass ) {
|
62 |
if ( !isset($args['hide_empty']) ) {
|
63 |
$args['hide_empty'] = false;
|
64 |
}
|
69 |
$args['include'] = $args['term_id'];
|
70 |
}
|
71 |
$terms = get_terms($taxonomies, $args);
|
72 |
+
foreach ( $terms as &$term ) {
|
73 |
$term = new $TermClass($term->term_id, $term->taxonomy);
|
74 |
}
|
75 |
return $terms;
|
79 |
* @param string $query_string
|
80 |
* @return stdClass
|
81 |
*/
|
82 |
+
protected static function get_term_query_from_query_string( $query_string ) {
|
83 |
$args = array();
|
84 |
parse_str($query_string, $args);
|
85 |
$ret = self::get_term_query_from_assoc_array($args);
|
90 |
* @param string $taxs
|
91 |
* @return stdClass
|
92 |
*/
|
93 |
+
protected static function get_term_query_from_string( $taxs ) {
|
94 |
+
$ret = new \stdClass();
|
95 |
$ret->args = array();
|
96 |
if ( is_string($taxs) ) {
|
97 |
$taxs = array($taxs);
|
104 |
* @param array $args
|
105 |
* @return stdClass
|
106 |
*/
|
107 |
+
public static function get_term_query_from_assoc_array( $args ) {
|
108 |
+
$ret = new \stdClass();
|
109 |
$ret->args = $args;
|
110 |
if ( isset($ret->args['tax']) ) {
|
111 |
$ret->taxonomies = $ret->args['tax'];
|
131 |
* @param array $args
|
132 |
* @return stdClass
|
133 |
*/
|
134 |
+
public static function get_term_query_from_array( $args ) {
|
135 |
if ( is_array($args) && !empty($args) ) {
|
136 |
//okay its an array with content
|
137 |
if ( is_int($args[0]) ) {
|
147 |
* @param integer[] $args
|
148 |
* @return stdClass
|
149 |
*/
|
150 |
+
public static function get_term_query_from_array_of_ids( $args ) {
|
151 |
+
$ret = new \stdClass();
|
152 |
$ret->taxonomies = get_taxonomies();
|
153 |
$ret->args['include'] = $args;
|
154 |
return $ret;
|
158 |
* @param string[] $args
|
159 |
* @return stdClass
|
160 |
*/
|
161 |
+
public static function get_term_query_from_array_of_strings( $args ) {
|
162 |
+
$ret = new \stdClass();
|
163 |
$ret->taxonomies = self::correct_taxonomy_names($args);
|
164 |
$ret->args = array();
|
165 |
return $ret;
|
169 |
* @param string|array $taxs
|
170 |
* @return array
|
171 |
*/
|
172 |
+
private static function correct_taxonomy_names( $taxs ) {
|
173 |
if ( is_string($taxs) ) {
|
174 |
$taxs = array($taxs);
|
175 |
}
|
176 |
+
foreach ( $taxs as &$tax ) {
|
177 |
if ( $tax == 'tags' || $tax == 'tag' ) {
|
178 |
$tax = 'post_tag';
|
179 |
} else if ( $tax == 'categories' ) {
|
lib/{timber-theme.php → Theme.php}
RENAMED
@@ -1,5 +1,11 @@
|
|
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,7 +23,7 @@
|
|
17 |
* ```
|
18 |
* @package Timber
|
19 |
*/
|
20 |
-
class
|
21 |
|
22 |
/**
|
23 |
* @api
|
@@ -62,7 +68,7 @@ class TimberTheme extends TimberCore {
|
|
62 |
* We are currently using the My Theme theme.
|
63 |
* ```
|
64 |
*/
|
65 |
-
function __construct($slug = null) {
|
66 |
$this->init($slug);
|
67 |
}
|
68 |
|
@@ -70,14 +76,14 @@ class TimberTheme extends TimberCore {
|
|
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 ( !
|
80 |
-
require_once(ABSPATH
|
81 |
}
|
82 |
|
83 |
$this->uri = get_stylesheet_directory_uri();
|
@@ -86,7 +92,7 @@ class TimberTheme extends TimberCore {
|
|
86 |
$this->uri = get_template_directory_uri();
|
87 |
}
|
88 |
if ( $this->parent_slug && $this->parent_slug != $this->slug ) {
|
89 |
-
$this->parent = new
|
90 |
}
|
91 |
}
|
92 |
|
@@ -103,7 +109,7 @@ class TimberTheme extends TimberCore {
|
|
103 |
* @return string the relative path to the theme (ex: `/wp-content/themes/my-timber-theme`)
|
104 |
*/
|
105 |
public function path() {
|
106 |
-
return
|
107 |
}
|
108 |
|
109 |
/**
|
@@ -111,7 +117,7 @@ class TimberTheme extends TimberCore {
|
|
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 |
|
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 |
* ```
|
24 |
* @package Timber
|
25 |
*/
|
26 |
+
class Theme extends Core {
|
27 |
|
28 |
/**
|
29 |
* @api
|
68 |
* We are currently using the My Theme theme.
|
69 |
* ```
|
70 |
*/
|
71 |
+
function __construct( $slug = null ) {
|
72 |
$this->init($slug);
|
73 |
}
|
74 |
|
76 |
* @internal
|
77 |
* @param string $slug
|
78 |
*/
|
79 |
+
protected function init( $slug = null ) {
|
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 |
$this->uri = get_template_directory_uri();
|
93 |
}
|
94 |
if ( $this->parent_slug && $this->parent_slug != $this->slug ) {
|
95 |
+
$this->parent = new Theme($this->parent_slug);
|
96 |
}
|
97 |
}
|
98 |
|
109 |
* @return string the relative path to the theme (ex: `/wp-content/themes/my-timber-theme`)
|
110 |
*/
|
111 |
public function path() {
|
112 |
+
return URLHelper::get_rel_url($this->link());
|
113 |
}
|
114 |
|
115 |
/**
|
117 |
* @param bool $default
|
118 |
* @return string
|
119 |
*/
|
120 |
+
public function theme_mod( $name, $default = false ) {
|
121 |
return get_theme_mod($name, $default);
|
122 |
}
|
123 |
|
lib/{timber.php → Timber.php}
RENAMED
@@ -1,5 +1,20 @@
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Timber Class.
|
5 |
*
|
@@ -24,6 +39,8 @@ class Timber {
|
|
24 |
public static $auto_meta = true;
|
25 |
public static $autoescape = false;
|
26 |
|
|
|
|
|
27 |
/**
|
28 |
* @codeCoverageIgnore
|
29 |
*/
|
@@ -32,6 +49,7 @@ class Timber {
|
|
32 |
return;
|
33 |
}
|
34 |
$this->test_compatibility();
|
|
|
35 |
$this->init_constants();
|
36 |
$this->init();
|
37 |
}
|
@@ -45,27 +63,38 @@ class Timber {
|
|
45 |
if ( is_admin() || $_SERVER['PHP_SELF'] == '/wp-login.php' ) {
|
46 |
return;
|
47 |
}
|
48 |
-
if ( version_compare(
|
49 |
-
trigger_error(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
-
|
52 |
-
|
|
|
|
|
53 |
}
|
54 |
}
|
55 |
|
56 |
function init_constants() {
|
57 |
-
defined(
|
58 |
}
|
59 |
|
60 |
/**
|
61 |
* @codeCoverageIgnore
|
62 |
*/
|
63 |
protected function init() {
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
TimberIntegrations::init();
|
69 |
}
|
70 |
|
71 |
/* Post Retrieval Routine
|
@@ -79,18 +108,24 @@ class Timber {
|
|
79 |
* @return array|bool|null
|
80 |
*/
|
81 |
public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
|
82 |
-
return
|
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
|
94 |
}
|
95 |
|
96 |
/**
|
@@ -101,7 +136,7 @@ class Timber {
|
|
101 |
* @return array|bool|null
|
102 |
*/
|
103 |
public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
104 |
-
return
|
105 |
}
|
106 |
|
107 |
/**
|
@@ -112,17 +147,7 @@ class Timber {
|
|
112 |
* @return array|bool|null
|
113 |
*/
|
114 |
public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
|
115 |
-
return
|
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,7 +162,7 @@ class Timber {
|
|
137 |
* @return mixed
|
138 |
*/
|
139 |
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
|
140 |
-
return
|
141 |
}
|
142 |
|
143 |
/* Site Retrieval
|
@@ -150,13 +175,13 @@ class Timber {
|
|
150 |
* @return array
|
151 |
*/
|
152 |
public static function get_sites( $blog_ids = false ) {
|
153 |
-
if ( !is_array(
|
154 |
global $wpdb;
|
155 |
-
$blog_ids = $wpdb->get_col(
|
156 |
}
|
157 |
$return = array();
|
158 |
foreach ( $blog_ids as $blog_id ) {
|
159 |
-
$return[] = new
|
160 |
}
|
161 |
return $return;
|
162 |
}
|
@@ -171,22 +196,27 @@ class Timber {
|
|
171 |
* @return array
|
172 |
*/
|
173 |
public static function get_context() {
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
-
|
188 |
-
|
189 |
-
return $data;
|
190 |
}
|
191 |
|
192 |
/**
|
@@ -199,27 +229,27 @@ class Timber {
|
|
199 |
* @param bool $via_render
|
200 |
* @return bool|string
|
201 |
*/
|
202 |
-
public static function compile( $filenames, $data = array(), $expires = false, $cache_mode =
|
203 |
$caller = self::get_calling_script_dir();
|
204 |
$caller_file = self::get_calling_script_file();
|
205 |
-
$caller_file = apply_filters(
|
206 |
-
$loader = new
|
207 |
-
$file = $loader->choose_template(
|
208 |
$output = '';
|
209 |
-
if ( is_null(
|
210 |
$data = array();
|
211 |
}
|
212 |
-
if ( strlen(
|
213 |
if ( $via_render ) {
|
214 |
-
$file = apply_filters(
|
215 |
-
$data = apply_filters(
|
216 |
} else {
|
217 |
-
$file = apply_filters(
|
218 |
-
$data = apply_filters(
|
219 |
}
|
220 |
-
$output = $loader->render(
|
221 |
}
|
222 |
-
do_action(
|
223 |
return $output;
|
224 |
}
|
225 |
|
@@ -231,13 +261,10 @@ class Timber {
|
|
231 |
* @return bool|string
|
232 |
*/
|
233 |
public static function compile_string( $string, $data = array() ) {
|
234 |
-
$dummy_loader = new
|
235 |
-
$dummy_loader->get_twig();
|
236 |
-
$
|
237 |
-
$
|
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,15 +276,15 @@ class Timber {
|
|
249 |
* @param string $cache_mode
|
250 |
* @return bool|string
|
251 |
*/
|
252 |
-
public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode =
|
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 =
|
258 |
}
|
259 |
-
$output = self::compile(
|
260 |
-
$output = apply_filters(
|
261 |
return $output;
|
262 |
}
|
263 |
|
@@ -270,8 +297,8 @@ class Timber {
|
|
270 |
* @param string $cache_mode
|
271 |
* @return bool|string
|
272 |
*/
|
273 |
-
public static function render( $filenames, $data = array(), $expires = false, $cache_mode =
|
274 |
-
$output =
|
275 |
echo $output;
|
276 |
return $output;
|
277 |
}
|
@@ -284,7 +311,7 @@ class Timber {
|
|
284 |
* @return bool|string
|
285 |
*/
|
286 |
public static function render_string( $string, $data = array() ) {
|
287 |
-
$compiled = self::compile_string(
|
288 |
echo $compiled;
|
289 |
return $compiled;
|
290 |
}
|
@@ -304,10 +331,10 @@ class Timber {
|
|
304 |
if ( $sidebar == '' ) {
|
305 |
$sidebar = 'sidebar.php';
|
306 |
}
|
307 |
-
if ( strstr(
|
308 |
-
return self::get_sidebar_from_php(
|
309 |
}
|
310 |
-
return self::compile(
|
311 |
}
|
312 |
|
313 |
/**
|
@@ -319,19 +346,19 @@ class Timber {
|
|
319 |
*/
|
320 |
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
321 |
$caller = self::get_calling_script_dir();
|
322 |
-
$loader = new
|
323 |
-
$uris = $loader->get_locations(
|
324 |
ob_start();
|
325 |
$found = false;
|
326 |
foreach ( $uris as $uri ) {
|
327 |
-
if ( file_exists(
|
328 |
-
include trailingslashit(
|
329 |
$found = true;
|
330 |
break;
|
331 |
}
|
332 |
}
|
333 |
if ( !$found ) {
|
334 |
-
|
335 |
}
|
336 |
$ret = ob_get_contents();
|
337 |
ob_end_clean();
|
@@ -348,44 +375,9 @@ class Timber {
|
|
348 |
* @return TimberFunctionWrapper
|
349 |
*/
|
350 |
public static function get_widgets( $widget_id ) {
|
351 |
-
return trim(
|
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,43 +392,43 @@ class Timber {
|
|
400 |
global $paged;
|
401 |
global $wp_rewrite;
|
402 |
$args = array();
|
403 |
-
$args['total'] = ceil(
|
404 |
if ( $wp_rewrite->using_permalinks() ) {
|
405 |
-
$url = explode(
|
406 |
-
if ( isset(
|
407 |
-
parse_str(
|
408 |
$args['add_args'] = $query;
|
409 |
}
|
410 |
-
$args['format'] = '
|
411 |
-
$args['base'] = trailingslashit(
|
412 |
} else {
|
413 |
$big = 999999999;
|
414 |
-
$args['base'] = str_replace(
|
415 |
}
|
416 |
$args['type'] = 'array';
|
417 |
-
$args['current'] = max(
|
418 |
-
$args['mid_size'] = max(
|
419 |
-
if ( is_int(
|
420 |
$args['mid_size'] = $prefs - 2;
|
421 |
} else {
|
422 |
-
$args = array_merge(
|
423 |
}
|
424 |
$data = array();
|
425 |
$data['current'] = $args['current'];
|
426 |
$data['total'] = $args['total'];
|
427 |
-
$data['pages'] =
|
428 |
-
$next = get_next_posts_page_link(
|
429 |
if ( $next ) {
|
430 |
-
$data['next'] = array(
|
431 |
}
|
432 |
-
$prev = previous_posts(
|
433 |
if ( $prev ) {
|
434 |
-
$data['prev'] = array(
|
435 |
}
|
436 |
if ( $paged < 2 ) {
|
437 |
$data['prev'] = '';
|
438 |
}
|
439 |
-
if ( $data['total'] === (
|
440 |
$data['next'] = '';
|
441 |
}
|
442 |
return $data;
|
@@ -451,14 +443,28 @@ class Timber {
|
|
451 |
* @return string
|
452 |
*/
|
453 |
public static function get_calling_script_dir( $offset = 0 ) {
|
454 |
-
$caller = self::get_calling_script_file(
|
455 |
-
if ( !is_null(
|
456 |
-
$pathinfo = pathinfo(
|
457 |
$dir = $pathinfo['dirname'];
|
458 |
return $dir;
|
459 |
}
|
460 |
}
|
461 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
/**
|
463 |
* Get calling script file.
|
464 |
*
|
@@ -482,6 +488,4 @@ class Timber {
|
|
482 |
}
|
483 |
return $caller;
|
484 |
}
|
485 |
-
|
486 |
-
|
487 |
-
}
|
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 |
public static $auto_meta = true;
|
40 |
public static $autoescape = false;
|
41 |
|
42 |
+
public static $context_cache = array();
|
43 |
+
|
44 |
/**
|
45 |
* @codeCoverageIgnore
|
46 |
*/
|
49 |
return;
|
50 |
}
|
51 |
$this->test_compatibility();
|
52 |
+
$this->backwards_compatibility();
|
53 |
$this->init_constants();
|
54 |
$this->init();
|
55 |
}
|
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 |
+
$names = array('Archives', 'Comment', 'Core', 'FunctionWrapper', 'Helper', 'Image', 'ImageHelper', 'Integrations', 'Loader', 'Menu', 'MenuItem', 'Post', 'PostGetter', 'PostsCollection', 'QueryIterator', 'Request', 'Site', 'Term', 'TermGetter', 'Theme', 'Twig', 'URLHelper', 'User');
|
80 |
+
class_alias(get_class($this), 'Timber');
|
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 |
+
Twig::init();
|
95 |
+
ImageHelper::init();
|
96 |
+
Admin::init();
|
97 |
+
Integrations::init();
|
|
|
98 |
}
|
99 |
|
100 |
/* Post Retrieval Routine
|
108 |
* @return array|bool|null
|
109 |
*/
|
110 |
public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
|
111 |
+
return PostGetter::get_post($query, $PostClass);
|
112 |
}
|
113 |
|
114 |
/**
|
115 |
* Get posts.
|
116 |
+
* @example
|
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|array $PostClass
|
125 |
* @return array|bool|null
|
126 |
*/
|
127 |
public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
|
128 |
+
return PostGetter::get_posts($query, $PostClass, $return_collection);
|
129 |
}
|
130 |
|
131 |
/**
|
136 |
* @return array|bool|null
|
137 |
*/
|
138 |
public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
139 |
+
return PostGetter::query_post($query, $PostClass);
|
140 |
}
|
141 |
|
142 |
/**
|
147 |
* @return array|bool|null
|
148 |
*/
|
149 |
public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
|
150 |
+
return PostGetter::query_posts($query, $PostClass);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
/* Term Retrieval
|
162 |
* @return mixed
|
163 |
*/
|
164 |
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
|
165 |
+
return TermGetter::get_terms($args, $maybe_args, $TermClass);
|
166 |
}
|
167 |
|
168 |
/* Site Retrieval
|
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 Site($blog_id);
|
185 |
}
|
186 |
return $return;
|
187 |
}
|
196 |
* @return array
|
197 |
*/
|
198 |
public static function get_context() {
|
199 |
+
if( empty(self::$context_cache) ) {
|
200 |
+
self::$context_cache['http_host'] = 'http://'.URLHelper::get_host();
|
201 |
+
self::$context_cache['wp_title'] = Helper::get_wp_title();
|
202 |
+
self::$context_cache['wp_head'] = Helper::function_wrapper('wp_head');
|
203 |
+
self::$context_cache['wp_footer'] = Helper::function_wrapper('wp_footer');
|
204 |
+
self::$context_cache['body_class'] = implode(' ', get_body_class());
|
205 |
+
|
206 |
+
self::$context_cache['site'] = new Site();
|
207 |
+
self::$context_cache['request'] = new Request();
|
208 |
+
$user = new User();
|
209 |
+
self::$context_cache['user'] = ($user->ID) ? $user : false;
|
210 |
+
self::$context_cache['theme'] = self::$context_cache['site']->theme;
|
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 |
+
return self::$context_cache;
|
|
|
220 |
}
|
221 |
|
222 |
/**
|
229 |
* @param bool $via_render
|
230 |
* @return bool|string
|
231 |
*/
|
232 |
+
public static function compile( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT, $via_render = false ) {
|
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 Loader($caller);
|
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 |
* @return bool|string
|
262 |
*/
|
263 |
public static function compile_string( $string, $data = array() ) {
|
264 |
+
$dummy_loader = new Loader();
|
265 |
+
$twig = $dummy_loader->get_twig();
|
266 |
+
$template = $twig->createTemplate($string);
|
267 |
+
return $template->render($data);
|
|
|
|
|
|
|
268 |
}
|
269 |
|
270 |
/**
|
276 |
* @param string $cache_mode
|
277 |
* @return bool|string
|
278 |
*/
|
279 |
+
public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
|
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 = Loader::CACHE_USE_DEFAULT;
|
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 |
* @param string $cache_mode
|
298 |
* @return bool|string
|
299 |
*/
|
300 |
+
public static function render( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
|
301 |
+
$output = self::fetch($filenames, $data, $expires, $cache_mode);
|
302 |
echo $output;
|
303 |
return $output;
|
304 |
}
|
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 |
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 |
*/
|
347 |
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
348 |
$caller = self::get_calling_script_dir();
|
349 |
+
$loader = new Loader();
|
350 |
+
$uris = $loader->get_locations($caller);
|
351 |
ob_start();
|
352 |
$found = false;
|
353 |
foreach ( $uris as $uri ) {
|
354 |
+
if ( file_exists(trailingslashit($uri).$sidebar) ) {
|
355 |
+
include trailingslashit($uri).$sidebar;
|
356 |
$found = true;
|
357 |
break;
|
358 |
}
|
359 |
}
|
360 |
if ( !$found ) {
|
361 |
+
Helper::error_log('error loading your sidebar, check to make sure the file exists');
|
362 |
}
|
363 |
$ret = ob_get_contents();
|
364 |
ob_end_clean();
|
375 |
* @return TimberFunctionWrapper
|
376 |
*/
|
377 |
public static function get_widgets( $widget_id ) {
|
378 |
+
return trim(Helper::function_wrapper('dynamic_sidebar', array($widget_id), true));
|
379 |
}
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
/* Pagination
|
382 |
================================ */
|
383 |
|
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'] = $wp_rewrite->pagination_base . '/%#%';
|
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'] = Helper::paginate_links($args);
|
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 |
* @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 |
}
|
489 |
return $caller;
|
490 |
}
|
491 |
+
}
|
|
|
|
lib/Twig.php
ADDED
@@ -0,0 +1,324 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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/{timber-url-helper.php → URLHelper.php}
RENAMED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
4 |
|
5 |
/**
|
6 |
*
|
@@ -9,13 +11,13 @@ class TimberURLHelper {
|
|
9 |
*/
|
10 |
public static function get_current_url() {
|
11 |
$pageURL = "http://";
|
12 |
-
if ( isset(
|
13 |
-
$pageURL = "https://"
|
14 |
}
|
15 |
if ( isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] && $_SERVER["SERVER_PORT"] != "80" ) {
|
16 |
-
$pageURL .= self::get_host()
|
17 |
} else {
|
18 |
-
$pageURL .= self::get_host()
|
19 |
}
|
20 |
return $pageURL;
|
21 |
}
|
@@ -27,11 +29,11 @@ class TimberURLHelper {
|
|
27 |
* @return bool
|
28 |
*/
|
29 |
public static function is_url( $url ) {
|
30 |
-
if ( !is_string(
|
31 |
return false;
|
32 |
}
|
33 |
-
$url = strtolower(
|
34 |
-
if ( strstr(
|
35 |
return true;
|
36 |
}
|
37 |
return false;
|
@@ -43,12 +45,12 @@ class TimberURLHelper {
|
|
43 |
* @return string
|
44 |
*/
|
45 |
public static function get_path_base() {
|
46 |
-
$struc = get_option(
|
47 |
-
$struc = explode(
|
48 |
$p = '/';
|
49 |
foreach ( $struc as $s ) {
|
50 |
-
if ( !strstr(
|
51 |
-
$p .= $s
|
52 |
}
|
53 |
}
|
54 |
return $p;
|
@@ -62,21 +64,21 @@ class TimberURLHelper {
|
|
62 |
* @return string
|
63 |
*/
|
64 |
public static function get_rel_url( $url, $force = false ) {
|
65 |
-
$url_info = parse_url(
|
66 |
-
if ( isset(
|
67 |
return $url;
|
68 |
}
|
69 |
$link = '';
|
70 |
-
if ( isset(
|
71 |
$link = $url_info['path'];
|
72 |
}
|
73 |
-
if ( isset(
|
74 |
-
$link .= '?'
|
75 |
}
|
76 |
-
if ( isset(
|
77 |
-
$link .= '#'
|
78 |
}
|
79 |
-
$link =
|
80 |
return $link;
|
81 |
}
|
82 |
|
@@ -86,10 +88,10 @@ class TimberURLHelper {
|
|
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,7 +104,7 @@ class TimberURLHelper {
|
|
102 |
* @return bool
|
103 |
*/
|
104 |
public static function is_local( $url ) {
|
105 |
-
if ( strstr(
|
106 |
return true;
|
107 |
}
|
108 |
return false;
|
@@ -116,8 +118,8 @@ class TimberURLHelper {
|
|
116 |
*/
|
117 |
public static function get_full_path( $src ) {
|
118 |
$root = ABSPATH;
|
119 |
-
$old_root_path = $root
|
120 |
-
$old_root_path = str_replace(
|
121 |
return $old_root_path;
|
122 |
}
|
123 |
|
@@ -130,15 +132,15 @@ class TimberURLHelper {
|
|
130 |
* @return string
|
131 |
*/
|
132 |
public static function url_to_file_system( $url ) {
|
133 |
-
$url_parts = parse_url(
|
134 |
-
$path = ABSPATH
|
135 |
-
$path = str_replace(
|
136 |
return $path;
|
137 |
}
|
138 |
|
139 |
public static function file_system_to_url( $fs ) {
|
140 |
-
$relative_path = self::get_rel_path(
|
141 |
-
$home = home_url(
|
142 |
return $home;
|
143 |
}
|
144 |
|
@@ -149,12 +151,12 @@ class TimberURLHelper {
|
|
149 |
* @return string
|
150 |
*/
|
151 |
public static function get_rel_path( $src ) {
|
152 |
-
if ( strstr(
|
153 |
-
return str_replace(
|
154 |
}
|
155 |
//its outside the wordpress directory, alternate setups:
|
156 |
-
$src = str_replace(
|
157 |
-
return WP_CONTENT_SUBDIR
|
158 |
}
|
159 |
|
160 |
/**
|
@@ -164,9 +166,9 @@ class TimberURLHelper {
|
|
164 |
* @return string
|
165 |
*/
|
166 |
public static function remove_double_slashes( $url ) {
|
167 |
-
$url = str_replace(
|
168 |
-
if ( strstr(
|
169 |
-
$url = str_replace(
|
170 |
}
|
171 |
return $url;
|
172 |
}
|
@@ -179,19 +181,19 @@ class TimberURLHelper {
|
|
179 |
* @return string
|
180 |
*/
|
181 |
public static function prepend_to_url( $url, $path ) {
|
182 |
-
if ( strstr(
|
183 |
-
$url_parts = parse_url(
|
184 |
-
$url = $url_parts['scheme']
|
185 |
-
if ( isset(
|
186 |
$url .= $url_parts['query'];
|
187 |
}
|
188 |
-
if ( isset(
|
189 |
$url .= $url_parts['fragment'];
|
190 |
}
|
191 |
} else {
|
192 |
-
$url = $url
|
193 |
}
|
194 |
-
return self::remove_double_slashes(
|
195 |
}
|
196 |
|
197 |
/**
|
@@ -201,8 +203,8 @@ class TimberURLHelper {
|
|
201 |
* @return string
|
202 |
*/
|
203 |
public static function preslashit( $path ) {
|
204 |
-
if ( strpos(
|
205 |
-
$path = '/'
|
206 |
}
|
207 |
return $path;
|
208 |
}
|
@@ -213,7 +215,7 @@ class TimberURLHelper {
|
|
213 |
* @return boolean true if $path is an absolute url, false if relative.
|
214 |
*/
|
215 |
public static function is_absolute( $path ) {
|
216 |
-
return (boolean) (
|
217 |
}
|
218 |
|
219 |
/**
|
@@ -225,21 +227,21 @@ class TimberURLHelper {
|
|
225 |
* @return boolean if $url points to an external location returns true
|
226 |
*/
|
227 |
public static function is_external_content( $url ) {
|
228 |
-
$is_external =
|
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(
|
239 |
|
240 |
// this case covers when the upload directory has been redefined
|
241 |
$upload_dir = wp_upload_dir();
|
242 |
-
$is_upload_url = strstr(
|
243 |
|
244 |
return $is_content_url || $is_upload_url;
|
245 |
}
|
@@ -252,8 +254,8 @@ class TimberURLHelper {
|
|
252 |
* true if it's a subdomain (http://cdn.example.org = true)
|
253 |
*/
|
254 |
public static function is_external( $url ) {
|
255 |
-
$has_http = strstr(
|
256 |
-
$on_domain = strstr(
|
257 |
if ( $has_http && !$on_domain ) {
|
258 |
return true;
|
259 |
}
|
@@ -268,41 +270,10 @@ class TimberURLHelper {
|
|
268 |
*/
|
269 |
public static function remove_trailing_slash( $link ) {
|
270 |
if ( $link != "/" )
|
271 |
-
$link = untrailingslashit(
|
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,10 +283,10 @@ class TimberURLHelper {
|
|
312 |
* @return array|string
|
313 |
*/
|
314 |
public static function get_params( $i = false ) {
|
315 |
-
$args = explode(
|
316 |
$newargs = array();
|
317 |
foreach ( $args as $arg ) {
|
318 |
-
if ( strlen(
|
319 |
$newargs[] = $arg;
|
320 |
}
|
321 |
}
|
@@ -324,9 +295,9 @@ class TimberURLHelper {
|
|
324 |
}
|
325 |
if ( $i < 0 ) {
|
326 |
//count from end
|
327 |
-
$i = count(
|
328 |
}
|
329 |
-
if ( isset(
|
330 |
return $newargs[$i];
|
331 |
}
|
332 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace Timber;
|
4 |
+
|
5 |
+
class URLHelper {
|
6 |
|
7 |
/**
|
8 |
*
|
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().":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
|
19 |
} else {
|
20 |
+
$pageURL .= self::get_host().$_SERVER["REQUEST_URI"];
|
21 |
}
|
22 |
return $pageURL;
|
23 |
}
|
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 |
* @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 |
* @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 .= '?'.$url_info['query'];
|
77 |
}
|
78 |
+
if ( isset($url_info['fragment']) && strlen($url_info['fragment']) ) {
|
79 |
+
$link .= '#'.$url_info['fragment'];
|
80 |
}
|
81 |
+
$link = self::remove_double_slashes($link);
|
82 |
return $link;
|
83 |
}
|
84 |
|
88 |
* @return string the HTTP_HOST or SERVER_NAME
|
89 |
*/
|
90 |
public static function get_host() {
|
91 |
+
if ( isset($_SERVER['HTTP_HOST']) ) {
|
92 |
return $_SERVER['HTTP_HOST'];
|
93 |
}
|
94 |
+
if ( isset($_SERVER['SERVER_NAME']) ) {
|
95 |
return $_SERVER['SERVER_NAME'];
|
96 |
}
|
97 |
return '';
|
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 |
*/
|
119 |
public static function get_full_path( $src ) {
|
120 |
$root = ABSPATH;
|
121 |
+
$old_root_path = $root.$src;
|
122 |
+
$old_root_path = str_replace('//', '/', $old_root_path);
|
123 |
return $old_root_path;
|
124 |
}
|
125 |
|
132 |
* @return string
|
133 |
*/
|
134 |
public static function url_to_file_system( $url ) {
|
135 |
+
$url_parts = parse_url($url);
|
136 |
+
$path = ABSPATH.$url_parts['path'];
|
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 |
* @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.$src;
|
160 |
}
|
161 |
|
162 |
/**
|
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 |
* @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'].'://'.$url_parts['host'].$path.$url_parts['path'];
|
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.$path;
|
195 |
}
|
196 |
+
return self::remove_double_slashes($url);
|
197 |
}
|
198 |
|
199 |
/**
|
203 |
* @return string
|
204 |
*/
|
205 |
public static function preslashit( $path ) {
|
206 |
+
if ( strpos($path, '/') != 0 ) {
|
207 |
+
$path = '/'.$path;
|
208 |
}
|
209 |
return $path;
|
210 |
}
|
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 |
* @return boolean if $url points to an external location returns true
|
228 |
*/
|
229 |
public static function is_external_content( $url ) {
|
230 |
+
$is_external = self::is_absolute($url) && !self::is_internal_content($url);
|
231 |
|
232 |
return $is_external;
|
233 |
}
|
234 |
|
235 |
+
private static function is_internal_content( $url ) {
|
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 |
* 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 |
*/
|
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 |
* @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 |
}
|
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 |
}
|
lib/{timber-user.php → User.php}
RENAMED
@@ -1,5 +1,14 @@
|
|
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,7 +26,7 @@
|
|
17 |
* <p class="article-info">This article is called "Consider the Lobster" and it's by David Foster Wallace
|
18 |
* ```
|
19 |
*/
|
20 |
-
class
|
21 |
|
22 |
public $object_type = 'user';
|
23 |
public static $representation = 'user';
|
@@ -31,6 +40,12 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
31 |
public $description;
|
32 |
public $display_name;
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* @api
|
36 |
* @var string The first name of the user
|
@@ -53,7 +68,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
53 |
/**
|
54 |
* @param int|bool $uid
|
55 |
*/
|
56 |
-
function __construct($uid = false) {
|
57 |
$this->init($uid);
|
58 |
}
|
59 |
|
@@ -84,7 +99,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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,7 +108,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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,7 +119,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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,6 +144,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
129 |
}
|
130 |
$this->id = $this->ID;
|
131 |
$this->name = $this->name();
|
|
|
132 |
$custom = $this->get_custom();
|
133 |
$this->import($custom);
|
134 |
}
|
@@ -137,7 +153,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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,7 +174,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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,7 +209,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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,7 +218,7 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
202 |
* @return string ex: /author/lincoln
|
203 |
*/
|
204 |
public function path() {
|
205 |
-
return
|
206 |
}
|
207 |
|
208 |
/**
|
@@ -212,37 +228,4 @@ class TimberUser extends TimberCore implements TimberCoreInterface {
|
|
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 |
-
}
|
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 |
* <p class="article-info">This article is called "Consider the Lobster" and it's by David Foster Wallace
|
27 |
* ```
|
28 |
*/
|
29 |
+
class User extends Core implements CoreInterface {
|
30 |
|
31 |
public $object_type = 'user';
|
32 |
public static $representation = 'user';
|
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 |
/**
|
69 |
* @param int|bool $uid
|
70 |
*/
|
71 |
+
function __construct( $uid = false ) {
|
72 |
$this->init($uid);
|
73 |
}
|
74 |
|
99 |
* @param string $field_name
|
100 |
* @return null
|
101 |
*/
|
102 |
+
function get_meta( $field_name ) {
|
103 |
return $this->get_meta_field($field_name);
|
104 |
}
|
105 |
|
108 |
* @param string $field
|
109 |
* @param mixed $value
|
110 |
*/
|
111 |
+
function __set( $field, $value ) {
|
112 |
if ( $field == 'name' ) {
|
113 |
$this->display_name = $value;
|
114 |
}
|
119 |
* @internal
|
120 |
* @param int|bool $uid The user ID to use
|
121 |
*/
|
122 |
+
protected function init( $uid = false ) {
|
123 |
if ( $uid === false ) {
|
124 |
$uid = get_current_user_id();
|
125 |
}
|
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 |
* @param string $field_name
|
154 |
* @return mixed
|
155 |
*/
|
156 |
+
function get_meta_field( $field_name ) {
|
157 |
$value = null;
|
158 |
$value = apply_filters('timber_user_get_meta_field_pre', $value, $this->ID, $field_name, $this);
|
159 |
if ( $value === null ) {
|
174 |
$um = get_user_meta($this->ID);
|
175 |
}
|
176 |
$custom = array();
|
177 |
+
foreach ( $um as $key => $value ) {
|
178 |
if ( is_array($value) && count($value) == 1 ) {
|
179 |
$value = $value[0];
|
180 |
}
|
209 |
* @param string $field_name
|
210 |
* @return mixed
|
211 |
*/
|
212 |
+
function meta( $field_name ) {
|
213 |
return $this->get_meta_field($field_name);
|
214 |
}
|
215 |
|
218 |
* @return string ex: /author/lincoln
|
219 |
*/
|
220 |
public function path() {
|
221 |
+
return URLHelper::get_rel_url($this->link());
|
222 |
}
|
223 |
|
224 |
/**
|
228 |
public function slug() {
|
229 |
return $this->user_nicename;
|
230 |
}
|
231 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/image/timber-image-operation-retina.php
DELETED
@@ -1,74 +0,0 @@
|
|
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/integrations/acf-timber.php
DELETED
@@ -1,58 +0,0 @@
|
|
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
DELETED
@@ -1,36 +0,0 @@
|
|
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
DELETED
@@ -1,57 +0,0 @@
|
|
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
DELETED
@@ -1,67 +0,0 @@
|
|
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/timber-core.php
DELETED
@@ -1,117 +0,0 @@
|
|
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
DELETED
@@ -1,92 +0,0 @@
|
|
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/timber-integrations.php
DELETED
@@ -1,24 +0,0 @@
|
|
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/timber-page.php
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* @ignore
|
5 |
-
* @deprecated 0.21.9
|
6 |
-
*/
|
7 |
-
class TimberPage extends TimberPost {
|
8 |
-
|
9 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/timber-post-getter.php
DELETED
@@ -1,104 +0,0 @@
|
|
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/timber-posts-collection.php
DELETED
@@ -1,97 +0,0 @@
|
|
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
DELETED
@@ -1,156 +0,0 @@
|
|
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/timber-routes.php
DELETED
@@ -1,33 +0,0 @@
|
|
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/timber-twig.php
DELETED
@@ -1,347 +0,0 @@
|
|
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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
=== Timber ===
|
2 |
-
Contributors: jarednova, lggorman
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
-
Stable tag: 0.
|
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,12 +41,43 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
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/
|
50 |
* Added tons of new tests and docs (thanks @lggorman and @jarednova)
|
51 |
|
52 |
= 0.22.3 =
|
@@ -61,7 +92,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
61 |
* Added support for animated gifs
|
62 |
|
63 |
= 0.22.1 =
|
64 |
-
* Added better support for [post.get_terms](https://github.com/
|
65 |
* Fix for issue with ACF date field (thanks @rpkoller)
|
66 |
* Fix for resizing jpEgs (thanks @eaton)
|
67 |
|
@@ -228,7 +259,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
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/
|
232 |
* Removed the Timber Starter Guide from the admin, a link to the GitHub wiki suffices.
|
233 |
|
234 |
= 0.16.8 =
|
@@ -323,7 +354,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
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/
|
327 |
|
328 |
= 0.14.1 =
|
329 |
* Added hooks to play nicely with Timber Debug Bar
|
@@ -446,7 +477,7 @@ Please post on [StackOverflow under the "Timber" tag](http://stackoverflow.com/q
|
|
446 |
== Frequently Asked Questions ==
|
447 |
|
448 |
= Can it be used in an existing theme? =
|
449 |
-
You bet! Watch these **[video tutorials](https://github.com/
|
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,4 +492,4 @@ Whatever. It simplifies the silly stuff so that you can focus on building more c
|
|
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/
|
1 |
=== Timber ===
|
2 |
+
Contributors: jarednova, connorjburton, lggorman
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
+
Stable tag: 1.0.3
|
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/timber/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/timber/timber/wiki/Video-Tutorials)**
|
24 |
+
* [Overview / Getting Started Guide](https://github.com/timber/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/timber/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 |
+
= 1.0.2 =
|
45 |
+
* Hot fix for PHP 5.3 support
|
46 |
+
|
47 |
+
= 1.0.1 =
|
48 |
+
* {{ user.avatar }} property is now available (thanks @connorjburton) d21eb85
|
49 |
+
* #947: Fix to pagination base (thanks @matsrietdijk) 270d7c2
|
50 |
+
* Fix to some namespacing issues (thanks @connorjburton) 0a8346a
|
51 |
+
* #958: Call the_post action to help other plugins (thanks @felthy) 4442703
|
52 |
+
* #976: Fixed problem with static declaration (@jarednova) c888606
|
53 |
+
* #978: Bug with arrays for post types (thanks @connorjburton) 571f6f8
|
54 |
+
|
55 |
+
= 1.0.0 =
|
56 |
+
* Added `{{ user }}` object to context
|
57 |
+
* Exposed translation functions
|
58 |
+
* Added better error reporting/warnings
|
59 |
+
* Fixed some things with function wrapper
|
60 |
+
* Timber is now namespaced, big big thanks to @connorjburton
|
61 |
+
* Cleanup of spacing
|
62 |
+
* Removed deprecated functions, added warning for key functions
|
63 |
+
* Updated version numbers and build script (@jarednova) 81a281e
|
64 |
+
* Corrected Routes -> /Routes which threw a fatal error (@jarednova) 26b6585
|
65 |
+
|
66 |
+
= 0.22.6 =
|
67 |
+
* New {{request}} object for post/get variables (thanks @connorjburton) #856
|
68 |
+
* New crop positions (thanks @salaros) #861
|
69 |
+
* Bug Fixes
|
70 |
+
|
71 |
+
* Fix to "next" in pagination (thanks @connorjburton) #900
|
72 |
+
* Fix to issue with tojpg filter's images not being deleted (thanks @connorjburton) #897
|
73 |
+
* `{{post.parent.children}}` used to return unpublished posts due to underlying behavior in WordPress, it now only returns published posts (thanks @connorjburton) #883
|
74 |
+
|
75 |
= 0.22.5 =
|
76 |
* Fixed errors in tests (thanks @lggorman)
|
77 |
* Fixed error in comments_link (thanks @tehlivi)
|
78 |
|
79 |
= 0.22.4 =
|
80 |
+
* Fixed [bug](https://github.com/timber/timber/issues/785) in get_calling_script file (thanks @gwagroves)
|
81 |
* Added tons of new tests and docs (thanks @lggorman and @jarednova)
|
82 |
|
83 |
= 0.22.3 =
|
92 |
* Added support for animated gifs
|
93 |
|
94 |
= 0.22.1 =
|
95 |
+
* Added better support for [post.get_terms](https://github.com/timber/timber/pull/737) (thanks @aaemnnosttv)
|
96 |
* Fix for issue with ACF date field (thanks @rpkoller)
|
97 |
* Fix for resizing jpEgs (thanks @eaton)
|
98 |
|
259 |
* Hotfix on timber-admin error
|
260 |
|
261 |
= 0.17.0 =
|
262 |
+
* Now you can resize/crop images with positional preferences, thanks @mmikkel. Here are the docs: https://github.com/timber/timber/wiki/TimberImage#resize
|
263 |
* Removed the Timber Starter Guide from the admin, a link to the GitHub wiki suffices.
|
264 |
|
265 |
= 0.16.8 =
|
354 |
* New Timber::compile method which _doesn't_ automatically echo. (Same args as Timber::render)
|
355 |
* Added post.get_next / post.get_prev for TimberPosts
|
356 |
* Fixed a thing to make get_preview easier when you want to omit the 'Read More' link
|
357 |
+
* Read the [Full Release Notes](https://github.com/timber/timber/releases/tag/0.15.0)
|
358 |
|
359 |
= 0.14.1 =
|
360 |
* Added hooks to play nicely with Timber Debug Bar
|
477 |
== Frequently Asked Questions ==
|
478 |
|
479 |
= Can it be used in an existing theme? =
|
480 |
+
You bet! Watch these **[video tutorials](https://github.com/timber/timber/wiki/Video-Tutorials)** to see how.
|
481 |
|
482 |
= Is it used in production? =
|
483 |
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)**.
|
492 |
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.
|
493 |
|
494 |
= Support? =
|
495 |
+
Leave a [GitHub issue](https://github.com/timber/timber/issues?state=open) and I'll holler back.
|
timber-starter-theme/single.php
CHANGED
@@ -12,7 +12,6 @@
|
|
12 |
$context = Timber::get_context();
|
13 |
$post = Timber::query_post();
|
14 |
$context['post'] = $post;
|
15 |
-
$context['comment_form'] = TimberHelper::get_comment_form();
|
16 |
|
17 |
if ( post_password_required( $post->ID ) ) {
|
18 |
Timber::render( 'single-password.twig', $context );
|
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 );
|
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="{{site.siteurl}}" 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,10 +12,11 @@
|
|
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,6 +24,7 @@
|
|
23 |
{% endfor %}
|
24 |
</div>
|
25 |
</section>
|
|
|
26 |
</article>
|
27 |
</div><!-- /content-wrapper -->
|
28 |
{% endblock %}
|
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 |
+
{{ fn('comment_form') }}
|
20 |
</div>
|
21 |
<div class="responses">
|
22 |
{% for cmt in post.get_comments() %}
|
24 |
{% endfor %}
|
25 |
</div>
|
26 |
</section>
|
27 |
+
{% endif %}
|
28 |
</article>
|
29 |
</div><!-- /content-wrapper -->
|
30 |
{% endblock %}
|
timber.php
CHANGED
@@ -4,24 +4,17 @@ 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: 0.
|
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 (
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
) {
|
23 |
-
|
24 |
}
|
25 |
-
|
26 |
-
$timber = new Timber();
|
27 |
-
Timber::$dirname = 'views';
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power Twig templates.
|
5 |
Plugin URI: http://timber.upstatement.com
|
6 |
Author: Jared Novack + Upstatement
|
7 |
+
Version: 1.0.3
|
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 ( file_exists( $composer_autoload = __DIR__ . '/vendor/autoload.php' ) /* check in self */
|
14 |
+
|| file_exists( $composer_autoload = WP_CONTENT_DIR.'/vendor/autoload.php') /* check in wp-content */
|
15 |
+
|| file_exists( $composer_autoload = plugin_dir_path( __FILE__ ).'vendor/autoload.php') /* check in plugin directory */
|
16 |
+
|| file_exists( $composer_autoload = get_stylesheet_directory().'/vendor/autoload.php') /* check in child theme */
|
17 |
+
|| file_exists( $composer_autoload = get_template_directory().'/vendor/autoload.php') /* check in parent theme */
|
18 |
) {
|
19 |
+
require_once $composer_autoload;
|
20 |
}
|
|
|
|
|
|
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 ComposerAutoloaderInit7abff383b4787c8ca40e89b5be93c957::getLoader();
|
vendor/composer/autoload_classmap.php
CHANGED
@@ -6,45 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
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 |
);
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
9 |
'AltoRouter' => $vendorDir . '/altorouter/altorouter/AltoRouter.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
);
|
vendor/composer/autoload_files.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_files.php @generated by Composer, it's nice
|
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,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
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 |
);
|
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 |
);
|
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 ComposerAutoloaderInitea51aada03cf312d1b81bbbcbceabfc8
|
|
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,6 +40,20 @@ class ComposerAutoloaderInitea51aada03cf312d1b81bbbcbceabfc8
|
|
40 |
|
41 |
$loader->register(true);
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
return $loader;
|
44 |
}
|
45 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit7abff383b4787c8ca40e89b5be93c957
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit7abff383b4787c8ca40e89b5be93c957', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit7abff383b4787c8ca40e89b5be93c957', 'loadClassLoader'));
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
40 |
|
41 |
$loader->register(true);
|
42 |
|
43 |
+
$includeFiles = require __DIR__ . '/autoload_files.php';
|
44 |
+
foreach ($includeFiles as $fileIdentifier => $file) {
|
45 |
+
composerRequire7abff383b4787c8ca40e89b5be93c957($fileIdentifier, $file);
|
46 |
+
}
|
47 |
+
|
48 |
return $loader;
|
49 |
}
|
50 |
}
|
51 |
+
|
52 |
+
function composerRequire7abff383b4787c8ca40e89b5be93c957($fileIdentifier, $file)
|
53 |
+
{
|
54 |
+
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
55 |
+
require $file;
|
56 |
+
|
57 |
+
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
58 |
+
}
|
59 |
+
}
|
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.25",
|
5 |
+
"version_normalized": "1.0.25.0",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/composer/installers.git",
|
9 |
+
"reference": "36e5b5843203d7f1cf6ffb0305a97e014387bd8e"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/composer/installers/zipball/36e5b5843203d7f1cf6ffb0305a97e014387bd8e",
|
14 |
+
"reference": "36e5b5843203d7f1cf6ffb0305a97e014387bd8e",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
25 |
"composer/composer": "1.0.*@dev",
|
26 |
"phpunit/phpunit": "4.1.*"
|
27 |
},
|
28 |
+
"time": "2016-04-13 19:46:30",
|
29 |
"type": "composer-plugin",
|
30 |
"extra": {
|
31 |
"class": "Composer\\Installers\\Plugin",
|
vendor/composer/installers/README.md
CHANGED
@@ -83,6 +83,7 @@ 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 |
| 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`
|
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`
|
vendor/composer/installers/src/Composer/Installers/Installer.php
CHANGED
@@ -65,6 +65,7 @@ class Installer extends LibraryInstaller
|
|
65 |
'symfony1' => 'Symfony1Installer',
|
66 |
'thelia' => 'TheliaInstaller',
|
67 |
'tusk' => 'TuskInstaller',
|
|
|
68 |
'typo3-flow' => 'TYPO3FlowInstaller',
|
69 |
'whmcs' => 'WHMCSInstaller',
|
70 |
'wolfcms' => 'WolfCMSInstaller',
|
65 |
'symfony1' => 'Symfony1Installer',
|
66 |
'thelia' => 'TheliaInstaller',
|
67 |
'tusk' => 'TuskInstaller',
|
68 |
+
'typo3-cms' => 'TYPO3CmsInstaller',
|
69 |
'typo3-flow' => 'TYPO3FlowInstaller',
|
70 |
'whmcs' => 'WHMCSInstaller',
|
71 |
'wolfcms' => 'WolfCMSInstaller',
|
vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,6 +169,7 @@ class InstallerTest extends TestCase
|
|
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,6 +299,7 @@ class InstallerTest extends TestCase
|
|
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'),
|
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 |
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'),
|