Version Description
Download this release
Release Info
Developer | jarednova |
Plugin | Timber |
Version | 1.0.0 |
Comparing to | |
See all releases |
Code changes from version 0.22.5 to 1.0.0
- README.md +35 -20
- init.php +6 -0
- lib/Admin.php +70 -0
- lib/{timber-archives.php → Archives.php} +35 -31
- 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 -250
- lib/{timber-image.php → Image.php} +83 -88
- lib/{image/timber-image-operation.php → Image/Operation.php} +13 -9
- lib/{image/timber-image-operation-letterbox.php → Image/Operation/Letterbox.php} +45 -30
- lib/{image/timber-image-operation-resize.php → Image/Operation/Resize.php} +77 -51
- 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} +131 -111
- 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} +800 -693
- lib/PostGetter.php +131 -0
- lib/PostsCollection.php +100 -0
- lib/QueryIterator.php +162 -0
- lib/Request.php +41 -0
- lib/{timber-site.php → Site.php} +61 -52
- lib/{timber-term.php → Term.php} +43 -56
- lib/{timber-term-getter.php → TermGetter.php} +22 -17
- lib/{timber-theme.php → Theme.php} +14 -8
- lib/Timber.php +486 -0
- lib/Twig.php +324 -0
- lib/{timber-url-helper.php → URLHelper.php} +60 -89
- lib/{timber-user.php → User.php} +17 -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 -26
- lib/timber-core.php +0 -117
- lib/timber-function-wrapper.php +0 -77
- 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 +13 -13
- timber-starter-theme/README.md +33 -3
- timber-starter-theme/archive.php +10 -10
- timber-starter-theme/author.php +5 -5
- timber-starter-theme/composer.json +8 -8
- timber-starter-theme/composer.lock +21 -15
- timber-starter-theme/footer.php +5 -1
- timber-starter-theme/functions.php +6 -6
- timber-starter-theme/header.php +5 -1
- timber-starter-theme/templates/base.twig +2 -17
- timber-starter-theme/templates/single-password.twig +1 -1
- timber-starter-theme/tests/test-timber-starter-theme.php +3 -3
- timber-starter-theme/views/menu.twig +8 -0
- timber.php +3 -614
- vendor/asm89/twig-cache-extension/.travis.yml +1 -1
- vendor/asm89/twig-cache-extension/composer.json +1 -1
- vendor/asm89/twig-cache-extension/lib/Asm89/Twig/CacheExtension/Node/CacheNode.php +1 -1
- vendor/autoload.php +1 -1
- vendor/composer/ClassLoader.php +4 -4
- vendor/composer/LICENSE +1 -1
- vendor/composer/autoload_classmap.php +0 -38
- vendor/composer/autoload_files.php +10 -0
- vendor/composer/autoload_namespaces.php +0 -1
- vendor/composer/autoload_psr4.php +2 -0
- vendor/composer/autoload_real.php +14 -5
- vendor/composer/installed.json +26 -24
- vendor/composer/installers/.travis.yml +1 -1
- vendor/composer/installers/README.md +21 -4
- vendor/composer/installers/composer.json +8 -3
- vendor/composer/installers/src/Composer/Installers/BaseInstaller.php +4 -3
- vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php +59 -25
- vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php +2 -0
- vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php +11 -0
- vendor/composer/installers/src/Composer/Installers/Installer.php +2 -0
- vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php +2 -0
- vendor/composer/installers/src/Composer/Installers/MauticInstaller.php +25 -0
- vendor/composer/installers/src/Composer/Installers/OxidInstaller.php +48 -0
- vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +2 -0
- vendor/composer/installers/tests/Composer/Installers/Test/InstallerTest.php +27 -0
- vendor/twig/twig/CHANGELOG +18 -1
- vendor/twig/twig/LICENSE +1 -1
- vendor/twig/twig/composer.json +1 -1
- vendor/twig/twig/doc/advanced.rst +1 -1
- vendor/twig/twig/doc/deprecated.rst +5 -3
- vendor/twig/twig/doc/templates.rst +8 -1
- vendor/twig/twig/ext/twig/php_twig.h +1 -1
- vendor/twig/twig/lib/Twig/Autoloader.php +3 -3
- vendor/twig/twig/lib/Twig/Cache/Filesystem.php +2 -2
- vendor/twig/twig/lib/Twig/Environment.php +23 -23
- vendor/twig/twig/lib/Twig/ExpressionParser.php +7 -1
- vendor/twig/twig/lib/Twig/Extension/Core.php +20 -16
- vendor/twig/twig/lib/Twig/Extension/Escaper.php +1 -1
- vendor/twig/twig/lib/Twig/ExtensionInterface.php +1 -1
- vendor/twig/twig/lib/Twig/Lexer.php +1 -1
- vendor/twig/twig/lib/Twig/Node.php +1 -1
- vendor/twig/twig/lib/Twig/Node/Expression/Call.php +51 -45
- vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php +4 -0
- vendor/twig/twig/lib/Twig/Node/Expression/Name.php +0 -8
- vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php +23 -0
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php +4 -2
- vendor/twig/twig/lib/Twig/Parser.php +6 -1
- vendor/twig/twig/lib/Twig/SimpleFilter.php +5 -0
- vendor/twig/twig/lib/Twig/SimpleFunction.php +5 -0
- vendor/twig/twig/lib/Twig/SimpleTest.php +5 -0
- vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php +1 -1
- vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php +42 -18
- vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php +6 -5
- vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php +1 -1
- vendor/twig/twig/test/Twig/Tests/FileCachingTest.php +7 -29
- vendor/twig/twig/test/Twig/Tests/FilesystemHelper.php +30 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test +4 -1
- vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined.test +21 -0
- vendor/twig/twig/test/Twig/Tests/Fixtures/tests/null_coalesce.test +30 -0
- vendor/twig/twig/test/Twig/Tests/TokenStreamTest.php +1 -1
- vendor/twig/twig/test/Twig/Tests/escapingTest.php +1 -1
README.md
CHANGED
@@ -1,16 +1,18 @@
|
|
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/jarednova/timber.svg?style=flat-square)](https://coveralls.io/r/
|
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 |
|
15 |
### Because WordPress is awesome, but the_loop isn't
|
16 |
Timber helps you create fully-customized WordPress themes faster with more sustainable code. With Timber, you write your HTML using the [Twig Template Engine](http://twig.sensiolabs.org/) separate from your PHP files.
|
@@ -33,23 +35,28 @@ This is what Timber's `.twig` files look like:
|
|
33 |
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.
|
34 |
|
35 |
### Looking for docs?
|
36 |
-
* [Timber Documentation](https://github.com/
|
37 |
* [Twig Reference](http://twig.sensiolabs.org/doc/templates.html)
|
38 |
-
* [Video Tutorials](https://github.com/
|
39 |
-
* [Overview / Getting Started Guide](https://github.com/
|
40 |
|
41 |
* * *
|
42 |
|
43 |
### Installation
|
44 |
|
45 |
-
The GitHub version of Timber requires [Composer](https://getcomposer.org/download/). If you'd prefer one-click installation, you should use the [WordPress.org](
|
46 |
|
47 |
```shell
|
48 |
-
composer
|
49 |
```
|
50 |
|
51 |
-
|
|
|
|
|
|
|
|
|
52 |
|
|
|
53 |
* * *
|
54 |
|
55 |
### Mission Statement
|
@@ -65,24 +72,32 @@ Nothing. Timber is meant for you to build a theme on. Like the [Starkers](https:
|
|
65 |
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.
|
66 |
|
67 |
#### Related Projects
|
68 |
-
* [**Timber Starter Theme**](https://github.com/
|
69 |
-
* [**Timber Debug Bar**](https://github.com/
|
70 |
* [**TimberPhoton**](https://github.com/slimndap/TimberPhoton) Plug-in to use JetPack's free Photon image manipulation and CDN with Timber.
|
71 |
-
* [**Timber
|
|
|
|
|
72 |
* [**Twig**](https://github.com/fabpot/Twig) The template language used by Timber.
|
73 |
|
74 |
#### Projects that use Timber
|
75 |
* [**Gantry5**](https://wordpress.org/plugins/gantry5/) a framework for theme development
|
76 |
|
77 |
#### Helpful Links
|
78 |
-
* [**CSS Tricks**](https://css-tricks.com/timber-and-twig-reignited-my-love-for-wordpress/) introduction to Timber
|
79 |
-
* [**Twig for Timber Cheatsheet**](http://notlaura.com/the-twig-for-timber-cheatsheet/) by @laras126
|
|
|
|
|
|
|
|
|
80 |
|
81 |
#### Should I use it?
|
82 |
-
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://
|
83 |
|
84 |
#### Contributing
|
85 |
-
Read the [contributor guidelines](https://github.com/
|
|
|
|
|
86 |
|
87 |
## How To...
|
88 |
|
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/jarednova/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
|
18 |
Timber helps you create fully-customized WordPress themes faster with more sustainable code. With Timber, you write your HTML using the [Twig Template Engine](http://twig.sensiolabs.org/) separate from your PHP files.
|
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 |
|
102 |
## How To...
|
103 |
|
init.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use Timber\Timber;
|
4 |
+
|
5 |
+
$timber = new Timber();
|
6 |
+
Timber::$dirname = 'views';
|
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('Timber\Admin', 'in_plugin_update_message'), 10, 2);
|
10 |
+
$action = add_action('in_plugin_update_message-timber/timber.php', array('Timber\Admin', '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 |
+
return $links;
|
29 |
+
}
|
30 |
+
return $links;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* in_plugin_update_message
|
35 |
+
*
|
36 |
+
* Displays an update message for plugin list screens.
|
37 |
+
* Shows only the version updates from the current until the newest version
|
38 |
+
*
|
39 |
+
* @type function
|
40 |
+
* @date 4/22/16
|
41 |
+
*
|
42 |
+
* @param {array} $plugin_data
|
43 |
+
* @param {object} $r
|
44 |
+
*/
|
45 |
+
function in_plugin_update_message( $plugin_data, $r ) {
|
46 |
+
|
47 |
+
|
48 |
+
//print_r($r);
|
49 |
+
// vars
|
50 |
+
if ( version_compare("1.0", $plugin_data->Version) > 0 ) {
|
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 |
+
if ( version_compare("0.22.6", $plugin_data->Version) > 0 ) {
|
58 |
+
$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";
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
|
63 |
+
|
64 |
+
|
65 |
+
// show message
|
66 |
+
echo '<br />'.sprintf($m, admin_url('edit.php?post_type=acf-field-group&page=acf-settings-updates'), 'http://www.advancedcustomfields.com/pro');
|
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 |
}
|
@@ -241,24 +250,19 @@ class TimberArchives extends TimberCore {
|
|
241 |
} elseif ( 'yearly' == $type ) {
|
242 |
$output = $this->get_items_yearly($args, $last_changed, $join, $where, $order, $limit);
|
243 |
} elseif ( 'monthly-nested' == $type ) {
|
244 |
-
$
|
245 |
-
foreach ( $years as &$year ) {
|
246 |
-
$args = array('show_year' => false);
|
247 |
-
$year['children'] = $this->get_items_monthly($args, $last_changed, $join, $where, $order, $limit);
|
248 |
-
}
|
249 |
-
$output = $years;
|
250 |
} elseif ( 'daily' == $type ) {
|
251 |
$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";
|
252 |
$key = md5($query);
|
253 |
$key = "wp_get_archives:$key:$last_changed";
|
254 |
-
if (!$results = wp_cache_get($key, 'posts')) {
|
255 |
$results = $wpdb->get_results($query);
|
256 |
$cache = array();
|
257 |
$cache[$key] = $results;
|
258 |
wp_cache_set($key, $results, 'posts');
|
259 |
}
|
260 |
if ( $results ) {
|
261 |
-
foreach ( (array)$results as $result ) {
|
262 |
$url = get_day_link($result->year, $result->month, $result->dayofmonth);
|
263 |
$date = sprintf('%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth);
|
264 |
$text = mysql2date($archive_day_date_format, $date);
|
@@ -271,13 +275,13 @@ class TimberArchives extends TimberCore {
|
|
271 |
. "count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
|
272 |
$key = md5($query);
|
273 |
$key = "wp_get_archives:$key:$last_changed";
|
274 |
-
if (!$results = wp_cache_get($key, 'posts')) {
|
275 |
$results = $wpdb->get_results($query);
|
276 |
wp_cache_set($key, $results, 'posts');
|
277 |
}
|
278 |
$arc_w_last = '';
|
279 |
if ( $results ) {
|
280 |
-
foreach ( (array)$results as $result ) {
|
281 |
if ( $result->week != $arc_w_last ) {
|
282 |
$arc_year = $result->yr;
|
283 |
$arc_w_last = $result->week;
|
@@ -285,7 +289,7 @@ class TimberArchives extends TimberCore {
|
|
285 |
$arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']);
|
286 |
$arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']);
|
287 |
$url = sprintf('%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&', '=', $result->week);
|
288 |
-
$text = $arc_week_start
|
289 |
$output[] = $this->get_archives_link($url, $text);
|
290 |
}
|
291 |
}
|
@@ -300,10 +304,10 @@ class TimberArchives extends TimberCore {
|
|
300 |
wp_cache_set($key, $results, 'posts');
|
301 |
}
|
302 |
if ( $results ) {
|
303 |
-
foreach ( (array)$results as $result ) {
|
304 |
-
if ($result->post_date != '0000-00-00 00:00:00') {
|
305 |
$url = get_permalink($result);
|
306 |
-
if ($result->post_title) {
|
307 |
/** This filter is documented in wp-includes/post-template.php */
|
308 |
$text = strip_tags(apply_filters('the_title', $result->post_title, $result->ID));
|
309 |
} 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 |
}
|
250 |
} elseif ( 'yearly' == $type ) {
|
251 |
$output = $this->get_items_yearly($args, $last_changed, $join, $where, $order, $limit);
|
252 |
} elseif ( 'monthly-nested' == $type ) {
|
253 |
+
$output = $this->get_items_monthly($args, $last_changed, $join, $where, $order, $limit);
|
|
|
|
|
|
|
|
|
|
|
254 |
} elseif ( 'daily' == $type ) {
|
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,16 +31,17 @@ class TimberHelper {
|
|
26 |
* @return mixed
|
27 |
*/
|
28 |
public static function transient( $slug, $callback, $transient_time = 0, $lock_timeout = 5, $force = false ) {
|
|
|
29 |
|
30 |
-
$enable_transients = (
|
31 |
-
$data = $enable_transients ? get_transient(
|
32 |
|
33 |
if ( false === $data ) {
|
34 |
|
35 |
-
if ( $enable_transients && self::_is_transient_locked(
|
36 |
|
37 |
-
$force = apply_filters(
|
38 |
-
$force = apply_filters(
|
39 |
|
40 |
if ( !$force ) {
|
41 |
//the server is currently executing the process.
|
@@ -48,14 +54,15 @@ class TimberHelper {
|
|
48 |
|
49 |
// lock timeout shouldn't be higher than 5 seconds, unless
|
50 |
// remote calls with high timeouts are made here
|
51 |
-
if ( $enable_transients )
|
52 |
-
|
|
|
53 |
|
54 |
$data = $callback();
|
55 |
|
56 |
if ( $enable_transients ) {
|
57 |
-
set_transient(
|
58 |
-
self::_unlock_transient(
|
59 |
}
|
60 |
|
61 |
}
|
@@ -70,7 +77,7 @@ class TimberHelper {
|
|
70 |
* @param integer $lock_timeout
|
71 |
*/
|
72 |
static function _lock_transient( $slug, $lock_timeout ) {
|
73 |
-
set_transient(
|
74 |
}
|
75 |
|
76 |
/**
|
@@ -78,7 +85,7 @@ class TimberHelper {
|
|
78 |
* @param string $slug
|
79 |
*/
|
80 |
static function _unlock_transient( $slug ) {
|
81 |
-
delete_transient(
|
82 |
}
|
83 |
|
84 |
/**
|
@@ -86,7 +93,7 @@ class TimberHelper {
|
|
86 |
* @param string $slug
|
87 |
*/
|
88 |
static function _is_transient_locked( $slug ) {
|
89 |
-
return (bool)get_transient(
|
90 |
}
|
91 |
|
92 |
/* These are for measuring page render time */
|
@@ -98,7 +105,7 @@ class TimberHelper {
|
|
98 |
*/
|
99 |
public static function start_timer() {
|
100 |
$time = microtime();
|
101 |
-
$time = explode(
|
102 |
$time = $time[1] + $time[0];
|
103 |
return $time;
|
104 |
}
|
@@ -116,11 +123,11 @@ class TimberHelper {
|
|
116 |
*/
|
117 |
public static function stop_timer( $start ) {
|
118 |
$time = microtime();
|
119 |
-
$time = explode(
|
120 |
$time = $time[1] + $time[0];
|
121 |
$finish = $time;
|
122 |
-
$total_time = round(
|
123 |
-
return $total_time
|
124 |
}
|
125 |
|
126 |
/* Function Utilities
|
@@ -152,24 +159,22 @@ class TimberHelper {
|
|
152 |
* @param array $args
|
153 |
* @return string
|
154 |
*/
|
155 |
-
public static function ob_function( $function, $args = array(
|
156 |
ob_start();
|
157 |
-
call_user_func_array(
|
158 |
$data = ob_get_contents();
|
159 |
ob_end_clean();
|
160 |
return $data;
|
161 |
}
|
162 |
|
163 |
/**
|
164 |
-
*
|
165 |
-
*
|
166 |
-
* @param
|
167 |
-
* @
|
168 |
-
* @param bool $return_output_buffer
|
169 |
-
* @return TimberFunctionWrapper
|
170 |
*/
|
171 |
public static function function_wrapper( $function_name, $defaults = array(), $return_output_buffer = false ) {
|
172 |
-
return new
|
173 |
}
|
174 |
|
175 |
/**
|
@@ -182,12 +187,20 @@ class TimberHelper {
|
|
182 |
if ( !WP_DEBUG ) {
|
183 |
return;
|
184 |
}
|
185 |
-
if ( is_object(
|
186 |
-
$arg = print_r(
|
187 |
}
|
188 |
-
return error_log(
|
189 |
}
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
/**
|
192 |
*
|
193 |
*
|
@@ -196,8 +209,8 @@ class TimberHelper {
|
|
196 |
* @return string
|
197 |
*/
|
198 |
public static function get_wp_title( $separator = ' ', $seplocation = 'left' ) {
|
199 |
-
$separator = apply_filters(
|
200 |
-
return trim(
|
201 |
}
|
202 |
|
203 |
/* Text Utilities
|
@@ -214,33 +227,33 @@ class TimberHelper {
|
|
214 |
*/
|
215 |
public static function trim_words( $text, $num_words = 55, $more = null, $allowed_tags = 'p a span b i br blockquote' ) {
|
216 |
if ( null === $more ) {
|
217 |
-
$more = __(
|
218 |
}
|
219 |
$original_text = $text;
|
220 |
$allowed_tag_string = '';
|
221 |
-
foreach ( explode(
|
222 |
-
$allowed_tag_string .= '<'
|
223 |
}
|
224 |
-
$text = strip_tags(
|
225 |
/* 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. */
|
226 |
-
if ( 'characters' == _x(
|
227 |
-
$text = trim(
|
228 |
-
preg_match_all(
|
229 |
-
$words_array = array_slice(
|
230 |
$sep = '';
|
231 |
} else {
|
232 |
-
$words_array = preg_split(
|
233 |
$sep = ' ';
|
234 |
}
|
235 |
-
if ( count(
|
236 |
-
array_pop(
|
237 |
-
$text = implode(
|
238 |
-
$text = $text
|
239 |
} else {
|
240 |
-
$text = implode(
|
241 |
}
|
242 |
-
$text = self::close_tags(
|
243 |
-
return apply_filters(
|
244 |
}
|
245 |
|
246 |
/**
|
@@ -251,87 +264,30 @@ class TimberHelper {
|
|
251 |
*/
|
252 |
public static function close_tags( $html ) {
|
253 |
//put all opened tags into an array
|
254 |
-
preg_match_all(
|
255 |
$openedtags = $result[1];
|
256 |
//put all closed tags into an array
|
257 |
-
preg_match_all(
|
258 |
$closedtags = $result[1];
|
259 |
-
$len_opened = count(
|
260 |
// all tags are closed
|
261 |
-
if ( count(
|
262 |
return $html;
|
263 |
}
|
264 |
-
$openedtags = array_reverse(
|
265 |
// close tags
|
266 |
for ( $i = 0; $i < $len_opened; $i++ ) {
|
267 |
-
if ( !in_array(
|
268 |
-
$html .= '</'
|
269 |
} else {
|
270 |
-
unset(
|
271 |
}
|
272 |
}
|
273 |
-
$html = str_replace(array('</br>','</hr>','</wbr>'), '', $html);
|
274 |
-
$html = str_replace(array('<br>','<hr>','<wbr>'), array('<br />','<hr />','<wbr />'), $html);
|
275 |
return $html;
|
276 |
}
|
277 |
|
278 |
-
/* WordPress Query Utilities
|
279 |
-
======================== */
|
280 |
-
|
281 |
-
/**
|
282 |
-
* @param string $key
|
283 |
-
* @param string $value
|
284 |
-
* @return array|int
|
285 |
-
* @deprecated 0.20.0
|
286 |
-
*/
|
287 |
-
public static function get_posts_by_meta( $key, $value ) {
|
288 |
-
global $wpdb;
|
289 |
-
$query = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s", $key, $value );
|
290 |
-
$results = $wpdb->get_col( $query );
|
291 |
-
$pids = array();
|
292 |
-
foreach ( $results as $result ) {
|
293 |
-
if ( get_post( $result ) ) {
|
294 |
-
$pids[] = $result;
|
295 |
-
}
|
296 |
-
}
|
297 |
-
if ( count( $pids ) ) {
|
298 |
-
return $pids;
|
299 |
-
}
|
300 |
-
return 0;
|
301 |
-
}
|
302 |
-
|
303 |
-
/**
|
304 |
-
*
|
305 |
-
*
|
306 |
-
* @param string $key
|
307 |
-
* @param string $value
|
308 |
-
* @return int
|
309 |
-
* @deprecated 0.20.0
|
310 |
-
*/
|
311 |
-
public static function get_post_by_meta( $key, $value ) {
|
312 |
-
global $wpdb;
|
313 |
-
$query = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s ORDER BY post_id", $key, $value );
|
314 |
-
$results = $wpdb->get_col( $query );
|
315 |
-
foreach ( $results as $result ) {
|
316 |
-
if ( $result && get_post( $result ) ) {
|
317 |
-
return $result;
|
318 |
-
}
|
319 |
-
}
|
320 |
-
return 0;
|
321 |
-
}
|
322 |
-
|
323 |
-
/**
|
324 |
-
*
|
325 |
-
* @deprecated 0.21.8
|
326 |
-
* @param int $ttid
|
327 |
-
* @return mixed
|
328 |
-
*/
|
329 |
-
public static function get_term_id_by_term_taxonomy_id( $ttid ) {
|
330 |
-
global $wpdb;
|
331 |
-
$query = $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %s", $ttid );
|
332 |
-
return $wpdb->get_var( $query );
|
333 |
-
}
|
334 |
-
|
335 |
/* Object Utilities
|
336 |
======================== */
|
337 |
|
@@ -343,7 +299,7 @@ class TimberHelper {
|
|
343 |
* @return void
|
344 |
*/
|
345 |
public static function osort( &$array, $prop ) {
|
346 |
-
usort(
|
347 |
return $a->$prop > $b->$prop ? 1 : -1;
|
348 |
} );
|
349 |
}
|
@@ -355,10 +311,10 @@ class TimberHelper {
|
|
355 |
* @return bool
|
356 |
*/
|
357 |
public static function is_array_assoc( $arr ) {
|
358 |
-
if ( !is_array(
|
359 |
return false;
|
360 |
}
|
361 |
-
return (bool)count(
|
362 |
}
|
363 |
|
364 |
/**
|
@@ -368,10 +324,10 @@ class TimberHelper {
|
|
368 |
* @return stdClass
|
369 |
*/
|
370 |
public static function array_to_object( $array ) {
|
371 |
-
$obj = new stdClass;
|
372 |
foreach ( $array as $k => $v ) {
|
373 |
-
if ( is_array(
|
374 |
-
$obj->{$k} = self::array_to_object(
|
375 |
} else {
|
376 |
$obj->{$k} = $v;
|
377 |
}
|
@@ -388,10 +344,10 @@ class TimberHelper {
|
|
388 |
* @return bool|int
|
389 |
*/
|
390 |
public static function get_object_index_by_property( $array, $key, $value ) {
|
391 |
-
if ( is_array(
|
392 |
$i = 0;
|
393 |
foreach ( $array as $arr ) {
|
394 |
-
if ( is_array(
|
395 |
if ( $arr[$key] == $value ) {
|
396 |
return $i;
|
397 |
}
|
@@ -416,15 +372,15 @@ class TimberHelper {
|
|
416 |
* @throws Exception
|
417 |
*/
|
418 |
public static function get_object_by_property( $array, $key, $value ) {
|
419 |
-
if ( is_array(
|
420 |
foreach ( $array as $arr ) {
|
421 |
if ( $arr->$key == $value ) {
|
422 |
return $arr;
|
423 |
}
|
424 |
}
|
425 |
} else {
|
426 |
-
throw new InvalidArgumentException(
|
427 |
-
|
428 |
}
|
429 |
}
|
430 |
|
@@ -436,8 +392,8 @@ class TimberHelper {
|
|
436 |
* @return array
|
437 |
*/
|
438 |
public static function array_truncate( $array, $len ) {
|
439 |
-
if ( sizeof(
|
440 |
-
$array = array_splice(
|
441 |
}
|
442 |
return $array;
|
443 |
}
|
@@ -452,11 +408,11 @@ class TimberHelper {
|
|
452 |
* @return bool
|
453 |
*/
|
454 |
public static function is_true( $value ) {
|
455 |
-
if ( isset(
|
456 |
-
if (is_string($value)) {
|
457 |
$value = strtolower($value);
|
458 |
}
|
459 |
-
if ( ($value == 'true' || $value === 1 || $value === '1' || $value == true) && $value !== false && $value !== 'false') {
|
460 |
return true;
|
461 |
}
|
462 |
}
|
@@ -470,7 +426,7 @@ class TimberHelper {
|
|
470 |
* @return bool
|
471 |
*/
|
472 |
public static function iseven( $i ) {
|
473 |
-
return (
|
474 |
}
|
475 |
|
476 |
/**
|
@@ -480,24 +436,12 @@ class TimberHelper {
|
|
480 |
* @return bool
|
481 |
*/
|
482 |
public static function isodd( $i ) {
|
483 |
-
return (
|
484 |
}
|
485 |
|
486 |
/* Links, Forms, Etc. Utilities
|
487 |
======================== */
|
488 |
|
489 |
-
/**
|
490 |
-
*
|
491 |
-
* Gets the comment form for use on a single article page
|
492 |
-
* @deprecated 0.21.8 use `{{ function('comment_form') }}` instead
|
493 |
-
* @param int $post_id which post_id should the form be tied to?
|
494 |
-
* @param array $args this $args thing is a fucking mess, [fix at some point](http://codex.wordpress.org/Function_Reference/comment_form)
|
495 |
-
* @return string
|
496 |
-
*/
|
497 |
-
public static function get_comment_form( $post_id = null, $args = array() ) {
|
498 |
-
return self::ob_function( 'comment_form', array( $args, $post_id ) );
|
499 |
-
}
|
500 |
-
|
501 |
/**
|
502 |
*
|
503 |
*
|
@@ -512,28 +456,28 @@ class TimberHelper {
|
|
512 |
'current' => 0,
|
513 |
'show_all' => false,
|
514 |
'prev_next' => false,
|
515 |
-
'prev_text' => __(
|
516 |
-
'next_text' => __(
|
517 |
'end_size' => 1,
|
518 |
'mid_size' => 2,
|
519 |
'type' => 'array',
|
520 |
'add_args' => false, // array of query args to add
|
521 |
'add_fragment' => ''
|
522 |
);
|
523 |
-
$args = wp_parse_args(
|
524 |
// Who knows what else people pass in $args
|
525 |
-
$args['total'] = intval(
|
526 |
if ( $args['total'] < 2 ) {
|
527 |
return array();
|
528 |
}
|
529 |
-
$args['current'] = (int)$args['current'];
|
530 |
-
$args['end_size'] = 0 < (int)$args['end_size'] ? (int)$args['end_size'] : 1; // Out of bounds? Make it the default.
|
531 |
-
$args['mid_size'] = 0 <= (int)$args['mid_size'] ? (int)$args['mid_size'] : 2;
|
532 |
-
$args['add_args'] = is_array(
|
533 |
$page_links = array();
|
534 |
$dots = false;
|
535 |
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
536 |
-
$n_display = number_format_i18n(
|
537 |
if ( $n == $args['current'] ) {
|
538 |
$page_links[] = array(
|
539 |
'class' => 'page-number page-numbers current',
|
@@ -544,18 +488,18 @@ class TimberHelper {
|
|
544 |
);
|
545 |
$dots = true;
|
546 |
} else {
|
547 |
-
if ( $args['show_all'] || (
|
548 |
-
$link = str_replace(
|
549 |
-
$link = str_replace(
|
550 |
-
$link = trailingslashit(
|
551 |
if ( $args['add_args'] ) {
|
552 |
-
$link = rtrim(
|
553 |
}
|
554 |
$link = str_replace(' ', '+', $link);
|
555 |
-
$link = untrailingslashit(
|
556 |
$page_links[] = array(
|
557 |
'class' => 'page-number page-numbers',
|
558 |
-
'link' => esc_url(
|
559 |
'title' => $n_display,
|
560 |
'name' => $n_display,
|
561 |
'current' => $args['current'] == $n
|
@@ -564,7 +508,7 @@ class TimberHelper {
|
|
564 |
} elseif ( $dots && !$args['show_all'] ) {
|
565 |
$page_links[] = array(
|
566 |
'class' => 'dots',
|
567 |
-
'title' => __(
|
568 |
);
|
569 |
$dots = false;
|
570 |
}
|
@@ -574,94 +518,10 @@ class TimberHelper {
|
|
574 |
}
|
575 |
|
576 |
/**
|
577 |
-
*
|
578 |
-
*/
|
579 |
-
static function get_current_url() {
|
580 |
-
return TimberURLHelper::get_current_url();
|
581 |
-
}
|
582 |
-
|
583 |
-
/**
|
584 |
-
* @deprecated 0.18.0
|
585 |
-
*/
|
586 |
-
static function is_url( $url ) {
|
587 |
-
return TimberURLHelper::is_url( $url );
|
588 |
-
}
|
589 |
-
|
590 |
-
/**
|
591 |
-
* @deprecated 0.18.0
|
592 |
-
*/
|
593 |
-
static function get_path_base() {
|
594 |
-
return TimberURLHelper::get_path_base();
|
595 |
-
}
|
596 |
-
|
597 |
-
/**
|
598 |
-
* @deprecated 0.18.0
|
599 |
-
*/
|
600 |
-
static function get_rel_url( $url, $force = false ) {
|
601 |
-
return TimberURLHelper::get_rel_url( $url, $force );
|
602 |
-
}
|
603 |
-
|
604 |
-
/**
|
605 |
-
* @deprecated 0.18.0
|
606 |
-
*/
|
607 |
-
static function is_local( $url ) {
|
608 |
-
return TimberURLHelper::is_local( $url );
|
609 |
-
}
|
610 |
-
|
611 |
-
/**
|
612 |
-
* @deprecated 0.18.0
|
613 |
-
*/
|
614 |
-
static function get_full_path( $src ) {
|
615 |
-
return TimberURLHelper::get_full_path( $src );
|
616 |
-
}
|
617 |
-
|
618 |
-
/**
|
619 |
-
* @deprecated 0.18.0
|
620 |
-
*/
|
621 |
-
static function get_rel_path( $src ) {
|
622 |
-
return TimberURLHelper::get_rel_path( $src );
|
623 |
-
}
|
624 |
-
|
625 |
-
/**
|
626 |
-
* @deprecated 0.18.0
|
627 |
-
*/
|
628 |
-
static function remove_double_slashes( $url ) {
|
629 |
-
return TimberURLHelper::remove_double_slashes( $url );
|
630 |
-
}
|
631 |
-
|
632 |
-
/**
|
633 |
-
* @deprecated 0.18.0
|
634 |
-
*/
|
635 |
-
static function prepend_to_url( $url, $path ) {
|
636 |
-
return TimberURLHelper::prepend_to_url( $url, $path );
|
637 |
-
}
|
638 |
-
|
639 |
-
/**
|
640 |
-
* @deprecated 0.18.0
|
641 |
-
*/
|
642 |
-
static function preslashit( $path ) {
|
643 |
-
return TimberURLHelper::preslashit( $path );
|
644 |
-
}
|
645 |
-
|
646 |
-
/**
|
647 |
-
* @deprecated 0.18.0
|
648 |
-
*/
|
649 |
-
static function is_external( $url ) {
|
650 |
-
return TimberURLHelper::is_external( $url );
|
651 |
-
}
|
652 |
-
|
653 |
-
/**
|
654 |
-
* @deprecated 0.18.0
|
655 |
-
*/
|
656 |
-
static function download_url( $url, $timeout = 300 ) {
|
657 |
-
return TimberURLHelper::download_url( $url, $timeout );
|
658 |
-
}
|
659 |
-
|
660 |
-
/**
|
661 |
-
* @deprecated 0.18.0
|
662 |
*/
|
663 |
-
|
664 |
-
|
|
|
665 |
}
|
666 |
-
|
667 |
-
}
|
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
|
443 |
======================== */
|
444 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
445 |
/**
|
446 |
*
|
447 |
*
|
456 |
'current' => 0,
|
457 |
'show_all' => false,
|
458 |
'prev_next' => false,
|
459 |
+
'prev_text' => __('« Previous'),
|
460 |
+
'next_text' => __('Next »'),
|
461 |
'end_size' => 1,
|
462 |
'mid_size' => 2,
|
463 |
'type' => 'array',
|
464 |
'add_args' => false, // array of query args to add
|
465 |
'add_fragment' => ''
|
466 |
);
|
467 |
+
$args = wp_parse_args($args, $defaults);
|
468 |
// Who knows what else people pass in $args
|
469 |
+
$args['total'] = intval((int) $args['total']);
|
470 |
if ( $args['total'] < 2 ) {
|
471 |
return array();
|
472 |
}
|
473 |
+
$args['current'] = (int) $args['current'];
|
474 |
+
$args['end_size'] = 0 < (int) $args['end_size'] ? (int) $args['end_size'] : 1; // Out of bounds? Make it the default.
|
475 |
+
$args['mid_size'] = 0 <= (int) $args['mid_size'] ? (int) $args['mid_size'] : 2;
|
476 |
+
$args['add_args'] = is_array($args['add_args']) ? $args['add_args'] : false;
|
477 |
$page_links = array();
|
478 |
$dots = false;
|
479 |
for ( $n = 1; $n <= $args['total']; $n++ ) {
|
480 |
+
$n_display = number_format_i18n($n);
|
481 |
if ( $n == $args['current'] ) {
|
482 |
$page_links[] = array(
|
483 |
'class' => 'page-number page-numbers current',
|
488 |
);
|
489 |
$dots = true;
|
490 |
} else {
|
491 |
+
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']) ) {
|
492 |
+
$link = str_replace('%_%', 1 == $n ? '' : $args['format'], $args['base']);
|
493 |
+
$link = str_replace('%#%', $n, $link);
|
494 |
+
$link = trailingslashit($link).ltrim($args['add_fragment'], '/');
|
495 |
if ( $args['add_args'] ) {
|
496 |
+
$link = rtrim(add_query_arg($args['add_args'], $link), '/');
|
497 |
}
|
498 |
$link = str_replace(' ', '+', $link);
|
499 |
+
$link = untrailingslashit($link);
|
500 |
$page_links[] = array(
|
501 |
'class' => 'page-number page-numbers',
|
502 |
+
'link' => esc_url(apply_filters('paginate_links', $link)),
|
503 |
'title' => $n_display,
|
504 |
'name' => $n_display,
|
505 |
'current' => $args['current'] == $n
|
508 |
} elseif ( $dots && !$args['show_all'] ) {
|
509 |
$page_links[] = array(
|
510 |
'class' => 'dots',
|
511 |
+
'title' => __('…')
|
512 |
);
|
513 |
$dots = false;
|
514 |
}
|
518 |
}
|
519 |
|
520 |
/**
|
521 |
+
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
522 |
*/
|
523 |
+
function get_current_url() {
|
524 |
+
Helper::warn('TimberHelper::get_current_url() is deprecated and will be removed in future versions, use Timber\URLHelper::get_current_url()');
|
525 |
+
return URLHelper::get_current_url();
|
526 |
}
|
527 |
+
}
|
|
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;
|
@@ -50,12 +58,21 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
50 |
* @var string $representation what does this class represent in WordPress terms?
|
51 |
*/
|
52 |
public static $representation = 'image';
|
|
|
|
|
|
|
|
|
53 |
/**
|
54 |
* @api
|
55 |
* @var string $file_loc the location of the image file in the filesystem (ex: `/var/www/htdocs/wp-content/uploads/2015/08/my-pic.jpg`)
|
56 |
*/
|
57 |
public $file_loc;
|
58 |
public $file;
|
|
|
|
|
|
|
|
|
|
|
59 |
public $sizes = array();
|
60 |
/**
|
61 |
* @api
|
@@ -79,7 +96,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
79 |
* ```
|
80 |
* @param int|string $iid
|
81 |
*/
|
82 |
-
public function __construct($iid) {
|
83 |
$this->init($iid);
|
84 |
}
|
85 |
|
@@ -87,8 +104,8 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
87 |
* @return string the src of the file
|
88 |
*/
|
89 |
public function __toString() {
|
90 |
-
if ( $this->
|
91 |
-
return $this->
|
92 |
}
|
93 |
return '';
|
94 |
}
|
@@ -106,7 +123,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
106 |
* @param string $dim
|
107 |
* @return array|int
|
108 |
*/
|
109 |
-
protected function get_dimensions($dim = null) {
|
110 |
if ( isset($this->_dimensions) ) {
|
111 |
return $this->get_dimensions_loaded($dim);
|
112 |
}
|
@@ -124,7 +141,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
124 |
* @param string|null $dim
|
125 |
* @return array|int
|
126 |
*/
|
127 |
-
protected function get_dimensions_loaded($dim) {
|
128 |
if ( $dim === null ) {
|
129 |
return $this->_dimensions;
|
130 |
}
|
@@ -143,25 +160,25 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
143 |
*/
|
144 |
protected function get_image_info( $iid ) {
|
145 |
$image_info = $iid;
|
146 |
-
if (is_numeric($iid)) {
|
147 |
$image_info = wp_get_attachment_metadata($iid);
|
148 |
-
if (!is_array($image_info)) {
|
149 |
$image_info = array();
|
150 |
}
|
151 |
$image_custom = get_post_custom($iid);
|
152 |
$basic = get_post($iid);
|
153 |
-
if ($basic) {
|
154 |
-
if (isset($basic->post_excerpt)) {
|
155 |
$this->caption = $basic->post_excerpt;
|
156 |
}
|
157 |
$image_custom = array_merge($image_custom, get_object_vars($basic));
|
158 |
}
|
159 |
return array_merge($image_info, $image_custom);
|
160 |
}
|
161 |
-
if (is_array($image_info) && isset($image_info['image'])) {
|
162 |
return $image_info['image'];
|
163 |
}
|
164 |
-
if (is_object($image_info)) {
|
165 |
return get_object_vars($image_info);
|
166 |
}
|
167 |
return $iid;
|
@@ -172,9 +189,9 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
172 |
* @param string $url for evaluation
|
173 |
* @return string with http/https corrected depending on what's appropriate for server
|
174 |
*/
|
175 |
-
protected static function _maybe_secure_url($url) {
|
176 |
if ( is_ssl() && strpos($url, 'https') !== 0 && strpos($url, 'http') === 0 ) {
|
177 |
-
$url = 'https'
|
178 |
}
|
179 |
return $url;
|
180 |
}
|
@@ -194,8 +211,10 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
194 |
* @param int $iid
|
195 |
*/
|
196 |
function init( $iid = false ) {
|
197 |
-
if (
|
198 |
-
|
|
|
|
|
199 |
$this->init_with_url($iid);
|
200 |
return;
|
201 |
}
|
@@ -203,10 +222,28 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
203 |
$this->init_with_file_path($iid);
|
204 |
return;
|
205 |
}
|
206 |
-
|
|
|
|
|
|
|
|
|
207 |
$this->init_with_relative_path($iid);
|
208 |
return;
|
209 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
}
|
211 |
|
212 |
$image_info = $this->get_image_info($iid);
|
@@ -215,10 +252,10 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
215 |
$basedir = self::wp_upload_dir();
|
216 |
$basedir = $basedir['basedir'];
|
217 |
if ( isset($this->file) ) {
|
218 |
-
$this->file_loc = $basedir
|
219 |
} else if ( isset($this->_wp_attached_file) ) {
|
220 |
$this->file = reset($this->_wp_attached_file);
|
221 |
-
$this->file_loc = $basedir
|
222 |
}
|
223 |
if ( isset($image_info['id']) ) {
|
224 |
$this->ID = $image_info['id'];
|
@@ -227,15 +264,16 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
227 |
}
|
228 |
if ( isset($this->ID) ) {
|
229 |
$custom = get_post_custom($this->ID);
|
230 |
-
foreach ($custom as $key => $value) {
|
231 |
$this->$key = $value[0];
|
232 |
}
|
|
|
233 |
} else {
|
234 |
if ( is_array($iid) || is_object($iid) ) {
|
235 |
-
|
236 |
-
|
237 |
} else {
|
238 |
-
|
239 |
}
|
240 |
}
|
241 |
}
|
@@ -245,8 +283,8 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
245 |
* @param string $relative_path
|
246 |
*/
|
247 |
protected function init_with_relative_path( $relative_path ) {
|
248 |
-
$this->abs_url = home_url(
|
249 |
-
$file_path =
|
250 |
$this->file_loc = $file_path;
|
251 |
$this->file = $file_path;
|
252 |
}
|
@@ -256,7 +294,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
256 |
* @param string $file_path
|
257 |
*/
|
258 |
protected function init_with_file_path( $file_path ) {
|
259 |
-
$url =
|
260 |
$this->abs_url = $url;
|
261 |
$this->file_loc = $file_path;
|
262 |
$this->file = $file_path;
|
@@ -266,11 +304,11 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
266 |
* @internal
|
267 |
* @param string $url
|
268 |
*/
|
269 |
-
protected function init_with_url($url) {
|
270 |
$this->abs_url = $url;
|
271 |
-
if (
|
272 |
-
$this->file = ABSPATH
|
273 |
-
$this->file_loc = ABSPATH
|
274 |
}
|
275 |
}
|
276 |
|
@@ -365,7 +403,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
365 |
* @return string the /relative/path/to/the/file
|
366 |
*/
|
367 |
public function path() {
|
368 |
-
return
|
369 |
}
|
370 |
|
371 |
/**
|
@@ -381,7 +419,7 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
381 |
* ```
|
382 |
* @return bool|string
|
383 |
*/
|
384 |
-
public function src($size = '') {
|
385 |
if ( isset($this->abs_url) ) {
|
386 |
return $this->_maybe_secure_url($this->abs_url);
|
387 |
}
|
@@ -402,19 +440,11 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
402 |
$dir = self::wp_upload_dir();
|
403 |
$base = $dir['baseurl'];
|
404 |
|
405 |
-
$src = trailingslashit($this->_maybe_secure_url($base))
|
406 |
$src = apply_filters('timber/image/src', $src, $this->ID);
|
407 |
return apply_filters('timber_image_src', $src, $this->ID);
|
408 |
}
|
409 |
|
410 |
-
/**
|
411 |
-
* @deprecated use src() instead
|
412 |
-
* @return string
|
413 |
-
*/
|
414 |
-
function url() {
|
415 |
-
return $this->get_src();
|
416 |
-
}
|
417 |
-
|
418 |
/**
|
419 |
* @api
|
420 |
* @example
|
@@ -430,69 +460,34 @@ class TimberImage extends TimberPost implements TimberCoreInterface {
|
|
430 |
return $this->get_dimensions('width');
|
431 |
}
|
432 |
|
433 |
-
|
434 |
-
/**
|
435 |
-
* @deprecated 0.21.9 use TimberImage::width() instead
|
436 |
-
* @internal
|
437 |
-
* @return int
|
438 |
-
*/
|
439 |
-
function get_width() {
|
440 |
-
return $this->width();
|
441 |
-
}
|
442 |
-
|
443 |
-
/**
|
444 |
-
* @deprecated 0.21.9 use TimberImage::height() instead
|
445 |
-
* @internal
|
446 |
-
* @return int
|
447 |
-
*/
|
448 |
-
function get_height() {
|
449 |
-
return $this->height();
|
450 |
-
}
|
451 |
-
|
452 |
/**
|
453 |
* @deprecated 0.21.9 use TimberImage::src
|
454 |
* @internal
|
455 |
* @param string $size
|
456 |
* @return bool|string
|
457 |
*/
|
458 |
-
function get_src( $size = '' ) {
|
459 |
-
|
|
|
460 |
}
|
461 |
|
462 |
-
/**
|
463 |
-
* @deprecated 0.21.9 use TimberImage::path()
|
464 |
-
* @internal
|
465 |
-
* @return string
|
466 |
-
*/
|
467 |
-
function get_path() {
|
468 |
-
return $this->link();
|
469 |
-
}
|
470 |
|
471 |
/**
|
472 |
-
* @deprecated use src() instead
|
473 |
* @return string
|
474 |
*/
|
475 |
-
function
|
476 |
-
|
|
|
477 |
}
|
478 |
|
479 |
-
/**
|
480 |
-
* @internal
|
481 |
-
* @deprecated 0.21.8
|
482 |
-
* @return bool|TimberPost
|
483 |
-
*/
|
484 |
-
function get_parent() {
|
485 |
-
return $this->parent();
|
486 |
-
}
|
487 |
|
488 |
/**
|
489 |
-
* @
|
490 |
-
* @deprecated 0.21.9
|
491 |
-
* @see TimberImage::alt
|
492 |
* @return string
|
493 |
*/
|
494 |
-
function
|
495 |
-
|
|
|
496 |
}
|
497 |
-
|
498 |
-
}
|
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;
|
58 |
* @var string $representation what does this class represent in WordPress terms?
|
59 |
*/
|
60 |
public static $representation = 'image';
|
61 |
+
/**
|
62 |
+
* @var array of supported relative file types
|
63 |
+
*/
|
64 |
+
private $file_types = array('jpg', 'jpeg', 'png', 'svg', 'bmp', 'ico', 'gif', 'tiff', 'pdf');
|
65 |
/**
|
66 |
* @api
|
67 |
* @var string $file_loc the location of the image file in the filesystem (ex: `/var/www/htdocs/wp-content/uploads/2015/08/my-pic.jpg`)
|
68 |
*/
|
69 |
public $file_loc;
|
70 |
public $file;
|
71 |
+
/**
|
72 |
+
* @api
|
73 |
+
* @var integer the ID of the image (which is a WP_Post)
|
74 |
+
*/
|
75 |
+
public $id;
|
76 |
public $sizes = array();
|
77 |
/**
|
78 |
* @api
|
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 |
}
|
160 |
*/
|
161 |
protected function get_image_info( $iid ) {
|
162 |
$image_info = $iid;
|
163 |
+
if ( is_numeric($iid) ) {
|
164 |
$image_info = wp_get_attachment_metadata($iid);
|
165 |
+
if ( !is_array($image_info) ) {
|
166 |
$image_info = array();
|
167 |
}
|
168 |
$image_custom = get_post_custom($iid);
|
169 |
$basic = get_post($iid);
|
170 |
+
if ( $basic ) {
|
171 |
+
if ( isset($basic->post_excerpt) ) {
|
172 |
$this->caption = $basic->post_excerpt;
|
173 |
}
|
174 |
$image_custom = array_merge($image_custom, get_object_vars($basic));
|
175 |
}
|
176 |
return array_merge($image_info, $image_custom);
|
177 |
}
|
178 |
+
if ( is_array($image_info) && isset($image_info['image']) ) {
|
179 |
return $image_info['image'];
|
180 |
}
|
181 |
+
if ( is_object($image_info) ) {
|
182 |
return get_object_vars($image_info);
|
183 |
}
|
184 |
return $iid;
|
189 |
* @param string $url for evaluation
|
190 |
* @return string with http/https corrected depending on what's appropriate for server
|
191 |
*/
|
192 |
+
protected static function _maybe_secure_url( $url ) {
|
193 |
if ( is_ssl() && strpos($url, 'https') !== 0 && strpos($url, 'http') === 0 ) {
|
194 |
+
$url = 'https'.substr($url, strlen('http'));
|
195 |
}
|
196 |
return $url;
|
197 |
}
|
211 |
* @param int $iid
|
212 |
*/
|
213 |
function init( $iid = false ) {
|
214 |
+
if ( !$iid ) { Helper::error_log('Initalized TimberImage without providing first parameter.'); return; }
|
215 |
+
|
216 |
+
if ( !is_numeric($iid) && is_string($iid) ) {
|
217 |
+
if ( strstr($iid, '://') ) {
|
218 |
$this->init_with_url($iid);
|
219 |
return;
|
220 |
}
|
222 |
$this->init_with_file_path($iid);
|
223 |
return;
|
224 |
}
|
225 |
+
|
226 |
+
$relative = false;
|
227 |
+
$iid_lower = strtolower($iid);
|
228 |
+
foreach ( $this->file_types as $type ) { if ( strstr($iid_lower, $type) ) { $relative = true; break; } };
|
229 |
+
if ( $relative ) {
|
230 |
$this->init_with_relative_path($iid);
|
231 |
return;
|
232 |
}
|
233 |
+
} else if ( $iid instanceof \WP_Post ) {
|
234 |
+
$ref = new \ReflectionClass($this);
|
235 |
+
$post = $ref->getParentClass()->newInstance($iid->ID);
|
236 |
+
if ( isset($post->_thumbnail_id) && $post->_thumbnail_id ) {
|
237 |
+
return $this->init((int) $post->_thumbnail_id);
|
238 |
+
}
|
239 |
+
return $this->init($iid->ID);
|
240 |
+
} else if ( $iid instanceof Post ) {
|
241 |
+
/**
|
242 |
+
* This will catch TimberPost and any post classes that extend TimberPost,
|
243 |
+
* see http://php.net/manual/en/internals2.opcodes.instanceof.php#109108
|
244 |
+
* and https://github.com/timber/timber/wiki/Extending-Timber
|
245 |
+
*/
|
246 |
+
$iid = (int) $iid->_thumbnail_id;
|
247 |
}
|
248 |
|
249 |
$image_info = $this->get_image_info($iid);
|
252 |
$basedir = self::wp_upload_dir();
|
253 |
$basedir = $basedir['basedir'];
|
254 |
if ( isset($this->file) ) {
|
255 |
+
$this->file_loc = $basedir.DIRECTORY_SEPARATOR.$this->file;
|
256 |
} else if ( isset($this->_wp_attached_file) ) {
|
257 |
$this->file = reset($this->_wp_attached_file);
|
258 |
+
$this->file_loc = $basedir.DIRECTORY_SEPARATOR.$this->file;
|
259 |
}
|
260 |
if ( isset($image_info['id']) ) {
|
261 |
$this->ID = $image_info['id'];
|
264 |
}
|
265 |
if ( isset($this->ID) ) {
|
266 |
$custom = get_post_custom($this->ID);
|
267 |
+
foreach ( $custom as $key => $value ) {
|
268 |
$this->$key = $value[0];
|
269 |
}
|
270 |
+
$this->id = $this->ID;
|
271 |
} else {
|
272 |
if ( is_array($iid) || is_object($iid) ) {
|
273 |
+
Helper::error_log('Not able to init in TimberImage with iid=');
|
274 |
+
Helper::error_log($iid);
|
275 |
} else {
|
276 |
+
Helper::error_log('Not able to init in TimberImage with iid='.$iid);
|
277 |
}
|
278 |
}
|
279 |
}
|
283 |
* @param string $relative_path
|
284 |
*/
|
285 |
protected function init_with_relative_path( $relative_path ) {
|
286 |
+
$this->abs_url = home_url($relative_path);
|
287 |
+
$file_path = URLHelper::get_full_path($relative_path);
|
288 |
$this->file_loc = $file_path;
|
289 |
$this->file = $file_path;
|
290 |
}
|
294 |
* @param string $file_path
|
295 |
*/
|
296 |
protected function init_with_file_path( $file_path ) {
|
297 |
+
$url = URLHelper::file_system_to_url($file_path);
|
298 |
$this->abs_url = $url;
|
299 |
$this->file_loc = $file_path;
|
300 |
$this->file = $file_path;
|
304 |
* @internal
|
305 |
* @param string $url
|
306 |
*/
|
307 |
+
protected function init_with_url( $url ) {
|
308 |
$this->abs_url = $url;
|
309 |
+
if ( URLHelper::is_local($url) ) {
|
310 |
+
$this->file = URLHelper::remove_double_slashes(ABSPATH.URLHelper::get_rel_url($url));
|
311 |
+
$this->file_loc = URLHelper::remove_double_slashes(ABSPATH.URLHelper::get_rel_url($url));
|
312 |
}
|
313 |
}
|
314 |
|
403 |
* @return string the /relative/path/to/the/file
|
404 |
*/
|
405 |
public function path() {
|
406 |
+
return URLHelper::get_rel_path($this->src());
|
407 |
}
|
408 |
|
409 |
/**
|
419 |
* ```
|
420 |
* @return bool|string
|
421 |
*/
|
422 |
+
public function src( $size = '' ) {
|
423 |
if ( isset($this->abs_url) ) {
|
424 |
return $this->_maybe_secure_url($this->abs_url);
|
425 |
}
|
440 |
$dir = self::wp_upload_dir();
|
441 |
$base = $dir['baseurl'];
|
442 |
|
443 |
+
$src = trailingslashit($this->_maybe_secure_url($base)).$this->file;
|
444 |
$src = apply_filters('timber/image/src', $src, $this->ID);
|
445 |
return apply_filters('timber_image_src', $src, $this->ID);
|
446 |
}
|
447 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
/**
|
449 |
* @api
|
450 |
* @example
|
460 |
return $this->get_dimensions('width');
|
461 |
}
|
462 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
463 |
/**
|
464 |
* @deprecated 0.21.9 use TimberImage::src
|
465 |
* @internal
|
466 |
* @param string $size
|
467 |
* @return bool|string
|
468 |
*/
|
469 |
+
public function get_src( $size = '' ) {
|
470 |
+
Helper::warn('{{image.get_src}} is deprecated and will be removed in 1.1; use {{image.src}}');
|
471 |
+
return $this->src($size);
|
472 |
}
|
473 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
474 |
|
475 |
/**
|
476 |
+
* @deprecated since 0.21.9 use src() instead
|
477 |
* @return string
|
478 |
*/
|
479 |
+
public function url( $size = '' ) {
|
480 |
+
Helper::warn('{{image.url}} is deprecated and will be removed in 1.1; use {{image.src}}');
|
481 |
+
return $this->src($size);
|
482 |
}
|
483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
|
485 |
/**
|
486 |
+
* @deprecated since 0.21.9 use src() instead
|
|
|
|
|
487 |
* @return string
|
488 |
*/
|
489 |
+
public function get_url( $size = '' ) {
|
490 |
+
Helper::warn('{{image.get_url}} is deprecated and will be removed in 1.1; use {{image.src}}');
|
491 |
+
return $this->src($size);
|
492 |
}
|
493 |
+
}
|
|
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,15 +1,21 @@
|
|
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.
|
5 |
-
*
|
6 |
* Arguments:
|
7 |
* - width of new image
|
8 |
* - height of new image
|
9 |
-
* - color of padding
|
10 |
*/
|
11 |
-
class
|
12 |
-
|
13 |
private $w, $h, $color;
|
14 |
|
15 |
/**
|
@@ -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;
|
@@ -26,36 +32,36 @@ class TimberImageOperationLetterbox extends TimberImageOperation {
|
|
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
|
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 |
|
39 |
/**
|
40 |
* Performs the actual image manipulation,
|
41 |
* including saving the target file.
|
42 |
-
*
|
43 |
-
* @param string $load_filename filepath (not URL) to source file
|
44 |
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
45 |
-
* @param string $save_filename filepath (not URL) where result file should be saved
|
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,29 +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 |
-
$image->save(
|
82 |
$func = 'imagecreatefromjpeg';
|
83 |
-
$
|
|
|
84 |
if ( $ext == 'gif' ) {
|
85 |
$func = 'imagecreatefromgif';
|
|
|
86 |
} else if ( $ext == 'png' ) {
|
87 |
$func = 'imagecreatefrompng';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
}
|
89 |
-
|
90 |
-
imagecopy( $bg, $image, $x, $y, 0, 0, $owt, $oht );
|
91 |
-
imagejpeg( $bg, $save_filename, $quality );
|
92 |
-
return true;
|
93 |
} else {
|
94 |
-
|
95 |
}
|
96 |
return false;
|
97 |
}
|
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.
|
11 |
+
*
|
12 |
* Arguments:
|
13 |
* - width of new image
|
14 |
* - height of new image
|
15 |
+
* - color of padding
|
16 |
*/
|
17 |
+
class Letterbox extends ImageOperation {
|
18 |
+
|
19 |
private $w, $h, $color;
|
20 |
|
21 |
/**
|
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;
|
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
|
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 |
|
45 |
/**
|
46 |
* Performs the actual image manipulation,
|
47 |
* including saving the target file.
|
48 |
+
*
|
49 |
+
* @param string $load_filename filepath (not URL) to source file
|
50 |
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
51 |
+
* @param string $save_filename filepath (not URL) where result file should be saved
|
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,21 +14,21 @@
|
|
8 |
* - height of new image
|
9 |
* - crop method
|
10 |
*/
|
11 |
-
class
|
12 |
|
13 |
private $w, $h, $crop;
|
14 |
|
15 |
/**
|
16 |
* @param int $w width of new image
|
17 |
* @param int $h height of new image
|
18 |
-
* @param string $crop cropping method, one of: 'default', 'center', 'top', 'bottom', 'left', 'right'.
|
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,34 +113,51 @@ 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 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
// Crop the image
|
123 |
-
|
124 |
-
|
125 |
'x' => 0, 'y' => $src_y,
|
126 |
'src_w' => $src_w, 'src_h' => $src_ht,
|
127 |
'target_w' => $w, 'target_h' => $h
|
|
|
|
|
|
|
|
|
|
|
128 |
);
|
129 |
-
}
|
130 |
-
return array(
|
131 |
-
'x' => $src_x, 'y' => 0,
|
132 |
-
'src_w' => $src_wt, 'src_h' => $src_h,
|
133 |
-
'target_w' => $w, 'target_h' => $h
|
134 |
-
);
|
135 |
}
|
136 |
|
137 |
/**
|
@@ -142,44 +168,44 @@ class TimberImageOperationResize extends TimberImageOperation {
|
|
142 |
* (ex: /src/var/www/wp-content/uploads/my-pic.jpg)
|
143 |
* @param string $save_filename filepath (not URL) where result file should be saved
|
144 |
* (ex: /src/var/www/wp-content/uploads/my-pic-300x200-c-default.jpg)
|
145 |
-
* @return
|
146 |
*/
|
147 |
-
public function run($load_filename, $save_filename) {
|
148 |
//should be resized by gif resizer
|
149 |
-
if (
|
150 |
//attempt to resize
|
151 |
//return if successful
|
152 |
//proceed if not
|
153 |
$gif = self::run_animated_gif($load_filename, $save_filename);
|
154 |
-
if ($gif) {
|
155 |
return true;
|
156 |
}
|
157 |
}
|
158 |
-
$image = wp_get_image_editor(
|
159 |
-
if ( !is_wp_error(
|
160 |
-
$crop = self::get_target_sizes(
|
161 |
-
$image->crop(
|
162 |
$crop['y'],
|
163 |
$crop['src_w'],
|
164 |
$crop['src_h'],
|
165 |
$crop['target_w'],
|
166 |
$crop['target_h']
|
167 |
);
|
168 |
-
$result = $image->save(
|
169 |
-
if ( is_wp_error(
|
170 |
// @codeCoverageIgnoreStart
|
171 |
-
|
172 |
-
|
173 |
return false;
|
174 |
// @codeCoverageIgnoreEnd
|
175 |
} else {
|
176 |
return true;
|
177 |
}
|
178 |
-
} else if ( isset(
|
179 |
// @codeCoverageIgnoreStart
|
180 |
-
|
181 |
} else {
|
182 |
-
|
183 |
// @codeCoverageIgnoreEnd
|
184 |
}
|
185 |
}
|
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 |
|
21 |
/**
|
22 |
* @param int $w width of new image
|
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':
|
126 |
+
$src_y = 0;
|
127 |
+
break;
|
128 |
+
|
129 |
+
case 'bottom':
|
130 |
+
$src_y = $src_h - $src_ht;
|
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':
|
142 |
+
$src_x = 0;
|
143 |
+
break;
|
144 |
+
|
145 |
+
case 'right':
|
146 |
+
$src_x = $src_w - $src_wt;
|
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,
|
154 |
'target_w' => $w, 'target_h' => $h
|
155 |
+
)
|
156 |
+
: array(
|
157 |
+
'x' => $src_x, 'y' => 0,
|
158 |
+
'src_w' => $src_wt, 'src_h' => $src_h,
|
159 |
+
'target_w' => $w, 'target_h' => $h
|
160 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
}
|
162 |
|
163 |
/**
|
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;
|
@@ -30,8 +40,8 @@ class TimberImageHelper {
|
|
30 |
*
|
31 |
* @api
|
32 |
* @param string $src an URL (absolute or relative) to the original image
|
33 |
-
* @param int|string $w target width(int) or WordPress image size (WP-set or user-defined)
|
34 |
-
* @param int $h target height (ignored if $w is WP image size)
|
35 |
* @param string $crop your choices are 'default', 'center', 'top', 'bottom', 'left', 'right'
|
36 |
* @param bool $force
|
37 |
* @example
|
@@ -44,15 +54,15 @@ class TimberImageHelper {
|
|
44 |
* @return string (ex: )
|
45 |
*/
|
46 |
public static function resize( $src, $w, $h = 0, $crop = 'default', $force = false ) {
|
47 |
-
if (!is_numeric($w) && is_string($w)) {
|
48 |
-
if ($sizes = self::find_wp_dimensions($w)) {
|
49 |
$w = $sizes['w'];
|
50 |
$h = $sizes['h'];
|
51 |
} else {
|
52 |
return $src;
|
53 |
}
|
54 |
}
|
55 |
-
$op = new
|
56 |
return self::_operate($src, $op, $force);
|
57 |
}
|
58 |
|
@@ -61,21 +71,21 @@ class TimberImageHelper {
|
|
61 |
* @param string $size the image size to search for
|
62 |
* can be WordPress-defined ("medium")
|
63 |
* or user-defined ("my-awesome-size")
|
64 |
-
* @return array {
|
65 |
* @type int w
|
66 |
* @type int h
|
67 |
* }
|
68 |
*/
|
69 |
private static function find_wp_dimensions( $size ) {
|
70 |
global $_wp_additional_image_sizes;
|
71 |
-
if (isset($_wp_additional_image_sizes[$size])) {
|
72 |
$w = $_wp_additional_image_sizes[$size]['width'];
|
73 |
$h = $_wp_additional_image_sizes[$size]['height'];
|
74 |
-
} else if (in_array($size, array('thumbnail', 'medium', 'large'))) {
|
75 |
$w = get_option($size.'_size_w');
|
76 |
$h = get_option($size.'_size_h');
|
77 |
}
|
78 |
-
if (isset($w) && isset($h) && ($w || $h)) {
|
79 |
return array('w' => $w, 'h' => $h);
|
80 |
}
|
81 |
return false;
|
@@ -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,25 +116,25 @@ class TimberImageHelper {
|
|
106 |
return false;
|
107 |
}
|
108 |
//its a gif so test
|
109 |
-
if( !($fh = @fopen($file, 'rb')) ) {
|
110 |
return false;
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
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 |
}
|
@@ -198,18 +208,20 @@ class TimberImageHelper {
|
|
198 |
/**
|
199 |
* Deletes the auto-generated files for resize and letterboxing created by Timber
|
200 |
* @param string $local_file ex: /var/www/wp-content/uploads/2015/my-pic.jpg
|
201 |
-
*
|
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 |
}
|
214 |
|
215 |
/**
|
@@ -226,19 +238,18 @@ class TimberImageHelper {
|
|
226 |
* @param string $search_pattern pattern of files to pluck from
|
227 |
* @param string $match_pattern pattern of files to go forth and delete
|
228 |
*/
|
229 |
-
protected static function process_delete_generated_files( $filename, $ext, $dir, $search_pattern, $match_pattern ) {
|
230 |
-
$searcher = '/'
|
231 |
-
foreach ( glob(
|
232 |
-
$regexdir = str_replace(
|
233 |
-
$pattern = '/'
|
234 |
-
$match = preg_match(
|
235 |
-
if ( $match ) {
|
236 |
-
unlink(
|
237 |
}
|
238 |
}
|
239 |
}
|
240 |
|
241 |
-
|
242 |
/**
|
243 |
* Determines the filepath corresponding to a given URL
|
244 |
*
|
@@ -247,7 +258,7 @@ class TimberImageHelper {
|
|
247 |
*/
|
248 |
public static function get_server_location( $url ) {
|
249 |
// if we're already an absolute dir, just return
|
250 |
-
if ( 0 === strpos(
|
251 |
return $url;
|
252 |
}
|
253 |
// otherwise, analyze URL then build mapping path
|
@@ -266,14 +277,14 @@ class TimberImageHelper {
|
|
266 |
$upload = wp_upload_dir();
|
267 |
$dir = $upload['path'];
|
268 |
$filename = $file;
|
269 |
-
$file = parse_url(
|
270 |
-
$path_parts = pathinfo(
|
271 |
-
$basename = md5(
|
272 |
$ext = 'jpg';
|
273 |
-
if ( isset(
|
274 |
$ext = $path_parts['extension'];
|
275 |
}
|
276 |
-
return $dir
|
277 |
}
|
278 |
|
279 |
/**
|
@@ -283,27 +294,27 @@ class TimberImageHelper {
|
|
283 |
* @return string the URL to the downloaded file
|
284 |
*/
|
285 |
public static function sideload_image( $file ) {
|
286 |
-
$loc = self::get_sideloaded_file_loc(
|
287 |
-
if ( file_exists(
|
288 |
-
return
|
289 |
}
|
290 |
// Download file to temp location
|
291 |
-
if ( !function_exists(
|
292 |
-
require_once ABSPATH
|
293 |
}
|
294 |
-
$tmp = download_url(
|
295 |
-
preg_match(
|
296 |
$file_array = array();
|
297 |
-
$file_array['name'] = basename(
|
298 |
$file_array['tmp_name'] = $tmp;
|
299 |
// If error storing temporarily, unlink
|
300 |
-
if ( is_wp_error(
|
301 |
-
@unlink(
|
302 |
$file_array['tmp_name'] = '';
|
303 |
}
|
304 |
// do the validation and storage stuff
|
305 |
-
$locinfo = pathinfo(
|
306 |
-
$file = wp_upload_bits(
|
307 |
return $file['url'];
|
308 |
}
|
309 |
|
@@ -315,10 +326,10 @@ class TimberImageHelper {
|
|
315 |
* @param string $url an URL (absolute or relative) pointing to an image
|
316 |
* @return array an array (see keys in code below)
|
317 |
*/
|
318 |
-
private static function analyze_url($url) {
|
319 |
$result = array(
|
320 |
'url' => $url, // the initial url
|
321 |
-
'absolute' =>
|
322 |
'base' => 0, // is the image in uploads dir, or in content dir (theme or plugin)
|
323 |
'subdir' => '', // the path between base (uploads or content) and file
|
324 |
'filename' => '', // the filename, without extension
|
@@ -327,31 +338,32 @@ class TimberImageHelper {
|
|
327 |
);
|
328 |
$upload_dir = wp_upload_dir();
|
329 |
$tmp = $url;
|
330 |
-
if ( 0 === strpos($tmp, ABSPATH) ) {
|
|
|
331 |
$result['absolute'] = true;
|
332 |
if ( 0 === strpos($tmp, $upload_dir['basedir']) ) {
|
333 |
-
$result['base']= self::BASE_UPLOADS; // upload based
|
334 |
$tmp = str_replace($upload_dir['basedir'], '', $tmp);
|
335 |
}
|
336 |
if ( 0 === strpos($tmp, WP_CONTENT_DIR) ) {
|
337 |
-
$result['base']= self::BASE_CONTENT; // content based
|
338 |
$tmp = str_replace(WP_CONTENT_DIR, '', $tmp);
|
339 |
}
|
340 |
} else {
|
341 |
-
if (!$result['absolute']) {
|
342 |
$tmp = home_url().$tmp;
|
343 |
}
|
344 |
-
if (0 === strpos($tmp, $upload_dir['baseurl'])) {
|
345 |
-
$result['base']= self::BASE_UPLOADS; // upload based
|
346 |
$tmp = str_replace($upload_dir['baseurl'], '', $tmp);
|
347 |
}
|
348 |
-
if (0 === strpos($tmp, content_url())) {
|
349 |
-
$result['base']= self::BASE_CONTENT; // content-based
|
350 |
$tmp = str_replace(content_url(), '', $tmp);
|
351 |
}
|
352 |
}
|
353 |
$parts = pathinfo($tmp);
|
354 |
-
$result['subdir'] = $parts['dirname'];
|
355 |
$result['filename'] = $parts['filename'];
|
356 |
$result['extension'] = $parts['extension'];
|
357 |
$result['basename'] = $parts['basename'];
|
@@ -368,20 +380,20 @@ class TimberImageHelper {
|
|
368 |
* @param bool $absolute should the returned URL be absolute (include protocol+host), or relative
|
369 |
* @return string the URL
|
370 |
*/
|
371 |
-
private static function _get_file_url($base, $subdir, $filename, $absolute) {
|
372 |
$url = '';
|
373 |
-
if( self::BASE_UPLOADS == $base ) {
|
374 |
$upload_dir = wp_upload_dir();
|
375 |
$url = $upload_dir['baseurl'];
|
376 |
}
|
377 |
-
if( self::BASE_CONTENT == $base ) {
|
378 |
$url = content_url();
|
379 |
}
|
380 |
-
if(!empty($subdir)) {
|
381 |
$url .= $subdir;
|
382 |
}
|
383 |
$url .= '/'.$filename;
|
384 |
-
if(!$absolute) {
|
385 |
$url = str_replace(home_url(), '', $url);
|
386 |
}
|
387 |
// $url = TimberURLHelper::remove_double_slashes( $url);
|
@@ -396,16 +408,16 @@ class TimberImageHelper {
|
|
396 |
* @param string $filename file name, including extension (but no path)
|
397 |
* @return string the file location
|
398 |
*/
|
399 |
-
private static function _get_file_path($base, $subdir, $filename) {
|
400 |
$path = '';
|
401 |
-
if(self::BASE_UPLOADS == $base) {
|
402 |
$upload_dir = wp_upload_dir();
|
403 |
$path = $upload_dir['basedir'];
|
404 |
}
|
405 |
-
if(self::BASE_CONTENT == $base) {
|
406 |
$path = WP_CONTENT_DIR;
|
407 |
}
|
408 |
-
if(!empty($subdir)) {
|
409 |
$path .= $subdir;
|
410 |
}
|
411 |
$path .= '/'.$filename;
|
@@ -427,12 +439,15 @@ class TimberImageHelper {
|
|
427 |
*
|
428 |
*/
|
429 |
private static function _operate( $src, $op, $force = false ) {
|
430 |
-
if ( empty(
|
431 |
return '';
|
432 |
}
|
|
|
|
|
433 |
// if external image, load it first
|
434 |
-
if (
|
435 |
-
$src = self::sideload_image(
|
|
|
436 |
}
|
437 |
// break down URL into components
|
438 |
$au = self::analyze_url($src);
|
@@ -453,18 +468,25 @@ class TimberImageHelper {
|
|
453 |
$au['subdir'],
|
454 |
$au['basename']
|
455 |
);
|
|
|
|
|
|
|
|
|
456 |
// if already exists...
|
457 |
-
if ( file_exists(
|
458 |
if ( $force ) {
|
459 |
// Force operation - warning: will regenerate the image on every pageload, use for testing purposes only!
|
460 |
-
unlink(
|
461 |
} else {
|
462 |
// return existing file (caching)
|
463 |
return $new_url;
|
464 |
}
|
465 |
}
|
466 |
// otherwise generate result file
|
467 |
-
if($op->run($old_server_path, $new_server_path)) {
|
|
|
|
|
|
|
468 |
return $new_url;
|
469 |
} else {
|
470 |
// in case of error, we return source file itself
|
@@ -475,9 +497,9 @@ class TimberImageHelper {
|
|
475 |
|
476 |
// -- the below methods are just used for unit testing the URL generation code
|
477 |
//
|
478 |
-
static function get_letterbox_file_url($url, $w, $h, $color) {
|
479 |
$au = self::analyze_url($url);
|
480 |
-
$op = new
|
481 |
$new_url = self::_get_file_url(
|
482 |
$au['base'],
|
483 |
$au['subdir'],
|
@@ -486,9 +508,9 @@ class TimberImageHelper {
|
|
486 |
);
|
487 |
return $new_url;
|
488 |
}
|
489 |
-
public static function get_letterbox_file_path($url, $w, $h, $color ) {
|
490 |
$au = self::analyze_url($url);
|
491 |
-
$op = new
|
492 |
$new_path = self::_get_file_path(
|
493 |
$au['base'],
|
494 |
$au['subdir'],
|
@@ -496,9 +518,9 @@ class TimberImageHelper {
|
|
496 |
);
|
497 |
return $new_path;
|
498 |
}
|
499 |
-
static function get_resize_file_url($url, $w, $h, $crop) {
|
500 |
$au = self::analyze_url($url);
|
501 |
-
$op = new
|
502 |
$new_url = self::_get_file_url(
|
503 |
$au['base'],
|
504 |
$au['subdir'],
|
@@ -507,9 +529,9 @@ class TimberImageHelper {
|
|
507 |
);
|
508 |
return $new_url;
|
509 |
}
|
510 |
-
static function get_resize_file_path($url, $w, $h, $crop) {
|
511 |
$au = self::analyze_url($url);
|
512 |
-
$op = new
|
513 |
$new_path = self::_get_file_path(
|
514 |
$au['base'],
|
515 |
$au['subdir'],
|
@@ -517,6 +539,4 @@ class TimberImageHelper {
|
|
517 |
);
|
518 |
return $new_path;
|
519 |
}
|
520 |
-
|
521 |
-
|
522 |
-
}
|
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;
|
40 |
*
|
41 |
* @api
|
42 |
* @param string $src an URL (absolute or relative) to the original image
|
43 |
+
* @param int|string $w target width(int) or WordPress image size (WP-set or user-defined).
|
44 |
+
* @param int $h target height (ignored if $w is WP image size). If not set, will ignore and resize based on $w only.
|
45 |
* @param string $crop your choices are 'default', 'center', 'top', 'bottom', 'left', 'right'
|
46 |
* @param bool $force
|
47 |
* @example
|
54 |
* @return string (ex: )
|
55 |
*/
|
56 |
public static function resize( $src, $w, $h = 0, $crop = 'default', $force = false ) {
|
57 |
+
if ( !is_numeric($w) && is_string($w) ) {
|
58 |
+
if ( $sizes = self::find_wp_dimensions($w) ) {
|
59 |
$w = $sizes['w'];
|
60 |
$h = $sizes['h'];
|
61 |
} else {
|
62 |
return $src;
|
63 |
}
|
64 |
}
|
65 |
+
$op = new Image\Operation\Resize($w, $h, $crop);
|
66 |
return self::_operate($src, $op, $force);
|
67 |
}
|
68 |
|
71 |
* @param string $size the image size to search for
|
72 |
* can be WordPress-defined ("medium")
|
73 |
* or user-defined ("my-awesome-size")
|
74 |
+
* @return false|array {
|
75 |
* @type int w
|
76 |
* @type int h
|
77 |
* }
|
78 |
*/
|
79 |
private static function find_wp_dimensions( $size ) {
|
80 |
global $_wp_additional_image_sizes;
|
81 |
+
if ( isset($_wp_additional_image_sizes[$size]) ) {
|
82 |
$w = $_wp_additional_image_sizes[$size]['width'];
|
83 |
$h = $_wp_additional_image_sizes[$size]['height'];
|
84 |
+
} else if ( in_array($size, array('thumbnail', 'medium', 'large')) ) {
|
85 |
$w = get_option($size.'_size_w');
|
86 |
$h = get_option($size.'_size_h');
|
87 |
}
|
88 |
+
if ( isset($w) && isset($h) && ($w || $h) ) {
|
89 |
return array('w' => $w, 'h' => $h);
|
90 |
}
|
91 |
return false;
|
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;
|
123 |
+
//an animated gif contains multiple "frames", with each frame having a
|
124 |
+
//header made up of:
|
125 |
+
// * a static 4-byte sequence (\x00\x21\xF9\x04)
|
126 |
+
// * 4 variable bytes
|
127 |
+
// * a static 2-byte sequence (\x00\x2C)
|
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 |
+
self::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 |
}
|
208 |
/**
|
209 |
* Deletes the auto-generated files for resize and letterboxing created by Timber
|
210 |
* @param string $local_file ex: /var/www/wp-content/uploads/2015/my-pic.jpg
|
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 |
/**
|
238 |
* @param string $search_pattern pattern of files to pluck from
|
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
|
453 |
$au = self::analyze_url($src);
|
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 {
|
492 |
// in case of error, we return source file itself
|
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 |
|
@@ -93,12 +98,6 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
93 |
*/
|
94 |
public $class;
|
95 |
|
96 |
-
/**
|
97 |
-
* @deprecated since 0.21.7
|
98 |
-
* @var string $display_date @deprecated stores the display date (ex: "October 6, 1984"),
|
99 |
-
*/
|
100 |
-
public $display_date;
|
101 |
-
|
102 |
/**
|
103 |
* @api
|
104 |
* @var string $id the numeric WordPress id of a post
|
@@ -162,13 +161,15 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
162 |
* If you send the constructor nothing it will try to figure out the current post id based on being inside The_Loop
|
163 |
* @example
|
164 |
* ```php
|
165 |
-
* $post = new
|
166 |
-
* $other_post = new
|
167 |
* ```
|
168 |
* @param mixed $pid
|
169 |
*/
|
170 |
-
public function __construct($pid = null) {
|
171 |
-
$
|
|
|
|
|
172 |
$this->init($pid);
|
173 |
}
|
174 |
|
@@ -178,7 +179,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
178 |
* @param mixed a value to test against
|
179 |
* @return int the numberic id we should be using for this post object
|
180 |
*/
|
181 |
-
protected function determine_id($pid) {
|
182 |
global $wp_query;
|
183 |
if ( $pid === null &&
|
184 |
isset($wp_query->queried_object_id)
|
@@ -187,14 +188,18 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
187 |
&& is_object($wp_query->queried_object)
|
188 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
189 |
) {
|
190 |
-
|
191 |
-
|
|
|
|
|
|
|
|
|
192 |
//hack for static page as home page
|
193 |
$pid = $wp_query->queried_object_id;
|
194 |
} else if ( $pid === null ) {
|
195 |
$gtid = false;
|
196 |
$maybe_post = get_post();
|
197 |
-
if ( isset($maybe_post->ID) ){
|
198 |
$gtid = true;
|
199 |
}
|
200 |
if ( $gtid ) {
|
@@ -207,7 +212,7 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
207 |
}
|
208 |
}
|
209 |
}
|
210 |
-
if ( $pid === null && ($pid_from_loop =
|
211 |
$pid = $pid_from_loop;
|
212 |
}
|
213 |
return $pid;
|
@@ -221,13 +226,43 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
221 |
return $this->title();
|
222 |
}
|
223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
/**
|
226 |
-
* Initializes a
|
227 |
* @internal
|
228 |
* @param int|bool $pid
|
229 |
*/
|
230 |
-
protected function init($pid = false) {
|
231 |
if ( $pid === false ) {
|
232 |
$pid = get_the_ID();
|
233 |
}
|
@@ -236,8 +271,6 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
236 |
}
|
237 |
$post_info = $this->get_info($pid);
|
238 |
$this->import($post_info);
|
239 |
-
/* deprecated, adding for support for older themes */
|
240 |
-
$this->display_date = $this->date();
|
241 |
//cant have a function, so gots to do it this way
|
242 |
$post_class = $this->post_class();
|
243 |
$this->class = $post_class;
|
@@ -246,13 +279,13 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
246 |
/**
|
247 |
* Get the URL that will edit the current post/object
|
248 |
* @internal
|
249 |
-
* @
|
|
|
|
|
250 |
* @return bool|string
|
251 |
*/
|
252 |
function get_edit_url() {
|
253 |
-
|
254 |
-
return get_edit_post_link($this->ID);
|
255 |
-
}
|
256 |
}
|
257 |
|
258 |
/**
|
@@ -316,11 +349,11 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
316 |
* @param string $post_name
|
317 |
* @return int
|
318 |
*/
|
319 |
-
static function get_post_id_by_name($post_name) {
|
320 |
global $wpdb;
|
321 |
$query = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s LIMIT 1", $post_name);
|
322 |
$result = $wpdb->get_row($query);
|
323 |
-
if (!$result) {
|
324 |
return null;
|
325 |
}
|
326 |
return $result->ID;
|
@@ -338,15 +371,16 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
338 |
* @param int $len The number of words that WP should use to make the tease. (Isn't this better than [this mess](http://wordpress.org/support/topic/changing-the-default-length-of-the_excerpt-1?replies=14)?). If you've set a post_excerpt on a post, we'll use that for the preview text; otherwise the first X words of the post_content
|
339 |
* @param bool $force What happens if your custom post excerpt is longer then the length requested? By default (`$force = false`) it will use the full `post_excerpt`. However, you can set this to true to *force* your excerpt to be of the desired length
|
340 |
* @param string $readmore The text you want to use on the 'readmore' link
|
341 |
-
* @param bool $strip
|
|
|
342 |
* @return string of the post preview
|
343 |
*/
|
344 |
-
function get_preview($len = 50, $force = false, $readmore = 'Read More', $strip = true) {
|
345 |
$text = '';
|
346 |
$trimmed = false;
|
347 |
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
348 |
if ( $force ) {
|
349 |
-
$text =
|
350 |
$trimmed = true;
|
351 |
} else {
|
352 |
$text = $this->post_excerpt;
|
@@ -356,26 +390,27 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
356 |
$pieces = explode($readmore_matches[0], $this->post_content);
|
357 |
$text = $pieces[0];
|
358 |
if ( $force ) {
|
359 |
-
$text =
|
360 |
$trimmed = true;
|
361 |
}
|
362 |
-
$text = do_shortcode(
|
363 |
}
|
364 |
if ( !strlen($text) ) {
|
365 |
-
$text =
|
366 |
$trimmed = true;
|
367 |
}
|
368 |
if ( !strlen(trim($text)) ) {
|
369 |
return trim($text);
|
370 |
}
|
371 |
if ( $strip ) {
|
372 |
-
$
|
|
|
373 |
}
|
374 |
if ( strlen($text) ) {
|
375 |
$text = trim($text);
|
376 |
$last = $text[strlen($text) - 1];
|
377 |
if ( $last != '.' && $trimmed ) {
|
378 |
-
$text .=
|
379 |
}
|
380 |
if ( !$strip ) {
|
381 |
$last_p_tag = strrpos($text, '</p>');
|
@@ -383,16 +418,16 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
383 |
$text = substr($text, 0, $last_p_tag);
|
384 |
}
|
385 |
if ( $last != '.' && $trimmed ) {
|
386 |
-
$text .= '
|
387 |
}
|
388 |
}
|
389 |
$read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
|
390 |
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
391 |
-
$text .= ' <a href="'
|
392 |
} elseif ( $readmore ) {
|
393 |
-
$text .= ' <a href="'
|
394 |
}
|
395 |
-
if ( !$strip && $last_p_tag && (
|
396 |
$text .= '</p>';
|
397 |
}
|
398 |
}
|
@@ -436,263 +471,313 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
436 |
}
|
437 |
|
438 |
/**
|
439 |
-
* @
|
440 |
-
* @
|
441 |
-
* @return null|TimberImage
|
442 |
*/
|
443 |
-
function
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
}
|
449 |
}
|
|
|
450 |
}
|
451 |
|
452 |
/**
|
|
|
453 |
* @internal
|
454 |
-
* @
|
455 |
-
* @return
|
456 |
*/
|
457 |
-
function
|
458 |
-
|
459 |
-
|
|
|
460 |
}
|
461 |
-
$
|
462 |
-
|
|
|
|
|
|
|
|
|
|
|
463 |
}
|
464 |
|
465 |
-
/**
|
466 |
-
* get the permalink for a post object
|
467 |
-
* In your templates you should use link:
|
468 |
-
* <a href="{{post.link}}">Read my post</a>
|
469 |
-
* @internal
|
470 |
-
* @return string
|
471 |
-
*/
|
472 |
-
function get_link() {
|
473 |
-
return $this->get_permalink();
|
474 |
-
}
|
475 |
|
476 |
/**
|
477 |
-
* Get the
|
478 |
-
*
|
479 |
-
* @
|
480 |
-
* @
|
|
|
|
|
481 |
*/
|
482 |
-
function
|
483 |
-
if ( !isset($this->_next) || !isset($this->_next[$taxonomy]) ) {
|
484 |
-
global $post;
|
485 |
-
$this->_next = array();
|
486 |
-
$old_global = $post;
|
487 |
-
$post = $this;
|
488 |
-
if ( $taxonomy ) {
|
489 |
-
$adjacent = get_adjacent_post(true, '', false, $taxonomy);
|
490 |
-
} else {
|
491 |
-
$adjacent = get_adjacent_post(false, '', false);
|
492 |
-
}
|
493 |
|
494 |
-
|
495 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
} else {
|
497 |
-
$
|
498 |
}
|
499 |
-
$post = $old_global;
|
500 |
}
|
501 |
-
return $this->_next[$taxonomy];
|
502 |
-
}
|
503 |
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
global $post, $page, $numpages, $multipage;
|
510 |
-
$post = $this;
|
511 |
-
$ret = array();
|
512 |
-
if ( $multipage ) {
|
513 |
-
for ( $i = 1; $i <= $numpages; $i++ ) {
|
514 |
-
$link = self::get_wp_link_page($i);
|
515 |
-
$data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
|
516 |
-
if ( $i == $page ) {
|
517 |
-
$data['current'] = true;
|
518 |
-
}
|
519 |
-
$ret['pages'][] = $data;
|
520 |
}
|
521 |
-
|
522 |
-
|
523 |
-
$link = self::get_wp_link_page($i);
|
524 |
-
$ret['prev'] = array('link' => $link);
|
525 |
}
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
530 |
}
|
531 |
}
|
532 |
-
return $
|
533 |
}
|
534 |
|
535 |
/**
|
536 |
-
* @param int $
|
537 |
-
* @
|
|
|
538 |
*/
|
539 |
-
|
540 |
-
$
|
541 |
-
|
542 |
-
|
543 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
}
|
545 |
-
return
|
546 |
}
|
547 |
|
548 |
/**
|
549 |
-
* Get the permalink for a post, but as a relative path
|
550 |
-
* For example, where {{post.link}} would return "http://example.org/2015/07/04/my-cool-post"
|
551 |
-
* this will return the relative version: "/2015/07/04/my-cool-post"
|
552 |
-
* @internal
|
553 |
* @return string
|
554 |
*/
|
555 |
-
function
|
556 |
-
return
|
557 |
}
|
558 |
-
|
559 |
/**
|
560 |
-
*
|
561 |
-
*
|
562 |
-
* @
|
563 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
*/
|
565 |
-
function
|
566 |
-
|
567 |
-
return $this->_prev[$taxonomy];
|
568 |
-
}
|
569 |
-
global $post;
|
570 |
-
$old_global = $post;
|
571 |
-
$post = $this;
|
572 |
-
$within_taxonomy = ($taxonomy) ? $taxonomy : 'category';
|
573 |
-
$adjacent = get_adjacent_post(($taxonomy), '', true, $within_taxonomy);
|
574 |
-
$prev_in_taxonomy = false;
|
575 |
-
if ( $adjacent ) {
|
576 |
-
$prev_in_taxonomy = new $this->PostClass($adjacent);
|
577 |
-
}
|
578 |
-
$this->_prev[$taxonomy] = $prev_in_taxonomy;
|
579 |
-
$post = $old_global;
|
580 |
-
return $this->_prev[$taxonomy];
|
581 |
}
|
582 |
|
583 |
/**
|
584 |
-
*
|
585 |
-
* @internal
|
586 |
-
* @return bool|TimberPost
|
587 |
*/
|
588 |
-
function
|
589 |
-
|
590 |
-
return false;
|
591 |
-
}
|
592 |
-
return new $this->PostClass($this->post_parent);
|
593 |
}
|
594 |
|
595 |
/**
|
596 |
-
*
|
597 |
-
* @
|
598 |
-
* @see TimberPost::author
|
599 |
-
* @return bool|TimberUser
|
600 |
*/
|
601 |
-
function
|
602 |
-
|
603 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
604 |
}
|
|
|
|
|
|
|
605 |
}
|
606 |
|
607 |
/**
|
608 |
-
* @
|
609 |
-
* @return bool|TimberUser
|
610 |
*/
|
611 |
-
function
|
612 |
-
$
|
613 |
-
return ($user_id ? new TimberUser($user_id) : $this->get_author());
|
614 |
}
|
615 |
|
616 |
/**
|
617 |
-
*
|
618 |
* @internal
|
619 |
-
* @param
|
620 |
-
* @
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
634 |
}
|
635 |
|
|
|
|
|
636 |
/**
|
637 |
-
*
|
638 |
-
* @
|
639 |
-
* @see TimberPost::date
|
640 |
-
* @param string $use
|
641 |
-
* @return string
|
642 |
*/
|
643 |
-
function
|
644 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
645 |
}
|
646 |
|
647 |
/**
|
648 |
-
*
|
649 |
-
* @
|
650 |
-
* @
|
651 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
652 |
*/
|
653 |
-
function
|
654 |
-
|
655 |
-
$the_date = (string)mysql2date($df, $this->post_date);
|
656 |
-
return apply_filters('get_the_date', $the_date, $df);
|
657 |
}
|
658 |
|
659 |
/**
|
660 |
-
*
|
661 |
-
* @
|
662 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
663 |
*/
|
664 |
-
function
|
665 |
-
$
|
666 |
-
$
|
667 |
-
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
668 |
}
|
669 |
|
670 |
/**
|
671 |
-
*
|
672 |
-
* @
|
673 |
-
* @return
|
674 |
*/
|
675 |
-
function
|
676 |
-
|
677 |
-
$the_time = get_post_modified_time($tf, false, $this->ID, true);
|
678 |
-
return apply_filters('get_the_modified_time', $the_time, $time_format);
|
679 |
}
|
680 |
|
681 |
/**
|
682 |
-
*
|
683 |
-
* @
|
684 |
-
*
|
685 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
686 |
* @return array
|
687 |
*/
|
688 |
-
function
|
689 |
if ( $childPostClass === false ) {
|
690 |
$childPostClass = $this->PostClass;
|
691 |
}
|
692 |
if ( $post_type == 'parent' ) {
|
693 |
$post_type = $this->post_type;
|
694 |
}
|
695 |
-
$children = get_children('post_parent='
|
696 |
foreach ( $children as &$child ) {
|
697 |
$child = new $childPostClass($child->ID);
|
698 |
}
|
@@ -700,21 +785,28 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
700 |
return $children;
|
701 |
}
|
702 |
|
703 |
-
|
704 |
/**
|
705 |
-
*
|
706 |
-
* @
|
707 |
-
* @
|
708 |
-
* @param
|
709 |
-
* @param string $
|
710 |
-
* @param string $
|
711 |
-
* @param string $
|
712 |
-
* @
|
713 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
714 |
*/
|
715 |
-
|
716 |
-
function get_comments($ct = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment') {
|
717 |
-
|
718 |
global $overridden_cpage, $user_ID;
|
719 |
$overridden_cpage = false;
|
720 |
|
@@ -722,50 +814,50 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
722 |
$comment_author_email = $commenter['comment_author_email'];
|
723 |
|
724 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
725 |
-
if ( $
|
726 |
-
$args['number'] = $
|
727 |
}
|
728 |
if ( strtolower($order) == 'wp' || strtolower($order) == 'wordpress' ) {
|
729 |
$args['order'] = get_option('comment_order');
|
730 |
}
|
731 |
|
732 |
if ( $user_ID ) {
|
733 |
-
$args['include_unapproved'] = array(
|
734 |
-
} elseif ( !
|
735 |
-
$args['include_unapproved'] = array(
|
736 |
}
|
737 |
|
738 |
$comments = get_comments($args);
|
739 |
$timber_comments = array();
|
740 |
|
741 |
if ( '' == get_query_var('cpage') && get_option('page_comments') ) {
|
742 |
-
set_query_var(
|
743 |
$overridden_cpage = true;
|
744 |
}
|
745 |
|
746 |
-
foreach($comments as $key => &$comment) {
|
747 |
$timber_comment = new $CommentClass($comment);
|
748 |
$timber_comments[$timber_comment->id] = $timber_comment;
|
749 |
}
|
750 |
|
751 |
// Build a flattened (depth=1) comment tree
|
752 |
$comments_tree = array();
|
753 |
-
foreach( $timber_comments as $key => $comment ) {
|
754 |
-
if (
|
755 |
continue;
|
756 |
}
|
757 |
|
758 |
$tree_element = $comment;
|
759 |
do {
|
760 |
$tree_element = $timber_comments[$tree_element->comment_parent];
|
761 |
-
} while( $tree_element->is_child() );
|
762 |
|
763 |
$comments_tree[$tree_element->id][] = $comment->id;
|
764 |
}
|
765 |
|
766 |
// Add child comments to the relative "super parents"
|
767 |
-
foreach($comments_tree as $comment_parent => $comment_children) {
|
768 |
-
foreach($comment_children as $comment_child) {
|
769 |
$timber_comments[$comment_parent]->children[] = $timber_comments[$comment_child];
|
770 |
unset($timber_comments[$comment_child]);
|
771 |
}
|
@@ -777,649 +869,664 @@ class TimberPost extends TimberCore implements TimberCoreInterface {
|
|
777 |
}
|
778 |
|
779 |
/**
|
780 |
-
*
|
781 |
-
* @
|
782 |
-
* @
|
783 |
-
*
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
* @
|
791 |
-
* @see TimberPost::category
|
792 |
-
* @return mixed
|
793 |
-
*/
|
794 |
-
function get_category( ) {
|
795 |
-
$cats = $this->get_categories();
|
796 |
-
if ( count($cats) && isset($cats[0]) ) {
|
797 |
-
return $cats[0];
|
798 |
-
}
|
799 |
-
}
|
800 |
-
|
801 |
-
/**
|
802 |
-
* @internal
|
803 |
-
* @param string|array $tax
|
804 |
-
* @param bool $merge
|
805 |
-
* @param string $TermClass
|
806 |
-
* @return array
|
807 |
*/
|
808 |
-
function
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
if ( is_string($merge) && class_exists($merge) ) {
|
813 |
-
$TermClass = $merge;
|
814 |
}
|
815 |
-
|
816 |
-
|
|
|
817 |
}
|
818 |
-
if (
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
$
|
823 |
}
|
824 |
}
|
825 |
-
|
826 |
-
$
|
827 |
-
|
828 |
-
foreach ( $taxonomies as $taxonomy ) {
|
829 |
-
if ( in_array($taxonomy, array('tag','tags')) ) {
|
830 |
-
$taxonomy = 'post_tag';
|
831 |
-
}
|
832 |
-
if ( $taxonomy == 'categories' ) {
|
833 |
-
$taxonomy = 'category';
|
834 |
-
}
|
835 |
-
|
836 |
-
$terms = wp_get_post_terms($this->ID, $taxonomy);
|
837 |
-
|
838 |
-
if ( is_wp_error($terms) ) {
|
839 |
-
/* @var $terms WP_Error */
|
840 |
-
TimberHelper::error_log("Error retrieving terms for taxonomy '$taxonomy' on a post in timber-post.php");
|
841 |
-
TimberHelper::error_log('tax = ' . print_r($tax, true));
|
842 |
-
TimberHelper::error_log('WP_Error: ' . $terms->get_error_message());
|
843 |
-
|
844 |
-
return $term_class_objects;
|
845 |
-
}
|
846 |
-
|
847 |
-
// map over array of wordpress terms, and transform them into instances of the TermClass
|
848 |
-
$terms = array_map(function($term) use ($TermClass, $taxonomy) {
|
849 |
-
return call_user_func(array($TermClass, 'from'), $term->term_id, $taxonomy);
|
850 |
-
}, $terms);
|
851 |
-
|
852 |
-
if ( $merge && is_array($terms) ) {
|
853 |
-
$term_class_objects = array_merge($term_class_objects, $terms);
|
854 |
-
} else if ( count($terms) ) {
|
855 |
-
$term_class_objects[$taxonomy] = $terms;
|
856 |
-
}
|
857 |
}
|
858 |
-
return $
|
859 |
}
|
860 |
|
861 |
/**
|
862 |
-
* @
|
863 |
-
* @param string $taxonomy
|
864 |
-
* @return bool
|
865 |
*/
|
866 |
-
function
|
867 |
-
|
868 |
-
|
869 |
-
$ret = false;
|
870 |
-
foreach ( $taxes as $tax ) {
|
871 |
-
if ( has_term($term_name_or_id, $tax, $this->ID) ) {
|
872 |
-
$ret = true;
|
873 |
-
break;
|
874 |
-
}
|
875 |
-
}
|
876 |
-
return $ret;
|
877 |
-
}
|
878 |
-
return has_term($term_name_or_id, $taxonomy, $this->ID);
|
879 |
}
|
880 |
|
881 |
/**
|
882 |
-
*
|
883 |
-
* @
|
884 |
-
*/
|
885 |
-
function get_image( $field ) {
|
886 |
-
return new $this->ImageClass($this->$field);
|
887 |
-
}
|
888 |
-
|
889 |
-
/**
|
890 |
-
* Gets an array of tags for you to use
|
891 |
-
* @internal
|
892 |
* @example
|
893 |
* ```twig
|
894 |
-
*
|
895 |
-
*
|
896 |
-
*
|
897 |
-
* {% endfor %}
|
898 |
-
* </ul>
|
899 |
* ```
|
900 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
901 |
*/
|
902 |
-
function
|
903 |
-
|
|
|
|
|
904 |
}
|
905 |
|
906 |
/**
|
907 |
-
*
|
908 |
-
* @
|
909 |
* @example
|
910 |
* ```twig
|
911 |
-
*
|
|
|
|
|
912 |
* ```
|
|
|
913 |
* ```html
|
914 |
-
*
|
|
|
|
|
915 |
* ```
|
|
|
916 |
* @return string
|
917 |
*/
|
918 |
-
function
|
919 |
-
|
|
|
|
|
920 |
}
|
921 |
|
922 |
/**
|
923 |
-
*
|
924 |
-
* @
|
925 |
-
* ```twig
|
926 |
-
* <div class="article-text">{{post.get_content}}</div>
|
927 |
-
* ```
|
928 |
-
* ```html
|
929 |
-
* <div class="article-text"><p>Blah blah blah</p><p>More blah blah blah.</p></div>
|
930 |
-
* ```
|
931 |
-
* @param int $len
|
932 |
-
* @param int $page
|
933 |
-
* @return string
|
934 |
*/
|
935 |
-
function
|
936 |
-
if ( $
|
937 |
-
return $this->
|
938 |
-
}
|
939 |
-
$content = $this->post_content;
|
940 |
-
if ( $len ) {
|
941 |
-
$content = wp_trim_words($content, $len);
|
942 |
-
}
|
943 |
-
if ( $page ) {
|
944 |
-
$contents = explode('<!--nextpage-->', $content);
|
945 |
-
$page--;
|
946 |
-
if ( count($contents) > $page ) {
|
947 |
-
$content = $contents[$page];
|
948 |
-
}
|
949 |
-
}
|
950 |
-
$content = apply_filters('the_content', ($content));
|
951 |
-
if ( $len == 0 && $page == 0 ) {
|
952 |
-
$this->_content = $content;
|
953 |
}
|
954 |
-
return $content;
|
955 |
}
|
956 |
|
957 |
/**
|
958 |
-
* @
|
|
|
959 |
*/
|
960 |
-
function
|
961 |
-
|
962 |
-
return $this->get_content(0, $page);
|
963 |
}
|
|
|
964 |
/**
|
965 |
-
*
|
966 |
-
*
|
967 |
* @example
|
968 |
* ```twig
|
969 |
-
*
|
970 |
-
* ```
|
971 |
-
*
|
972 |
-
* ```html
|
973 |
-
* This post is from <span>Recipes</span>
|
974 |
* ```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
975 |
* @return mixed
|
976 |
*/
|
977 |
-
public function
|
978 |
-
|
|
|
|
|
|
|
|
|
979 |
}
|
980 |
|
981 |
/**
|
982 |
-
* @return
|
983 |
*/
|
984 |
-
public function
|
985 |
-
return
|
986 |
}
|
987 |
|
988 |
/**
|
989 |
-
* @param string $
|
990 |
-
* @return
|
991 |
*/
|
992 |
-
public function
|
993 |
-
$
|
994 |
-
|
995 |
-
|
996 |
-
if ( is_array($value) && count($value) == 1 ) {
|
997 |
-
$value = $value[0];
|
998 |
-
}
|
999 |
-
if ( is_array($value) && count($value) == 0 ) {
|
1000 |
-
$value = null;
|
1001 |
-
}
|
1002 |
-
}
|
1003 |
-
$value = apply_filters('timber_post_get_meta_field', $value, $this->ID, $field_name, $this);
|
1004 |
-
return $value;
|
1005 |
}
|
1006 |
|
1007 |
/**
|
1008 |
-
* @param string $
|
|
|
1009 |
*/
|
1010 |
-
function
|
1011 |
-
|
1012 |
}
|
1013 |
|
1014 |
/**
|
1015 |
-
* @
|
|
|
1016 |
* @return mixed
|
1017 |
*/
|
1018 |
-
function
|
1019 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1020 |
}
|
1021 |
|
1022 |
/**
|
1023 |
-
* Get
|
1024 |
-
* @
|
1025 |
-
* @param string $class additional classes you want to add
|
1026 |
-
* @see TimberPost::$class
|
1027 |
-
* @example
|
1028 |
-
* ```twig
|
1029 |
-
* <article class="{{ post.class }}">
|
1030 |
-
* {# Some stuff here #}
|
1031 |
-
* </article>
|
1032 |
-
* ```
|
1033 |
-
*
|
1034 |
-
* ```html
|
1035 |
-
* <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">
|
1036 |
-
* {# Some stuff here #}
|
1037 |
-
* </article>
|
1038 |
-
* ```
|
1039 |
-
* @return string a space-seperated list of classes
|
1040 |
*/
|
1041 |
-
public function
|
1042 |
-
global $post;
|
1043 |
-
$old_global_post = $post;
|
1044 |
$post = $this;
|
1045 |
-
$
|
1046 |
-
$
|
1047 |
-
|
1048 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1049 |
}
|
1050 |
-
return $
|
1051 |
}
|
1052 |
|
1053 |
-
|
1054 |
|
1055 |
/**
|
1056 |
-
*
|
1057 |
-
* @
|
1058 |
*/
|
1059 |
-
public function
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
$ret['prev'] = $this->prev();
|
1075 |
-
$ret['terms'] = $this->terms();
|
1076 |
-
$ret['tags'] = $this->tags();
|
1077 |
-
$ret['thumbnail'] = $this->thumbnail();
|
1078 |
-
$ret['title'] = $this->title();
|
1079 |
-
return $ret;
|
1080 |
}
|
1081 |
|
1082 |
/**
|
1083 |
-
*
|
1084 |
* @api
|
1085 |
* @example
|
1086 |
* ```twig
|
1087 |
-
* <
|
1088 |
-
* <p class="byline">
|
1089 |
-
* <a href="{{post.author.link}}">{{post.author.name}}</a>
|
1090 |
-
* </p>
|
1091 |
* ```
|
1092 |
-
* @return
|
|
|
1093 |
*/
|
1094 |
-
public function
|
1095 |
-
|
|
|
|
|
|
|
1096 |
}
|
1097 |
|
1098 |
/**
|
1099 |
-
*
|
|
|
|
|
1100 |
* @example
|
1101 |
* ```twig
|
1102 |
-
*
|
1103 |
-
* ```
|
1104 |
-
* ```html
|
1105 |
-
* Last updated by Harper Lee
|
1106 |
* ```
|
1107 |
-
* @return
|
1108 |
*/
|
1109 |
-
public function
|
1110 |
-
return $this->
|
1111 |
}
|
1112 |
|
1113 |
/**
|
1114 |
-
* Get the
|
1115 |
* @api
|
1116 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1117 |
*/
|
1118 |
-
public function
|
1119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1120 |
}
|
1121 |
|
1122 |
/**
|
1123 |
-
*
|
1124 |
* @api
|
1125 |
-
*
|
1126 |
-
* @return TimberTerm|null
|
1127 |
*/
|
1128 |
-
public function
|
1129 |
-
return $this->
|
1130 |
}
|
1131 |
|
1132 |
/**
|
1133 |
-
*
|
1134 |
-
* (or other claass as you define).
|
1135 |
* @api
|
1136 |
* @example
|
1137 |
* ```twig
|
1138 |
-
* {
|
1139 |
-
* Here are the child pages:
|
1140 |
-
* {% for child in page.children %}
|
1141 |
-
* <a href="{{ child.link }}">{{ child.title }}</a>
|
1142 |
-
* {% endfor %}
|
1143 |
-
* {% endif %}
|
1144 |
* ```
|
1145 |
-
* @
|
1146 |
-
* @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.
|
1147 |
-
* @return array
|
1148 |
*/
|
1149 |
-
public function
|
1150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1151 |
}
|
1152 |
|
1153 |
/**
|
1154 |
-
*
|
1155 |
* @api
|
1156 |
-
* @param int $count Set the number of comments you want to get. `0` is analogous to "all"
|
1157 |
-
* @param string $order use ordering set in WordPress admin, or a different scheme
|
1158 |
-
* @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
|
1159 |
-
* @param string $status Could be 'pending', etc.
|
1160 |
-
* @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)
|
1161 |
* @example
|
1162 |
* ```twig
|
1163 |
-
* {
|
1164 |
-
* <h4>Comments:</h4>
|
1165 |
-
* {% for comment in post.comments %}
|
1166 |
-
* <div class="comment-{{comment.ID}} comment-order-{{loop.index}}">
|
1167 |
-
* <p>{{comment.author.name}} said:</p>
|
1168 |
-
* <p>{{comment.content}}</p>
|
1169 |
-
* </div>
|
1170 |
-
* {% endfor %}
|
1171 |
* ```
|
1172 |
-
* @return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1173 |
*/
|
1174 |
-
|
1175 |
-
return $this->
|
1176 |
}
|
1177 |
|
1178 |
/**
|
1179 |
-
*
|
1180 |
-
* @
|
1181 |
-
* @
|
1182 |
-
*
|
1183 |
-
*
|
1184 |
-
* <h2>{{post.title}}</h2>
|
1185 |
-
* <div class="content">{{ post.content }}</div>
|
1186 |
-
* </div>
|
1187 |
-
* ```
|
1188 |
-
* @param int $page
|
1189 |
-
* @return string
|
1190 |
*/
|
1191 |
-
|
1192 |
-
|
|
|
|
|
|
|
1193 |
}
|
1194 |
|
1195 |
/**
|
1196 |
-
* @
|
|
|
1197 |
*/
|
1198 |
-
|
1199 |
-
return $this->
|
1200 |
}
|
1201 |
|
1202 |
/**
|
1203 |
-
*
|
1204 |
-
* @
|
|
|
|
|
1205 |
* @example
|
1206 |
* ```twig
|
1207 |
-
*
|
1208 |
-
*
|
1209 |
-
*
|
1210 |
-
*
|
1211 |
-
*
|
1212 |
-
* ```html
|
1213 |
-
* Published on January 12, 2015
|
1214 |
-
* OR
|
1215 |
-
* Published on Jan 12th
|
1216 |
* ```
|
1217 |
-
* @
|
1218 |
-
* @return string
|
1219 |
*/
|
1220 |
-
|
1221 |
-
return $this->
|
1222 |
}
|
1223 |
|
1224 |
/**
|
1225 |
-
*
|
1226 |
-
* @
|
|
|
|
|
1227 |
* @example
|
1228 |
* ```twig
|
1229 |
-
*
|
1230 |
-
* OR
|
1231 |
-
* Published at {{ post.time | time('G:i') }} // 13:25
|
1232 |
* ```
|
1233 |
-
*
|
1234 |
* ```html
|
1235 |
-
*
|
1236 |
-
* OR
|
1237 |
-
* Published at 13:25
|
1238 |
* ```
|
1239 |
-
* @param string $time_format
|
1240 |
* @return string
|
1241 |
*/
|
1242 |
-
|
1243 |
-
|
1244 |
-
$the_time = (string)mysql2date($tf, $this->post_date);
|
1245 |
-
return apply_filters('get_the_time', $the_time, $tf);
|
1246 |
}
|
1247 |
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1253 |
}
|
1254 |
|
1255 |
/**
|
1256 |
-
* @
|
|
|
1257 |
* @return mixed
|
1258 |
*/
|
1259 |
-
|
1260 |
-
return $this->
|
1261 |
}
|
1262 |
|
1263 |
/**
|
1264 |
-
*
|
1265 |
-
*
|
1266 |
-
* @
|
1267 |
-
*
|
1268 |
-
*
|
1269 |
-
*
|
1270 |
-
* @
|
|
|
1271 |
*/
|
1272 |
-
public function
|
1273 |
-
return $this->
|
1274 |
}
|
1275 |
|
1276 |
/**
|
1277 |
-
* @
|
1278 |
-
* @
|
|
|
1279 |
*/
|
1280 |
-
public function
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1286 |
}
|
1287 |
|
1288 |
/**
|
|
|
|
|
|
|
|
|
|
|
1289 |
* @return string
|
1290 |
*/
|
1291 |
-
|
1292 |
-
return $this->
|
1293 |
}
|
1294 |
|
1295 |
/**
|
1296 |
-
* @
|
|
|
1297 |
* @return string
|
1298 |
*/
|
1299 |
-
|
1300 |
-
|
|
|
|
|
1301 |
}
|
1302 |
|
1303 |
/**
|
1304 |
-
* @
|
1305 |
-
* @
|
|
|
|
|
|
|
|
|
|
|
1306 |
*/
|
1307 |
-
|
1308 |
-
return $this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1309 |
}
|
1310 |
|
1311 |
/**
|
1312 |
-
*
|
1313 |
-
* @
|
1314 |
-
* @
|
|
|
|
|
|
|
1315 |
*/
|
1316 |
-
|
1317 |
-
return $this->
|
1318 |
}
|
1319 |
|
1320 |
/**
|
1321 |
-
*
|
|
|
|
|
|
|
|
|
1322 |
*/
|
1323 |
-
|
1324 |
-
return $this->
|
1325 |
}
|
1326 |
|
1327 |
/**
|
1328 |
-
* Gets
|
1329 |
-
* @
|
1330 |
-
* @
|
1331 |
-
*
|
1332 |
-
*
|
1333 |
-
*
|
1334 |
-
* @return bool|TimberPost
|
1335 |
*/
|
1336 |
-
|
1337 |
-
|
|
|
|
|
1338 |
}
|
1339 |
|
1340 |
/**
|
1341 |
-
*
|
1342 |
-
*
|
1343 |
-
* @
|
1344 |
-
* @
|
1345 |
-
* ```twig
|
1346 |
-
* <a href="{{post.path}}">{{post.title}}</a>
|
1347 |
-
* ```
|
1348 |
-
* @return string
|
1349 |
*/
|
1350 |
-
|
1351 |
-
return $this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1352 |
}
|
1353 |
|
1354 |
/**
|
1355 |
-
* @
|
|
|
|
|
|
|
1356 |
* @return string
|
1357 |
*/
|
1358 |
-
|
1359 |
-
return $this->
|
1360 |
}
|
1361 |
|
1362 |
/**
|
1363 |
-
*
|
1364 |
-
*
|
1365 |
-
*
|
1366 |
-
*
|
1367 |
-
*
|
1368 |
-
*
|
1369 |
-
*
|
1370 |
-
* ```
|
1371 |
-
* @param bool $in_same_cat
|
1372 |
-
* @return mixed
|
1373 |
*/
|
1374 |
-
|
1375 |
-
return $this->
|
1376 |
}
|
1377 |
|
1378 |
/**
|
1379 |
-
* Get the
|
1380 |
-
*
|
1381 |
-
* @
|
1382 |
-
* @
|
1383 |
-
* @param bool $
|
1384 |
-
* @return
|
1385 |
*/
|
1386 |
-
|
1387 |
-
return $this->
|
1388 |
}
|
1389 |
|
1390 |
/**
|
1391 |
-
*
|
1392 |
-
* @
|
|
|
|
|
|
|
1393 |
* @return array
|
1394 |
*/
|
1395 |
-
public function
|
1396 |
-
return $this->
|
1397 |
}
|
1398 |
|
1399 |
-
/**
|
1400 |
-
* get the featured image as a TimberImage
|
1401 |
-
* @api
|
1402 |
-
* @example
|
1403 |
-
* ```twig
|
1404 |
-
* <img src="{{post.thumbnail.src}}" />
|
1405 |
-
* ```
|
1406 |
-
* @return TimberImage|null of your thumbnail
|
1407 |
-
*/
|
1408 |
-
public function thumbnail() {
|
1409 |
-
return $this->get_thumbnail();
|
1410 |
-
}
|
1411 |
|
1412 |
/**
|
1413 |
-
*
|
1414 |
-
* @
|
1415 |
-
* @
|
1416 |
-
*
|
1417 |
-
*
|
1418 |
-
*
|
1419 |
-
* @
|
|
|
|
|
1420 |
*/
|
1421 |
-
|
1422 |
-
return $this->
|
1423 |
}
|
1424 |
|
1425 |
}
|
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 |
|
98 |
*/
|
99 |
public $class;
|
100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
/**
|
102 |
* @api
|
103 |
* @var string $id the numeric WordPress id of a post
|
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 |
+
$this->namespacing();
|
171 |
+
|
172 |
+
$pid = $this->determine_id($pid);
|
173 |
$this->init($pid);
|
174 |
}
|
175 |
|
179 |
* @param mixed a value to test against
|
180 |
* @return int the numberic id we should be using for this post object
|
181 |
*/
|
182 |
+
protected function determine_id( $pid ) {
|
183 |
global $wp_query;
|
184 |
if ( $pid === null &&
|
185 |
isset($wp_query->queried_object_id)
|
188 |
&& is_object($wp_query->queried_object)
|
189 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
190 |
) {
|
191 |
+
if ( isset($_GET['preview']) && isset($_GET['preview_nonce']) && wp_verify_nonce($_GET['preview_nonce'], 'post_preview_'.$wp_query->queried_object_id) ) {
|
192 |
+
$pid = $this->get_post_preview_id($wp_query);
|
193 |
+
} else if ( !$pid ) {
|
194 |
+
$pid = $wp_query->queried_object_id;
|
195 |
+
}
|
196 |
+
} else if ( $pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
|
197 |
//hack for static page as home page
|
198 |
$pid = $wp_query->queried_object_id;
|
199 |
} else if ( $pid === null ) {
|
200 |
$gtid = false;
|
201 |
$maybe_post = get_post();
|
202 |
+
if ( isset($maybe_post->ID) ) {
|
203 |
$gtid = true;
|
204 |
}
|
205 |
if ( $gtid ) {
|
212 |
}
|
213 |
}
|
214 |
}
|
215 |
+
if ( $pid === null && ($pid_from_loop = PostGetter::loop_to_id()) ) {
|
216 |
$pid = $pid_from_loop;
|
217 |
}
|
218 |
return $pid;
|
226 |
return $this->title();
|
227 |
}
|
228 |
|
229 |
+
protected function get_post_preview_id( $query ) {
|
230 |
+
$can = array(
|
231 |
+
'edit_'.$query->queried_object->post_type.'s',
|
232 |
+
);
|
233 |
+
|
234 |
+
if ( $query->queried_object->author_id !== get_current_user_id() ) {
|
235 |
+
$can[] = 'edit_others_'.$query->queried_object->post_type.'s';
|
236 |
+
}
|
237 |
+
|
238 |
+
$can_preview = array();
|
239 |
+
|
240 |
+
foreach ( $can as $type ) {
|
241 |
+
if ( current_user_can($type) ) {
|
242 |
+
$can_preview[] = true;
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
if ( count($can_preview) !== count($can) ) {
|
247 |
+
return;
|
248 |
+
}
|
249 |
+
|
250 |
+
$revisions = wp_get_post_revisions($query->queried_object_id);
|
251 |
+
|
252 |
+
if ( !empty($revisions) ) {
|
253 |
+
$last = end($revisions);
|
254 |
+
return $last->ID;
|
255 |
+
}
|
256 |
+
|
257 |
+
return false;
|
258 |
+
}
|
259 |
|
260 |
/**
|
261 |
+
* Initializes a Post
|
262 |
* @internal
|
263 |
* @param int|bool $pid
|
264 |
*/
|
265 |
+
protected function init( $pid = false ) {
|
266 |
if ( $pid === false ) {
|
267 |
$pid = get_the_ID();
|
268 |
}
|
271 |
}
|
272 |
$post_info = $this->get_info($pid);
|
273 |
$this->import($post_info);
|
|
|
|
|
274 |
//cant have a function, so gots to do it this way
|
275 |
$post_class = $this->post_class();
|
276 |
$this->class = $post_class;
|
279 |
/**
|
280 |
* Get the URL that will edit the current post/object
|
281 |
* @internal
|
282 |
+
* @deprecated since 1.0
|
283 |
+
* @codeCoverageIgnore
|
284 |
+
* @see Timber\Post::edit_link
|
285 |
* @return bool|string
|
286 |
*/
|
287 |
function get_edit_url() {
|
288 |
+
return $this->edit_link();
|
|
|
|
|
289 |
}
|
290 |
|
291 |
/**
|
349 |
* @param string $post_name
|
350 |
* @return int
|
351 |
*/
|
352 |
+
static function get_post_id_by_name( $post_name ) {
|
353 |
global $wpdb;
|
354 |
$query = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name = %s LIMIT 1", $post_name);
|
355 |
$result = $wpdb->get_row($query);
|
356 |
+
if ( !$result ) {
|
357 |
return null;
|
358 |
}
|
359 |
return $result->ID;
|
371 |
* @param int $len The number of words that WP should use to make the tease. (Isn't this better than [this mess](http://wordpress.org/support/topic/changing-the-default-length-of-the_excerpt-1?replies=14)?). If you've set a post_excerpt on a post, we'll use that for the preview text; otherwise the first X words of the post_content
|
372 |
* @param bool $force What happens if your custom post excerpt is longer then the length requested? By default (`$force = false`) it will use the full `post_excerpt`. However, you can set this to true to *force* your excerpt to be of the desired length
|
373 |
* @param string $readmore The text you want to use on the 'readmore' link
|
374 |
+
* @param bool|string $strip true for default, false for none, string for list of custom attributes
|
375 |
+
* @param string $end The text to end the preview with (defaults to ...)
|
376 |
* @return string of the post preview
|
377 |
*/
|
378 |
+
function get_preview( $len = 50, $force = false, $readmore = 'Read More', $strip = true, $end = '…' ) {
|
379 |
$text = '';
|
380 |
$trimmed = false;
|
381 |
if ( isset($this->post_excerpt) && strlen($this->post_excerpt) ) {
|
382 |
if ( $force ) {
|
383 |
+
$text = Helper::trim_words($this->post_excerpt, $len, false);
|
384 |
$trimmed = true;
|
385 |
} else {
|
386 |
$text = $this->post_excerpt;
|
390 |
$pieces = explode($readmore_matches[0], $this->post_content);
|
391 |
$text = $pieces[0];
|
392 |
if ( $force ) {
|
393 |
+
$text = Helper::trim_words($text, $len, false);
|
394 |
$trimmed = true;
|
395 |
}
|
396 |
+
$text = do_shortcode($text);
|
397 |
}
|
398 |
if ( !strlen($text) ) {
|
399 |
+
$text = Helper::trim_words($this->get_content(), $len, false);
|
400 |
$trimmed = true;
|
401 |
}
|
402 |
if ( !strlen(trim($text)) ) {
|
403 |
return trim($text);
|
404 |
}
|
405 |
if ( $strip ) {
|
406 |
+
$allowable_tags = (is_string($strip)) ? $strip : null;
|
407 |
+
$text = trim(strip_tags($text, $allowable_tags));
|
408 |
}
|
409 |
if ( strlen($text) ) {
|
410 |
$text = trim($text);
|
411 |
$last = $text[strlen($text) - 1];
|
412 |
if ( $last != '.' && $trimmed ) {
|
413 |
+
$text .= $end;
|
414 |
}
|
415 |
if ( !$strip ) {
|
416 |
$last_p_tag = strrpos($text, '</p>');
|
418 |
$text = substr($text, 0, $last_p_tag);
|
419 |
}
|
420 |
if ( $last != '.' && $trimmed ) {
|
421 |
+
$text .= $end.' ';
|
422 |
}
|
423 |
}
|
424 |
$read_more_class = apply_filters('timber/post/get_preview/read_more_class', "read-more");
|
425 |
if ( $readmore && isset($readmore_matches) && !empty($readmore_matches[1]) ) {
|
426 |
+
$text .= ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore_matches[1]).'</a>';
|
427 |
} elseif ( $readmore ) {
|
428 |
+
$text .= ' <a href="'.$this->link().'" class="'.$read_more_class.'">'.trim($readmore).'</a>';
|
429 |
}
|
430 |
+
if ( !$strip && $last_p_tag && (strpos($text, '<p>') || strpos($text, '<p ')) ) {
|
431 |
$text .= '</p>';
|
432 |
}
|
433 |
}
|
471 |
}
|
472 |
|
473 |
/**
|
474 |
+
* @param int $i
|
475 |
+
* @return string
|
|
|
476 |
*/
|
477 |
+
protected static function get_wp_link_page( $i ) {
|
478 |
+
$link = _wp_link_page($i);
|
479 |
+
$link = new \SimpleXMLElement($link.'</a>');
|
480 |
+
if ( isset($link['href']) ) {
|
481 |
+
return $link['href'];
|
|
|
482 |
}
|
483 |
+
return '';
|
484 |
}
|
485 |
|
486 |
/**
|
487 |
+
* Used internally by init, etc. to build TimberPost object
|
488 |
* @internal
|
489 |
+
* @param int $pid
|
490 |
+
* @return null|object|WP_Post
|
491 |
*/
|
492 |
+
protected function get_info( $pid ) {
|
493 |
+
$post = $this->prepare_post_info($pid);
|
494 |
+
if ( !isset($post->post_status) ) {
|
495 |
+
return null;
|
496 |
}
|
497 |
+
$post->status = $post->post_status;
|
498 |
+
$post->id = $post->ID;
|
499 |
+
$post->slug = $post->post_name;
|
500 |
+
$customs = $this->get_post_custom($post->ID);
|
501 |
+
$post->custom = $customs;
|
502 |
+
$post = (object) array_merge((array) $customs, (array) $post);
|
503 |
+
return $post;
|
504 |
}
|
505 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
506 |
|
507 |
/**
|
508 |
+
* Get the terms associated with the post
|
509 |
+
* This goes across all taxonomies by default
|
510 |
+
* @api
|
511 |
+
* @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.
|
512 |
+
* @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)?
|
513 |
+
* @return array
|
514 |
*/
|
515 |
+
public function terms( $tax = '', $merge = true, $TermClass = '' ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
516 |
|
517 |
+
$TermClass = $TermClass ?: $this->TermClass;
|
518 |
+
|
519 |
+
if ( is_string($merge) && class_exists($merge) ) {
|
520 |
+
$TermClass = $merge;
|
521 |
+
}
|
522 |
+
if ( is_array($tax) ) {
|
523 |
+
$taxonomies = $tax;
|
524 |
+
}
|
525 |
+
if ( is_string($tax) ) {
|
526 |
+
if ( in_array($tax, array('all', 'any', '')) ) {
|
527 |
+
$taxonomies = get_object_taxonomies($this->post_type);
|
528 |
} else {
|
529 |
+
$taxonomies = array($tax);
|
530 |
}
|
|
|
531 |
}
|
|
|
|
|
532 |
|
533 |
+
$term_class_objects = array();
|
534 |
+
|
535 |
+
foreach ( $taxonomies as $taxonomy ) {
|
536 |
+
if ( in_array($taxonomy, array('tag', 'tags')) ) {
|
537 |
+
$taxonomy = 'post_tag';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
538 |
}
|
539 |
+
if ( $taxonomy == 'categories' ) {
|
540 |
+
$taxonomy = 'category';
|
|
|
|
|
541 |
}
|
542 |
+
|
543 |
+
$terms = wp_get_post_terms($this->ID, $taxonomy);
|
544 |
+
|
545 |
+
if ( is_wp_error($terms) ) {
|
546 |
+
/* @var $terms WP_Error */
|
547 |
+
Helper::error_log("Error retrieving terms for taxonomy '$taxonomy' on a post in timber-post.php");
|
548 |
+
Helper::error_log('tax = '.print_r($tax, true));
|
549 |
+
Helper::error_log('WP_Error: '.$terms->get_error_message());
|
550 |
+
|
551 |
+
return $term_class_objects;
|
552 |
+
}
|
553 |
+
|
554 |
+
// map over array of wordpress terms, and transform them into instances of the TermClass
|
555 |
+
$terms = array_map(function( $term ) use ($TermClass, $taxonomy) {
|
556 |
+
return call_user_func(array($TermClass, 'from'), $term->term_id, $taxonomy);
|
557 |
+
}, $terms);
|
558 |
+
|
559 |
+
if ( $merge && is_array($terms) ) {
|
560 |
+
$term_class_objects = array_merge($term_class_objects, $terms);
|
561 |
+
} else if ( count($terms) ) {
|
562 |
+
$term_class_objects[$taxonomy] = $terms;
|
563 |
}
|
564 |
}
|
565 |
+
return $term_class_objects;
|
566 |
}
|
567 |
|
568 |
/**
|
569 |
+
* @param string|int $term_name_or_id
|
570 |
+
* @param string $taxonomy
|
571 |
+
* @return bool
|
572 |
*/
|
573 |
+
function has_term( $term_name_or_id, $taxonomy = 'all' ) {
|
574 |
+
if ( $taxonomy == 'all' || $taxonomy == 'any' ) {
|
575 |
+
$taxes = get_object_taxonomies($this->post_type, 'names');
|
576 |
+
$ret = false;
|
577 |
+
foreach ( $taxes as $tax ) {
|
578 |
+
if ( has_term($term_name_or_id, $tax, $this->ID) ) {
|
579 |
+
$ret = true;
|
580 |
+
break;
|
581 |
+
}
|
582 |
+
}
|
583 |
+
return $ret;
|
584 |
}
|
585 |
+
return has_term($term_name_or_id, $taxonomy, $this->ID);
|
586 |
}
|
587 |
|
588 |
/**
|
|
|
|
|
|
|
|
|
589 |
* @return string
|
590 |
*/
|
591 |
+
function get_paged_content() {
|
592 |
+
return $this->paged_content();
|
593 |
}
|
|
|
594 |
/**
|
595 |
+
*
|
596 |
+
* Here is my summary
|
597 |
+
* @example
|
598 |
+
* ```twig
|
599 |
+
* This post is from <span>{{ post.get_post_type.labels.plural }}</span>
|
600 |
+
* ```
|
601 |
+
*
|
602 |
+
* ```html
|
603 |
+
* This post is from <span>Recipes</span>
|
604 |
+
* ```
|
605 |
+
* @return mixed
|
606 |
*/
|
607 |
+
public function get_post_type() {
|
608 |
+
return get_post_type_object($this->post_type);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
609 |
}
|
610 |
|
611 |
/**
|
612 |
+
* @return int the number of comments on a post
|
|
|
|
|
613 |
*/
|
614 |
+
public function get_comment_count() {
|
615 |
+
return get_comments_number($this->ID);
|
|
|
|
|
|
|
616 |
}
|
617 |
|
618 |
/**
|
619 |
+
* @param string $field_name
|
620 |
+
* @return mixed
|
|
|
|
|
621 |
*/
|
622 |
+
public function get_field( $field_name ) {
|
623 |
+
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
624 |
+
if ( $value === null ) {
|
625 |
+
$value = get_post_meta($this->ID, $field_name);
|
626 |
+
if ( is_array($value) && count($value) == 1 ) {
|
627 |
+
$value = $value[0];
|
628 |
+
}
|
629 |
+
if ( is_array($value) && count($value) == 0 ) {
|
630 |
+
$value = null;
|
631 |
+
}
|
632 |
}
|
633 |
+
$value = apply_filters('timber_post_get_meta_field', $value, $this->ID, $field_name, $this);
|
634 |
+
$value = $this->convert($value, __CLASS__);
|
635 |
+
return $value;
|
636 |
}
|
637 |
|
638 |
/**
|
639 |
+
* @param string $field_name
|
|
|
640 |
*/
|
641 |
+
function import_field( $field_name ) {
|
642 |
+
$this->$field_name = $this->get_field($field_name);
|
|
|
643 |
}
|
644 |
|
645 |
/**
|
646 |
+
* Get the CSS classes for a post. For usage you should use `{{post.class}}` instead of `{{post.post_class}}`
|
647 |
* @internal
|
648 |
+
* @param string $class additional classes you want to add
|
649 |
+
* @see Timber\Post::$class
|
650 |
+
* @example
|
651 |
+
* ```twig
|
652 |
+
* <article class="{{ post.class }}">
|
653 |
+
* {# Some stuff here #}
|
654 |
+
* </article>
|
655 |
+
* ```
|
656 |
+
*
|
657 |
+
* ```html
|
658 |
+
* <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">
|
659 |
+
* {# Some stuff here #}
|
660 |
+
* </article>
|
661 |
+
* ```
|
662 |
+
* @return string a space-seperated list of classes
|
663 |
+
*/
|
664 |
+
public function post_class( $class = '' ) {
|
665 |
+
global $post;
|
666 |
+
$old_global_post = $post;
|
667 |
+
$post = $this;
|
668 |
+
$class_array = get_post_class($class, $this->ID);
|
669 |
+
$post = $old_global_post;
|
670 |
+
if ( is_array($class_array) ) {
|
671 |
+
return implode(' ', $class_array);
|
672 |
+
}
|
673 |
+
return $class_array;
|
674 |
}
|
675 |
|
676 |
+
// Docs
|
677 |
+
|
678 |
/**
|
679 |
+
* @return array
|
680 |
+
* @codeCoverageIgnore
|
|
|
|
|
|
|
681 |
*/
|
682 |
+
public function get_method_values() {
|
683 |
+
$ret = parent::get_method_values();
|
684 |
+
$ret['author'] = $this->author();
|
685 |
+
$ret['categories'] = $this->categories();
|
686 |
+
$ret['category'] = $this->category();
|
687 |
+
$ret['children'] = $this->children();
|
688 |
+
$ret['comments'] = $this->comments();
|
689 |
+
$ret['content'] = $this->content();
|
690 |
+
$ret['edit_link'] = $this->edit_link();
|
691 |
+
$ret['format'] = $this->format();
|
692 |
+
$ret['link'] = $this->link();
|
693 |
+
$ret['next'] = $this->next();
|
694 |
+
$ret['pagination'] = $this->pagination();
|
695 |
+
$ret['parent'] = $this->parent();
|
696 |
+
$ret['path'] = $this->path();
|
697 |
+
$ret['prev'] = $this->prev();
|
698 |
+
$ret['terms'] = $this->terms();
|
699 |
+
$ret['tags'] = $this->tags();
|
700 |
+
$ret['thumbnail'] = $this->thumbnail();
|
701 |
+
$ret['title'] = $this->title();
|
702 |
+
return $ret;
|
703 |
}
|
704 |
|
705 |
/**
|
706 |
+
* Return the author of a post
|
707 |
+
* @api
|
708 |
+
* @example
|
709 |
+
* ```twig
|
710 |
+
* <h1>{{post.title}}</h1>
|
711 |
+
* <p class="byline">
|
712 |
+
* <a href="{{post.author.link}}">{{post.author.name}}</a>
|
713 |
+
* </p>
|
714 |
+
* ```
|
715 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
716 |
*/
|
717 |
+
public function author() {
|
718 |
+
return $this->get_author();
|
|
|
|
|
719 |
}
|
720 |
|
721 |
/**
|
722 |
+
* Get the author (WordPress user) who last modified the post
|
723 |
+
* @example
|
724 |
+
* ```twig
|
725 |
+
* Last updated by {{ post.modified_author.name }}
|
726 |
+
* ```
|
727 |
+
* ```html
|
728 |
+
* Last updated by Harper Lee
|
729 |
+
* ```
|
730 |
+
* @return TimberUser|bool A TimberUser object if found, false if not
|
731 |
*/
|
732 |
+
public function modified_author() {
|
733 |
+
$user_id = get_post_meta($this->ID, '_edit_last', true);
|
734 |
+
return ($user_id ? new User($user_id) : $this->get_author());
|
|
|
735 |
}
|
736 |
|
737 |
/**
|
738 |
+
* Get the categoires on a particular post
|
739 |
+
* @api
|
740 |
+
* @return array of TimberTerms
|
741 |
*/
|
742 |
+
public function categories() {
|
743 |
+
return $this->get_terms('category');
|
|
|
|
|
744 |
}
|
745 |
|
746 |
/**
|
747 |
+
* Returns a category attached to a post
|
748 |
+
* @api
|
749 |
+
* If mulitpuile categories are set, it will return just the first one
|
750 |
+
* @return TimberTerm|null
|
751 |
+
*/
|
752 |
+
public function category() {
|
753 |
+
return $this->get_category();
|
754 |
+
}
|
755 |
+
|
756 |
+
/**
|
757 |
+
* Returns an array of children on the post as Timber\Posts
|
758 |
+
* (or other claass as you define).
|
759 |
+
* @api
|
760 |
+
* @example
|
761 |
+
* ```twig
|
762 |
+
* {% if post.children %}
|
763 |
+
* Here are the child pages:
|
764 |
+
* {% for child in page.children %}
|
765 |
+
* <a href="{{ child.link }}">{{ child.title }}</a>
|
766 |
+
* {% endfor %}
|
767 |
+
* {% endif %}
|
768 |
+
* ```
|
769 |
+
* @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
|
770 |
+
* @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.
|
771 |
* @return array
|
772 |
*/
|
773 |
+
public function children( $post_type = 'any', $childPostClass = false ) {
|
774 |
if ( $childPostClass === false ) {
|
775 |
$childPostClass = $this->PostClass;
|
776 |
}
|
777 |
if ( $post_type == 'parent' ) {
|
778 |
$post_type = $this->post_type;
|
779 |
}
|
780 |
+
$children = get_children('post_parent='.$this->ID.'&post_type='.$post_type.'&numberposts=-1&orderby=menu_order title&order=ASC&post_status=publish');
|
781 |
foreach ( $children as &$child ) {
|
782 |
$child = new $childPostClass($child->ID);
|
783 |
}
|
785 |
return $children;
|
786 |
}
|
787 |
|
|
|
788 |
/**
|
789 |
+
* Gets the comments on a Timber\Post and returns them as an array of [TimberComments](#TimberComment) (or whatever comment class you set).
|
790 |
+
* @api
|
791 |
+
* @param int $count Set the number of comments you want to get. `0` is analogous to "all"
|
792 |
+
* @param string $order use ordering set in WordPress admin, or a different scheme
|
793 |
+
* @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
|
794 |
+
* @param string $status Could be 'pending', etc.
|
795 |
+
* @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)
|
796 |
+
* @example
|
797 |
+
* ```twig
|
798 |
+
* {# single.twig #}
|
799 |
+
* <h4>Comments:</h4>
|
800 |
+
* {% for comment in post.comments %}
|
801 |
+
* <div class="comment-{{comment.ID}} comment-order-{{loop.index}}">
|
802 |
+
* <p>{{comment.author.name}} said:</p>
|
803 |
+
* <p>{{comment.content}}</p>
|
804 |
+
* </div>
|
805 |
+
* {% endfor %}
|
806 |
+
* ```
|
807 |
+
* @return bool|array
|
808 |
*/
|
809 |
+
public function comments( $count = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment' ) {
|
|
|
|
|
810 |
global $overridden_cpage, $user_ID;
|
811 |
$overridden_cpage = false;
|
812 |
|
814 |
$comment_author_email = $commenter['comment_author_email'];
|
815 |
|
816 |
$args = array('post_id' => $this->ID, 'status' => $status, 'order' => $order);
|
817 |
+
if ( $count > 0 ) {
|
818 |
+
$args['number'] = $count;
|
819 |
}
|
820 |
if ( strtolower($order) == 'wp' || strtolower($order) == 'wordpress' ) {
|
821 |
$args['order'] = get_option('comment_order');
|
822 |
}
|
823 |
|
824 |
if ( $user_ID ) {
|
825 |
+
$args['include_unapproved'] = array($user_ID);
|
826 |
+
} elseif ( !empty($comment_author_email) ) {
|
827 |
+
$args['include_unapproved'] = array($comment_author_email);
|
828 |
}
|
829 |
|
830 |
$comments = get_comments($args);
|
831 |
$timber_comments = array();
|
832 |
|
833 |
if ( '' == get_query_var('cpage') && get_option('page_comments') ) {
|
834 |
+
set_query_var('cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1);
|
835 |
$overridden_cpage = true;
|
836 |
}
|
837 |
|
838 |
+
foreach ( $comments as $key => &$comment ) {
|
839 |
$timber_comment = new $CommentClass($comment);
|
840 |
$timber_comments[$timber_comment->id] = $timber_comment;
|
841 |
}
|
842 |
|
843 |
// Build a flattened (depth=1) comment tree
|
844 |
$comments_tree = array();
|
845 |
+
foreach ( $timber_comments as $key => $comment ) {
|
846 |
+
if ( !$comment->is_child() ) {
|
847 |
continue;
|
848 |
}
|
849 |
|
850 |
$tree_element = $comment;
|
851 |
do {
|
852 |
$tree_element = $timber_comments[$tree_element->comment_parent];
|
853 |
+
} while ( $tree_element->is_child() );
|
854 |
|
855 |
$comments_tree[$tree_element->id][] = $comment->id;
|
856 |
}
|
857 |
|
858 |
// Add child comments to the relative "super parents"
|
859 |
+
foreach ( $comments_tree as $comment_parent => $comment_children ) {
|
860 |
+
foreach ( $comment_children as $comment_child ) {
|
861 |
$timber_comments[$comment_parent]->children[] = $timber_comments[$comment_child];
|
862 |
unset($timber_comments[$comment_child]);
|
863 |
}
|
869 |
}
|
870 |
|
871 |
/**
|
872 |
+
* 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).
|
873 |
+
* @api
|
874 |
+
* @example
|
875 |
+
* ```twig
|
876 |
+
* <div class="article">
|
877 |
+
* <h2>{{post.title}}</h2>
|
878 |
+
* <div class="content">{{ post.content }}</div>
|
879 |
+
* </div>
|
880 |
+
* ```
|
881 |
+
* @param int $page
|
882 |
+
* @return string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
883 |
*/
|
884 |
+
public function content( $page = 0, $len = -1 ) {
|
885 |
+
if ( $len == -1 && $page == 0 && $this->_content ) {
|
886 |
+
return $this->_content;
|
|
|
|
|
|
|
887 |
}
|
888 |
+
$content = $this->post_content;
|
889 |
+
if ( $len > 0 ) {
|
890 |
+
$content = wp_trim_words($content, $len);
|
891 |
}
|
892 |
+
if ( $page ) {
|
893 |
+
$contents = explode('<!--nextpage-->', $content);
|
894 |
+
$page--;
|
895 |
+
if ( count($contents) > $page ) {
|
896 |
+
$content = $contents[$page];
|
897 |
}
|
898 |
}
|
899 |
+
$content = apply_filters('the_content', ($content));
|
900 |
+
if ( $len == -1 && $page == 0 ) {
|
901 |
+
$this->_content = $content;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
902 |
}
|
903 |
+
return $content;
|
904 |
}
|
905 |
|
906 |
/**
|
907 |
+
* @return string
|
|
|
|
|
908 |
*/
|
909 |
+
public function paged_content() {
|
910 |
+
global $page;
|
911 |
+
return $this->content($page, -1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
912 |
}
|
913 |
|
914 |
/**
|
915 |
+
* Get the date to use in your template!
|
916 |
+
* @api
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
917 |
* @example
|
918 |
* ```twig
|
919 |
+
* Published on {{ post.date }} // Uses WP's formatting set in Admin
|
920 |
+
* OR
|
921 |
+
* Published on {{ post.date | date('F jS') }} // Jan 12th
|
|
|
|
|
922 |
* ```
|
923 |
+
*
|
924 |
+
* ```html
|
925 |
+
* Published on January 12, 2015
|
926 |
+
* OR
|
927 |
+
* Published on Jan 12th
|
928 |
+
* ```
|
929 |
+
* @param string $date_format
|
930 |
+
* @return string
|
931 |
*/
|
932 |
+
public function date( $date_format = '' ) {
|
933 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
934 |
+
$the_date = (string) mysql2date($df, $this->post_date);
|
935 |
+
return apply_filters('get_the_date', $the_date, $df);
|
936 |
}
|
937 |
|
938 |
/**
|
939 |
+
* Get the time to use in your template
|
940 |
+
* @api
|
941 |
* @example
|
942 |
* ```twig
|
943 |
+
* Published at {{ post.time }} // Uses WP's formatting set in Admin
|
944 |
+
* OR
|
945 |
+
* Published at {{ post.time | time('G:i') }} // 13:25
|
946 |
* ```
|
947 |
+
*
|
948 |
* ```html
|
949 |
+
* Published at 1:25 pm
|
950 |
+
* OR
|
951 |
+
* Published at 13:25
|
952 |
* ```
|
953 |
+
* @param string $time_format
|
954 |
* @return string
|
955 |
*/
|
956 |
+
public function time( $time_format = '' ) {
|
957 |
+
$tf = $time_format ? $time_format : get_option('time_format');
|
958 |
+
$the_time = (string) mysql2date($tf, $this->post_date);
|
959 |
+
return apply_filters('get_the_time', $the_time, $tf);
|
960 |
}
|
961 |
|
962 |
/**
|
963 |
+
* Returns the edit URL of a post if the user has access to it
|
964 |
+
* @return bool|string the edit URL of a post in the WordPress admin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
965 |
*/
|
966 |
+
public function edit_link() {
|
967 |
+
if ( $this->can_edit() ) {
|
968 |
+
return get_edit_post_link($this->ID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
969 |
}
|
|
|
970 |
}
|
971 |
|
972 |
/**
|
973 |
+
* @api
|
974 |
+
* @return mixed
|
975 |
*/
|
976 |
+
public function format() {
|
977 |
+
return get_post_format($this->ID);
|
|
|
978 |
}
|
979 |
+
|
980 |
/**
|
981 |
+
* get the permalink for a post object
|
982 |
+
* @api
|
983 |
* @example
|
984 |
* ```twig
|
985 |
+
* <a href="{{post.link}}">Read my post</a>
|
|
|
|
|
|
|
|
|
986 |
* ```
|
987 |
+
* @return string ex: http://example.org/2015/07/my-awesome-post
|
988 |
+
*/
|
989 |
+
public function link() {
|
990 |
+
if ( isset($this->_permalink) ) {
|
991 |
+
return $this->_permalink;
|
992 |
+
}
|
993 |
+
$this->_permalink = get_permalink($this->ID);
|
994 |
+
return $this->_permalink;
|
995 |
+
}
|
996 |
+
|
997 |
+
/**
|
998 |
+
* @param string $field_name
|
999 |
* @return mixed
|
1000 |
*/
|
1001 |
+
public function meta( $field_name = null ) {
|
1002 |
+
if ( $field_name === null ) {
|
1003 |
+
//on the off-chance the field is actually named meta
|
1004 |
+
$field_name = 'meta';
|
1005 |
+
}
|
1006 |
+
return $this->get_field($field_name);
|
1007 |
}
|
1008 |
|
1009 |
/**
|
1010 |
+
* @return string
|
1011 |
*/
|
1012 |
+
public function name() {
|
1013 |
+
return $this->title();
|
1014 |
}
|
1015 |
|
1016 |
/**
|
1017 |
+
* @param string $date_format
|
1018 |
+
* @return string
|
1019 |
*/
|
1020 |
+
public function modified_date( $date_format = '' ) {
|
1021 |
+
$df = $date_format ? $date_format : get_option('date_format');
|
1022 |
+
$the_time = $this->get_modified_time($df);
|
1023 |
+
return apply_filters('get_the_modified_date', $the_time, $date_format);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1024 |
}
|
1025 |
|
1026 |
/**
|
1027 |
+
* @param string $time_format
|
1028 |
+
* @return string
|
1029 |
*/
|
1030 |
+
public function modified_time( $time_format = '' ) {
|
1031 |
+
return $this->get_modified_time($time_format);
|
1032 |
}
|
1033 |
|
1034 |
/**
|
1035 |
+
* @api
|
1036 |
+
* @param bool $in_same_cat
|
1037 |
* @return mixed
|
1038 |
*/
|
1039 |
+
public function next( $in_same_term = false ) {
|
1040 |
+
if ( !isset($this->_next) || !isset($this->_next[$in_same_term]) ) {
|
1041 |
+
global $post;
|
1042 |
+
$this->_next = array();
|
1043 |
+
$old_global = $post;
|
1044 |
+
$post = $this;
|
1045 |
+
if ( $in_same_term ) {
|
1046 |
+
$adjacent = get_adjacent_post(true, '', false, $in_same_term);
|
1047 |
+
} else {
|
1048 |
+
$adjacent = get_adjacent_post(false, '', false);
|
1049 |
+
}
|
1050 |
+
|
1051 |
+
if ( $adjacent ) {
|
1052 |
+
$this->_next[$in_same_term] = new $this->PostClass($adjacent);
|
1053 |
+
} else {
|
1054 |
+
$this->_next[$in_same_term] = false;
|
1055 |
+
}
|
1056 |
+
$post = $old_global;
|
1057 |
+
}
|
1058 |
+
return $this->_next[$in_same_term];
|
1059 |
}
|
1060 |
|
1061 |
/**
|
1062 |
+
* Get a data array of pagination so you can navigate to the previous/next for a paginated post
|
1063 |
+
* @return array
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1064 |
*/
|
1065 |
+
public function pagination() {
|
1066 |
+
global $post, $page, $numpages, $multipage;
|
|
|
1067 |
$post = $this;
|
1068 |
+
$ret = array();
|
1069 |
+
if ( $multipage ) {
|
1070 |
+
for ( $i = 1; $i <= $numpages; $i++ ) {
|
1071 |
+
$link = self::get_wp_link_page($i);
|
1072 |
+
$data = array('name' => $i, 'title' => $i, 'text' => $i, 'link' => $link);
|
1073 |
+
if ( $i == $page ) {
|
1074 |
+
$data['current'] = true;
|
1075 |
+
}
|
1076 |
+
$ret['pages'][] = $data;
|
1077 |
+
}
|
1078 |
+
$i = $page - 1;
|
1079 |
+
if ( $i ) {
|
1080 |
+
$link = self::get_wp_link_page($i);
|
1081 |
+
$ret['prev'] = array('link' => $link);
|
1082 |
+
}
|
1083 |
+
$i = $page + 1;
|
1084 |
+
if ( $i <= $numpages ) {
|
1085 |
+
$link = self::get_wp_link_page($i);
|
1086 |
+
$ret['next'] = array('link' => $link);
|
1087 |
+
}
|
1088 |
}
|
1089 |
+
return $ret;
|
1090 |
}
|
1091 |
|
1092 |
+
|
1093 |
|
1094 |
/**
|
1095 |
+
* Finds any WP_Post objects and converts them to Timber\Posts
|
1096 |
+
* @param array $data
|
1097 |
*/
|
1098 |
+
public function convert( $data, $class ) {
|
1099 |
+
if ( is_array($data) ) {
|
1100 |
+
$func = __FUNCTION__;
|
1101 |
+
foreach ( $data as &$ele ) {
|
1102 |
+
if ( gettype($ele) === 'array' ) {
|
1103 |
+
$ele = $this->$func($ele, $class);
|
1104 |
+
} else {
|
1105 |
+
if ( $ele instanceof WP_Post ) {
|
1106 |
+
$ele = new $class($ele);
|
1107 |
+
}
|
1108 |
+
}
|
1109 |
+
}
|
1110 |
+
}
|
1111 |
+
|
1112 |
+
return $data;
|
|
|
|
|
|
|
|
|
|
|
|
|
1113 |
}
|
1114 |
|
1115 |
/**
|
1116 |
+
* Gets the parent (if one exists) from a post as a Timber\Post object (or whatever is set in Timber\Post::$PostClass)
|
1117 |
* @api
|
1118 |
* @example
|
1119 |
* ```twig
|
1120 |
+
* Parent page: <a href="{{ post.parent.link }}">{{ post.parent.title }}</a>
|
|
|
|
|
|
|
1121 |
* ```
|
1122 |
+
* @return bool|Timber\Post
|
1123 |
+
* @param string $field_name
|
1124 |
*/
|
1125 |
+
public function parent() {
|
1126 |
+
if ( !$this->post_parent ) {
|
1127 |
+
return false;
|
1128 |
+
}
|
1129 |
+
return new $this->PostClass($this->post_parent);
|
1130 |
}
|
1131 |
|
1132 |
/**
|
1133 |
+
* Gets the relative path of a WP Post, so while link() will return http://example.org/2015/07/my-cool-post
|
1134 |
+
* this will return just /2015/07/my-cool-post
|
1135 |
+
* @api
|
1136 |
* @example
|
1137 |
* ```twig
|
1138 |
+
* <a href="{{post.path}}">{{post.title}}</a>
|
|
|
|
|
|
|
1139 |
* ```
|
1140 |
+
* @return string
|
1141 |
*/
|
1142 |
+
public function path() {
|
1143 |
+
return URLHelper::get_rel_url($this->get_link());
|
1144 |
}
|
1145 |
|
1146 |
/**
|
1147 |
+
* Get the previous post in a set
|
1148 |
* @api
|
1149 |
+
* @example
|
1150 |
+
* ```twig
|
1151 |
+
* <h4>Prior Entry:</h4>
|
1152 |
+
* <h3>{{post.prev.title}}</h3>
|
1153 |
+
* <p>{{post.prev.get_preview(25)}}</p>
|
1154 |
+
* ```
|
1155 |
+
* @param bool $in_same_term
|
1156 |
+
* @return mixed
|
1157 |
*/
|
1158 |
+
public function prev( $in_same_term = false ) {
|
1159 |
+
if ( isset($this->_prev) && isset($this->_prev[$in_same_term]) ) {
|
1160 |
+
return $this->_prev[$in_same_term];
|
1161 |
+
}
|
1162 |
+
global $post;
|
1163 |
+
$old_global = $post;
|
1164 |
+
$post = $this;
|
1165 |
+
$within_taxonomy = ($in_same_term) ? $in_same_term : 'category';
|
1166 |
+
$adjacent = get_adjacent_post(($in_same_term), '', true, $within_taxonomy);
|
1167 |
+
$prev_in_taxonomy = false;
|
1168 |
+
if ( $adjacent ) {
|
1169 |
+
$prev_in_taxonomy = new $this->PostClass($adjacent);
|
1170 |
+
}
|
1171 |
+
$this->_prev[$in_same_term] = $prev_in_taxonomy;
|
1172 |
+
$post = $old_global;
|
1173 |
+
return $this->_prev[$in_same_term];
|
1174 |
}
|
1175 |
|
1176 |
/**
|
1177 |
+
* Gets the tags on a post, uses WP's post_tag taxonomy
|
1178 |
* @api
|
1179 |
+
* @return array
|
|
|
1180 |
*/
|
1181 |
+
public function tags() {
|
1182 |
+
return $this->get_tags();
|
1183 |
}
|
1184 |
|
1185 |
/**
|
1186 |
+
* get the featured image as a TimberImage
|
|
|
1187 |
* @api
|
1188 |
* @example
|
1189 |
* ```twig
|
1190 |
+
* <img src="{{post.thumbnail.src}}" />
|
|
|
|
|
|
|
|
|
|
|
1191 |
* ```
|
1192 |
+
* @return TimberImage|null of your thumbnail
|
|
|
|
|
1193 |
*/
|
1194 |
+
public function thumbnail() {
|
1195 |
+
if ( function_exists('get_post_thumbnail_id') ) {
|
1196 |
+
$tid = get_post_thumbnail_id($this->ID);
|
1197 |
+
if ( $tid ) {
|
1198 |
+
//return new Image($tid);
|
1199 |
+
return new $this->ImageClass($tid);
|
1200 |
+
}
|
1201 |
+
}
|
1202 |
}
|
1203 |
|
1204 |
/**
|
1205 |
+
* 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.
|
1206 |
* @api
|
|
|
|
|
|
|
|
|
|
|
1207 |
* @example
|
1208 |
* ```twig
|
1209 |
+
* <h1>{{ post.title }}</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1210 |
* ```
|
1211 |
+
* @return string
|
1212 |
+
*/
|
1213 |
+
public function title() {
|
1214 |
+
return apply_filters('the_title', $this->post_title, $this->ID);
|
1215 |
+
}
|
1216 |
+
|
1217 |
+
/**
|
1218 |
+
*
|
1219 |
+
* ===================================
|
1220 |
+
* DEPRECATED FUNCTIONS LIVE DOWN HERE
|
1221 |
+
* ===================================
|
1222 |
+
*
|
1223 |
+
*/
|
1224 |
+
|
1225 |
+
/**
|
1226 |
+
* Get the categories for a post
|
1227 |
+
* @internal
|
1228 |
+
* @deprecated since 1.0
|
1229 |
+
* @codeCoverageIgnore
|
1230 |
+
* @see Timber\Post::categories
|
1231 |
+
* @return array of TimberTerms
|
1232 |
*/
|
1233 |
+
function get_categories() {
|
1234 |
+
return $this->get_terms('category');
|
1235 |
}
|
1236 |
|
1237 |
/**
|
1238 |
+
* @internal
|
1239 |
+
* @deprecated since 1.0
|
1240 |
+
* @codeCoverageIgnore
|
1241 |
+
* @see Timber\Post::category
|
1242 |
+
* @return mixed
|
|
|
|
|
|
|
|
|
|
|
|
|
1243 |
*/
|
1244 |
+
function get_category( ) {
|
1245 |
+
$cats = $this->get_categories();
|
1246 |
+
if ( count($cats) && isset($cats[0]) ) {
|
1247 |
+
return $cats[0];
|
1248 |
+
}
|
1249 |
}
|
1250 |
|
1251 |
/**
|
1252 |
+
* @param string $field
|
1253 |
+
* @return TimberImage
|
1254 |
*/
|
1255 |
+
function get_image( $field ) {
|
1256 |
+
return new $this->ImageClass($this->$field);
|
1257 |
}
|
1258 |
|
1259 |
/**
|
1260 |
+
* Gets an array of tags for you to use
|
1261 |
+
* @internal
|
1262 |
+
* @deprecated since 1.0
|
1263 |
+
* @codeCoverageIgnore
|
1264 |
* @example
|
1265 |
* ```twig
|
1266 |
+
* <ul class="tags">
|
1267 |
+
* {% for tag in post.tags %}
|
1268 |
+
* <li>{{tag.name}}</li>
|
1269 |
+
* {% endfor %}
|
1270 |
+
* </ul>
|
|
|
|
|
|
|
|
|
1271 |
* ```
|
1272 |
+
* @return array
|
|
|
1273 |
*/
|
1274 |
+
function get_tags() {
|
1275 |
+
return $this->get_terms('post_tag');
|
1276 |
}
|
1277 |
|
1278 |
/**
|
1279 |
+
* Outputs the title with filters applied
|
1280 |
+
* @internal
|
1281 |
+
* @deprecated since 1.0
|
1282 |
+
* @codeCoverageIgnore
|
1283 |
* @example
|
1284 |
* ```twig
|
1285 |
+
* <h1>{{post.get_title}}</h1>
|
|
|
|
|
1286 |
* ```
|
|
|
1287 |
* ```html
|
1288 |
+
* <h1>Hello World!</h1>
|
|
|
|
|
1289 |
* ```
|
|
|
1290 |
* @return string
|
1291 |
*/
|
1292 |
+
function get_title() {
|
1293 |
+
return $this->title();
|
|
|
|
|
1294 |
}
|
1295 |
|
1296 |
+
/**
|
1297 |
+
* Displays the content of the post with filters, shortcodes and wpautop applied
|
1298 |
+
* @example
|
1299 |
+
* ```twig
|
1300 |
+
* <div class="article-text">{{post.get_content}}</div>
|
1301 |
+
* ```
|
1302 |
+
* ```html
|
1303 |
+
* <div class="article-text"><p>Blah blah blah</p><p>More blah blah blah.</p></div>
|
1304 |
+
* ```
|
1305 |
+
* @param int $len
|
1306 |
+
* @param int $page
|
1307 |
+
* @return string
|
1308 |
+
*/
|
1309 |
+
function get_content( $len = -1, $page = 0 ) {
|
1310 |
+
if ( $len === 0 ) {
|
1311 |
+
$len = -1;
|
1312 |
+
}
|
1313 |
+
return $this->content($page, $len);
|
1314 |
}
|
1315 |
|
1316 |
/**
|
1317 |
+
* @internal
|
1318 |
+
* @deprecated since 1.0
|
1319 |
* @return mixed
|
1320 |
*/
|
1321 |
+
function get_format() {
|
1322 |
+
return $this->format();
|
1323 |
}
|
1324 |
|
1325 |
/**
|
1326 |
+
* Get the terms associated with the post
|
1327 |
+
* This goes across all taxonomies by default
|
1328 |
+
* @internal
|
1329 |
+
* @deprecated since 1.0
|
1330 |
+
* @codeCoverageIgnore
|
1331 |
+
* @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.
|
1332 |
+
* @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)?
|
1333 |
+
* @return array
|
1334 |
*/
|
1335 |
+
public function get_terms( $tax = '', $merge = true ) {
|
1336 |
+
return $this->terms($tax, $merge);
|
1337 |
}
|
1338 |
|
1339 |
/**
|
1340 |
+
* @deprecated 0.20.0 use link() instead
|
1341 |
+
* @codeCoverageIgnore
|
1342 |
+
* @return string
|
1343 |
*/
|
1344 |
+
public function permalink() {
|
1345 |
+
Helper::warn('post.permalink has been removed, please use post.link');
|
1346 |
+
return $this->link();
|
1347 |
+
}
|
1348 |
+
|
1349 |
+
/**
|
1350 |
+
* @internal
|
1351 |
+
* @see Timber\Post::date
|
1352 |
+
* @deprecated since 1.0
|
1353 |
+
* @codeCoverageIgnore
|
1354 |
+
* @param string $date_format
|
1355 |
+
* @return string
|
1356 |
+
*/
|
1357 |
+
function get_date( $date_format = '' ) {
|
1358 |
+
return $this->date($date_format);
|
1359 |
}
|
1360 |
|
1361 |
/**
|
1362 |
+
* @internal
|
1363 |
+
* @see Timber\Post::modified_date
|
1364 |
+
* @deprecated since 1.0
|
1365 |
+
* @codeCoverageIgnore
|
1366 |
+
* @param string $date_format
|
1367 |
* @return string
|
1368 |
*/
|
1369 |
+
function get_modified_date( $date_format = '' ) {
|
1370 |
+
return $this->modified_date($date_format);
|
1371 |
}
|
1372 |
|
1373 |
/**
|
1374 |
+
* @internal
|
1375 |
+
* @param string $time_format
|
1376 |
* @return string
|
1377 |
*/
|
1378 |
+
function get_modified_time( $time_format = '' ) {
|
1379 |
+
$tf = $time_format ? $time_format : get_option('time_format');
|
1380 |
+
$the_time = get_post_modified_time($tf, false, $this->ID, true);
|
1381 |
+
return apply_filters('get_the_modified_time', $the_time, $time_format);
|
1382 |
}
|
1383 |
|
1384 |
/**
|
1385 |
+
* @internal
|
1386 |
+
* @see Timber\Post::children
|
1387 |
+
* @deprecated since 1.0
|
1388 |
+
* @codeCoverageIgnore
|
1389 |
+
* @param string $post_type
|
1390 |
+
* @param bool|string $childPostClass
|
1391 |
+
* @return array
|
1392 |
*/
|
1393 |
+
function get_children( $post_type = 'any', $childPostClass = false ) {
|
1394 |
+
return $this->children($post_type, $childPostClass);
|
1395 |
+
}
|
1396 |
+
|
1397 |
+
/**
|
1398 |
+
* Get the permalink for a post, but as a relative path
|
1399 |
+
* For example, where {{post.link}} would return "http://example.org/2015/07/04/my-cool-post"
|
1400 |
+
* this will return the relative version: "/2015/07/04/my-cool-post"
|
1401 |
+
* @internal
|
1402 |
+
* @deprecated since 1.0
|
1403 |
+
* @codeCoverageIgnore
|
1404 |
+
* @return string
|
1405 |
+
*/
|
1406 |
+
function get_path() {
|
1407 |
+
return $this->path();
|
1408 |
}
|
1409 |
|
1410 |
/**
|
1411 |
+
* Get the next post in WordPress's ordering
|
1412 |
+
* @internal
|
1413 |
+
* @deprecated since 1.0
|
1414 |
+
* @codeCoverageIgnore
|
1415 |
+
* @param bool $taxonomy
|
1416 |
+
* @return TimberPost|boolean
|
1417 |
*/
|
1418 |
+
function get_prev( $in_same_term = false ) {
|
1419 |
+
return $this->prev($in_same_term);
|
1420 |
}
|
1421 |
|
1422 |
/**
|
1423 |
+
* Get the parent post of the post
|
1424 |
+
* @internal
|
1425 |
+
* @deprecated since 1.0
|
1426 |
+
* @codeCoverageIgnore
|
1427 |
+
* @return bool|TimberPost
|
1428 |
*/
|
1429 |
+
function get_parent() {
|
1430 |
+
return $this->parent();
|
1431 |
}
|
1432 |
|
1433 |
/**
|
1434 |
+
* Gets a User object from the author of the post
|
1435 |
+
* @internal
|
1436 |
+
* @deprecated since 1.0
|
1437 |
+
* @codeCoverageIgnore
|
1438 |
+
* @see TimberPost::author
|
1439 |
+
* @return bool|TimberUser
|
|
|
1440 |
*/
|
1441 |
+
function get_author() {
|
1442 |
+
if ( isset($this->post_author) ) {
|
1443 |
+
return new User($this->post_author);
|
1444 |
+
}
|
1445 |
}
|
1446 |
|
1447 |
/**
|
1448 |
+
* @internal
|
1449 |
+
* @deprecated since 1.0
|
1450 |
+
* @codeCoverageIgnore
|
1451 |
+
* @return bool|TimberUser
|
|
|
|
|
|
|
|
|
1452 |
*/
|
1453 |
+
function get_modified_author() {
|
1454 |
+
return $this->modified_author();
|
1455 |
+
}
|
1456 |
+
|
1457 |
+
/**
|
1458 |
+
* @internal
|
1459 |
+
* @see TimberPost::thumbnail
|
1460 |
+
* @deprecated since 1.0
|
1461 |
+
* @codeCoverageIgnore
|
1462 |
+
* @return null|TimberImage
|
1463 |
+
*/
|
1464 |
+
function get_thumbnail() {
|
1465 |
+
return $this->thumbnail();
|
1466 |
}
|
1467 |
|
1468 |
/**
|
1469 |
+
* @internal
|
1470 |
+
* @see TimberPost::link
|
1471 |
+
* @deprecated since 1.0
|
1472 |
+
* @codeCoverageIgnore
|
1473 |
* @return string
|
1474 |
*/
|
1475 |
+
function get_permalink() {
|
1476 |
+
return $this->link();
|
1477 |
}
|
1478 |
|
1479 |
/**
|
1480 |
+
* get the permalink for a post object
|
1481 |
+
* In your templates you should use link:
|
1482 |
+
* <a href="{{post.link}}">Read my post</a>
|
1483 |
+
* @internal
|
1484 |
+
* @deprecated since 1.0
|
1485 |
+
* @codeCoverageIgnore
|
1486 |
+
* @return string
|
|
|
|
|
|
|
1487 |
*/
|
1488 |
+
function get_link() {
|
1489 |
+
return $this->get_permalink();
|
1490 |
}
|
1491 |
|
1492 |
/**
|
1493 |
+
* Get the next post in WordPress's ordering
|
1494 |
+
* @internal
|
1495 |
+
* @deprecated since 1.0
|
1496 |
+
* @codeCoverageIgnore
|
1497 |
+
* @param bool $taxonomy
|
1498 |
+
* @return TimberPost|boolean
|
1499 |
*/
|
1500 |
+
function get_next( $taxonomy = false ) {
|
1501 |
+
return $this->next($taxonomy);
|
1502 |
}
|
1503 |
|
1504 |
/**
|
1505 |
+
* Get a data array of pagination so you can navigate to the previous/next for a paginated post
|
1506 |
+
* @internal
|
1507 |
+
* @see Timber\Post::pagination();
|
1508 |
+
* @deprecated since 1.0
|
1509 |
+
* @codeCoverageIgnore
|
1510 |
* @return array
|
1511 |
*/
|
1512 |
+
public function get_pagination() {
|
1513 |
+
return $this->pagination();
|
1514 |
}
|
1515 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1516 |
|
1517 |
/**
|
1518 |
+
* Get the comments for a post
|
1519 |
+
* @internal
|
1520 |
+
* @see Timber\Post::comments
|
1521 |
+
* @param int $count
|
1522 |
+
* @param string $order
|
1523 |
+
* @param string $type
|
1524 |
+
* @param string $status
|
1525 |
+
* @param string $CommentClass
|
1526 |
+
* @return array|mixed
|
1527 |
*/
|
1528 |
+
function get_comments( $count = 0, $order = 'wp', $type = 'comment', $status = 'approve', $CommentClass = 'TimberComment' ) {
|
1529 |
+
return $this->comments($count, $order, $type, $status, $CommentClass);
|
1530 |
}
|
1531 |
|
1532 |
}
|
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 = 'TimberPost' ) {
|
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 = 'TimberPost', $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 = 'TimberPost' ) {
|
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 = 'TimberPost' ) {
|
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 ( class_exists($type) && is_subclass_of($type, 'TimberPost') ) {
|
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/Request.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
16 |
+
/**
|
17 |
+
* Constructs a TimberRequest object
|
18 |
+
* @example
|
19 |
+
*/
|
20 |
+
function __construct() {
|
21 |
+
$this->init();
|
22 |
+
}
|
23 |
+
/**
|
24 |
+
* @internal
|
25 |
+
*/
|
26 |
+
protected function init() {
|
27 |
+
$this->post = $_POST;
|
28 |
+
$this->get = $_GET;
|
29 |
+
}
|
30 |
+
|
31 |
+
public function __call( $field, $args ) {}
|
32 |
+
|
33 |
+
public function __get( $field ) {}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return boolean
|
37 |
+
*/
|
38 |
+
public function __isset( $field ) {}
|
39 |
+
|
40 |
+
public function meta( $key ) {}
|
41 |
+
}
|
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 |
/**
|
@@ -88,7 +96,7 @@ class TimberSite extends TimberCore implements TimberCoreInterface {
|
|
88 |
public $rss;
|
89 |
public $rss2;
|
90 |
public $atom;
|
91 |
-
|
92 |
/**
|
93 |
* Constructs a TimberSite object
|
94 |
* @example
|
@@ -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 |
/**
|
96 |
public $rss;
|
97 |
public $rss2;
|
98 |
public $atom;
|
99 |
+
|
100 |
/**
|
101 |
* Constructs a TimberSite object
|
102 |
* @example
|
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,15 @@
|
|
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 +41,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 +66,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 +104,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 +125,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 +142,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 +165,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 +217,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 +228,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 +253,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 +267,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 +302,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 +317,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 +339,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 +355,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 +380,10 @@ class TimberTerm extends TimberCore implements TimberCoreInterface {
|
|
378 |
* @return string
|
379 |
*/
|
380 |
public function path() {
|
381 |
-
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
/**
|
@@ -408,22 +413,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\Term;
|
10 |
+
use Timber\Helper;
|
11 |
+
use Timber\URLHelper;
|
12 |
+
|
13 |
/**
|
14 |
* 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
|
15 |
* @example
|
41 |
* </ul>
|
42 |
* ```
|
43 |
*/
|
44 |
+
class Term extends Core implements CoreInterface {
|
45 |
|
46 |
+
public $PostClass = 'Timber\Post';
|
47 |
+
public $TermClass = 'Term';
|
48 |
|
49 |
public $object_type = 'term';
|
50 |
public static $representation = 'term';
|
66 |
* @param string $tax
|
67 |
*/
|
68 |
public function __construct( $tid = null, $tax = '' ) {
|
69 |
+
if ( $tid === null ) {
|
70 |
$tid = $this->get_term_from_query();
|
71 |
}
|
72 |
+
if ( strlen($tax) ) {
|
73 |
$this->taxonomy = $tax;
|
74 |
}
|
75 |
$this->init($tid);
|
104 |
global $wp_query;
|
105 |
if ( isset($wp_query->queried_object) ) {
|
106 |
$qo = $wp_query->queried_object;
|
107 |
+
if ( isset($qo->term_id) ) {
|
108 |
return $qo->term_id;
|
109 |
}
|
110 |
}
|
125 |
$term->ID = $term->term_id;
|
126 |
} else if ( is_string($tid) ) {
|
127 |
//echo 'bad call using '.$tid;
|
128 |
+
//Helper::error_log(debug_backtrace());
|
129 |
}
|
130 |
+
if ( isset($term->ID) ) {
|
131 |
$term->id = $term->ID;
|
132 |
$this->import($term);
|
133 |
if ( isset($term->term_id) ) {
|
142 |
* @param int $tid
|
143 |
* @return array
|
144 |
*/
|
145 |
+
protected function get_term_meta( $tid ) {
|
146 |
$customs = array();
|
147 |
$customs = apply_filters('timber_term_get_meta', $customs, $tid, $this);
|
148 |
return apply_filters('timber/term/meta', $customs, $tid, $this);
|
165 |
global $wpdb;
|
166 |
$query = $wpdb->prepare("SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d LIMIT 1", $tid);
|
167 |
$tax = $wpdb->get_var($query);
|
168 |
+
if ( isset($tax) && strlen($tax) ) {
|
169 |
$this->taxonomy = $tax;
|
170 |
return get_term($tid, $tax);
|
171 |
}
|
217 |
* @return string
|
218 |
*/
|
219 |
public function get_meta_field( $field_name ) {
|
220 |
+
if ( !isset($this->$field_name) ) {
|
221 |
$field_value = '';
|
222 |
$field_value = apply_filters('timber_term_get_meta_field', $field_value, $this->ID, $field_name, $this);
|
223 |
$field_value = apply_filters('timber/term/meta/field', $field_value, $this->ID, $field_name, $this);
|
228 |
|
229 |
/**
|
230 |
* @internal
|
231 |
+
* @deprecated since 1.0
|
232 |
* @return string
|
233 |
*/
|
234 |
public function get_path() {
|
235 |
+
return $this->path();
|
|
|
|
|
|
|
236 |
}
|
237 |
|
238 |
/**
|
239 |
* @internal
|
240 |
+
* @deprecated since 1.0
|
241 |
* @return string
|
242 |
*/
|
243 |
public function get_link() {
|
244 |
+
return $this->link();
|
|
|
|
|
245 |
}
|
246 |
|
247 |
/**
|
253 |
* @return array|bool|null
|
254 |
*/
|
255 |
public function get_posts( $numberposts = 10, $post_type = 'any', $PostClass = '' ) {
|
256 |
+
if ( !strlen($PostClass) ) {
|
257 |
$PostClass = $this->PostClass;
|
258 |
}
|
259 |
$default_tax_query = array(array(
|
267 |
parse_str($args, $new_args);
|
268 |
$args = $new_args;
|
269 |
$args['tax_query'] = $default_tax_query;
|
270 |
+
if ( !isset($args['post_type']) ) {
|
271 |
$args['post_type'] = 'any';
|
272 |
}
|
273 |
+
if ( class_exists($post_type) ) {
|
274 |
$PostClass = $post_type;
|
275 |
}
|
276 |
} else if ( is_array($numberposts) ) {
|
302 |
public function get_children() {
|
303 |
if ( !isset($this->_children) ) {
|
304 |
$children = get_term_children($this->ID, $this->taxonomy);
|
305 |
+
foreach ( $children as &$child ) {
|
306 |
+
$child = new Term($child);
|
307 |
}
|
308 |
$this->_children = $children;
|
309 |
}
|
317 |
* @param mixed $value
|
318 |
*/
|
319 |
function update( $key, $value ) {
|
320 |
+
$value = apply_filters('timber_term_set_meta', $value, $key, $this->ID, $this);
|
321 |
$this->$key = $value;
|
322 |
}
|
323 |
|
339 |
public function description() {
|
340 |
$prefix = '<p>';
|
341 |
$suffix = '</p>';
|
342 |
+
$desc = term_description($this->ID, $this->taxonomy);
|
343 |
+
if ( substr($desc, 0, strlen($prefix)) == $prefix ) {
|
344 |
$desc = substr($desc, strlen($prefix));
|
345 |
}
|
346 |
+
$desc = preg_replace('/'.preg_quote('</p>', '/').'$/', '', $desc);
|
347 |
return trim($desc);
|
348 |
}
|
349 |
|
355 |
return $this->get_edit_url();
|
356 |
}
|
357 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
|
359 |
/**
|
360 |
* @api
|
361 |
* @return string
|
362 |
*/
|
363 |
public function link() {
|
364 |
+
$link = get_term_link($this);
|
365 |
+
$link = apply_filters('timber_term_link', $link, $this);
|
366 |
+
return apply_filters('timber/term/link', $link, $this);
|
367 |
}
|
368 |
|
369 |
/**
|
380 |
* @return string
|
381 |
*/
|
382 |
public function path() {
|
383 |
+
$link = $this->get_link();
|
384 |
+
$rel = URLHelper::get_rel_url($link, true);
|
385 |
+
$rel = apply_filters('timber_term_path', $rel, $this);
|
386 |
+
return apply_filters('timber/term/path', $rel, $this);
|
387 |
}
|
388 |
|
389 |
/**
|
413 |
public function title() {
|
414 |
return $this->name;
|
415 |
}
|
416 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,486 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
*
|
21 |
+
* Main class called Timber for this plugin.
|
22 |
+
*
|
23 |
+
* Usage:
|
24 |
+
* $posts = Timber::get_posts();
|
25 |
+
* $posts = Timber::get_posts('post_type = article')
|
26 |
+
* $posts = Timber::get_posts(array('post_type' => 'article', 'category_name' => 'sports')); // uses wp_query format.
|
27 |
+
* $posts = Timber::get_posts(array(23,24,35,67), 'InkwellArticle');
|
28 |
+
*
|
29 |
+
* $context = Timber::get_context(); // returns wp favorites!
|
30 |
+
* $context['posts'] = $posts;
|
31 |
+
* Timber::render('index.twig', $context);
|
32 |
+
*/
|
33 |
+
class Timber {
|
34 |
+
|
35 |
+
public static $locations;
|
36 |
+
public static $dirname;
|
37 |
+
public static $twig_cache = false;
|
38 |
+
public static $cache = false;
|
39 |
+
public static $auto_meta = true;
|
40 |
+
public static $autoescape = false;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @codeCoverageIgnore
|
44 |
+
*/
|
45 |
+
public function __construct() {
|
46 |
+
if ( !defined('ABSPATH') ) {
|
47 |
+
return;
|
48 |
+
}
|
49 |
+
$this->test_compatibility();
|
50 |
+
$this->backwards_compatibility();
|
51 |
+
$this->init_constants();
|
52 |
+
$this->init();
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Tests whether we can use Timber
|
57 |
+
* @codeCoverageIgnore
|
58 |
+
* @return
|
59 |
+
*/
|
60 |
+
protected function test_compatibility() {
|
61 |
+
if ( is_admin() || $_SERVER['PHP_SELF'] == '/wp-login.php' ) {
|
62 |
+
return;
|
63 |
+
}
|
64 |
+
if ( version_compare(phpversion(), '5.3.0', '<') && !is_admin() ) {
|
65 |
+
trigger_error('Timber requires PHP 5.3.0 or greater. You have '.phpversion(), E_USER_ERROR);
|
66 |
+
}
|
67 |
+
if ( !class_exists('Twig_Autoloader') ) {
|
68 |
+
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);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
private function backwards_compatibility() {
|
73 |
+
if ( class_exists('TimberArchives') ) {
|
74 |
+
//already run, so bail
|
75 |
+
return;
|
76 |
+
}
|
77 |
+
$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');
|
78 |
+
class_alias(get_class($this), 'Timber');
|
79 |
+
foreach ( $names as $name ) {
|
80 |
+
class_alias('Timber\\'.$name, 'Timber'.$name);
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
function init_constants() {
|
85 |
+
defined("TIMBER_LOC") or define("TIMBER_LOC", realpath(dirname(__DIR__)));
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @codeCoverageIgnore
|
90 |
+
*/
|
91 |
+
protected function init() {
|
92 |
+
Twig::init();
|
93 |
+
ImageHelper::init();
|
94 |
+
Admin::init();
|
95 |
+
Integrations::init();
|
96 |
+
}
|
97 |
+
|
98 |
+
/* Post Retrieval Routine
|
99 |
+
================================ */
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Get post.
|
103 |
+
*
|
104 |
+
* @param mixed $query
|
105 |
+
* @param string $PostClass
|
106 |
+
* @return array|bool|null
|
107 |
+
*/
|
108 |
+
public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
|
109 |
+
return PostGetter::get_post($query, $PostClass);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Get posts.
|
114 |
+
* @example
|
115 |
+
* ```php
|
116 |
+
* $posts = Timber::get_posts();
|
117 |
+
* $posts = Timber::get_posts('post_type = article')
|
118 |
+
* $posts = Timber::get_posts(array('post_type' => 'article', 'category_name' => 'sports')); // uses wp_query format.
|
119 |
+
* $posts = Timber::get_posts('post_type=any', array('portfolio' => 'MyPortfolioClass', 'alert' => 'MyAlertClass')); //use a classmap for the $PostClass
|
120 |
+
* ```
|
121 |
+
* @param mixed $query
|
122 |
+
* @param string|array $PostClass
|
123 |
+
* @return array|bool|null
|
124 |
+
*/
|
125 |
+
public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
|
126 |
+
return PostGetter::get_posts($query, $PostClass, $return_collection);
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Query post.
|
131 |
+
*
|
132 |
+
* @param mixed $query
|
133 |
+
* @param string $PostClass
|
134 |
+
* @return array|bool|null
|
135 |
+
*/
|
136 |
+
public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
137 |
+
return PostGetter::query_post($query, $PostClass);
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Query posts.
|
142 |
+
*
|
143 |
+
* @param mixed $query
|
144 |
+
* @param string $PostClass
|
145 |
+
* @return array|bool|null
|
146 |
+
*/
|
147 |
+
public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
|
148 |
+
return PostGetter::query_posts($query, $PostClass);
|
149 |
+
}
|
150 |
+
|
151 |
+
/* Term Retrieval
|
152 |
+
================================ */
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Get terms.
|
156 |
+
*
|
157 |
+
* @param string|array $args
|
158 |
+
* @param array $maybe_args
|
159 |
+
* @param string $TermClass
|
160 |
+
* @return mixed
|
161 |
+
*/
|
162 |
+
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
|
163 |
+
return TermGetter::get_terms($args, $maybe_args, $TermClass);
|
164 |
+
}
|
165 |
+
|
166 |
+
/* Site Retrieval
|
167 |
+
================================ */
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Get sites.
|
171 |
+
*
|
172 |
+
* @param array|bool $blog_ids
|
173 |
+
* @return array
|
174 |
+
*/
|
175 |
+
public static function get_sites( $blog_ids = false ) {
|
176 |
+
if ( !is_array($blog_ids) ) {
|
177 |
+
global $wpdb;
|
178 |
+
$blog_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id ASC");
|
179 |
+
}
|
180 |
+
$return = array();
|
181 |
+
foreach ( $blog_ids as $blog_id ) {
|
182 |
+
$return[] = new Site($blog_id);
|
183 |
+
}
|
184 |
+
return $return;
|
185 |
+
}
|
186 |
+
|
187 |
+
|
188 |
+
/* Template Setup and Display
|
189 |
+
================================ */
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Get context.
|
193 |
+
*
|
194 |
+
* @return array
|
195 |
+
*/
|
196 |
+
public static function get_context() {
|
197 |
+
$data = array();
|
198 |
+
$data['http_host'] = 'http://'.URLHelper::get_host();
|
199 |
+
$data['wp_title'] = Helper::get_wp_title();
|
200 |
+
$data['wp_head'] = Helper::function_wrapper('wp_head');
|
201 |
+
$data['wp_footer'] = Helper::function_wrapper('wp_footer');
|
202 |
+
$data['body_class'] = implode(' ', get_body_class());
|
203 |
+
|
204 |
+
$data['site'] = new Site();
|
205 |
+
$data['request'] = new Request();
|
206 |
+
$user = new User();
|
207 |
+
$data['user'] = ($user->ID) ? $user : false;
|
208 |
+
$data['theme'] = $data['site']->theme;
|
209 |
+
|
210 |
+
$data['posts'] = Timber::query_posts();
|
211 |
+
|
212 |
+
$data = apply_filters('timber_context', $data);
|
213 |
+
$data = apply_filters('timber/context', $data);
|
214 |
+
return $data;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Compile function.
|
219 |
+
*
|
220 |
+
* @param array $filenames
|
221 |
+
* @param array $data
|
222 |
+
* @param bool $expires
|
223 |
+
* @param string $cache_mode
|
224 |
+
* @param bool $via_render
|
225 |
+
* @return bool|string
|
226 |
+
*/
|
227 |
+
public static function compile( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT, $via_render = false ) {
|
228 |
+
$caller = self::get_calling_script_dir();
|
229 |
+
$caller_file = self::get_calling_script_file();
|
230 |
+
$caller_file = apply_filters('timber_calling_php_file', $caller_file);
|
231 |
+
$loader = new Loader($caller);
|
232 |
+
$file = $loader->choose_template($filenames);
|
233 |
+
$output = '';
|
234 |
+
if ( is_null($data) ) {
|
235 |
+
$data = array();
|
236 |
+
}
|
237 |
+
if ( strlen($file) ) {
|
238 |
+
if ( $via_render ) {
|
239 |
+
$file = apply_filters('timber_render_file', $file);
|
240 |
+
$data = apply_filters('timber_render_data', $data);
|
241 |
+
} else {
|
242 |
+
$file = apply_filters('timber_compile_file', $file);
|
243 |
+
$data = apply_filters('timber_compile_data', $data);
|
244 |
+
}
|
245 |
+
$output = $loader->render($file, $data, $expires, $cache_mode);
|
246 |
+
}
|
247 |
+
do_action('timber_compile_done');
|
248 |
+
return $output;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Compile string.
|
253 |
+
*
|
254 |
+
* @param string $string a string with twig variables.
|
255 |
+
* @param array $data an array with data in it.
|
256 |
+
* @return bool|string
|
257 |
+
*/
|
258 |
+
public static function compile_string( $string, $data = array() ) {
|
259 |
+
$dummy_loader = new Loader();
|
260 |
+
$twig = $dummy_loader->get_twig();
|
261 |
+
$template = $twig->createTemplate($string);
|
262 |
+
return $template->render($data);
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Fetch function.
|
267 |
+
*
|
268 |
+
* @param array $filenames
|
269 |
+
* @param array $data
|
270 |
+
* @param bool $expires
|
271 |
+
* @param string $cache_mode
|
272 |
+
* @return bool|string
|
273 |
+
*/
|
274 |
+
public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
|
275 |
+
if ( $expires === true ) {
|
276 |
+
//if this is reading as true; the user probably is using the old $echo param
|
277 |
+
//so we should move all vars up by a spot
|
278 |
+
$expires = $cache_mode;
|
279 |
+
$cache_mode = Loader::CACHE_USE_DEFAULT;
|
280 |
+
}
|
281 |
+
$output = self::compile($filenames, $data, $expires, $cache_mode, true);
|
282 |
+
$output = apply_filters('timber_compile_result', $output);
|
283 |
+
return $output;
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Render function.
|
288 |
+
*
|
289 |
+
* @param array $filenames
|
290 |
+
* @param array $data
|
291 |
+
* @param bool $expires
|
292 |
+
* @param string $cache_mode
|
293 |
+
* @return bool|string
|
294 |
+
*/
|
295 |
+
public static function render( $filenames, $data = array(), $expires = false, $cache_mode = Loader::CACHE_USE_DEFAULT ) {
|
296 |
+
$output = self::fetch($filenames, $data, $expires, $cache_mode);
|
297 |
+
echo $output;
|
298 |
+
return $output;
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Render string.
|
303 |
+
*
|
304 |
+
* @param string $string a string with twig variables.
|
305 |
+
* @param array $data an array with data in it.
|
306 |
+
* @return bool|string
|
307 |
+
*/
|
308 |
+
public static function render_string( $string, $data = array() ) {
|
309 |
+
$compiled = self::compile_string($string, $data);
|
310 |
+
echo $compiled;
|
311 |
+
return $compiled;
|
312 |
+
}
|
313 |
+
|
314 |
+
|
315 |
+
/* Sidebar
|
316 |
+
================================ */
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Get sidebar.
|
320 |
+
*
|
321 |
+
* @param string $sidebar
|
322 |
+
* @param array $data
|
323 |
+
* @return bool|string
|
324 |
+
*/
|
325 |
+
public static function get_sidebar( $sidebar = '', $data = array() ) {
|
326 |
+
if ( $sidebar == '' ) {
|
327 |
+
$sidebar = 'sidebar.php';
|
328 |
+
}
|
329 |
+
if ( strstr(strtolower($sidebar), '.php') ) {
|
330 |
+
return self::get_sidebar_from_php($sidebar, $data);
|
331 |
+
}
|
332 |
+
return self::compile($sidebar, $data);
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Get sidebar from PHP
|
337 |
+
*
|
338 |
+
* @param string $sidebar
|
339 |
+
* @param array $data
|
340 |
+
* @return string
|
341 |
+
*/
|
342 |
+
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
343 |
+
$caller = self::get_calling_script_dir();
|
344 |
+
$loader = new Loader();
|
345 |
+
$uris = $loader->get_locations($caller);
|
346 |
+
ob_start();
|
347 |
+
$found = false;
|
348 |
+
foreach ( $uris as $uri ) {
|
349 |
+
if ( file_exists(trailingslashit($uri).$sidebar) ) {
|
350 |
+
include trailingslashit($uri).$sidebar;
|
351 |
+
$found = true;
|
352 |
+
break;
|
353 |
+
}
|
354 |
+
}
|
355 |
+
if ( !$found ) {
|
356 |
+
Helper::error_log('error loading your sidebar, check to make sure the file exists');
|
357 |
+
}
|
358 |
+
$ret = ob_get_contents();
|
359 |
+
ob_end_clean();
|
360 |
+
return $ret;
|
361 |
+
}
|
362 |
+
|
363 |
+
/* Widgets
|
364 |
+
================================ */
|
365 |
+
|
366 |
+
/**
|
367 |
+
* Get widgets.
|
368 |
+
*
|
369 |
+
* @param int $widget_id
|
370 |
+
* @return TimberFunctionWrapper
|
371 |
+
*/
|
372 |
+
public static function get_widgets( $widget_id ) {
|
373 |
+
return trim(Helper::function_wrapper('dynamic_sidebar', array($widget_id), true));
|
374 |
+
}
|
375 |
+
|
376 |
+
/* Pagination
|
377 |
+
================================ */
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Get pagination.
|
381 |
+
*
|
382 |
+
* @param array $prefs
|
383 |
+
* @return array mixed
|
384 |
+
*/
|
385 |
+
public static function get_pagination( $prefs = array() ) {
|
386 |
+
global $wp_query;
|
387 |
+
global $paged;
|
388 |
+
global $wp_rewrite;
|
389 |
+
$args = array();
|
390 |
+
$args['total'] = ceil($wp_query->found_posts / $wp_query->query_vars['posts_per_page']);
|
391 |
+
if ( $wp_rewrite->using_permalinks() ) {
|
392 |
+
$url = explode('?', get_pagenum_link(0));
|
393 |
+
if ( isset($url[1]) ) {
|
394 |
+
parse_str($url[1], $query);
|
395 |
+
$args['add_args'] = $query;
|
396 |
+
}
|
397 |
+
$args['format'] = 'page/%#%';
|
398 |
+
$args['base'] = trailingslashit($url[0]).'%_%';
|
399 |
+
} else {
|
400 |
+
$big = 999999999;
|
401 |
+
$args['base'] = str_replace($big, '%#%', esc_url(get_pagenum_link($big)));
|
402 |
+
}
|
403 |
+
$args['type'] = 'array';
|
404 |
+
$args['current'] = max(1, get_query_var('paged'));
|
405 |
+
$args['mid_size'] = max(9 - $args['current'], 3);
|
406 |
+
if ( is_int($prefs) ) {
|
407 |
+
$args['mid_size'] = $prefs - 2;
|
408 |
+
} else {
|
409 |
+
$args = array_merge($args, $prefs);
|
410 |
+
}
|
411 |
+
$data = array();
|
412 |
+
$data['current'] = $args['current'];
|
413 |
+
$data['total'] = $args['total'];
|
414 |
+
$data['pages'] = Helper::paginate_links($args);
|
415 |
+
$next = get_next_posts_page_link($args['total']);
|
416 |
+
if ( $next ) {
|
417 |
+
$data['next'] = array('link' => untrailingslashit($next), 'class' => 'page-numbers next');
|
418 |
+
}
|
419 |
+
$prev = previous_posts(false);
|
420 |
+
if ( $prev ) {
|
421 |
+
$data['prev'] = array('link' => untrailingslashit($prev), 'class' => 'page-numbers prev');
|
422 |
+
}
|
423 |
+
if ( $paged < 2 ) {
|
424 |
+
$data['prev'] = '';
|
425 |
+
}
|
426 |
+
if ( $data['total'] === (double) 0 ) {
|
427 |
+
$data['next'] = '';
|
428 |
+
}
|
429 |
+
return $data;
|
430 |
+
}
|
431 |
+
|
432 |
+
/* Utility
|
433 |
+
================================ */
|
434 |
+
|
435 |
+
/**
|
436 |
+
* Get calling script dir.
|
437 |
+
*
|
438 |
+
* @return string
|
439 |
+
*/
|
440 |
+
public static function get_calling_script_dir( $offset = 0 ) {
|
441 |
+
$caller = self::get_calling_script_file($offset);
|
442 |
+
if ( !is_null($caller) ) {
|
443 |
+
$pathinfo = pathinfo($caller);
|
444 |
+
$dir = $pathinfo['dirname'];
|
445 |
+
return $dir;
|
446 |
+
}
|
447 |
+
}
|
448 |
+
|
449 |
+
|
450 |
+
/**
|
451 |
+
* Add route.
|
452 |
+
*
|
453 |
+
* @param string $route
|
454 |
+
* @param callable $callback
|
455 |
+
* @param array $args
|
456 |
+
* @deprecated since 0.20.0 and will be removed in 1.1
|
457 |
+
*/
|
458 |
+
public static function add_route( $route, $callback, $args = array() ) {
|
459 |
+
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');
|
460 |
+
Routes::map($route, $callback, $args);
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Get calling script file.
|
465 |
+
*
|
466 |
+
* @param int $offset
|
467 |
+
* @return string|null
|
468 |
+
* @deprecated since 0.20.0
|
469 |
+
*/
|
470 |
+
public static function get_calling_script_file( $offset = 0 ) {
|
471 |
+
$caller = null;
|
472 |
+
$backtrace = debug_backtrace();
|
473 |
+
$i = 0;
|
474 |
+
foreach ( $backtrace as $trace ) {
|
475 |
+
if ( array_key_exists('file', $trace) && $trace['file'] != __FILE__ ) {
|
476 |
+
$caller = $trace['file'];
|
477 |
+
break;
|
478 |
+
}
|
479 |
+
$i++;
|
480 |
+
}
|
481 |
+
if ( $offset ) {
|
482 |
+
$caller = $backtrace[$i + $offset]['file'];
|
483 |
+
}
|
484 |
+
return $caller;
|
485 |
+
}
|
486 |
+
}
|
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,12 @@
|
|
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 +24,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';
|
@@ -53,7 +60,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 +91,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 +100,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 +111,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 |
}
|
@@ -137,7 +144,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 +165,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 +200,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 +209,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 +219,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 |
/**
|
11 |
* 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.
|
12 |
* @example
|
24 |
* <p class="article-info">This article is called "Consider the Lobster" and it's by David Foster Wallace
|
25 |
* ```
|
26 |
*/
|
27 |
+
class User extends Core implements CoreInterface {
|
28 |
|
29 |
public $object_type = 'user';
|
30 |
public static $representation = 'user';
|
60 |
/**
|
61 |
* @param int|bool $uid
|
62 |
*/
|
63 |
+
function __construct( $uid = false ) {
|
64 |
$this->init($uid);
|
65 |
}
|
66 |
|
91 |
* @param string $field_name
|
92 |
* @return null
|
93 |
*/
|
94 |
+
function get_meta( $field_name ) {
|
95 |
return $this->get_meta_field($field_name);
|
96 |
}
|
97 |
|
100 |
* @param string $field
|
101 |
* @param mixed $value
|
102 |
*/
|
103 |
+
function __set( $field, $value ) {
|
104 |
if ( $field == 'name' ) {
|
105 |
$this->display_name = $value;
|
106 |
}
|
111 |
* @internal
|
112 |
* @param int|bool $uid The user ID to use
|
113 |
*/
|
114 |
+
protected function init( $uid = false ) {
|
115 |
if ( $uid === false ) {
|
116 |
$uid = get_current_user_id();
|
117 |
}
|
144 |
* @param string $field_name
|
145 |
* @return mixed
|
146 |
*/
|
147 |
+
function get_meta_field( $field_name ) {
|
148 |
$value = null;
|
149 |
$value = apply_filters('timber_user_get_meta_field_pre', $value, $this->ID, $field_name, $this);
|
150 |
if ( $value === null ) {
|
165 |
$um = get_user_meta($this->ID);
|
166 |
}
|
167 |
$custom = array();
|
168 |
+
foreach ( $um as $key => $value ) {
|
169 |
if ( is_array($value) && count($value) == 1 ) {
|
170 |
$value = $value[0];
|
171 |
}
|
200 |
* @param string $field_name
|
201 |
* @return mixed
|
202 |
*/
|
203 |
+
function meta( $field_name ) {
|
204 |
return $this->get_meta_field($field_name);
|
205 |
}
|
206 |
|
209 |
* @return string ex: /author/lincoln
|
210 |
*/
|
211 |
public function path() {
|
212 |
+
return URLHelper::get_rel_url($this->link());
|
213 |
}
|
214 |
|
215 |
/**
|
219 |
public function slug() {
|
220 |
return $this->user_nicename;
|
221 |
}
|
222 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,26 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class TimberAdmin {
|
4 |
-
|
5 |
-
public static function init() {
|
6 |
-
return add_filter( 'plugin_row_meta', array( __CLASS__, 'meta_links' ), 10, 2 );
|
7 |
-
}
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @param array $links
|
11 |
-
* @param string $file
|
12 |
-
* @return array
|
13 |
-
*/
|
14 |
-
public static function meta_links( $links, $file ) {
|
15 |
-
if ( strstr( $file, '/timber.php' ) ) {
|
16 |
-
unset($links[2]);
|
17 |
-
$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>';
|
18 |
-
$links[] = '<a href="http://upstatement.com/timber" target="_blank">Homepage</a>';
|
19 |
-
$links[] = '<a href="https://github.com/jarednova/timber/wiki" target="_blank">Documentation</a>';
|
20 |
-
$links[] = '<a href="https://github.com/jarednova/timber/wiki/getting-started" target="_blank">Starter Guide</a>';
|
21 |
-
return $links;
|
22 |
-
}
|
23 |
-
return $links;
|
24 |
-
}
|
25 |
-
|
26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,77 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class TimberFunctionWrapper {
|
4 |
-
|
5 |
-
private $_function;
|
6 |
-
private $_args;
|
7 |
-
private $_use_ob;
|
8 |
-
|
9 |
-
public function __toString() {
|
10 |
-
return (string)$this->call();
|
11 |
-
}
|
12 |
-
|
13 |
-
/**
|
14 |
-
*
|
15 |
-
*
|
16 |
-
* @param callable $function
|
17 |
-
* @param array $args
|
18 |
-
* @param bool $return_output_buffer
|
19 |
-
*/
|
20 |
-
public function __construct( $function, $args = array(), $return_output_buffer = false ) {
|
21 |
-
$this->_function = $function;
|
22 |
-
$this->_args = $args;
|
23 |
-
$this->_use_ob = $return_output_buffer;
|
24 |
-
|
25 |
-
add_filter( 'get_twig', array( &$this, 'add_to_twig' ) );
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
*
|
30 |
-
*
|
31 |
-
* @param Twig_Environment $twig
|
32 |
-
* @return Twig_Environment
|
33 |
-
*/
|
34 |
-
public function add_to_twig( $twig ) {
|
35 |
-
$wrapper = $this;
|
36 |
-
|
37 |
-
$twig->addFunction( new Twig_SimpleFunction( $this->_function, function () use ( $wrapper ) {
|
38 |
-
return call_user_func_array( array( $wrapper, 'call' ), func_get_args() );
|
39 |
-
} ) );
|
40 |
-
|
41 |
-
return $twig;
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
*
|
46 |
-
*
|
47 |
-
* @return string
|
48 |
-
*/
|
49 |
-
public function call() {
|
50 |
-
$args = $this->_parse_args( func_get_args(), $this->_args );
|
51 |
-
|
52 |
-
if ( $this->_use_ob ) {
|
53 |
-
return TimberHelper::ob_function( $this->_function, $args );
|
54 |
-
} else {
|
55 |
-
return call_user_func_array( $this->_function, $args );
|
56 |
-
}
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
*
|
61 |
-
*
|
62 |
-
* @param array $args
|
63 |
-
* @param array $defaults
|
64 |
-
* @return array
|
65 |
-
*/
|
66 |
-
private function _parse_args( $args, $defaults ) {
|
67 |
-
$_arg = reset( $defaults );
|
68 |
-
|
69 |
-
foreach ( $args as $index => $arg ) {
|
70 |
-
$defaults[$index] = is_null( $arg ) ? $_arg : $arg;
|
71 |
-
$_arg = next( $defaults );
|
72 |
-
}
|
73 |
-
|
74 |
-
return $defaults;
|
75 |
-
}
|
76 |
-
|
77 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/timber-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)) {
|
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();
|
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
@@ -2,8 +2,8 @@
|
|
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.
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -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 |
|
@@ -46,7 +46,7 @@ Timber is great for any WordPress developer who cares about writing good, mainta
|
|
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 +61,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 +228,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 +323,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
|
@@ -441,12 +441,12 @@ That's Timber!
|
|
441 |
|
442 |
== Support ==
|
443 |
|
444 |
-
Please
|
445 |
|
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 +461,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/
|
2 |
Contributors: jarednova, lggorman
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 3.7
|
5 |
+
Stable tag: 1.0.0
|
6 |
+
Tested up to: 4.5.1
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
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 |
|
46 |
* Fixed error in comments_link (thanks @tehlivi)
|
47 |
|
48 |
= 0.22.4 =
|
49 |
+
* Fixed [bug](https://github.com/timber/timber/issues/785) in get_calling_script file (thanks @gwagroves)
|
50 |
* Added tons of new tests and docs (thanks @lggorman and @jarednova)
|
51 |
|
52 |
= 0.22.3 =
|
61 |
* Added support for animated gifs
|
62 |
|
63 |
= 0.22.1 =
|
64 |
+
* Added better support for [post.get_terms](https://github.com/timber/timber/pull/737) (thanks @aaemnnosttv)
|
65 |
* Fix for issue with ACF date field (thanks @rpkoller)
|
66 |
* Fix for resizing jpEgs (thanks @eaton)
|
67 |
|
228 |
* Hotfix on timber-admin error
|
229 |
|
230 |
= 0.17.0 =
|
231 |
+
* Now you can resize/crop images with positional preferences, thanks @mmikkel. Here are the docs: https://github.com/timber/timber/wiki/TimberImage#resize
|
232 |
* Removed the Timber Starter Guide from the admin, a link to the GitHub wiki suffices.
|
233 |
|
234 |
= 0.16.8 =
|
323 |
* New Timber::compile method which _doesn't_ automatically echo. (Same args as Timber::render)
|
324 |
* Added post.get_next / post.get_prev for TimberPosts
|
325 |
* Fixed a thing to make get_preview easier when you want to omit the 'Read More' link
|
326 |
+
* Read the [Full Release Notes](https://github.com/timber/timber/releases/tag/0.15.0)
|
327 |
|
328 |
= 0.14.1 =
|
329 |
* Added hooks to play nicely with Timber Debug Bar
|
441 |
|
442 |
== Support ==
|
443 |
|
444 |
+
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.
|
445 |
|
446 |
== Frequently Asked Questions ==
|
447 |
|
448 |
= Can it be used in an existing theme? =
|
449 |
+
You bet! Watch these **[video tutorials](https://github.com/timber/timber/wiki/Video-Tutorials)** to see how.
|
450 |
|
451 |
= Is it used in production? =
|
452 |
At Upstatement we've now used it on more than a dozen client sites. Hundreds of other sites use it too. You can check some of them out in the **[showcase](http://upstatement.com/timber/#showcase)**.
|
461 |
As stated above, we're using it in dozens of sites (and dozens more planned) -- dozens of other developers are using it too. This isn't going anywhere. Twig is the chosen language for other PHP platforms like Symfony, Drupal 8 and Craft. WordPress will eventually adopt Twig too, I promise you that.
|
462 |
|
463 |
= Support? =
|
464 |
+
Leave a [GitHub issue](https://github.com/timber/timber/issues?state=open) and I'll holler back.
|
timber-starter-theme/README.md
CHANGED
@@ -1,5 +1,35 @@
|
|
1 |
-
# timber-starter-theme
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
The "_s" for Timber: a dead-simple theme that you can build from
|
|
|
1 |
|
2 |
+
# The Timber Starter Theme
|
3 |
+
|
4 |
+
The "_s" for Timber: a dead-simple theme that you can build from. The primary purpose of this theme is to provide a file structure rather than a framework for markup or styles. Configure your Sass, scripts, and task runners however you would like!
|
5 |
+
|
6 |
+
[![Build Status](https://travis-ci.org/timber/starter-theme.svg)](https://travis-ci.org/timber/starter-theme)
|
7 |
+
|
8 |
+
## Installing the Theme
|
9 |
+
|
10 |
+
Install this theme as you would any other, and be sure the Timber plugin is activated. But hey, let's break it down into some bullets:
|
11 |
+
|
12 |
+
1. Make sure you have installed the plugin for the [Timber Library](https://wordpress.org/plugins/timber-library/) (and Advanced Custom Fields - they [play quite nicely](https://github.com/jarednova/timber/wiki/ACF-Cookbook) together).
|
13 |
+
2. Download the zip for this theme (or clone it) and move it to `wp-content/themes` in your WordPress installation.
|
14 |
+
3. Rename the folder to something that makes sense for your website (generally no spaces and all lowercase). You could keep the name `timber-starter-theme` but the point of a starter theme is to make it your own!
|
15 |
+
4. Activate the theme in Appearance > Themes.
|
16 |
+
5. Do your thing! And read [the docs](https://github.com/jarednova/timber/wiki).
|
17 |
+
|
18 |
+
## What's here?
|
19 |
+
|
20 |
+
`static/` is where you can keep your static front-end scripts, styles, or images. In other words, your Sass files, JS files, fonts, and SVGs would live here.
|
21 |
+
|
22 |
+
`templates/` contains all of your Twig templates. These pretty much correspond 1 to 1 with the PHP files that respond to the WordPress template hierarchy. At the end of each PHP template, you'll notice a `Timber::render()` function whose first parameter is the Twig file where that data (or `$context`) will be used. Just an FYI.
|
23 |
+
|
24 |
+
`bin/` and `tests/` ... basically don't worry about (or remove) these unless you know what they are and want to.
|
25 |
+
|
26 |
+
## Other Resources
|
27 |
+
|
28 |
+
The [main Timber Wiki](https://github.com/jarednova/timber/wiki) is super great, so reference those often. Also, check out these articles and projects for more info:
|
29 |
+
|
30 |
+
* [This branch](https://github.com/laras126/timber-starter-theme/tree/tackle-box) of the starter theme has some more example code with ACF and a slightly different set up.
|
31 |
+
* [Twig for Timber Cheatsheet](http://notlaura.com/the-twig-for-timber-cheatsheet/)
|
32 |
+
* [Timber and Twig Reignited My Love for WordPress](https://css-tricks.com/timber-and-twig-reignited-my-love-for-wordpress/) on CSS-Tricks
|
33 |
+
* [A real live Timber theme](https://github.com/laras126/yuling-theme).
|
34 |
+
* [Timber Video Tutorials](https://github.com/jarednova/timber/wiki/Video-Tutorials) and [an incomplete set of screencasts](https://www.youtube.com/playlist?list=PLuIlodXmVQ6pkqWyR6mtQ5gQZ6BrnuFx-) for building a Timber theme from scratch.
|
35 |
|
|
timber-starter-theme/archive.php
CHANGED
@@ -16,25 +16,25 @@
|
|
16 |
|
17 |
$templates = array( 'archive.twig', 'index.twig' );
|
18 |
|
19 |
-
$
|
20 |
|
21 |
-
$
|
22 |
if ( is_day() ) {
|
23 |
-
$
|
24 |
} else if ( is_month() ) {
|
25 |
-
$
|
26 |
} else if ( is_year() ) {
|
27 |
-
$
|
28 |
} else if ( is_tag() ) {
|
29 |
-
$
|
30 |
} else if ( is_category() ) {
|
31 |
-
$
|
32 |
array_unshift( $templates, 'archive-' . get_query_var( 'cat' ) . '.twig' );
|
33 |
} else if ( is_post_type_archive() ) {
|
34 |
-
$
|
35 |
array_unshift( $templates, 'archive-' . get_post_type() . '.twig' );
|
36 |
}
|
37 |
|
38 |
-
$
|
39 |
|
40 |
-
Timber::render( $templates, $
|
16 |
|
17 |
$templates = array( 'archive.twig', 'index.twig' );
|
18 |
|
19 |
+
$context = Timber::get_context();
|
20 |
|
21 |
+
$context['title'] = 'Archive';
|
22 |
if ( is_day() ) {
|
23 |
+
$context['title'] = 'Archive: '.get_the_date( 'D M Y' );
|
24 |
} else if ( is_month() ) {
|
25 |
+
$context['title'] = 'Archive: '.get_the_date( 'M Y' );
|
26 |
} else if ( is_year() ) {
|
27 |
+
$context['title'] = 'Archive: '.get_the_date( 'Y' );
|
28 |
} else if ( is_tag() ) {
|
29 |
+
$context['title'] = single_tag_title( '', false );
|
30 |
} else if ( is_category() ) {
|
31 |
+
$context['title'] = single_cat_title( '', false );
|
32 |
array_unshift( $templates, 'archive-' . get_query_var( 'cat' ) . '.twig' );
|
33 |
} else if ( is_post_type_archive() ) {
|
34 |
+
$context['title'] = post_type_archive_title( '', false );
|
35 |
array_unshift( $templates, 'archive-' . get_post_type() . '.twig' );
|
36 |
}
|
37 |
|
38 |
+
$context['posts'] = Timber::get_posts();
|
39 |
|
40 |
+
Timber::render( $templates, $context );
|
timber-starter-theme/author.php
CHANGED
@@ -10,11 +10,11 @@
|
|
10 |
*/
|
11 |
global $wp_query;
|
12 |
|
13 |
-
$
|
14 |
-
$
|
15 |
if ( isset( $wp_query->query_vars['author'] ) ) {
|
16 |
$author = new TimberUser( $wp_query->query_vars['author'] );
|
17 |
-
$
|
18 |
-
$
|
19 |
}
|
20 |
-
Timber::render( array( 'author.twig', 'archive.twig' ), $
|
10 |
*/
|
11 |
global $wp_query;
|
12 |
|
13 |
+
$context = Timber::get_context();
|
14 |
+
$context['posts'] = Timber::get_posts();
|
15 |
if ( isset( $wp_query->query_vars['author'] ) ) {
|
16 |
$author = new TimberUser( $wp_query->query_vars['author'] );
|
17 |
+
$context['author'] = $author;
|
18 |
+
$context['title'] = 'Author Archives: ' . $author->name();
|
19 |
}
|
20 |
+
Timber::render( array( 'author.twig', 'archive.twig' ), $context );
|
timber-starter-theme/composer.json
CHANGED
@@ -9,6 +9,12 @@
|
|
9 |
"email": "jared@upstatement.com"
|
10 |
}
|
11 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
"extra": {
|
13 |
"installer-paths": {
|
14 |
"../../plugins/{$name}/": [
|
@@ -18,12 +24,6 @@
|
|
18 |
}
|
19 |
},
|
20 |
"require": {
|
21 |
-
"wpackagist-plugin/timber-library": "0.
|
22 |
-
}
|
23 |
-
"repositories": [
|
24 |
-
{
|
25 |
-
"type": "composer",
|
26 |
-
"url": "http://wpackagist.org"
|
27 |
-
}
|
28 |
-
]
|
29 |
}
|
9 |
"email": "jared@upstatement.com"
|
10 |
}
|
11 |
],
|
12 |
+
"repositories": [
|
13 |
+
{
|
14 |
+
"type": "composer",
|
15 |
+
"url": "https://wpackagist.org"
|
16 |
+
}
|
17 |
+
],
|
18 |
"extra": {
|
19 |
"installer-paths": {
|
20 |
"../../plugins/{$name}/": [
|
24 |
}
|
25 |
},
|
26 |
"require": {
|
27 |
+
"wpackagist-plugin/timber-library": "0.22.*"
|
28 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
timber-starter-theme/composer.lock
CHANGED
@@ -4,22 +4,26 @@
|
|
4 |
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
5 |
"This file is @generated automatically"
|
6 |
],
|
7 |
-
"hash": "
|
|
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "composer/installers",
|
11 |
-
"version": "v1.0.
|
12 |
"source": {
|
13 |
"type": "git",
|
14 |
"url": "https://github.com/composer/installers.git",
|
15 |
-
"reference": "
|
16 |
},
|
17 |
"dist": {
|
18 |
"type": "zip",
|
19 |
-
"url": "https://api.github.com/repos/composer/installers/zipball/
|
20 |
-
"reference": "
|
21 |
"shasum": ""
|
22 |
},
|
|
|
|
|
|
|
23 |
"replace": {
|
24 |
"roundcube/plugin-installer": "*",
|
25 |
"shama/baton": "*"
|
@@ -28,16 +32,16 @@
|
|
28 |
"composer/composer": "1.0.*@dev",
|
29 |
"phpunit/phpunit": "4.1.*"
|
30 |
},
|
31 |
-
"type": "composer-
|
32 |
"extra": {
|
33 |
-
"class": "Composer\\Installers\\
|
34 |
"branch-alias": {
|
35 |
"dev-master": "1.0-dev"
|
36 |
}
|
37 |
},
|
38 |
"autoload": {
|
39 |
-
"psr-
|
40 |
-
"Composer\\Installers\\": "src/"
|
41 |
}
|
42 |
},
|
43 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -52,12 +56,14 @@
|
|
52 |
}
|
53 |
],
|
54 |
"description": "A multi-framework Composer library installer",
|
55 |
-
"homepage": "
|
56 |
"keywords": [
|
57 |
"Craft",
|
58 |
"Dolibarr",
|
59 |
"Hurad",
|
|
|
60 |
"MODX Evo",
|
|
|
61 |
"OXID",
|
62 |
"SMF",
|
63 |
"Thelia",
|
@@ -99,19 +105,19 @@
|
|
99 |
"zend",
|
100 |
"zikula"
|
101 |
],
|
102 |
-
"time": "
|
103 |
},
|
104 |
{
|
105 |
"name": "wpackagist-plugin/timber-library",
|
106 |
-
"version": "0.
|
107 |
"source": {
|
108 |
"type": "svn",
|
109 |
-
"url": "
|
110 |
-
"reference": "tags/0.
|
111 |
},
|
112 |
"dist": {
|
113 |
"type": "zip",
|
114 |
-
"url": "https://downloads.wordpress.org/plugin/timber-library.0.
|
115 |
"reference": null,
|
116 |
"shasum": null
|
117 |
},
|
4 |
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
5 |
"This file is @generated automatically"
|
6 |
],
|
7 |
+
"hash": "03c15e6c57468a60aa7ddc84134dfb24",
|
8 |
+
"content-hash": "ddbdaaec9f3f849d39a5aa1525e75c79",
|
9 |
"packages": [
|
10 |
{
|
11 |
"name": "composer/installers",
|
12 |
+
"version": "v1.0.25",
|
13 |
"source": {
|
14 |
"type": "git",
|
15 |
"url": "https://github.com/composer/installers.git",
|
16 |
+
"reference": "36e5b5843203d7f1cf6ffb0305a97e014387bd8e"
|
17 |
},
|
18 |
"dist": {
|
19 |
"type": "zip",
|
20 |
+
"url": "https://api.github.com/repos/composer/installers/zipball/36e5b5843203d7f1cf6ffb0305a97e014387bd8e",
|
21 |
+
"reference": "36e5b5843203d7f1cf6ffb0305a97e014387bd8e",
|
22 |
"shasum": ""
|
23 |
},
|
24 |
+
"require": {
|
25 |
+
"composer-plugin-api": "^1.0"
|
26 |
+
},
|
27 |
"replace": {
|
28 |
"roundcube/plugin-installer": "*",
|
29 |
"shama/baton": "*"
|
32 |
"composer/composer": "1.0.*@dev",
|
33 |
"phpunit/phpunit": "4.1.*"
|
34 |
},
|
35 |
+
"type": "composer-plugin",
|
36 |
"extra": {
|
37 |
+
"class": "Composer\\Installers\\Plugin",
|
38 |
"branch-alias": {
|
39 |
"dev-master": "1.0-dev"
|
40 |
}
|
41 |
},
|
42 |
"autoload": {
|
43 |
+
"psr-4": {
|
44 |
+
"Composer\\Installers\\": "src/Composer/Installers"
|
45 |
}
|
46 |
},
|
47 |
"notification-url": "https://packagist.org/downloads/",
|
56 |
}
|
57 |
],
|
58 |
"description": "A multi-framework Composer library installer",
|
59 |
+
"homepage": "https://composer.github.io/installers/",
|
60 |
"keywords": [
|
61 |
"Craft",
|
62 |
"Dolibarr",
|
63 |
"Hurad",
|
64 |
+
"ImageCMS",
|
65 |
"MODX Evo",
|
66 |
+
"Mautic",
|
67 |
"OXID",
|
68 |
"SMF",
|
69 |
"Thelia",
|
105 |
"zend",
|
106 |
"zikula"
|
107 |
],
|
108 |
+
"time": "2016-04-13 19:46:30"
|
109 |
},
|
110 |
{
|
111 |
"name": "wpackagist-plugin/timber-library",
|
112 |
+
"version": "0.22.5",
|
113 |
"source": {
|
114 |
"type": "svn",
|
115 |
+
"url": "https://plugins.svn.wordpress.org/timber-library/",
|
116 |
+
"reference": "tags/0.22.5"
|
117 |
},
|
118 |
"dist": {
|
119 |
"type": "zip",
|
120 |
+
"url": "https://downloads.wordpress.org/plugin/timber-library.0.22.5.zip",
|
121 |
"reference": null,
|
122 |
"shasum": null
|
123 |
},
|
timber-starter-theme/footer.php
CHANGED
@@ -1,8 +1,12 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
* Third party plugins that hijack the theme will call wp_footer() to get the footer template.
|
4 |
* We use this to end our output buffer (started in header.php) and render into the view/page-plugin.twig template.
|
|
|
|
|
|
|
5 |
*/
|
|
|
6 |
$timberContext = $GLOBALS['timberContext'];
|
7 |
if ( ! isset( $timberContext ) ) {
|
8 |
throw new \Exception( 'Timber context not set in footer.' );
|
1 |
<?php
|
2 |
+
/**
|
3 |
* Third party plugins that hijack the theme will call wp_footer() to get the footer template.
|
4 |
* We use this to end our output buffer (started in header.php) and render into the view/page-plugin.twig template.
|
5 |
+
*
|
6 |
+
* If you're not using a plugin that requries this behavior (ones that do include Events Calendar Pro and
|
7 |
+
* WooCommerce) you can delete this file and header.php
|
8 |
*/
|
9 |
+
|
10 |
$timberContext = $GLOBALS['timberContext'];
|
11 |
if ( ! isset( $timberContext ) ) {
|
12 |
throw new \Exception( 'Timber context not set in footer.' );
|
timber-starter-theme/functions.php
CHANGED
@@ -39,18 +39,18 @@ class StarterSite extends TimberSite {
|
|
39 |
return $context;
|
40 |
}
|
41 |
|
|
|
|
|
|
|
|
|
|
|
42 |
function add_to_twig( $twig ) {
|
43 |
/* this is where you can add your own fuctions to twig */
|
44 |
$twig->addExtension( new Twig_Extension_StringLoader() );
|
45 |
-
$twig->addFilter(
|
46 |
return $twig;
|
47 |
}
|
48 |
|
49 |
}
|
50 |
|
51 |
new StarterSite();
|
52 |
-
|
53 |
-
function myfoo( $text ) {
|
54 |
-
$text .= ' bar!';
|
55 |
-
return $text;
|
56 |
-
}
|
39 |
return $context;
|
40 |
}
|
41 |
|
42 |
+
function myfoo( $text ) {
|
43 |
+
$text .= ' bar!';
|
44 |
+
return $text;
|
45 |
+
}
|
46 |
+
|
47 |
function add_to_twig( $twig ) {
|
48 |
/* this is where you can add your own fuctions to twig */
|
49 |
$twig->addExtension( new Twig_Extension_StringLoader() );
|
50 |
+
$twig->addFilter('myfoo', new Twig_SimpleFilter('myfoo', array($this, 'myfoo')));
|
51 |
return $twig;
|
52 |
}
|
53 |
|
54 |
}
|
55 |
|
56 |
new StarterSite();
|
|
|
|
|
|
|
|
|
|
timber-starter-theme/header.php
CHANGED
@@ -1,7 +1,11 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
* Third party plugins that hijack the theme will call wp_head() to get the header template.
|
4 |
* We use this to start our output buffer and render into the view/page-plugin.twig template in footer.php
|
|
|
|
|
|
|
5 |
*/
|
|
|
6 |
$GLOBALS['timberContext'] = Timber::get_context();
|
7 |
ob_start();
|
1 |
<?php
|
2 |
+
/**
|
3 |
* Third party plugins that hijack the theme will call wp_head() to get the header template.
|
4 |
* We use this to start our output buffer and render into the view/page-plugin.twig template in footer.php
|
5 |
+
*
|
6 |
+
* If you're not using a plugin that requries this behavior (ones that do include Events Calendar Pro and
|
7 |
+
* WooCommerce) you can delete this file and footer.php
|
8 |
*/
|
9 |
+
|
10 |
$GLOBALS['timberContext'] = Timber::get_context();
|
11 |
ob_start();
|
timber-starter-theme/templates/base.twig
CHANGED
@@ -14,22 +14,7 @@
|
|
14 |
<a class="hdr-logo-link" href="/" rel="home">{{site.name}}</a>
|
15 |
</h1>
|
16 |
<nav id="nav-main" class="nav-main" role="navigation">
|
17 |
-
|
18 |
-
{% for item in menu.get_items %}
|
19 |
-
<li class="nav-item {{item.classes | join(' ')}}">
|
20 |
-
<a class="nav-link" href="{{item.get_link}}">{{item.title}}</a>
|
21 |
-
{% if item.get_children %}
|
22 |
-
<ul class="nav nav-drop">
|
23 |
-
{% for child in item.get_children %}
|
24 |
-
<li class="nav-drop-item">
|
25 |
-
<a class="nav-link" href="{{child.get_link}}">{{child.title}}</a>
|
26 |
-
</li>
|
27 |
-
{% endfor %}
|
28 |
-
</ul>
|
29 |
-
{% endif %}
|
30 |
-
</li>
|
31 |
-
{% endfor %}
|
32 |
-
</ul>
|
33 |
</nav><!-- #nav -->
|
34 |
</div>
|
35 |
{% endblock %}
|
@@ -56,4 +41,4 @@
|
|
56 |
{{ function('wp_footer') }}
|
57 |
{% endblock %}
|
58 |
</body>
|
59 |
-
</html>
|
14 |
<a class="hdr-logo-link" href="/" rel="home">{{site.name}}</a>
|
15 |
</h1>
|
16 |
<nav id="nav-main" class="nav-main" role="navigation">
|
17 |
+
{% include "menu.twig" with {'menu': menu.get_items} %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
</nav><!-- #nav -->
|
19 |
</div>
|
20 |
{% endblock %}
|
41 |
{{ function('wp_footer') }}
|
42 |
{% endblock %}
|
43 |
</body>
|
44 |
+
</html>
|
timber-starter-theme/templates/single-password.twig
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
{% extends "base.twig" %}
|
2 |
|
3 |
{% block content %}
|
4 |
-
<form class="password-form" action="/wp-login.php?action=postpass" method="post">
|
5 |
<label for="pwbox-{{post.ID}}">Password:</label>
|
6 |
<input class="password-box" name="post_password" id="pwbox-{{post.ID}}" type="password" placeholder="Password" size="20" maxlength="20" />
|
7 |
<input class="password-btn" type="submit" name="Submit" value="Submit" />
|
1 |
{% extends "base.twig" %}
|
2 |
|
3 |
{% block content %}
|
4 |
+
<form class="password-form" action="{{site.link}}/wp-login.php?action=postpass" method="post">
|
5 |
<label for="pwbox-{{post.ID}}">Password:</label>
|
6 |
<input class="password-box" name="post_password" id="pwbox-{{post.ID}}" type="password" placeholder="Password" size="20" maxlength="20" />
|
7 |
<input class="password-btn" type="submit" name="Submit" value="Submit" />
|
timber-starter-theme/tests/test-timber-starter-theme.php
CHANGED
@@ -25,11 +25,11 @@
|
|
25 |
}
|
26 |
|
27 |
static function _setupStarterTheme(){
|
28 |
-
$dest = WP_CONTENT_DIR.'/themes/
|
29 |
-
$src = __DIR__.'/../../
|
30 |
if (is_dir($src)) {
|
31 |
self::_copyDirectory($src, $dest);
|
32 |
-
switch_theme('
|
33 |
} else {
|
34 |
echo 'no its not';
|
35 |
}
|
25 |
}
|
26 |
|
27 |
static function _setupStarterTheme(){
|
28 |
+
$dest = WP_CONTENT_DIR.'/themes/starter-theme/';
|
29 |
+
$src = __DIR__.'/../../starter-theme/';
|
30 |
if (is_dir($src)) {
|
31 |
self::_copyDirectory($src, $dest);
|
32 |
+
switch_theme('starter-theme');
|
33 |
} else {
|
34 |
echo 'no its not';
|
35 |
}
|
timber-starter-theme/views/menu.twig
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<ul>
|
2 |
+
{% for item in menu %}
|
3 |
+
<li class="{{item.classes | join(' ')}}">
|
4 |
+
<a href="{{item.get_link}}">{{item.title}}</a>
|
5 |
+
{% include "menu.twig" with {'menu': item.get_children} %}
|
6 |
+
</li>
|
7 |
+
{% endfor %}
|
8 |
+
</ul>
|
timber.php
CHANGED
@@ -4,628 +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 |
|| file_exists( $composer_autoload = WP_CONTENT_DIR.'/vendor/autoload.php') /* check in wp-content */
|
19 |
|| file_exists( $composer_autoload = plugin_dir_path( __FILE__ ).'vendor/autoload.php') /* check in plugin directory */
|
20 |
|| file_exists( $composer_autoload = get_stylesheet_directory().'/vendor/autoload.php') /* check in child theme */
|
21 |
|| file_exists( $composer_autoload = get_template_directory().'/vendor/autoload.php') /* check in parent theme */
|
22 |
-
|
23 |
require_once $composer_autoload;
|
24 |
}
|
25 |
-
|
26 |
-
$timber = new Timber();
|
27 |
-
Timber::$dirname = 'views';
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Timber Class.
|
31 |
-
*
|
32 |
-
* Main class called Timber for this plugin.
|
33 |
-
*
|
34 |
-
* Usage:
|
35 |
-
* $posts = Timber::get_posts();
|
36 |
-
* $posts = Timber::get_posts('post_type = article')
|
37 |
-
* $posts = Timber::get_posts(array('post_type' => 'article', 'category_name' => 'sports')); // uses wp_query format.
|
38 |
-
* $posts = Timber::get_posts(array(23,24,35,67), 'InkwellArticle');
|
39 |
-
*
|
40 |
-
* $context = Timber::get_context(); // returns wp favorites!
|
41 |
-
* $context['posts'] = $posts;
|
42 |
-
* Timber::render('index.twig', $context);
|
43 |
-
*/
|
44 |
-
class Timber {
|
45 |
-
|
46 |
-
public static $locations;
|
47 |
-
public static $dirname;
|
48 |
-
public static $twig_cache = false;
|
49 |
-
public static $cache = false;
|
50 |
-
public static $auto_meta = true;
|
51 |
-
public static $autoescape = false;
|
52 |
-
|
53 |
-
/**
|
54 |
-
* @codeCoverageIgnore
|
55 |
-
*/
|
56 |
-
public function __construct() {
|
57 |
-
if ( !defined('ABSPATH') ) {
|
58 |
-
return;
|
59 |
-
}
|
60 |
-
$this->test_compatibility();
|
61 |
-
$this->init_constants();
|
62 |
-
$this->init();
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Tests whether we can use Timber
|
67 |
-
* @codeCoverageIgnore
|
68 |
-
* @return
|
69 |
-
*/
|
70 |
-
protected function test_compatibility() {
|
71 |
-
if ( is_admin() || $_SERVER['PHP_SELF'] == '/wp-login.php' ) {
|
72 |
-
return;
|
73 |
-
}
|
74 |
-
if ( version_compare( phpversion(), '5.3.0', '<' ) && !is_admin() ) {
|
75 |
-
trigger_error( 'Timber requires PHP 5.3.0 or greater. You have '.phpversion(), E_USER_ERROR );
|
76 |
-
}
|
77 |
-
if ( !class_exists( 'Twig_Autoloader' ) ) {
|
78 |
-
trigger_error( 'You have not run "composer install" to download required dependencies for Timber, you can read more on https://github.com/jarednova/timber#installation', E_USER_ERROR );
|
79 |
-
}
|
80 |
-
}
|
81 |
-
|
82 |
-
function init_constants() {
|
83 |
-
defined( "TIMBER_LOC" ) or define( "TIMBER_LOC", realpath( __DIR__ ) );
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* @codeCoverageIgnore
|
88 |
-
*/
|
89 |
-
protected function init() {
|
90 |
-
TimberTwig::init();
|
91 |
-
TimberRoutes::init( $this );
|
92 |
-
TimberImageHelper::init();
|
93 |
-
TimberAdmin::init();
|
94 |
-
TimberIntegrations::init();
|
95 |
-
}
|
96 |
-
|
97 |
-
/* Post Retrieval Routine
|
98 |
-
================================ */
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Get post.
|
102 |
-
*
|
103 |
-
* @param mixed $query
|
104 |
-
* @param string $PostClass
|
105 |
-
* @return array|bool|null
|
106 |
-
*/
|
107 |
-
public static function get_post( $query = false, $PostClass = 'TimberPost' ) {
|
108 |
-
return TimberPostGetter::get_post( $query, $PostClass );
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Get posts.
|
113 |
-
*
|
114 |
-
* @param mixed $query
|
115 |
-
* @param string $PostClass
|
116 |
-
* @return array|bool|null
|
117 |
-
*/
|
118 |
-
public static function get_posts( $query = false, $PostClass = 'TimberPost', $return_collection = false ) {
|
119 |
-
return TimberPostGetter::get_posts( $query, $PostClass, $return_collection );
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* Query post.
|
124 |
-
*
|
125 |
-
* @param mixed $query
|
126 |
-
* @param string $PostClass
|
127 |
-
* @return array|bool|null
|
128 |
-
*/
|
129 |
-
public static function query_post( $query = false, $PostClass = 'TimberPost' ) {
|
130 |
-
return TimberPostGetter::query_post( $query, $PostClass );
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Query posts.
|
135 |
-
*
|
136 |
-
* @param mixed $query
|
137 |
-
* @param string $PostClass
|
138 |
-
* @return array|bool|null
|
139 |
-
*/
|
140 |
-
public static function query_posts( $query = false, $PostClass = 'TimberPost' ) {
|
141 |
-
return TimberPostGetter::query_posts( $query, $PostClass );
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* Get pids.
|
146 |
-
*
|
147 |
-
* @param array|string $query
|
148 |
-
* @return array
|
149 |
-
* @deprecated since 0.20.0
|
150 |
-
*/
|
151 |
-
static function get_pids( $query = null ) {
|
152 |
-
return TimberPostGetter::get_pids( $query );
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Get posts from loop.
|
157 |
-
*
|
158 |
-
* @param string $PostClass
|
159 |
-
* @return array
|
160 |
-
* @deprecated since 0.20.0
|
161 |
-
*/
|
162 |
-
static function get_posts_from_loop( $PostClass ) {
|
163 |
-
return TimberPostGetter::get_posts( $PostClass );
|
164 |
-
}
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Get posts from slug.
|
168 |
-
*
|
169 |
-
* @param string $slug
|
170 |
-
* @param string $PostClass
|
171 |
-
* @return array
|
172 |
-
* @deprecated since 0.20.0
|
173 |
-
*/
|
174 |
-
static function get_posts_from_slug( $slug, $PostClass = 'TimberPost' ) {
|
175 |
-
return TimberPostGetter::get_posts( $slug, $PostClass );
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* Get posts from WP_Query.
|
180 |
-
*
|
181 |
-
* @param array $query
|
182 |
-
* @param string $PostClass
|
183 |
-
* @return array
|
184 |
-
* @deprecated since 0.20.0
|
185 |
-
*/
|
186 |
-
static function get_posts_from_wp_query( $query = array(), $PostClass = 'TimberPost' ) {
|
187 |
-
return TimberPostGetter::query_posts( $query, $PostClass );
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* Get posts from array of ids.
|
192 |
-
*
|
193 |
-
* @param array $query
|
194 |
-
* @param string $PostClass
|
195 |
-
* @return array|null
|
196 |
-
* @deprecated since 0.20.0
|
197 |
-
*/
|
198 |
-
static function get_posts_from_array_of_ids( $query = array(), $PostClass = 'TimberPost' ) {
|
199 |
-
return TimberPostGetter::get_posts( $query, $PostClass );
|
200 |
-
}
|
201 |
-
|
202 |
-
/**
|
203 |
-
* Get pid.
|
204 |
-
*
|
205 |
-
* @param unknown $query
|
206 |
-
* @return int
|
207 |
-
* @deprecated since 0.20.0
|
208 |
-
*/
|
209 |
-
static function get_pid( $query ) {
|
210 |
-
$pids = TimberPostGetter::get_pids( $query );
|
211 |
-
if ( is_array( $pids ) && count( $pids ) ) {
|
212 |
-
return $pids[0];
|
213 |
-
}
|
214 |
-
}
|
215 |
-
|
216 |
-
/**
|
217 |
-
* WP_Query has posts.
|
218 |
-
*
|
219 |
-
* @return bool
|
220 |
-
* @deprecated since 0.20.0
|
221 |
-
*/
|
222 |
-
static function wp_query_has_posts() {
|
223 |
-
return TimberPostGetter::wp_query_has_posts();
|
224 |
-
}
|
225 |
-
|
226 |
-
/* Term Retrieval
|
227 |
-
================================ */
|
228 |
-
|
229 |
-
/**
|
230 |
-
* Get terms.
|
231 |
-
*
|
232 |
-
* @param string|array $args
|
233 |
-
* @param array $maybe_args
|
234 |
-
* @param string $TermClass
|
235 |
-
* @return mixed
|
236 |
-
*/
|
237 |
-
public static function get_terms( $args = null, $maybe_args = array(), $TermClass = 'TimberTerm' ) {
|
238 |
-
return TimberTermGetter::get_terms( $args, $maybe_args, $TermClass );
|
239 |
-
}
|
240 |
-
|
241 |
-
/* Site Retrieval
|
242 |
-
================================ */
|
243 |
-
|
244 |
-
/**
|
245 |
-
* Get sites.
|
246 |
-
*
|
247 |
-
* @param array|bool $blog_ids
|
248 |
-
* @return array
|
249 |
-
*/
|
250 |
-
public static function get_sites( $blog_ids = false ) {
|
251 |
-
if ( !is_array( $blog_ids ) ) {
|
252 |
-
global $wpdb;
|
253 |
-
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id ASC" );
|
254 |
-
}
|
255 |
-
$return = array();
|
256 |
-
foreach ( $blog_ids as $blog_id ) {
|
257 |
-
$return[] = new TimberSite( $blog_id );
|
258 |
-
}
|
259 |
-
return $return;
|
260 |
-
}
|
261 |
-
|
262 |
-
|
263 |
-
/* Template Setup and Display
|
264 |
-
================================ */
|
265 |
-
|
266 |
-
/**
|
267 |
-
* Get context.
|
268 |
-
*
|
269 |
-
* @return array
|
270 |
-
*/
|
271 |
-
public static function get_context() {
|
272 |
-
$data = array();
|
273 |
-
$data['http_host'] = 'http://' . TimberURLHelper::get_host();
|
274 |
-
$data['wp_title'] = TimberHelper::get_wp_title();
|
275 |
-
$data['wp_head'] = TimberHelper::function_wrapper( 'wp_head' );
|
276 |
-
$data['wp_footer'] = TimberHelper::function_wrapper( 'wp_footer' );
|
277 |
-
$data['body_class'] = implode( ' ', get_body_class() );
|
278 |
-
|
279 |
-
$data['site'] = new TimberSite();
|
280 |
-
$data['theme'] = $data['site']->theme;
|
281 |
-
//deprecated, these should be fetched via TimberSite or TimberTheme
|
282 |
-
$data['theme_dir'] = WP_CONTENT_SUBDIR.str_replace( WP_CONTENT_DIR, '', get_stylesheet_directory() );
|
283 |
-
$data['language_attributes'] = TimberHelper::function_wrapper( 'language_attributes' );
|
284 |
-
$data['stylesheet_uri'] = get_stylesheet_uri();
|
285 |
-
$data['template_uri'] = get_template_directory_uri();
|
286 |
-
|
287 |
-
$data['posts'] = Timber::query_posts();
|
288 |
-
|
289 |
-
//deprecated, this should be fetched via TimberMenu
|
290 |
-
if ( function_exists( 'wp_nav_menu' ) ) {
|
291 |
-
$locations = get_nav_menu_locations();
|
292 |
-
if ( count( $locations ) ) {
|
293 |
-
$data['wp_nav_menu'] = wp_nav_menu( array( 'container_class' => 'menu-header', 'echo' => false, 'menu_class' => 'nav-menu' ) );
|
294 |
-
}
|
295 |
-
}
|
296 |
-
$data = apply_filters( 'timber_context', $data );
|
297 |
-
$data = apply_filters( 'timber/context', $data );
|
298 |
-
return $data;
|
299 |
-
}
|
300 |
-
|
301 |
-
/**
|
302 |
-
* Compile function.
|
303 |
-
*
|
304 |
-
* @param array $filenames
|
305 |
-
* @param array $data
|
306 |
-
* @param bool $expires
|
307 |
-
* @param string $cache_mode
|
308 |
-
* @param bool $via_render
|
309 |
-
* @return bool|string
|
310 |
-
*/
|
311 |
-
public static function compile( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT, $via_render = false ) {
|
312 |
-
$caller = self::get_calling_script_dir();
|
313 |
-
$caller_file = self::get_calling_script_file();
|
314 |
-
$caller_file = apply_filters( 'timber_calling_php_file', $caller_file );
|
315 |
-
$loader = new TimberLoader( $caller );
|
316 |
-
$file = $loader->choose_template( $filenames );
|
317 |
-
$output = '';
|
318 |
-
if ( is_null( $data ) ) {
|
319 |
-
$data = array();
|
320 |
-
}
|
321 |
-
if ( strlen( $file ) ) {
|
322 |
-
if ( $via_render ) {
|
323 |
-
$file = apply_filters( 'timber_render_file', $file );
|
324 |
-
$data = apply_filters( 'timber_render_data', $data );
|
325 |
-
} else {
|
326 |
-
$file = apply_filters( 'timber_compile_file', $file );
|
327 |
-
$data = apply_filters( 'timber_compile_data', $data );
|
328 |
-
}
|
329 |
-
$output = $loader->render( $file, $data, $expires, $cache_mode );
|
330 |
-
}
|
331 |
-
do_action( 'timber_compile_done' );
|
332 |
-
return $output;
|
333 |
-
}
|
334 |
-
|
335 |
-
/**
|
336 |
-
* Compile string.
|
337 |
-
*
|
338 |
-
* @param string $string a string with twig variables.
|
339 |
-
* @param array $data an array with data in it.
|
340 |
-
* @return bool|string
|
341 |
-
*/
|
342 |
-
public static function compile_string( $string, $data = array() ) {
|
343 |
-
$dummy_loader = new TimberLoader();
|
344 |
-
$dummy_loader->get_twig();
|
345 |
-
$loader = new Twig_Loader_String();
|
346 |
-
$twig = new Twig_Environment( $loader );
|
347 |
-
$twig = apply_filters( 'timber/twig/filters', $twig );
|
348 |
-
$twig = apply_filters( 'twig_apply_filters', $twig );
|
349 |
-
return $twig->render( $string, $data );
|
350 |
-
}
|
351 |
-
|
352 |
-
/**
|
353 |
-
* Fetch function.
|
354 |
-
*
|
355 |
-
* @param array $filenames
|
356 |
-
* @param array $data
|
357 |
-
* @param bool $expires
|
358 |
-
* @param string $cache_mode
|
359 |
-
* @return bool|string
|
360 |
-
*/
|
361 |
-
public static function fetch( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT ) {
|
362 |
-
if ( $expires === true ) {
|
363 |
-
//if this is reading as true; the user probably is using the old $echo param
|
364 |
-
//so we should move all vars up by a spot
|
365 |
-
$expires = $cache_mode;
|
366 |
-
$cache_mode = TimberLoader::CACHE_USE_DEFAULT;
|
367 |
-
}
|
368 |
-
$output = self::compile( $filenames, $data, $expires, $cache_mode, true );
|
369 |
-
$output = apply_filters( 'timber_compile_result', $output );
|
370 |
-
return $output;
|
371 |
-
}
|
372 |
-
|
373 |
-
/**
|
374 |
-
* Render function.
|
375 |
-
*
|
376 |
-
* @param array $filenames
|
377 |
-
* @param array $data
|
378 |
-
* @param bool $expires
|
379 |
-
* @param string $cache_mode
|
380 |
-
* @return bool|string
|
381 |
-
*/
|
382 |
-
public static function render( $filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT ) {
|
383 |
-
$output = static::fetch( $filenames, $data, $expires, $cache_mode );
|
384 |
-
echo $output;
|
385 |
-
return $output;
|
386 |
-
}
|
387 |
-
|
388 |
-
/**
|
389 |
-
* Render string.
|
390 |
-
*
|
391 |
-
* @param string $string a string with twig variables.
|
392 |
-
* @param array $data an array with data in it.
|
393 |
-
* @return bool|string
|
394 |
-
*/
|
395 |
-
public static function render_string( $string, $data = array() ) {
|
396 |
-
$compiled = self::compile_string( $string, $data );
|
397 |
-
echo $compiled;
|
398 |
-
return $compiled;
|
399 |
-
}
|
400 |
-
|
401 |
-
|
402 |
-
/* Sidebar
|
403 |
-
================================ */
|
404 |
-
|
405 |
-
/**
|
406 |
-
* Get sidebar.
|
407 |
-
*
|
408 |
-
* @param string $sidebar
|
409 |
-
* @param array $data
|
410 |
-
* @return bool|string
|
411 |
-
*/
|
412 |
-
public static function get_sidebar( $sidebar = '', $data = array() ) {
|
413 |
-
if ( $sidebar == '' ) {
|
414 |
-
$sidebar = 'sidebar.php';
|
415 |
-
}
|
416 |
-
if ( strstr( strtolower( $sidebar ), '.php' ) ) {
|
417 |
-
return self::get_sidebar_from_php( $sidebar, $data );
|
418 |
-
}
|
419 |
-
return self::compile( $sidebar, $data );
|
420 |
-
}
|
421 |
-
|
422 |
-
/**
|
423 |
-
* Get sidebar from PHP
|
424 |
-
*
|
425 |
-
* @param string $sidebar
|
426 |
-
* @param array $data
|
427 |
-
* @return string
|
428 |
-
*/
|
429 |
-
public static function get_sidebar_from_php( $sidebar = '', $data ) {
|
430 |
-
$caller = self::get_calling_script_dir();
|
431 |
-
$loader = new TimberLoader();
|
432 |
-
$uris = $loader->get_locations( $caller );
|
433 |
-
ob_start();
|
434 |
-
$found = false;
|
435 |
-
foreach ( $uris as $uri ) {
|
436 |
-
if ( file_exists( trailingslashit( $uri ) . $sidebar ) ) {
|
437 |
-
include trailingslashit( $uri ) . $sidebar;
|
438 |
-
$found = true;
|
439 |
-
break;
|
440 |
-
}
|
441 |
-
}
|
442 |
-
if ( !$found ) {
|
443 |
-
TimberHelper::error_log( 'error loading your sidebar, check to make sure the file exists' );
|
444 |
-
}
|
445 |
-
$ret = ob_get_contents();
|
446 |
-
ob_end_clean();
|
447 |
-
return $ret;
|
448 |
-
}
|
449 |
-
|
450 |
-
/* Widgets
|
451 |
-
================================ */
|
452 |
-
|
453 |
-
/**
|
454 |
-
* Get widgets.
|
455 |
-
*
|
456 |
-
* @param int $widget_id
|
457 |
-
* @return TimberFunctionWrapper
|
458 |
-
*/
|
459 |
-
public static function get_widgets( $widget_id ) {
|
460 |
-
return TimberHelper::function_wrapper( 'dynamic_sidebar', array( $widget_id ), true );
|
461 |
-
}
|
462 |
-
|
463 |
-
|
464 |
-
/* Routes
|
465 |
-
================================ */
|
466 |
-
|
467 |
-
/**
|
468 |
-
* Add route.
|
469 |
-
*
|
470 |
-
* @param string $route
|
471 |
-
* @param callable $callback
|
472 |
-
* @param array $args
|
473 |
-
* @deprecated since 0.20.0
|
474 |
-
*/
|
475 |
-
public static function add_route( $route, $callback, $args = array() ) {
|
476 |
-
Routes::map( $route, $callback, $args );
|
477 |
-
}
|
478 |
-
|
479 |
-
/**
|
480 |
-
* @deprecated since 0.22.2
|
481 |
-
*/
|
482 |
-
public function cancel_query() {
|
483 |
-
add_action( 'posts_request', array( $this, 'cancel_query_posts_request' ) );
|
484 |
-
}
|
485 |
-
|
486 |
-
/**
|
487 |
-
* @deprecated since 0.22.2
|
488 |
-
*/
|
489 |
-
function cancel_query_posts_request() {
|
490 |
-
if ( is_main_query() ) {
|
491 |
-
wp_reset_query();
|
492 |
-
}
|
493 |
-
}
|
494 |
-
|
495 |
-
/**
|
496 |
-
* Load template.
|
497 |
-
*
|
498 |
-
* @deprecated since 0.20.0
|
499 |
-
*/
|
500 |
-
public static function load_template( $template, $query = false, $status_code = 200, $tparams = false ) {
|
501 |
-
return Routes::load( $template, $tparams, $query, $status_code );
|
502 |
-
}
|
503 |
-
|
504 |
-
/**
|
505 |
-
* Load view.
|
506 |
-
*
|
507 |
-
* @deprecated since 0.20.2
|
508 |
-
*/
|
509 |
-
public static function load_view( $template, $query = false, $status_code = 200, $tparams = false ) {
|
510 |
-
return Routes::load( $template, $tparams, $query, $status_code );
|
511 |
-
}
|
512 |
-
|
513 |
-
|
514 |
-
/* Pagination
|
515 |
-
================================ */
|
516 |
-
|
517 |
-
/**
|
518 |
-
* Get pagination.
|
519 |
-
*
|
520 |
-
* @param array $prefs
|
521 |
-
* @return array mixed
|
522 |
-
*/
|
523 |
-
public static function get_pagination( $prefs = array() ) {
|
524 |
-
global $wp_query;
|
525 |
-
global $paged;
|
526 |
-
global $wp_rewrite;
|
527 |
-
$args = array();
|
528 |
-
$args['total'] = ceil( $wp_query->found_posts / $wp_query->query_vars['posts_per_page'] );
|
529 |
-
if ( $wp_rewrite->using_permalinks() ) {
|
530 |
-
$url = explode( '?', get_pagenum_link( 0 ) );
|
531 |
-
if ( isset( $url[1] ) ) {
|
532 |
-
parse_str( $url[1], $query );
|
533 |
-
$args['add_args'] = $query;
|
534 |
-
}
|
535 |
-
$args['format'] = 'page/%#%';
|
536 |
-
$args['base'] = trailingslashit( $url[0] ).'%_%';
|
537 |
-
} else {
|
538 |
-
$big = 999999999;
|
539 |
-
$args['base'] = str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) );
|
540 |
-
}
|
541 |
-
$args['type'] = 'array';
|
542 |
-
$args['current'] = max( 1, get_query_var( 'paged' ) );
|
543 |
-
$args['mid_size'] = max( 9 - $args['current'], 3 );
|
544 |
-
if ( is_int( $prefs ) ) {
|
545 |
-
$args['mid_size'] = $prefs - 2;
|
546 |
-
} else {
|
547 |
-
$args = array_merge( $args, $prefs );
|
548 |
-
}
|
549 |
-
$data = array();
|
550 |
-
$data['current'] = $args['current'];
|
551 |
-
$data['total'] = $args['total'];
|
552 |
-
$data['pages'] = TimberHelper::paginate_links( $args );
|
553 |
-
$next = get_next_posts_page_link( $args['total'] );
|
554 |
-
if ( $next ) {
|
555 |
-
$data['next'] = array( 'link' => untrailingslashit( $next ), 'class' => 'page-numbers next' );
|
556 |
-
}
|
557 |
-
$prev = previous_posts( false );
|
558 |
-
if ( $prev ) {
|
559 |
-
$data['prev'] = array( 'link' => untrailingslashit( $prev ), 'class' => 'page-numbers prev' );
|
560 |
-
}
|
561 |
-
if ( $paged < 2 ) {
|
562 |
-
$data['prev'] = '';
|
563 |
-
}
|
564 |
-
return $data;
|
565 |
-
}
|
566 |
-
|
567 |
-
/* Utility
|
568 |
-
================================ */
|
569 |
-
|
570 |
-
/**
|
571 |
-
* Get calling script path.
|
572 |
-
*
|
573 |
-
* @param int $offset
|
574 |
-
* @return string
|
575 |
-
* @deprecated since 0.20.0
|
576 |
-
*/
|
577 |
-
public static function get_calling_script_path( $offset = 0 ) {
|
578 |
-
$dir = self::get_calling_script_dir( $offset );
|
579 |
-
return str_replace( ABSPATH, '', realpath( $dir ) );
|
580 |
-
}
|
581 |
-
|
582 |
-
/**
|
583 |
-
* Get calling script dir.
|
584 |
-
*
|
585 |
-
* @return string
|
586 |
-
*/
|
587 |
-
public static function get_calling_script_dir( $offset = 0 ) {
|
588 |
-
$caller = self::get_calling_script_file( $offset );
|
589 |
-
if ( !is_null( $caller ) ) {
|
590 |
-
$pathinfo = pathinfo( $caller );
|
591 |
-
$dir = $pathinfo['dirname'];
|
592 |
-
return $dir;
|
593 |
-
}
|
594 |
-
}
|
595 |
-
|
596 |
-
/**
|
597 |
-
* Get calling script file.
|
598 |
-
*
|
599 |
-
* @param int $offset
|
600 |
-
* @return string|null
|
601 |
-
* @deprecated since 0.20.0
|
602 |
-
*/
|
603 |
-
public static function get_calling_script_file( $offset = 0 ) {
|
604 |
-
$caller = null;
|
605 |
-
$backtrace = debug_backtrace();
|
606 |
-
$i = 0;
|
607 |
-
foreach ( $backtrace as $trace ) {
|
608 |
-
if ( array_key_exists('file', $trace) && $trace['file'] != __FILE__ ) {
|
609 |
-
$caller = $trace['file'];
|
610 |
-
break;
|
611 |
-
}
|
612 |
-
$i++;
|
613 |
-
}
|
614 |
-
if ( $offset ) {
|
615 |
-
$caller = $backtrace[$i + $offset]['file'];
|
616 |
-
}
|
617 |
-
return $caller;
|
618 |
-
}
|
619 |
-
|
620 |
-
/**
|
621 |
-
* Is post class or class map.
|
622 |
-
*
|
623 |
-
* @param string|array $args
|
624 |
-
* @return bool
|
625 |
-
* @deprecated since 0.20.0
|
626 |
-
*/
|
627 |
-
public static function is_post_class_or_class_map( $args ) {
|
628 |
-
return TimberPostGetter::is_post_class_or_class_map( $args );
|
629 |
-
}
|
630 |
-
|
631 |
-
}
|
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.0
|
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/asm89/twig-cache-extension/.travis.yml
CHANGED
@@ -13,6 +13,6 @@ php:
|
|
13 |
- 7.0
|
14 |
- hhvm
|
15 |
|
16 |
-
before_script: composer install
|
17 |
|
18 |
script: phpunit
|
13 |
- 7.0
|
14 |
- hhvm
|
15 |
|
16 |
+
before_script: composer install
|
17 |
|
18 |
script: phpunit
|
vendor/asm89/twig-cache-extension/composer.json
CHANGED
@@ -30,7 +30,7 @@
|
|
30 |
},
|
31 |
"extra": {
|
32 |
"branch-alias": {
|
33 |
-
"dev-master": "1.
|
34 |
}
|
35 |
}
|
36 |
}
|
30 |
},
|
31 |
"extra": {
|
32 |
"branch-alias": {
|
33 |
+
"dev-master": "1.1-dev"
|
34 |
}
|
35 |
}
|
36 |
}
|
vendor/asm89/twig-cache-extension/lib/Asm89/Twig/CacheExtension/Node/CacheNode.php
CHANGED
@@ -27,7 +27,7 @@ class CacheNode extends \Twig_Node
|
|
27 |
* @param integer $lineno
|
28 |
* @param string $tag
|
29 |
*/
|
30 |
-
public function __construct(\Twig_Node_Expression $annotation, \Twig_Node_Expression $keyInfo, \
|
31 |
{
|
32 |
parent::__construct(array('key_info' => $keyInfo, 'body' => $body, 'annotation' => $annotation), array(), $lineno, $tag);
|
33 |
}
|
27 |
* @param integer $lineno
|
28 |
* @param string $tag
|
29 |
*/
|
30 |
+
public function __construct(\Twig_Node_Expression $annotation, \Twig_Node_Expression $keyInfo, \Twig_Node $body, $lineno, $tag = null)
|
31 |
{
|
32 |
parent::__construct(array('key_info' => $keyInfo, 'body' => $body, 'annotation' => $annotation), array(), $lineno, $tag);
|
33 |
}
|
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 ComposerAutoloaderInit977d5902edc1085fc45cbf70be497654::getLoader();
|
vendor/composer/ClassLoader.php
CHANGED
@@ -13,9 +13,7 @@
|
|
13 |
namespace Composer\Autoload;
|
14 |
|
15 |
/**
|
16 |
-
* ClassLoader implements a PSR-0 class loader
|
17 |
-
*
|
18 |
-
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
19 |
*
|
20 |
* $loader = new \Composer\Autoload\ClassLoader();
|
21 |
*
|
@@ -39,6 +37,8 @@ namespace Composer\Autoload;
|
|
39 |
*
|
40 |
* @author Fabien Potencier <fabien@symfony.com>
|
41 |
* @author Jordi Boggiano <j.boggiano@seld.be>
|
|
|
|
|
42 |
*/
|
43 |
class ClassLoader
|
44 |
{
|
@@ -147,7 +147,7 @@ class ClassLoader
|
|
147 |
* appending or prepending to the ones previously set for this namespace.
|
148 |
*
|
149 |
* @param string $prefix The prefix/namespace, with trailing '\\'
|
150 |
-
* @param array|string $paths The PSR-
|
151 |
* @param bool $prepend Whether to prepend the directories
|
152 |
*
|
153 |
* @throws \InvalidArgumentException
|
13 |
namespace Composer\Autoload;
|
14 |
|
15 |
/**
|
16 |
+
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
|
|
|
|
17 |
*
|
18 |
* $loader = new \Composer\Autoload\ClassLoader();
|
19 |
*
|
37 |
*
|
38 |
* @author Fabien Potencier <fabien@symfony.com>
|
39 |
* @author Jordi Boggiano <j.boggiano@seld.be>
|
40 |
+
* @see http://www.php-fig.org/psr/psr-0/
|
41 |
+
* @see http://www.php-fig.org/psr/psr-4/
|
42 |
*/
|
43 |
class ClassLoader
|
44 |
{
|
147 |
* appending or prepending to the ones previously set for this namespace.
|
148 |
*
|
149 |
* @param string $prefix The prefix/namespace, with trailing '\\'
|
150 |
+
* @param array|string $paths The PSR-4 base directories
|
151 |
* @param bool $prepend Whether to prepend the directories
|
152 |
*
|
153 |
* @throws \InvalidArgumentException
|
vendor/composer/LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
|
2 |
-
Copyright (c)
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
1 |
|
2 |
+
Copyright (c) 2016 Nils Adermann, Jordi Boggiano
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
vendor/composer/autoload_classmap.php
CHANGED
@@ -6,43 +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 |
-
'TimberAdmin' => $baseDir . '/lib/timber-admin.php',
|
12 |
-
'TimberArchives' => $baseDir . '/lib/timber-archives.php',
|
13 |
-
'TimberCommand' => $baseDir . '/lib/integrations/timber-command.php',
|
14 |
-
'TimberComment' => $baseDir . '/lib/timber-comment.php',
|
15 |
-
'TimberCore' => $baseDir . '/lib/timber-core.php',
|
16 |
-
'TimberCoreInterface' => $baseDir . '/lib/timber-core-interface.php',
|
17 |
-
'TimberFunctionWrapper' => $baseDir . '/lib/timber-function-wrapper.php',
|
18 |
-
'TimberHelper' => $baseDir . '/lib/timber-helper.php',
|
19 |
-
'TimberImage' => $baseDir . '/lib/timber-image.php',
|
20 |
-
'TimberImageHelper' => $baseDir . '/lib/timber-image-helper.php',
|
21 |
-
'TimberImageOperation' => $baseDir . '/lib/image/timber-image-operation.php',
|
22 |
-
'TimberImageOperationLetterbox' => $baseDir . '/lib/image/timber-image-operation-letterbox.php',
|
23 |
-
'TimberImageOperationResize' => $baseDir . '/lib/image/timber-image-operation-resize.php',
|
24 |
-
'TimberImageOperationRetina' => $baseDir . '/lib/image/timber-image-operation-retina.php',
|
25 |
-
'TimberImageOperationToJpg' => $baseDir . '/lib/image/timber-image-operation-tojpg.php',
|
26 |
-
'TimberIntegrations' => $baseDir . '/lib/timber-integrations.php',
|
27 |
-
'TimberLoader' => $baseDir . '/lib/timber-loader.php',
|
28 |
-
'TimberMenu' => $baseDir . '/lib/timber-menu.php',
|
29 |
-
'TimberMenuItem' => $baseDir . '/lib/timber-menu-item.php',
|
30 |
-
'TimberPage' => $baseDir . '/lib/timber-page.php',
|
31 |
-
'TimberPost' => $baseDir . '/lib/timber-post.php',
|
32 |
-
'TimberPostGetter' => $baseDir . '/lib/timber-post-getter.php',
|
33 |
-
'TimberPostsCollection' => $baseDir . '/lib/timber-posts-collection.php',
|
34 |
-
'TimberPostsIterator' => $baseDir . '/lib/timber-posts-collection.php',
|
35 |
-
'TimberQueryIterator' => $baseDir . '/lib/timber-query-iterator.php',
|
36 |
-
'TimberRoutes' => $baseDir . '/lib/timber-routes.php',
|
37 |
-
'TimberSite' => $baseDir . '/lib/timber-site.php',
|
38 |
-
'TimberTerm' => $baseDir . '/lib/timber-term.php',
|
39 |
-
'TimberTermGetter' => $baseDir . '/lib/timber-term-getter.php',
|
40 |
-
'TimberTheme' => $baseDir . '/lib/timber-theme.php',
|
41 |
-
'TimberTwig' => $baseDir . '/lib/timber-twig.php',
|
42 |
-
'TimberURLHelper' => $baseDir . '/lib/timber-url-helper.php',
|
43 |
-
'TimberUser' => $baseDir . '/lib/timber-user.php',
|
44 |
-
'Timber\\Cache\\KeyGenerator' => $baseDir . '/lib/cache/KeyGenerator.php',
|
45 |
-
'Timber\\Cache\\TimberKeyGeneratorInterface' => $baseDir . '/lib/cache/TimberKeyGeneratorInterface.php',
|
46 |
-
'Timber\\Cache\\WPObjectCacheAdapter' => $baseDir . '/lib/cache/WPObjectCacheAdapter.php',
|
47 |
-
'Timber_WP_CLI_Command' => $baseDir . '/lib/integrations/wpcli-timber.php',
|
48 |
);
|
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
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'cb78221880aa21d756cc44a8539bb425' => $baseDir . '/init.php',
|
10 |
+
);
|
vendor/composer/autoload_namespaces.php
CHANGED
@@ -8,5 +8,4 @@ $baseDir = dirname($vendorDir);
|
|
8 |
return array(
|
9 |
'Twig_' => array($vendorDir . '/twig/twig/lib'),
|
10 |
'Routes' => array($vendorDir . '/upstatement/routes'),
|
11 |
-
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src'),
|
12 |
);
|
8 |
return array(
|
9 |
'Twig_' => array($vendorDir . '/twig/twig/lib'),
|
10 |
'Routes' => array($vendorDir . '/upstatement/routes'),
|
|
|
11 |
);
|
vendor/composer/autoload_psr4.php
CHANGED
@@ -6,5 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
|
|
9 |
'' => array($vendorDir . '/asm89/twig-cache-extension/lib'),
|
10 |
);
|
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 ComposerAutoloaderInita300217f36ff83f02ad639201f3add11
|
|
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,11 +40,20 @@ class ComposerAutoloaderInita300217f36ff83f02ad639201f3add11
|
|
40 |
|
41 |
$loader->register(true);
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
return $loader;
|
44 |
}
|
45 |
}
|
46 |
|
47 |
-
function
|
48 |
{
|
49 |
-
|
|
|
|
|
|
|
|
|
50 |
}
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit977d5902edc1085fc45cbf70be497654
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit977d5902edc1085fc45cbf70be497654', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit977d5902edc1085fc45cbf70be497654', '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 |
+
composerRequire977d5902edc1085fc45cbf70be497654($fileIdentifier, $file);
|
46 |
+
}
|
47 |
+
|
48 |
return $loader;
|
49 |
}
|
50 |
}
|
51 |
|
52 |
+
function composerRequire977d5902edc1085fc45cbf70be497654($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,21 +1,21 @@
|
|
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": {
|
18 |
-
"composer-plugin-api": "1.0
|
19 |
},
|
20 |
"replace": {
|
21 |
"roundcube/plugin-installer": "*",
|
@@ -25,7 +25,7 @@
|
|
25 |
"composer/composer": "1.0.*@dev",
|
26 |
"phpunit/phpunit": "4.1.*"
|
27 |
},
|
28 |
-
"time": "
|
29 |
"type": "composer-plugin",
|
30 |
"extra": {
|
31 |
"class": "Composer\\Installers\\Plugin",
|
@@ -35,8 +35,8 @@
|
|
35 |
},
|
36 |
"installation-source": "dist",
|
37 |
"autoload": {
|
38 |
-
"psr-
|
39 |
-
"Composer\\Installers\\": "src/"
|
40 |
}
|
41 |
},
|
42 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -51,12 +51,14 @@
|
|
51 |
}
|
52 |
],
|
53 |
"description": "A multi-framework Composer library installer",
|
54 |
-
"homepage": "
|
55 |
"keywords": [
|
56 |
"Craft",
|
57 |
"Dolibarr",
|
58 |
"Hurad",
|
|
|
59 |
"MODX Evo",
|
|
|
60 |
"OXID",
|
61 |
"SMF",
|
62 |
"Thelia",
|
@@ -101,17 +103,17 @@
|
|
101 |
},
|
102 |
{
|
103 |
"name": "twig/twig",
|
104 |
-
"version": "v1.
|
105 |
-
"version_normalized": "1.
|
106 |
"source": {
|
107 |
"type": "git",
|
108 |
"url": "https://github.com/twigphp/Twig.git",
|
109 |
-
"reference": "
|
110 |
},
|
111 |
"dist": {
|
112 |
"type": "zip",
|
113 |
-
"url": "https://api.github.com/repos/twigphp/Twig/zipball/
|
114 |
-
"reference": "
|
115 |
"shasum": ""
|
116 |
},
|
117 |
"require": {
|
@@ -121,11 +123,11 @@
|
|
121 |
"symfony/debug": "~2.7",
|
122 |
"symfony/phpunit-bridge": "~2.7"
|
123 |
},
|
124 |
-
"time": "
|
125 |
"type": "library",
|
126 |
"extra": {
|
127 |
"branch-alias": {
|
128 |
-
"dev-master": "1.
|
129 |
}
|
130 |
},
|
131 |
"installation-source": "dist",
|
@@ -164,17 +166,17 @@
|
|
164 |
},
|
165 |
{
|
166 |
"name": "asm89/twig-cache-extension",
|
167 |
-
"version": "1.
|
168 |
-
"version_normalized": "1.
|
169 |
"source": {
|
170 |
"type": "git",
|
171 |
"url": "https://github.com/asm89/twig-cache-extension.git",
|
172 |
-
"reference": "
|
173 |
},
|
174 |
"dist": {
|
175 |
"type": "zip",
|
176 |
-
"url": "https://api.github.com/repos/asm89/twig-cache-extension/zipball/
|
177 |
-
"reference": "
|
178 |
"shasum": ""
|
179 |
},
|
180 |
"require": {
|
@@ -184,11 +186,11 @@
|
|
184 |
"require-dev": {
|
185 |
"doctrine/cache": "~1.0"
|
186 |
},
|
187 |
-
"time": "
|
188 |
"type": "library",
|
189 |
"extra": {
|
190 |
"branch-alias": {
|
191 |
-
"dev-master": "1.
|
192 |
}
|
193 |
},
|
194 |
"installation-source": "dist",
|
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": {
|
18 |
+
"composer-plugin-api": "^1.0"
|
19 |
},
|
20 |
"replace": {
|
21 |
"roundcube/plugin-installer": "*",
|
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",
|
35 |
},
|
36 |
"installation-source": "dist",
|
37 |
"autoload": {
|
38 |
+
"psr-4": {
|
39 |
+
"Composer\\Installers\\": "src/Composer/Installers"
|
40 |
}
|
41 |
},
|
42 |
"notification-url": "https://packagist.org/downloads/",
|
51 |
}
|
52 |
],
|
53 |
"description": "A multi-framework Composer library installer",
|
54 |
+
"homepage": "https://composer.github.io/installers/",
|
55 |
"keywords": [
|
56 |
"Craft",
|
57 |
"Dolibarr",
|
58 |
"Hurad",
|
59 |
+
"ImageCMS",
|
60 |
"MODX Evo",
|
61 |
+
"Mautic",
|
62 |
"OXID",
|
63 |
"SMF",
|
64 |
"Thelia",
|
103 |
},
|
104 |
{
|
105 |
"name": "twig/twig",
|
106 |
+
"version": "v1.24.0",
|
107 |
+
"version_normalized": "1.24.0.0",
|
108 |
"source": {
|
109 |
"type": "git",
|
110 |
"url": "https://github.com/twigphp/Twig.git",
|
111 |
+
"reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8"
|
112 |
},
|
113 |
"dist": {
|
114 |
"type": "zip",
|
115 |
+
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8",
|
116 |
+
"reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8",
|
117 |
"shasum": ""
|
118 |
},
|
119 |
"require": {
|
123 |
"symfony/debug": "~2.7",
|
124 |
"symfony/phpunit-bridge": "~2.7"
|
125 |
},
|
126 |
+
"time": "2016-01-25 21:22:18",
|
127 |
"type": "library",
|
128 |
"extra": {
|
129 |
"branch-alias": {
|
130 |
+
"dev-master": "1.24-dev"
|
131 |
}
|
132 |
},
|
133 |
"installation-source": "dist",
|
166 |
},
|
167 |
{
|
168 |
"name": "asm89/twig-cache-extension",
|
169 |
+
"version": "1.2.0",
|
170 |
+
"version_normalized": "1.2.0.0",
|
171 |
"source": {
|
172 |
"type": "git",
|
173 |
"url": "https://github.com/asm89/twig-cache-extension.git",
|
174 |
+
"reference": "76a801d6da8e1a1015af974d93df4ade0dda7267"
|
175 |
},
|
176 |
"dist": {
|
177 |
"type": "zip",
|
178 |
+
"url": "https://api.github.com/repos/asm89/twig-cache-extension/zipball/76a801d6da8e1a1015af974d93df4ade0dda7267",
|
179 |
+
"reference": "76a801d6da8e1a1015af974d93df4ade0dda7267",
|
180 |
"shasum": ""
|
181 |
},
|
182 |
"require": {
|
186 |
"require-dev": {
|
187 |
"doctrine/cache": "~1.0"
|
188 |
},
|
189 |
+
"time": "2016-02-14 13:52:38",
|
190 |
"type": "library",
|
191 |
"extra": {
|
192 |
"branch-alias": {
|
193 |
+
"dev-master": "1.1-dev"
|
194 |
}
|
195 |
},
|
196 |
"installation-source": "dist",
|
vendor/composer/installers/.travis.yml
CHANGED
@@ -18,4 +18,4 @@ before_script:
|
|
18 |
- composer install
|
19 |
|
20 |
script:
|
21 |
-
-
|
18 |
- composer install
|
19 |
|
20 |
script:
|
21 |
+
- composer test
|
vendor/composer/installers/README.md
CHANGED
@@ -48,20 +48,22 @@ is not needed to install packages with these frameworks:
|
|
48 |
| Croogo | `croogo-plugin`<br>`croogo-theme`
|
49 |
| DokuWiki | `dokuwiki-plugin`<br>`dokuwiki-template`
|
50 |
| Dolibarr | `dolibarr-module`
|
51 |
-
| Drupal | <b>`drupal-module`<br>`drupal-theme`</b><br>`drupal-library`<br>`drupal-profile`<br>`drupal-drush`
|
52 |
| Elgg | `elgg-plugin`
|
53 |
| FuelPHP v1.x | `fuel-module`<br>`fuel-package`<br/>`fuel-theme`
|
54 |
| FuelPHP v2.x | `fuelphp-component`
|
55 |
| Grav | `grav-plugin`<br>`grav-theme`
|
56 |
| Hurad | `hurad-plugin`<br>`hurad-theme`
|
|
|
57 |
| Joomla | `joomla-component`<br>`joomla-module`<br>`joomla-template`<br>`joomla-plugin`<br>`joomla-library`
|
58 |
-
| Kirby | **`kirby-plugin
|
59 |
| KodiCMS | `kodicms-plugin`<br>`kodicms-media`
|
60 |
| Kohana | **`kohana-module`**
|
61 |
| Laravel | `laravel-library`
|
62 |
| Lithium | **`lithium-library`<br>`lithium-source`**
|
63 |
| Magento | `magento-library`<br>`magento-skin`<br>`magento-theme`
|
64 |
| Mako | `mako-package`
|
|
|
65 |
| MODX Evo | `modxevo-snippet`<br>`modxevo-plugin`<br>`modxevo-module`<br>`modxevo-template`<br>`modxevo-lib`
|
66 |
| MediaWiki | `mediawiki-extension`
|
67 |
| October | **`october-module`<br>`october-plugin`<br>`october-theme`**
|
@@ -81,7 +83,7 @@ is not needed to install packages with these frameworks:
|
|
81 |
| symfony1 | **`symfony1-plugin`**
|
82 |
| Tusk | `tusk-task`<br>`tusk-command`<br>`tusk-asset`
|
83 |
| 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`
|
84 |
-
| TYPO3 CMS | `typo3-cms-extension`
|
85 |
| Wolf CMS | `wolfcms-plugin`
|
86 |
| WordPress | <b>`wordpress-plugin`<br>`wordpress-theme`</b><br>`wordpress-muplugin`
|
87 |
| Zend | `zend-library`<br>`zend-extra`<br>`zend-module`
|
@@ -137,7 +139,20 @@ A package type can have a custom installation path with a `type:` prefix.
|
|
137 |
}
|
138 |
```
|
139 |
|
140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
variables to use in your paths are: `{$name}`, `{$vendor}`, `{$type}`.
|
142 |
|
143 |
## Custom Install Names
|
@@ -191,3 +206,5 @@ It has been proposed many times. Even implemented once early on and then
|
|
191 |
removed. `installers` won't do this because it would allow a single package
|
192 |
author to wipe out entire folders without the user's consent. That user would
|
193 |
then come here to yell at us.
|
|
|
|
48 |
| Croogo | `croogo-plugin`<br>`croogo-theme`
|
49 |
| DokuWiki | `dokuwiki-plugin`<br>`dokuwiki-template`
|
50 |
| Dolibarr | `dolibarr-module`
|
51 |
+
| Drupal | <b>`drupal-core`<br>`drupal-module`<br>`drupal-theme`</b><br>`drupal-library`<br>`drupal-profile`<br>`drupal-drush`
|
52 |
| Elgg | `elgg-plugin`
|
53 |
| FuelPHP v1.x | `fuel-module`<br>`fuel-package`<br/>`fuel-theme`
|
54 |
| FuelPHP v2.x | `fuelphp-component`
|
55 |
| Grav | `grav-plugin`<br>`grav-theme`
|
56 |
| Hurad | `hurad-plugin`<br>`hurad-theme`
|
57 |
+
| ImageCMS | `imagecms-template`<br>`imagecms-module`<br>`imagecms-library`
|
58 |
| Joomla | `joomla-component`<br>`joomla-module`<br>`joomla-template`<br>`joomla-plugin`<br>`joomla-library`
|
59 |
+
| Kirby | **`kirby-plugin`**<br>`kirby-field`<br>`kirby-tag`
|
60 |
| KodiCMS | `kodicms-plugin`<br>`kodicms-media`
|
61 |
| Kohana | **`kohana-module`**
|
62 |
| Laravel | `laravel-library`
|
63 |
| Lithium | **`lithium-library`<br>`lithium-source`**
|
64 |
| Magento | `magento-library`<br>`magento-skin`<br>`magento-theme`
|
65 |
| Mako | `mako-package`
|
66 |
+
| Mautic | `mautic-plugin`<br>`mautic-theme`
|
67 |
| MODX Evo | `modxevo-snippet`<br>`modxevo-plugin`<br>`modxevo-module`<br>`modxevo-template`<br>`modxevo-lib`
|
68 |
| MediaWiki | `mediawiki-extension`
|
69 |
| October | **`october-module`<br>`october-plugin`<br>`october-theme`**
|
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`
|
139 |
}
|
140 |
```
|
141 |
|
142 |
+
You can also have the same vendor packages with a custom installation path by
|
143 |
+
using the `vendor:` prefix.
|
144 |
+
|
145 |
+
``` json
|
146 |
+
{
|
147 |
+
"extra": {
|
148 |
+
"installer-paths": {
|
149 |
+
"your/custom/path/{$name}/": ["vendor:my_organization"]
|
150 |
+
}
|
151 |
+
}
|
152 |
+
}
|
153 |
+
```
|
154 |
+
|
155 |
+
These would use your custom path for each of the listed packages. The available
|
156 |
variables to use in your paths are: `{$name}`, `{$vendor}`, `{$type}`.
|
157 |
|
158 |
## Custom Install Names
|
206 |
removed. `installers` won't do this because it would allow a single package
|
207 |
author to wipe out entire folders without the user's consent. That user would
|
208 |
then come here to yell at us.
|
209 |
+
|
210 |
+
Anyone still wanting this capability should consider requiring https://github.com/oomphinc/composer-installers-extender.
|
vendor/composer/installers/composer.json
CHANGED
@@ -22,12 +22,14 @@
|
|
22 |
"FuelPHP",
|
23 |
"Grav",
|
24 |
"Hurad",
|
|
|
25 |
"Joomla",
|
26 |
"Kohana",
|
27 |
"Laravel",
|
28 |
"Lithium",
|
29 |
"Magento",
|
30 |
"Mako",
|
|
|
31 |
"MODX Evo",
|
32 |
"MediaWiki",
|
33 |
"OXID",
|
@@ -49,7 +51,7 @@
|
|
49 |
"Zend",
|
50 |
"Zikula"
|
51 |
],
|
52 |
-
"homepage": "
|
53 |
"authors": [
|
54 |
{
|
55 |
"name": "Kyle Robinson Young",
|
@@ -58,7 +60,7 @@
|
|
58 |
}
|
59 |
],
|
60 |
"autoload": {
|
61 |
-
"psr-
|
62 |
},
|
63 |
"extra": {
|
64 |
"class": "Composer\\Installers\\Plugin",
|
@@ -71,10 +73,13 @@
|
|
71 |
"roundcube/plugin-installer": "*"
|
72 |
},
|
73 |
"require": {
|
74 |
-
"composer-plugin-api": "1.0
|
75 |
},
|
76 |
"require-dev": {
|
77 |
"composer/composer": "1.0.*@dev",
|
78 |
"phpunit/phpunit": "4.1.*"
|
|
|
|
|
|
|
79 |
}
|
80 |
}
|
22 |
"FuelPHP",
|
23 |
"Grav",
|
24 |
"Hurad",
|
25 |
+
"ImageCMS",
|
26 |
"Joomla",
|
27 |
"Kohana",
|
28 |
"Laravel",
|
29 |
"Lithium",
|
30 |
"Magento",
|
31 |
"Mako",
|
32 |
+
"Mautic",
|
33 |
"MODX Evo",
|
34 |
"MediaWiki",
|
35 |
"OXID",
|
51 |
"Zend",
|
52 |
"Zikula"
|
53 |
],
|
54 |
+
"homepage": "https://composer.github.io/installers/",
|
55 |
"authors": [
|
56 |
{
|
57 |
"name": "Kyle Robinson Young",
|
60 |
}
|
61 |
],
|
62 |
"autoload": {
|
63 |
+
"psr-4": { "Composer\\Installers\\": "src/Composer/Installers" }
|
64 |
},
|
65 |
"extra": {
|
66 |
"class": "Composer\\Installers\\Plugin",
|
73 |
"roundcube/plugin-installer": "*"
|
74 |
},
|
75 |
"require": {
|
76 |
+
"composer-plugin-api": "^1.0"
|
77 |
},
|
78 |
"require-dev": {
|
79 |
"composer/composer": "1.0.*@dev",
|
80 |
"phpunit/phpunit": "4.1.*"
|
81 |
+
},
|
82 |
+
"scripts": {
|
83 |
+
"test": "phpunit"
|
84 |
}
|
85 |
}
|
vendor/composer/installers/src/Composer/Installers/BaseInstaller.php
CHANGED
@@ -55,7 +55,7 @@ abstract class BaseInstaller
|
|
55 |
if ($this->composer->getPackage()) {
|
56 |
$extra = $this->composer->getPackage()->getExtra();
|
57 |
if (!empty($extra['installer-paths'])) {
|
58 |
-
$customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type);
|
59 |
if ($customPath !== false) {
|
60 |
return $this->templatePath($customPath, $availableVars);
|
61 |
}
|
@@ -120,12 +120,13 @@ abstract class BaseInstaller
|
|
120 |
* @param array $paths
|
121 |
* @param string $name
|
122 |
* @param string $type
|
|
|
123 |
* @return string
|
124 |
*/
|
125 |
-
protected function mapCustomInstallPaths(array $paths, $name, $type)
|
126 |
{
|
127 |
foreach ($paths as $path => $names) {
|
128 |
-
if (in_array($name, $names) || in_array('type:' . $type, $names)) {
|
129 |
return $path;
|
130 |
}
|
131 |
}
|
55 |
if ($this->composer->getPackage()) {
|
56 |
$extra = $this->composer->getPackage()->getExtra();
|
57 |
if (!empty($extra['installer-paths'])) {
|
58 |
+
$customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type, $vendor);
|
59 |
if ($customPath !== false) {
|
60 |
return $this->templatePath($customPath, $availableVars);
|
61 |
}
|
120 |
* @param array $paths
|
121 |
* @param string $name
|
122 |
* @param string $type
|
123 |
+
* @param string $vendor = NULL
|
124 |
* @return string
|
125 |
*/
|
126 |
+
protected function mapCustomInstallPaths(array $paths, $name, $type, $vendor = NULL)
|
127 |
{
|
128 |
foreach ($paths as $path => $names) {
|
129 |
+
if (in_array($name, $names) || in_array('type:' . $type, $names) || in_array('vendor:' . $vendor, $names)) {
|
130 |
return $path;
|
131 |
}
|
132 |
}
|
vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php
CHANGED
@@ -1,10 +1,24 @@
|
|
1 |
<?php
|
|
|
2 |
namespace Composer\Installers;
|
3 |
|
4 |
use Composer\Util\Filesystem;
|
5 |
|
6 |
/**
|
7 |
-
* Installer for Bitrix Framework
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
*
|
9 |
* @author Nik Samokhvalov <nik@samokhvalov.info>
|
10 |
* @author Denis Kulichkin <onexhovia@gmail.com>
|
@@ -12,16 +26,36 @@ use Composer\Util\Filesystem;
|
|
12 |
class BitrixInstaller extends BaseInstaller
|
13 |
{
|
14 |
protected $locations = array(
|
15 |
-
'module' => '
|
16 |
-
'component' => '
|
17 |
-
'theme' => '
|
18 |
);
|
19 |
|
20 |
/**
|
21 |
-
* @var array Storage for informations about duplicates at all the time of installation packages
|
22 |
*/
|
23 |
private static $checkedDuplicates = array();
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
* {@inheritdoc}
|
27 |
*/
|
@@ -34,39 +68,39 @@ class BitrixInstaller extends BaseInstaller
|
|
34 |
}
|
35 |
|
36 |
/**
|
37 |
-
* Duplicates search packages
|
38 |
*
|
39 |
-
* @param string $
|
40 |
* @param array $vars
|
41 |
*/
|
42 |
-
protected function checkDuplicates($
|
43 |
{
|
44 |
-
/**
|
45 |
-
* Incorrect paths for backward compatibility
|
46 |
-
*/
|
47 |
-
$oldLocations = array(
|
48 |
-
'module' => 'local/modules/{$name}/',
|
49 |
-
'component' => 'local/components/{$name}/',
|
50 |
-
'theme' => 'local/templates/{$name}/'
|
51 |
-
);
|
52 |
-
|
53 |
$packageType = substr($vars['type'], strlen('bitrix') + 1);
|
54 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
-
if (in_array($
|
57 |
return;
|
58 |
}
|
59 |
|
60 |
-
if ($
|
61 |
|
62 |
$this->io->writeError(' <error>Duplication of packages:</error>');
|
63 |
-
$this->io->writeError(' <info>Package ' . $
|
64 |
|
65 |
while (true) {
|
66 |
-
switch ($this->io->ask(' <info>Delete ' . $
|
67 |
case 'y':
|
68 |
$fs = new Filesystem();
|
69 |
-
$fs->removeDirectory($
|
70 |
break 2;
|
71 |
|
72 |
case 'n':
|
@@ -75,7 +109,7 @@ class BitrixInstaller extends BaseInstaller
|
|
75 |
case '?':
|
76 |
default:
|
77 |
$this->io->writeError(array(
|
78 |
-
' y - delete package ' . $
|
79 |
' n - don\'t delete and to continue with the installation',
|
80 |
));
|
81 |
$this->io->writeError(' ? - print help');
|
@@ -84,6 +118,6 @@ class BitrixInstaller extends BaseInstaller
|
|
84 |
}
|
85 |
}
|
86 |
|
87 |
-
static::$checkedDuplicates[] = $
|
88 |
}
|
89 |
}
|
1 |
<?php
|
2 |
+
|
3 |
namespace Composer\Installers;
|
4 |
|
5 |
use Composer\Util\Filesystem;
|
6 |
|
7 |
/**
|
8 |
+
* Installer for Bitrix Framework. Supported types of extensions:
|
9 |
+
* - `bitrix-module` — copy the module to directory `bitrix/modules/` directory.
|
10 |
+
* - `bitrix-component` — copy the component to directory `bitrix/components/`.
|
11 |
+
* - `bitrix-template` — copy the template to directory `bitrix/templates/`.
|
12 |
+
*
|
13 |
+
* You can set custom path to directory with Bitrix kernel in `composer.json`:
|
14 |
+
*
|
15 |
+
* ```json
|
16 |
+
* {
|
17 |
+
* "extra": {
|
18 |
+
* "bitrix-dir": "s1/bitrix"
|
19 |
+
* }
|
20 |
+
* }
|
21 |
+
* ```
|
22 |
*
|
23 |
* @author Nik Samokhvalov <nik@samokhvalov.info>
|
24 |
* @author Denis Kulichkin <onexhovia@gmail.com>
|
26 |
class BitrixInstaller extends BaseInstaller
|
27 |
{
|
28 |
protected $locations = array(
|
29 |
+
'module' => '{$bitrix_dir}/modules/{$name}/',
|
30 |
+
'component' => '{$bitrix_dir}/components/{$name}/',
|
31 |
+
'theme' => '{$bitrix_dir}/templates/{$name}/',
|
32 |
);
|
33 |
|
34 |
/**
|
35 |
+
* @var array Storage for informations about duplicates at all the time of installation packages.
|
36 |
*/
|
37 |
private static $checkedDuplicates = array();
|
38 |
|
39 |
+
/**
|
40 |
+
* {@inheritdoc}
|
41 |
+
*/
|
42 |
+
public function inflectPackageVars($vars)
|
43 |
+
{
|
44 |
+
if ($this->composer->getPackage()) {
|
45 |
+
$extra = $this->composer->getPackage()->getExtra();
|
46 |
+
|
47 |
+
if (isset($extra['bitrix-dir'])) {
|
48 |
+
$vars['bitrix_dir'] = $extra['bitrix-dir'];
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
if (!isset($vars['bitrix_dir'])) {
|
53 |
+
$vars['bitrix_dir'] = 'bitrix';
|
54 |
+
}
|
55 |
+
|
56 |
+
return parent::inflectPackageVars($vars);
|
57 |
+
}
|
58 |
+
|
59 |
/**
|
60 |
* {@inheritdoc}
|
61 |
*/
|
68 |
}
|
69 |
|
70 |
/**
|
71 |
+
* Duplicates search packages.
|
72 |
*
|
73 |
+
* @param string $path
|
74 |
* @param array $vars
|
75 |
*/
|
76 |
+
protected function checkDuplicates($path, array $vars = array())
|
77 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
$packageType = substr($vars['type'], strlen('bitrix') + 1);
|
79 |
+
$localDir = explode('/', $vars['bitrix_dir']);
|
80 |
+
array_pop($localDir);
|
81 |
+
$localDir[] = 'local';
|
82 |
+
$localDir = implode('/', $localDir);
|
83 |
+
|
84 |
+
$oldPath = str_replace(
|
85 |
+
array('{$bitrix_dir}', '{$name}'),
|
86 |
+
array($localDir, $vars['name']),
|
87 |
+
$this->locations[$packageType]
|
88 |
+
);
|
89 |
|
90 |
+
if (in_array($oldPath, static::$checkedDuplicates)) {
|
91 |
return;
|
92 |
}
|
93 |
|
94 |
+
if ($oldPath !== $path && file_exists($oldPath) && $this->io && $this->io->isInteractive()) {
|
95 |
|
96 |
$this->io->writeError(' <error>Duplication of packages:</error>');
|
97 |
+
$this->io->writeError(' <info>Package ' . $oldPath . ' will be called instead package ' . $path . '</info>');
|
98 |
|
99 |
while (true) {
|
100 |
+
switch ($this->io->ask(' <info>Delete ' . $oldPath . ' [y,n,?]?</info> ', '?')) {
|
101 |
case 'y':
|
102 |
$fs = new Filesystem();
|
103 |
+
$fs->removeDirectory($oldPath);
|
104 |
break 2;
|
105 |
|
106 |
case 'n':
|
109 |
case '?':
|
110 |
default:
|
111 |
$this->io->writeError(array(
|
112 |
+
' y - delete package ' . $oldPath . ' and to continue with the installation',
|
113 |
' n - don\'t delete and to continue with the installation',
|
114 |
));
|
115 |
$this->io->writeError(' ? - print help');
|
118 |
}
|
119 |
}
|
120 |
|
121 |
+
static::$checkedDuplicates[] = $oldPath;
|
122 |
}
|
123 |
}
|
vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php
CHANGED
@@ -10,5 +10,7 @@ class DrupalInstaller extends BaseInstaller
|
|
10 |
'library' => 'libraries/{$name}/',
|
11 |
'profile' => 'profiles/{$name}/',
|
12 |
'drush' => 'drush/{$name}/',
|
|
|
|
|
13 |
);
|
14 |
}
|
10 |
'library' => 'libraries/{$name}/',
|
11 |
'profile' => 'profiles/{$name}/',
|
12 |
'drush' => 'drush/{$name}/',
|
13 |
+
'custom-theme' => 'themes/custom/{$name}/',
|
14 |
+
'custom-module' => 'modules/custom/{$name}',
|
15 |
);
|
16 |
}
|
vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Composer\Installers;
|
3 |
+
|
4 |
+
class ImageCMSInstaller extends BaseInstaller
|
5 |
+
{
|
6 |
+
protected $locations = array(
|
7 |
+
'template' => 'templates/{$name}/',
|
8 |
+
'module' => 'application/modules/{$name}/',
|
9 |
+
'library' => 'application/libraries/{$name}/',
|
10 |
+
);
|
11 |
+
}
|
vendor/composer/installers/src/Composer/Installers/Installer.php
CHANGED
@@ -35,6 +35,7 @@ class Installer extends LibraryInstaller
|
|
35 |
'fuelphp' => 'FuelphpInstaller',
|
36 |
'grav' => 'GravInstaller',
|
37 |
'hurad' => 'HuradInstaller',
|
|
|
38 |
'joomla' => 'JoomlaInstaller',
|
39 |
'kirby' => 'KirbyInstaller',
|
40 |
'kodicms' => 'KodiCMSInstaller',
|
@@ -43,6 +44,7 @@ class Installer extends LibraryInstaller
|
|
43 |
'lithium' => 'LithiumInstaller',
|
44 |
'magento' => 'MagentoInstaller',
|
45 |
'mako' => 'MakoInstaller',
|
|
|
46 |
'mediawiki' => 'MediaWikiInstaller',
|
47 |
'microweber' => 'MicroweberInstaller',
|
48 |
'modulework' => 'MODULEWorkInstaller',
|
35 |
'fuelphp' => 'FuelphpInstaller',
|
36 |
'grav' => 'GravInstaller',
|
37 |
'hurad' => 'HuradInstaller',
|
38 |
+
'imagecms' => 'ImageCMSInstaller',
|
39 |
'joomla' => 'JoomlaInstaller',
|
40 |
'kirby' => 'KirbyInstaller',
|
41 |
'kodicms' => 'KodiCMSInstaller',
|
44 |
'lithium' => 'LithiumInstaller',
|
45 |
'magento' => 'MagentoInstaller',
|
46 |
'mako' => 'MakoInstaller',
|
47 |
+
'mautic' => 'MauticInstaller',
|
48 |
'mediawiki' => 'MediaWikiInstaller',
|
49 |
'microweber' => 'MicroweberInstaller',
|
50 |
'modulework' => 'MODULEWorkInstaller',
|
vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php
CHANGED
@@ -5,5 +5,7 @@ class KirbyInstaller extends BaseInstaller
|
|
5 |
{
|
6 |
protected $locations = array(
|
7 |
'plugin' => 'site/plugins/{$name}/',
|
|
|
|
|
8 |
);
|
9 |
}
|
5 |
{
|
6 |
protected $locations = array(
|
7 |
'plugin' => 'site/plugins/{$name}/',
|
8 |
+
'field' => 'site/fields/{$name}/',
|
9 |
+
'tag' => 'site/tags/{$name}/'
|
10 |
);
|
11 |
}
|
vendor/composer/installers/src/Composer/Installers/MauticInstaller.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Composer\Installers;
|
3 |
+
|
4 |
+
class MauticInstaller extends BaseInstaller
|
5 |
+
{
|
6 |
+
protected $locations = array(
|
7 |
+
'plugin' => 'plugins/{$name}/',
|
8 |
+
'theme' => 'themes/{$name}/',
|
9 |
+
);
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Format package name of mautic-plugins to CamelCase
|
13 |
+
*/
|
14 |
+
public function inflectPackageVars($vars)
|
15 |
+
{
|
16 |
+
if ($vars['type'] == 'mautic-plugin') {
|
17 |
+
$vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) {
|
18 |
+
return strtoupper($matches[0][1]);
|
19 |
+
}, ucfirst($vars['name']));
|
20 |
+
}
|
21 |
+
|
22 |
+
return $vars;
|
23 |
+
}
|
24 |
+
|
25 |
+
}
|
vendor/composer/installers/src/Composer/Installers/OxidInstaller.php
CHANGED
@@ -1,11 +1,59 @@
|
|
1 |
<?php
|
2 |
namespace Composer\Installers;
|
3 |
|
|
|
|
|
4 |
class OxidInstaller extends BaseInstaller
|
5 |
{
|
|
|
|
|
6 |
protected $locations = array(
|
7 |
'module' => 'modules/{$name}/',
|
8 |
'theme' => 'application/views/{$name}/',
|
9 |
'out' => 'out/{$name}/',
|
10 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
}
|
1 |
<?php
|
2 |
namespace Composer\Installers;
|
3 |
|
4 |
+
use Composer\Package\PackageInterface;
|
5 |
+
|
6 |
class OxidInstaller extends BaseInstaller
|
7 |
{
|
8 |
+
const VENDOR_PATTERN = '/^modules\/(?P<vendor>.+)\/.+/';
|
9 |
+
|
10 |
protected $locations = array(
|
11 |
'module' => 'modules/{$name}/',
|
12 |
'theme' => 'application/views/{$name}/',
|
13 |
'out' => 'out/{$name}/',
|
14 |
);
|
15 |
+
|
16 |
+
/**
|
17 |
+
* getInstallPath
|
18 |
+
*
|
19 |
+
* @param PackageInterface $package
|
20 |
+
* @param string $frameworkType
|
21 |
+
* @return void
|
22 |
+
*/
|
23 |
+
public function getInstallPath(PackageInterface $package, $frameworkType = '')
|
24 |
+
{
|
25 |
+
$installPath = parent::getInstallPath($package, $frameworkType);
|
26 |
+
$type = $this->package->getType();
|
27 |
+
if ($type === 'oxid-module') {
|
28 |
+
$this->prepareVendorDirectory($installPath);
|
29 |
+
}
|
30 |
+
return $installPath;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* prepareVendorDirectory
|
35 |
+
*
|
36 |
+
* Makes sure there is a vendormetadata.php file inside
|
37 |
+
* the vendor folder if there is a vendor folder.
|
38 |
+
*
|
39 |
+
* @param string $installPath
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
protected function prepareVendorDirectory($installPath)
|
43 |
+
{
|
44 |
+
$matches = '';
|
45 |
+
$hasVendorDirectory = preg_match(self::VENDOR_PATTERN, $installPath, $matches);
|
46 |
+
if (!$hasVendorDirectory) {
|
47 |
+
return;
|
48 |
+
}
|
49 |
+
|
50 |
+
$vendorDirectory = $matches['vendor'];
|
51 |
+
$vendorPath = getcwd() . '/modules/' . $vendorDirectory;
|
52 |
+
if (!file_exists($vendorPath)) {
|
53 |
+
mkdir($vendorPath, 0755, true);
|
54 |
+
}
|
55 |
+
|
56 |
+
$vendorMetaDataPath = $vendorPath . '/vendormetadata.php';
|
57 |
+
touch($vendorMetaDataPath);
|
58 |
+
}
|
59 |
}
|
vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php
CHANGED
@@ -4,6 +4,8 @@ namespace Composer\Installers;
|
|
4 |
/**
|
5 |
* Extension installer for TYPO3 CMS
|
6 |
*
|
|
|
|
|
7 |
* @author Sascha Egerer <sascha.egerer@dkd.de>
|
8 |
*/
|
9 |
class TYPO3CmsInstaller extends BaseInstaller
|
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
|
vendor/composer/installers/tests/Composer/Installers/Test/InstallerTest.php
CHANGED
@@ -121,6 +121,9 @@ class InstallerTest extends TestCase
|
|
121 |
array('fuelphp-component', true),
|
122 |
array('hurad-plugin', true),
|
123 |
array('hurad-theme', true),
|
|
|
|
|
|
|
124 |
array('joomla-library', true),
|
125 |
array('kirby-plugin', true),
|
126 |
array('kohana-module', true),
|
@@ -235,6 +238,9 @@ class InstallerTest extends TestCase
|
|
235 |
array('fuelphp-component', 'components/demo/', 'fuelphp/demo'),
|
236 |
array('hurad-plugin', 'plugins/Akismet/', 'atkrad/akismet'),
|
237 |
array('hurad-theme', 'plugins/Hurad2013/', 'atkrad/Hurad2013'),
|
|
|
|
|
|
|
238 |
array('joomla-plugin', 'plugins/my_plugin/', 'shama/my_plugin'),
|
239 |
array('kirby-plugin', 'site/plugins/my_plugin/', 'shama/my_plugin'),
|
240 |
array('kohana-module', 'modules/my_package/', 'shama/my_package'),
|
@@ -380,6 +386,27 @@ class InstallerTest extends TestCase
|
|
380 |
$this->assertEquals('my/custom/path/my_plugin/', $result);
|
381 |
}
|
382 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
/**
|
384 |
* testNoVendorName
|
385 |
*/
|
121 |
array('fuelphp-component', true),
|
122 |
array('hurad-plugin', true),
|
123 |
array('hurad-theme', true),
|
124 |
+
array('imagecms-template', true),
|
125 |
+
array('imagecms-module', true),
|
126 |
+
array('imagecms-library', true),
|
127 |
array('joomla-library', true),
|
128 |
array('kirby-plugin', true),
|
129 |
array('kohana-module', true),
|
238 |
array('fuelphp-component', 'components/demo/', 'fuelphp/demo'),
|
239 |
array('hurad-plugin', 'plugins/Akismet/', 'atkrad/akismet'),
|
240 |
array('hurad-theme', 'plugins/Hurad2013/', 'atkrad/Hurad2013'),
|
241 |
+
array('imagecms-template', 'templates/my_template/', 'shama/my_template'),
|
242 |
+
array('imagecms-module', 'application/modules/my_module/', 'shama/my_module'),
|
243 |
+
array('imagecms-library', 'application/libraries/my_library/', 'shama/my_library'),
|
244 |
array('joomla-plugin', 'plugins/my_plugin/', 'shama/my_plugin'),
|
245 |
array('kirby-plugin', 'site/plugins/my_plugin/', 'shama/my_plugin'),
|
246 |
array('kohana-module', 'modules/my_package/', 'shama/my_package'),
|
386 |
$this->assertEquals('my/custom/path/my_plugin/', $result);
|
387 |
}
|
388 |
|
389 |
+
/**
|
390 |
+
* testVendorPath
|
391 |
+
*/
|
392 |
+
public function testVendorPath()
|
393 |
+
{
|
394 |
+
$installer = new Installer($this->io, $this->composer);
|
395 |
+
$package = new Package('penyaskito/my_module', '1.0.0', '1.0.0');
|
396 |
+
$package->setType('drupal-module');
|
397 |
+
$consumerPackage = new RootPackage('drupal/drupal', '1.0.0', '1.0.0');
|
398 |
+
$this->composer->setPackage($consumerPackage);
|
399 |
+
$consumerPackage->setExtra(array(
|
400 |
+
'installer-paths' => array(
|
401 |
+
'modules/custom/{$name}/' => array(
|
402 |
+
'vendor:penyaskito'
|
403 |
+
),
|
404 |
+
),
|
405 |
+
));
|
406 |
+
$result = $installer->getInstallPath($package);
|
407 |
+
$this->assertEquals('modules/custom/my_module/', $result);
|
408 |
+
}
|
409 |
+
|
410 |
/**
|
411 |
* testNoVendorName
|
412 |
*/
|
vendor/twig/twig/CHANGELOG
CHANGED
@@ -1,4 +1,21 @@
|
|
1 |
-
* 1.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
* fixed some exception messages which triggered PHP warnings
|
4 |
* fixed BC on Twig_Test_NodeTestCase
|
1 |
+
* 1.24.0 (2016-01-25)
|
2 |
+
|
3 |
+
* adding support for the ?? operator
|
4 |
+
* fixed the defined test when used on a constant, a map, or a sequence
|
5 |
+
* undeprecated _self (should only be used to get the template name, not the template instance)
|
6 |
+
* fixed parsing on PHP7
|
7 |
+
|
8 |
+
* 1.23.3 (2016-01-11)
|
9 |
+
|
10 |
+
* fixed typo
|
11 |
+
|
12 |
+
* 1.23.2 (2015-01-11)
|
13 |
+
|
14 |
+
* added versions in deprecated messages
|
15 |
+
* made file cache tolerant for trailing (back)slashes on directory configuration
|
16 |
+
* deprecated unused Twig_Node_Expression_ExtensionReference class
|
17 |
+
|
18 |
+
* 1.23.1 (2015-11-05)
|
19 |
|
20 |
* fixed some exception messages which triggered PHP warnings
|
21 |
* fixed BC on Twig_Test_NodeTestCase
|
vendor/twig/twig/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
Copyright (c) 2009-
|
2 |
|
3 |
Some rights reserved.
|
4 |
|
1 |
+
Copyright (c) 2009-2016 by the Twig Team.
|
2 |
|
3 |
Some rights reserved.
|
4 |
|
vendor/twig/twig/composer.json
CHANGED
@@ -40,7 +40,7 @@
|
|
40 |
},
|
41 |
"extra": {
|
42 |
"branch-alias": {
|
43 |
-
"dev-master": "1.
|
44 |
}
|
45 |
}
|
46 |
}
|
40 |
},
|
41 |
"extra": {
|
42 |
"branch-alias": {
|
43 |
+
"dev-master": "1.24-dev"
|
44 |
}
|
45 |
}
|
46 |
}
|
vendor/twig/twig/doc/advanced.rst
CHANGED
@@ -554,7 +554,7 @@ An extension is a class that implements the following interface::
|
|
554 |
*
|
555 |
* @param Twig_Environment $environment The current Twig_Environment instance
|
556 |
*
|
557 |
-
* @deprecated since 1.23 (to be removed in 2.0), implement
|
558 |
*/
|
559 |
function initRuntime(Twig_Environment $environment);
|
560 |
|
554 |
*
|
555 |
* @param Twig_Environment $environment The current Twig_Environment instance
|
556 |
*
|
557 |
+
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
558 |
*/
|
559 |
function initRuntime(Twig_Environment $environment);
|
560 |
|
vendor/twig/twig/doc/deprecated.rst
CHANGED
@@ -144,9 +144,11 @@ Globals
|
|
144 |
or the extensions have been initialized is not possible anymore (but
|
145 |
changing the value of an already registered global is possible).
|
146 |
|
147 |
-
* As of Twig 1.x, the ``_self`` global variable
|
148 |
-
|
149 |
-
|
|
|
|
|
150 |
|
151 |
Miscellaneous
|
152 |
-------------
|
144 |
or the extensions have been initialized is not possible anymore (but
|
145 |
changing the value of an already registered global is possible).
|
146 |
|
147 |
+
* As of Twig 1.x, using the ``_self`` global variable to get access to the
|
148 |
+
current ``Twig_Template`` instance is deprecated; most usages only need the
|
149 |
+
current template name, which will continue to work in Twig 2.0. In Twig 2.0,
|
150 |
+
``_self`` returns the current template name instead of the current
|
151 |
+
``Twig_Template`` instance.
|
152 |
|
153 |
Miscellaneous
|
154 |
-------------
|
vendor/twig/twig/doc/templates.rst
CHANGED
@@ -127,7 +127,7 @@ Global Variables
|
|
127 |
|
128 |
The following variables are always available in templates:
|
129 |
|
130 |
-
* ``_self``: references the current template
|
131 |
* ``_context``: references the current context;
|
132 |
* ``_charset``: references the current charset.
|
133 |
|
@@ -808,6 +808,13 @@ The following operators don't fit into any of the other categories:
|
|
808 |
{{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
|
809 |
{{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
|
810 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
811 |
String Interpolation
|
812 |
~~~~~~~~~~~~~~~~~~~~
|
813 |
|
127 |
|
128 |
The following variables are always available in templates:
|
129 |
|
130 |
+
* ``_self``: references the current template;
|
131 |
* ``_context``: references the current context;
|
132 |
* ``_charset``: references the current charset.
|
133 |
|
808 |
{{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
|
809 |
{{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
|
810 |
|
811 |
+
* ``??``: The null-coalescing operator:
|
812 |
+
|
813 |
+
.. code-block:: jinja
|
814 |
+
|
815 |
+
{# returns the value of foo if it is defined and not null, 'no' otherwise #}
|
816 |
+
{{ foo ?? 'no' }}
|
817 |
+
|
818 |
String Interpolation
|
819 |
~~~~~~~~~~~~~~~~~~~~
|
820 |
|
vendor/twig/twig/ext/twig/php_twig.h
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
-
#define PHP_TWIG_VERSION "1.
|
19 |
|
20 |
#include "php.h"
|
21 |
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
+
#define PHP_TWIG_VERSION "1.24.0"
|
19 |
|
20 |
#include "php.h"
|
21 |
|
vendor/twig/twig/lib/Twig/Autoloader.php
CHANGED
@@ -9,14 +9,14 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
-
@trigger_error('The Twig_Autoloader class is deprecated and will be removed in 2.0. Use Composer instead.', E_USER_DEPRECATED);
|
13 |
|
14 |
/**
|
15 |
* Autoloads Twig classes.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*
|
19 |
-
* @deprecated
|
20 |
*/
|
21 |
class Twig_Autoloader
|
22 |
{
|
@@ -27,7 +27,7 @@ class Twig_Autoloader
|
|
27 |
*/
|
28 |
public static function register($prepend = false)
|
29 |
{
|
30 |
-
@trigger_error('Using Twig_Autoloader is deprecated. Use Composer instead.', E_USER_DEPRECATED);
|
31 |
|
32 |
if (PHP_VERSION_ID < 50300) {
|
33 |
spl_autoload_register(array(__CLASS__, 'autoload'));
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
@trigger_error('The Twig_Autoloader class is deprecated since version 1.21 and will be removed in 2.0. Use Composer instead.', E_USER_DEPRECATED);
|
13 |
|
14 |
/**
|
15 |
* Autoloads Twig classes.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*
|
19 |
+
* @deprecated since 1.21 and will be removed in 2.0. Use Composer instead. 2.0.
|
20 |
*/
|
21 |
class Twig_Autoloader
|
22 |
{
|
27 |
*/
|
28 |
public static function register($prepend = false)
|
29 |
{
|
30 |
+
@trigger_error('Using Twig_Autoloader is deprecated since version 1.21. Use Composer instead.', E_USER_DEPRECATED);
|
31 |
|
32 |
if (PHP_VERSION_ID < 50300) {
|
33 |
spl_autoload_register(array(__CLASS__, 'autoload'));
|
vendor/twig/twig/lib/Twig/Cache/Filesystem.php
CHANGED
@@ -27,7 +27,7 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
|
|
27 |
*/
|
28 |
public function __construct($directory, $options = 0)
|
29 |
{
|
30 |
-
$this->directory = $directory;
|
31 |
$this->options = $options;
|
32 |
}
|
33 |
|
@@ -38,7 +38,7 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
|
|
38 |
{
|
39 |
$hash = hash('sha256', $className);
|
40 |
|
41 |
-
return $this->directory
|
42 |
}
|
43 |
|
44 |
/**
|
27 |
*/
|
28 |
public function __construct($directory, $options = 0)
|
29 |
{
|
30 |
+
$this->directory = rtrim($directory, '\/').'/';
|
31 |
$this->options = $options;
|
32 |
}
|
33 |
|
38 |
{
|
39 |
$hash = hash('sha256', $className);
|
40 |
|
41 |
+
return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
|
42 |
}
|
43 |
|
44 |
/**
|
vendor/twig/twig/lib/Twig/Environment.php
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
-
const VERSION = '1.
|
20 |
|
21 |
protected $charset;
|
22 |
protected $loader;
|
@@ -93,7 +93,7 @@ class Twig_Environment
|
|
93 |
if (null !== $loader) {
|
94 |
$this->setLoader($loader);
|
95 |
} else {
|
96 |
-
@trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated.', E_USER_DEPRECATED);
|
97 |
}
|
98 |
|
99 |
$options = array_merge(array(
|
@@ -123,14 +123,14 @@ class Twig_Environment
|
|
123 |
if (is_string($this->originalCache)) {
|
124 |
$r = new ReflectionMethod($this, 'writeCacheFile');
|
125 |
if ($r->getDeclaringClass()->getName() !== __CLASS__) {
|
126 |
-
@trigger_error('The Twig_Environment::writeCacheFile method is deprecated and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
127 |
|
128 |
$this->bcWriteCacheFile = true;
|
129 |
}
|
130 |
|
131 |
$r = new ReflectionMethod($this, 'getCacheFilename');
|
132 |
if ($r->getDeclaringClass()->getName() !== __CLASS__) {
|
133 |
-
@trigger_error('The Twig_Environment::getCacheFilename method is deprecated and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
134 |
|
135 |
$this->bcGetCacheFilename = true;
|
136 |
}
|
@@ -265,7 +265,7 @@ class Twig_Environment
|
|
265 |
$this->originalCache = $cache;
|
266 |
$this->cache = new Twig_Cache_Null();
|
267 |
} elseif (null === $cache) {
|
268 |
-
@trigger_error('Using "null" as the cache strategy is deprecated and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
269 |
$this->originalCache = false;
|
270 |
$this->cache = new Twig_Cache_Null();
|
271 |
} elseif ($cache instanceof Twig_CacheInterface) {
|
@@ -286,7 +286,7 @@ class Twig_Environment
|
|
286 |
*/
|
287 |
public function getCacheFilename($name)
|
288 |
{
|
289 |
-
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
290 |
|
291 |
$key = $this->cache->generateKey($name, $this->getTemplateClass($name));
|
292 |
|
@@ -325,7 +325,7 @@ class Twig_Environment
|
|
325 |
*/
|
326 |
public function getTemplateClassPrefix()
|
327 |
{
|
328 |
-
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
329 |
|
330 |
return $this->templateClassPrefix;
|
331 |
}
|
@@ -515,7 +515,7 @@ class Twig_Environment
|
|
515 |
*/
|
516 |
public function clearTemplateCache()
|
517 |
{
|
518 |
-
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
519 |
|
520 |
$this->loadedTemplates = array();
|
521 |
}
|
@@ -527,7 +527,7 @@ class Twig_Environment
|
|
527 |
*/
|
528 |
public function clearCacheFiles()
|
529 |
{
|
530 |
-
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
531 |
|
532 |
if (is_string($this->originalCache)) {
|
533 |
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
@@ -737,7 +737,7 @@ class Twig_Environment
|
|
737 |
$m = new ReflectionMethod($extension, 'initRuntime');
|
738 |
|
739 |
if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
|
740 |
-
@trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated. Use the `needs_environment` option to get the Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig_Extension_InitRuntimeInterface if needed (not recommended).', $name), E_USER_DEPRECATED);
|
741 |
}
|
742 |
}
|
743 |
|
@@ -787,7 +787,7 @@ class Twig_Environment
|
|
787 |
}
|
788 |
|
789 |
if (isset($this->extensions[$name])) {
|
790 |
-
@trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $name), E_USER_DEPRECATED);
|
791 |
}
|
792 |
|
793 |
$this->lastModifiedExtension = 0;
|
@@ -806,7 +806,7 @@ class Twig_Environment
|
|
806 |
*/
|
807 |
public function removeExtension($name)
|
808 |
{
|
809 |
-
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
810 |
|
811 |
if ($this->extensionInitialized) {
|
812 |
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
|
@@ -928,7 +928,7 @@ class Twig_Environment
|
|
928 |
$filter = $name;
|
929 |
$name = $filter->getName();
|
930 |
} else {
|
931 |
-
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
932 |
}
|
933 |
|
934 |
if ($this->extensionInitialized) {
|
@@ -988,7 +988,7 @@ class Twig_Environment
|
|
988 |
/**
|
989 |
* Gets the registered Filters.
|
990 |
*
|
991 |
-
* Be warned that this method cannot return filters defined with
|
992 |
*
|
993 |
* @return Twig_FilterInterface[] An array of Twig_FilterInterface instances
|
994 |
*
|
@@ -1019,7 +1019,7 @@ class Twig_Environment
|
|
1019 |
$test = $name;
|
1020 |
$name = $test->getName();
|
1021 |
} else {
|
1022 |
-
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
1023 |
}
|
1024 |
|
1025 |
if ($this->extensionInitialized) {
|
@@ -1079,7 +1079,7 @@ class Twig_Environment
|
|
1079 |
$function = $name;
|
1080 |
$name = $function->getName();
|
1081 |
} else {
|
1082 |
-
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
1083 |
}
|
1084 |
|
1085 |
if ($this->extensionInitialized) {
|
@@ -1172,7 +1172,7 @@ class Twig_Environment
|
|
1172 |
|
1173 |
if (!array_key_exists($name, $this->globals)) {
|
1174 |
// The deprecation notice must be turned into the following exception in Twig 2.0
|
1175 |
-
@trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated.', $name), E_USER_DEPRECATED);
|
1176 |
//throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
|
1177 |
}
|
1178 |
}
|
@@ -1256,7 +1256,7 @@ class Twig_Environment
|
|
1256 |
*/
|
1257 |
public function computeAlternatives($name, $items)
|
1258 |
{
|
1259 |
-
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
1260 |
|
1261 |
return Twig_Error_Syntax::computeAlternatives($name, $items);
|
1262 |
}
|
@@ -1269,7 +1269,7 @@ class Twig_Environment
|
|
1269 |
$m = new ReflectionMethod($extension, 'getGlobals');
|
1270 |
|
1271 |
if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
|
1272 |
-
@trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension
|
1273 |
}
|
1274 |
}
|
1275 |
|
@@ -1314,7 +1314,7 @@ class Twig_Environment
|
|
1314 |
if ($filter instanceof Twig_SimpleFilter) {
|
1315 |
$name = $filter->getName();
|
1316 |
} else {
|
1317 |
-
@trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED);
|
1318 |
}
|
1319 |
|
1320 |
$this->filters[$name] = $filter;
|
@@ -1325,7 +1325,7 @@ class Twig_Environment
|
|
1325 |
if ($function instanceof Twig_SimpleFunction) {
|
1326 |
$name = $function->getName();
|
1327 |
} else {
|
1328 |
-
@trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED);
|
1329 |
}
|
1330 |
|
1331 |
$this->functions[$name] = $function;
|
@@ -1336,7 +1336,7 @@ class Twig_Environment
|
|
1336 |
if ($test instanceof Twig_SimpleTest) {
|
1337 |
$name = $test->getName();
|
1338 |
} else {
|
1339 |
-
@trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated. Use Twig_SimpleTest instead.', get_class($test), $name), E_USER_DEPRECATED);
|
1340 |
}
|
1341 |
|
1342 |
$this->tests[$name] = $test;
|
@@ -1347,7 +1347,7 @@ class Twig_Environment
|
|
1347 |
if ($parser instanceof Twig_TokenParserInterface) {
|
1348 |
$this->parsers->addTokenParser($parser);
|
1349 |
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
|
1350 |
-
@trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated.', E_USER_DEPRECATED);
|
1351 |
|
1352 |
$this->parsers->addTokenParserBroker($parser);
|
1353 |
} else {
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
+
const VERSION = '1.24.0';
|
20 |
|
21 |
protected $charset;
|
22 |
protected $loader;
|
93 |
if (null !== $loader) {
|
94 |
$this->setLoader($loader);
|
95 |
} else {
|
96 |
+
@trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated since version 1.21.', E_USER_DEPRECATED);
|
97 |
}
|
98 |
|
99 |
$options = array_merge(array(
|
123 |
if (is_string($this->originalCache)) {
|
124 |
$r = new ReflectionMethod($this, 'writeCacheFile');
|
125 |
if ($r->getDeclaringClass()->getName() !== __CLASS__) {
|
126 |
+
@trigger_error('The Twig_Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
127 |
|
128 |
$this->bcWriteCacheFile = true;
|
129 |
}
|
130 |
|
131 |
$r = new ReflectionMethod($this, 'getCacheFilename');
|
132 |
if ($r->getDeclaringClass()->getName() !== __CLASS__) {
|
133 |
+
@trigger_error('The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
134 |
|
135 |
$this->bcGetCacheFilename = true;
|
136 |
}
|
265 |
$this->originalCache = $cache;
|
266 |
$this->cache = new Twig_Cache_Null();
|
267 |
} elseif (null === $cache) {
|
268 |
+
@trigger_error('Using "null" as the cache strategy is deprecated since version 1.23 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
269 |
$this->originalCache = false;
|
270 |
$this->cache = new Twig_Cache_Null();
|
271 |
} elseif ($cache instanceof Twig_CacheInterface) {
|
286 |
*/
|
287 |
public function getCacheFilename($name)
|
288 |
{
|
289 |
+
@trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
290 |
|
291 |
$key = $this->cache->generateKey($name, $this->getTemplateClass($name));
|
292 |
|
325 |
*/
|
326 |
public function getTemplateClassPrefix()
|
327 |
{
|
328 |
+
@trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
329 |
|
330 |
return $this->templateClassPrefix;
|
331 |
}
|
515 |
*/
|
516 |
public function clearTemplateCache()
|
517 |
{
|
518 |
+
@trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
519 |
|
520 |
$this->loadedTemplates = array();
|
521 |
}
|
527 |
*/
|
528 |
public function clearCacheFiles()
|
529 |
{
|
530 |
+
@trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
531 |
|
532 |
if (is_string($this->originalCache)) {
|
533 |
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
737 |
$m = new ReflectionMethod($extension, 'initRuntime');
|
738 |
|
739 |
if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
|
740 |
+
@trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated since version 1.23. Use the `needs_environment` option to get the Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig_Extension_InitRuntimeInterface if needed (not recommended).', $name), E_USER_DEPRECATED);
|
741 |
}
|
742 |
}
|
743 |
|
787 |
}
|
788 |
|
789 |
if (isset($this->extensions[$name])) {
|
790 |
+
@trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $name), E_USER_DEPRECATED);
|
791 |
}
|
792 |
|
793 |
$this->lastModifiedExtension = 0;
|
806 |
*/
|
807 |
public function removeExtension($name)
|
808 |
{
|
809 |
+
@trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
810 |
|
811 |
if ($this->extensionInitialized) {
|
812 |
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
|
928 |
$filter = $name;
|
929 |
$name = $filter->getName();
|
930 |
} else {
|
931 |
+
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
932 |
}
|
933 |
|
934 |
if ($this->extensionInitialized) {
|
988 |
/**
|
989 |
* Gets the registered Filters.
|
990 |
*
|
991 |
+
* Be warned that this method cannot return filters defined with registerUndefinedFilterCallback.
|
992 |
*
|
993 |
* @return Twig_FilterInterface[] An array of Twig_FilterInterface instances
|
994 |
*
|
1019 |
$test = $name;
|
1020 |
$name = $test->getName();
|
1021 |
} else {
|
1022 |
+
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
1023 |
}
|
1024 |
|
1025 |
if ($this->extensionInitialized) {
|
1079 |
$function = $name;
|
1080 |
$name = $function->getName();
|
1081 |
} else {
|
1082 |
+
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
1083 |
}
|
1084 |
|
1085 |
if ($this->extensionInitialized) {
|
1172 |
|
1173 |
if (!array_key_exists($name, $this->globals)) {
|
1174 |
// The deprecation notice must be turned into the following exception in Twig 2.0
|
1175 |
+
@trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated since version 1.21.', $name), E_USER_DEPRECATED);
|
1176 |
//throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
|
1177 |
}
|
1178 |
}
|
1256 |
*/
|
1257 |
public function computeAlternatives($name, $items)
|
1258 |
{
|
1259 |
+
@trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
1260 |
|
1261 |
return Twig_Error_Syntax::computeAlternatives($name, $items);
|
1262 |
}
|
1269 |
$m = new ReflectionMethod($extension, 'getGlobals');
|
1270 |
|
1271 |
if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
|
1272 |
+
@trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension without explicitly implementing Twig_Extension_GlobalsInterface is deprecated since version 1.23.', $name), E_USER_DEPRECATED);
|
1273 |
}
|
1274 |
}
|
1275 |
|
1314 |
if ($filter instanceof Twig_SimpleFilter) {
|
1315 |
$name = $filter->getName();
|
1316 |
} else {
|
1317 |
+
@trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated since version 1.21. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED);
|
1318 |
}
|
1319 |
|
1320 |
$this->filters[$name] = $filter;
|
1325 |
if ($function instanceof Twig_SimpleFunction) {
|
1326 |
$name = $function->getName();
|
1327 |
} else {
|
1328 |
+
@trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated since version 1.21. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED);
|
1329 |
}
|
1330 |
|
1331 |
$this->functions[$name] = $function;
|
1336 |
if ($test instanceof Twig_SimpleTest) {
|
1337 |
$name = $test->getName();
|
1338 |
} else {
|
1339 |
+
@trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated since version 1.21. Use Twig_SimpleTest instead.', get_class($test), $name), E_USER_DEPRECATED);
|
1340 |
}
|
1341 |
|
1342 |
$this->tests[$name] = $test;
|
1347 |
if ($parser instanceof Twig_TokenParserInterface) {
|
1348 |
$this->parsers->addTokenParser($parser);
|
1349 |
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
|
1350 |
+
@trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED);
|
1351 |
|
1352 |
$this->parsers->addTokenParserBroker($parser);
|
1353 |
} else {
|
vendor/twig/twig/lib/Twig/ExpressionParser.php
CHANGED
@@ -373,7 +373,7 @@ class Twig_ExpressionParser
|
|
373 |
$arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
|
374 |
|
375 |
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
376 |
-
$type =
|
377 |
foreach ($this->parseArguments() as $n) {
|
378 |
$arguments->addElement($n);
|
379 |
}
|
@@ -578,6 +578,9 @@ class Twig_ExpressionParser
|
|
578 |
|
579 |
if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
|
580 |
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
|
|
|
|
|
|
|
581 |
if ($function->getAlternative()) {
|
582 |
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
|
583 |
}
|
@@ -606,6 +609,9 @@ class Twig_ExpressionParser
|
|
606 |
|
607 |
if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
|
608 |
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
|
|
|
|
|
|
|
609 |
if ($filter->getAlternative()) {
|
610 |
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
|
611 |
}
|
373 |
$arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
|
374 |
|
375 |
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
376 |
+
$type = Twig_Template::METHOD_CALL;
|
377 |
foreach ($this->parseArguments() as $n) {
|
378 |
$arguments->addElement($n);
|
379 |
}
|
578 |
|
579 |
if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
|
580 |
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
|
581 |
+
if (!is_bool($function->getDeprecatedVersion())) {
|
582 |
+
$message .= sprintf(' since version %s', $function->getDeprecatedVersion());
|
583 |
+
}
|
584 |
if ($function->getAlternative()) {
|
585 |
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
|
586 |
}
|
609 |
|
610 |
if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
|
611 |
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
|
612 |
+
if (!is_bool($filter->getDeprecatedVersion())) {
|
613 |
+
$message .= sprintf(' since version %s', $filter->getDeprecatedVersion());
|
614 |
+
}
|
615 |
if ($filter->getAlternative()) {
|
616 |
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
|
617 |
}
|
vendor/twig/twig/lib/Twig/Extension/Core.php
CHANGED
@@ -213,11 +213,11 @@ class Twig_Extension_Core extends Twig_Extension
|
|
213 |
new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
|
214 |
new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
|
215 |
new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
|
216 |
-
new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas', 'deprecated' =>
|
217 |
new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
|
218 |
new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
|
219 |
new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
|
220 |
-
new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby', 'deprecated' =>
|
221 |
new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
|
222 |
new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
|
223 |
new Twig_SimpleTest('empty', 'twig_test_empty'),
|
@@ -261,6 +261,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|
261 |
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
262 |
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
263 |
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
|
|
264 |
),
|
265 |
);
|
266 |
}
|
@@ -277,6 +278,9 @@ class Twig_Extension_Core extends Twig_Extension
|
|
277 |
|
278 |
if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
|
279 |
$message = sprintf('Twig Test "%s" is deprecated', $name);
|
|
|
|
|
|
|
280 |
if ($test->getAlternative()) {
|
281 |
$message .= sprintf('. Use "%s" instead', $test->getAlternative());
|
282 |
}
|
@@ -383,7 +387,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
383 |
return '';
|
384 |
}
|
385 |
if (null !== $charset = $env->getCharset()) {
|
386 |
-
if ('UTF-8'
|
387 |
$values = twig_convert_encoding($values, 'UTF-8', $charset);
|
388 |
}
|
389 |
|
@@ -391,7 +395,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
391 |
// split at all positions, but not after the start and not before the end
|
392 |
$values = preg_split('/(?<!^)(?!$)/u', $values);
|
393 |
|
394 |
-
if ('UTF-8'
|
395 |
foreach ($values as $i => $value) {
|
396 |
$values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
|
397 |
}
|
@@ -536,7 +540,7 @@ function twig_replace_filter($str, $from, $to = null)
|
|
536 |
if ($from instanceof Traversable) {
|
537 |
$from = iterator_to_array($from);
|
538 |
} elseif (is_string($from) && is_string($to)) {
|
539 |
-
@trigger_error('Using "replace" with character by character replacement is deprecated and will be removed in Twig 2.0', E_USER_DEPRECATED);
|
540 |
|
541 |
return strtr($str, $from, $to);
|
542 |
} elseif (!is_array($from)) {
|
@@ -916,7 +920,7 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
|
|
916 |
if (null !== $charset = $env->getCharset()) {
|
917 |
$string = (string) $item;
|
918 |
|
919 |
-
if ('UTF-8'
|
920 |
$item = twig_convert_encoding($string, 'UTF-8', $charset);
|
921 |
}
|
922 |
|
@@ -924,7 +928,7 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
|
|
924 |
|
925 |
$string = implode('', array_reverse($matches[0]));
|
926 |
|
927 |
-
if ('UTF-8'
|
928 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
929 |
}
|
930 |
|
@@ -1050,7 +1054,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1050 |
case 'js':
|
1051 |
// escape all non-alphanumeric characters
|
1052 |
// into their \xHH or \uHHHH representations
|
1053 |
-
if ('UTF-8'
|
1054 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1055 |
}
|
1056 |
|
@@ -1060,14 +1064,14 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1060 |
|
1061 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
|
1062 |
|
1063 |
-
if ('UTF-8'
|
1064 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
1065 |
}
|
1066 |
|
1067 |
return $string;
|
1068 |
|
1069 |
case 'css':
|
1070 |
-
if ('UTF-8'
|
1071 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1072 |
}
|
1073 |
|
@@ -1077,14 +1081,14 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1077 |
|
1078 |
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
|
1079 |
|
1080 |
-
if ('UTF-8'
|
1081 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
1082 |
}
|
1083 |
|
1084 |
return $string;
|
1085 |
|
1086 |
case 'html_attr':
|
1087 |
-
if ('UTF-8'
|
1088 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1089 |
}
|
1090 |
|
@@ -1094,7 +1098,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1094 |
|
1095 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
|
1096 |
|
1097 |
-
if ('UTF-8'
|
1098 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
1099 |
}
|
1100 |
|
@@ -1272,7 +1276,7 @@ if (function_exists('mb_get_info')) {
|
|
1272 |
*/
|
1273 |
function twig_upper_filter(Twig_Environment $env, $string)
|
1274 |
{
|
1275 |
-
if (null !==
|
1276 |
return mb_strtoupper($string, $charset);
|
1277 |
}
|
1278 |
|
@@ -1289,7 +1293,7 @@ if (function_exists('mb_get_info')) {
|
|
1289 |
*/
|
1290 |
function twig_lower_filter(Twig_Environment $env, $string)
|
1291 |
{
|
1292 |
-
if (null !==
|
1293 |
return mb_strtolower($string, $charset);
|
1294 |
}
|
1295 |
|
@@ -1306,7 +1310,7 @@ if (function_exists('mb_get_info')) {
|
|
1306 |
*/
|
1307 |
function twig_title_string_filter(Twig_Environment $env, $string)
|
1308 |
{
|
1309 |
-
if (null !==
|
1310 |
return mb_convert_case($string, MB_CASE_TITLE, $charset);
|
1311 |
}
|
1312 |
|
213 |
new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
|
214 |
new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
|
215 |
new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
|
216 |
+
new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas', 'deprecated' => '1.21', 'alternative' => 'same as')),
|
217 |
new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
|
218 |
new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
|
219 |
new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
|
220 |
+
new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby', 'deprecated' => '1.21', 'alternative' => 'divisible by')),
|
221 |
new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
|
222 |
new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
|
223 |
new Twig_SimpleTest('empty', 'twig_test_empty'),
|
261 |
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
262 |
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
263 |
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
264 |
+
'??' => array('precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
265 |
),
|
266 |
);
|
267 |
}
|
278 |
|
279 |
if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
|
280 |
$message = sprintf('Twig Test "%s" is deprecated', $name);
|
281 |
+
if (!is_bool($test->getDeprecatedVersion())) {
|
282 |
+
$message .= sprintf(' since version %s', $test->getDeprecatedVersion());
|
283 |
+
}
|
284 |
if ($test->getAlternative()) {
|
285 |
$message .= sprintf('. Use "%s" instead', $test->getAlternative());
|
286 |
}
|
387 |
return '';
|
388 |
}
|
389 |
if (null !== $charset = $env->getCharset()) {
|
390 |
+
if ('UTF-8' !== $charset) {
|
391 |
$values = twig_convert_encoding($values, 'UTF-8', $charset);
|
392 |
}
|
393 |
|
395 |
// split at all positions, but not after the start and not before the end
|
396 |
$values = preg_split('/(?<!^)(?!$)/u', $values);
|
397 |
|
398 |
+
if ('UTF-8' !== $charset) {
|
399 |
foreach ($values as $i => $value) {
|
400 |
$values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
|
401 |
}
|
540 |
if ($from instanceof Traversable) {
|
541 |
$from = iterator_to_array($from);
|
542 |
} elseif (is_string($from) && is_string($to)) {
|
543 |
+
@trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED);
|
544 |
|
545 |
return strtr($str, $from, $to);
|
546 |
} elseif (!is_array($from)) {
|
920 |
if (null !== $charset = $env->getCharset()) {
|
921 |
$string = (string) $item;
|
922 |
|
923 |
+
if ('UTF-8' !== $charset) {
|
924 |
$item = twig_convert_encoding($string, 'UTF-8', $charset);
|
925 |
}
|
926 |
|
928 |
|
929 |
$string = implode('', array_reverse($matches[0]));
|
930 |
|
931 |
+
if ('UTF-8' !== $charset) {
|
932 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
933 |
}
|
934 |
|
1054 |
case 'js':
|
1055 |
// escape all non-alphanumeric characters
|
1056 |
// into their \xHH or \uHHHH representations
|
1057 |
+
if ('UTF-8' !== $charset) {
|
1058 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1059 |
}
|
1060 |
|
1064 |
|
1065 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
|
1066 |
|
1067 |
+
if ('UTF-8' !== $charset) {
|
1068 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
1069 |
}
|
1070 |
|
1071 |
return $string;
|
1072 |
|
1073 |
case 'css':
|
1074 |
+
if ('UTF-8' !== $charset) {
|
1075 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1076 |
}
|
1077 |
|
1081 |
|
1082 |
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
|
1083 |
|
1084 |
+
if ('UTF-8' !== $charset) {
|
1085 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
1086 |
}
|
1087 |
|
1088 |
return $string;
|
1089 |
|
1090 |
case 'html_attr':
|
1091 |
+
if ('UTF-8' !== $charset) {
|
1092 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1093 |
}
|
1094 |
|
1098 |
|
1099 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
|
1100 |
|
1101 |
+
if ('UTF-8' !== $charset) {
|
1102 |
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
1103 |
}
|
1104 |
|
1276 |
*/
|
1277 |
function twig_upper_filter(Twig_Environment $env, $string)
|
1278 |
{
|
1279 |
+
if (null !== $charset = $env->getCharset()) {
|
1280 |
return mb_strtoupper($string, $charset);
|
1281 |
}
|
1282 |
|
1293 |
*/
|
1294 |
function twig_lower_filter(Twig_Environment $env, $string)
|
1295 |
{
|
1296 |
+
if (null !== $charset = $env->getCharset()) {
|
1297 |
return mb_strtolower($string, $charset);
|
1298 |
}
|
1299 |
|
1310 |
*/
|
1311 |
function twig_title_string_filter(Twig_Environment $env, $string)
|
1312 |
{
|
1313 |
+
if (null !== $charset = $env->getCharset()) {
|
1314 |
return mb_convert_case($string, MB_CASE_TITLE, $charset);
|
1315 |
}
|
1316 |
|
vendor/twig/twig/lib/Twig/Extension/Escaper.php
CHANGED
@@ -53,7 +53,7 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
53 |
{
|
54 |
// for BC
|
55 |
if (true === $defaultStrategy) {
|
56 |
-
@trigger_error('Using "true" as the default strategy is deprecated. Use "html" instead.', E_USER_DEPRECATED);
|
57 |
|
58 |
$defaultStrategy = 'html';
|
59 |
}
|
53 |
{
|
54 |
// for BC
|
55 |
if (true === $defaultStrategy) {
|
56 |
+
@trigger_error('Using "true" as the default strategy is deprecated since version 1.21. Use "html" instead.', E_USER_DEPRECATED);
|
57 |
|
58 |
$defaultStrategy = 'html';
|
59 |
}
|
vendor/twig/twig/lib/Twig/ExtensionInterface.php
CHANGED
@@ -23,7 +23,7 @@ interface Twig_ExtensionInterface
|
|
23 |
*
|
24 |
* @param Twig_Environment $environment The current Twig_Environment instance
|
25 |
*
|
26 |
-
* @deprecated since 1.23 (to be removed in 2.0), implement
|
27 |
*/
|
28 |
public function initRuntime(Twig_Environment $environment);
|
29 |
|
23 |
*
|
24 |
* @param Twig_Environment $environment The current Twig_Environment instance
|
25 |
*
|
26 |
+
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
27 |
*/
|
28 |
public function initRuntime(Twig_Environment $environment);
|
29 |
|
vendor/twig/twig/lib/Twig/Lexer.php
CHANGED
@@ -288,7 +288,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
288 |
protected function lexRawData($tag)
|
289 |
{
|
290 |
if ('raw' === $tag) {
|
291 |
-
@trigger_error(sprintf('Twig Tag "raw" is deprecated. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED);
|
292 |
}
|
293 |
|
294 |
if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
288 |
protected function lexRawData($tag)
|
289 |
{
|
290 |
if ('raw' === $tag) {
|
291 |
+
@trigger_error(sprintf('Twig Tag "raw" is deprecated since version 1.21. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED);
|
292 |
}
|
293 |
|
294 |
if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
vendor/twig/twig/lib/Twig/Node.php
CHANGED
@@ -74,7 +74,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
74 |
*/
|
75 |
public function toXml($asDom = false)
|
76 |
{
|
77 |
-
@trigger_error(sprintf('%s is deprecated.', __METHOD__), E_USER_DEPRECATED);
|
78 |
|
79 |
$dom = new DOMDocument('1.0', 'UTF-8');
|
80 |
$dom->formatOutput = true;
|
74 |
*/
|
75 |
public function toXml($asDom = false)
|
76 |
{
|
77 |
+
@trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
|
78 |
|
79 |
$dom = new DOMDocument('1.0', 'UTF-8');
|
80 |
$dom->formatOutput = true;
|
vendor/twig/twig/lib/Twig/Node/Expression/Call.php
CHANGED
@@ -122,53 +122,14 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
122 |
}
|
123 |
|
124 |
// manage named arguments
|
125 |
-
|
126 |
-
$r = new ReflectionMethod($callable[0], $callable[1]);
|
127 |
-
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
128 |
-
$r = new ReflectionObject($callable);
|
129 |
-
$r = $r->getMethod('__invoke');
|
130 |
-
} elseif (is_string($callable) && false !== strpos($callable, '::')) {
|
131 |
-
$r = new ReflectionMethod($callable);
|
132 |
-
} else {
|
133 |
-
$r = new ReflectionFunction($callable);
|
134 |
-
}
|
135 |
-
|
136 |
-
$definition = $r->getParameters();
|
137 |
-
if ($this->hasNode('node')) {
|
138 |
-
array_shift($definition);
|
139 |
-
}
|
140 |
-
if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
|
141 |
-
array_shift($definition);
|
142 |
-
}
|
143 |
-
if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
|
144 |
-
array_shift($definition);
|
145 |
-
}
|
146 |
-
if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
|
147 |
-
foreach ($this->getAttribute('arguments') as $argument) {
|
148 |
-
array_shift($definition);
|
149 |
-
}
|
150 |
-
}
|
151 |
-
if ($isVariadic) {
|
152 |
-
$argument = end($definition);
|
153 |
-
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
|
154 |
-
array_pop($definition);
|
155 |
-
} else {
|
156 |
-
$callableName = $r->name;
|
157 |
-
if ($r->getDeclaringClass()) {
|
158 |
-
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
159 |
-
}
|
160 |
-
|
161 |
-
throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $callType, $callName));
|
162 |
-
}
|
163 |
-
}
|
164 |
-
|
165 |
$arguments = array();
|
166 |
$names = array();
|
167 |
$missingArguments = array();
|
168 |
$optionalArguments = array();
|
169 |
$pos = 0;
|
170 |
-
foreach ($
|
171 |
-
$names[] = $name = $this->normalizeName($
|
172 |
|
173 |
if (array_key_exists($name, $parameters)) {
|
174 |
if (array_key_exists($pos, $parameters)) {
|
@@ -192,9 +153,9 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
192 |
unset($parameters[$pos]);
|
193 |
$optionalArguments = array();
|
194 |
++$pos;
|
195 |
-
} elseif ($
|
196 |
-
$optionalArguments[] = new Twig_Node_Expression_Constant($
|
197 |
-
} elseif ($
|
198 |
if (empty($parameters)) {
|
199 |
break;
|
200 |
} else {
|
@@ -244,4 +205,49 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
244 |
{
|
245 |
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
|
246 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
}
|
122 |
}
|
123 |
|
124 |
// manage named arguments
|
125 |
+
$callableParameters = $this->getCallableParameters($callable, $isVariadic);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
$arguments = array();
|
127 |
$names = array();
|
128 |
$missingArguments = array();
|
129 |
$optionalArguments = array();
|
130 |
$pos = 0;
|
131 |
+
foreach ($callableParameters as $callableParameter) {
|
132 |
+
$names[] = $name = $this->normalizeName($callableParameter->name);
|
133 |
|
134 |
if (array_key_exists($name, $parameters)) {
|
135 |
if (array_key_exists($pos, $parameters)) {
|
153 |
unset($parameters[$pos]);
|
154 |
$optionalArguments = array();
|
155 |
++$pos;
|
156 |
+
} elseif ($callableParameter->isDefaultValueAvailable()) {
|
157 |
+
$optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1);
|
158 |
+
} elseif ($callableParameter->isOptional()) {
|
159 |
if (empty($parameters)) {
|
160 |
break;
|
161 |
} else {
|
205 |
{
|
206 |
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
|
207 |
}
|
208 |
+
|
209 |
+
private function getCallableParameters($callable, $isVariadic)
|
210 |
+
{
|
211 |
+
if (is_array($callable)) {
|
212 |
+
$r = new ReflectionMethod($callable[0], $callable[1]);
|
213 |
+
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
214 |
+
$r = new ReflectionObject($callable);
|
215 |
+
$r = $r->getMethod('__invoke');
|
216 |
+
} elseif (is_string($callable) && false !== strpos($callable, '::')) {
|
217 |
+
$r = new ReflectionMethod($callable);
|
218 |
+
} else {
|
219 |
+
$r = new ReflectionFunction($callable);
|
220 |
+
}
|
221 |
+
|
222 |
+
$parameters = $r->getParameters();
|
223 |
+
if ($this->hasNode('node')) {
|
224 |
+
array_shift($parameters);
|
225 |
+
}
|
226 |
+
if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
|
227 |
+
array_shift($parameters);
|
228 |
+
}
|
229 |
+
if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
|
230 |
+
array_shift($parameters);
|
231 |
+
}
|
232 |
+
if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
|
233 |
+
foreach ($this->getAttribute('arguments') as $argument) {
|
234 |
+
array_shift($parameters);
|
235 |
+
}
|
236 |
+
}
|
237 |
+
if ($isVariadic) {
|
238 |
+
$argument = end($parameters);
|
239 |
+
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
|
240 |
+
array_pop($parameters);
|
241 |
+
} else {
|
242 |
+
$callableName = $r->name;
|
243 |
+
if ($r->getDeclaringClass()) {
|
244 |
+
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
245 |
+
}
|
246 |
+
|
247 |
+
throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
return $parameters;
|
252 |
+
}
|
253 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php
CHANGED
@@ -9,10 +9,14 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Represents an extension call node.
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
|
|
16 |
*/
|
17 |
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
18 |
{
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
@trigger_error('The Twig_Node_Expression_ExtensionReference class is deprecated since version 1.23 and will be removed in 2.0.', E_USER_DEPRECATED);
|
13 |
+
|
14 |
/**
|
15 |
* Represents an extension call node.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
+
*
|
19 |
+
* @deprecated since 1.23 and will be removed in 2.0.
|
20 |
*/
|
21 |
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
22 |
{
|
vendor/twig/twig/lib/Twig/Node/Expression/Name.php
CHANGED
@@ -30,19 +30,11 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|
30 |
|
31 |
if ($this->getAttribute('is_defined_test')) {
|
32 |
if ($this->isSpecial()) {
|
33 |
-
if ('_self' === $name) {
|
34 |
-
@trigger_error(sprintf('Global variable "_self" is deprecated in %s at line %d', '?', $this->getLine()), E_USER_DEPRECATED);
|
35 |
-
}
|
36 |
-
|
37 |
$compiler->repr(true);
|
38 |
} else {
|
39 |
$compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
|
40 |
}
|
41 |
} elseif ($this->isSpecial()) {
|
42 |
-
if ('_self' === $name) {
|
43 |
-
@trigger_error(sprintf('Global variable "_self" is deprecated in %s at line %d', '?', $this->getLine()), E_USER_DEPRECATED);
|
44 |
-
}
|
45 |
-
|
46 |
$compiler->raw($this->specialVars[$name]);
|
47 |
} elseif ($this->getAttribute('always_defined')) {
|
48 |
$compiler
|
30 |
|
31 |
if ($this->getAttribute('is_defined_test')) {
|
32 |
if ($this->isSpecial()) {
|
|
|
|
|
|
|
|
|
33 |
$compiler->repr(true);
|
34 |
} else {
|
35 |
$compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
|
36 |
}
|
37 |
} elseif ($this->isSpecial()) {
|
|
|
|
|
|
|
|
|
38 |
$compiler->raw($this->specialVars[$name]);
|
39 |
} elseif ($this->getAttribute('always_defined')) {
|
40 |
$compiler
|
vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) Fabien Potencier
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
class Twig_Node_Expression_NullCoalesce extends Twig_Node_Expression_Conditional
|
12 |
+
{
|
13 |
+
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
14 |
+
{
|
15 |
+
$test = new Twig_Node_Expression_Binary_And(
|
16 |
+
new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getLine()),
|
17 |
+
new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getLine()), $left->getLine()),
|
18 |
+
$left->getLine()
|
19 |
+
);
|
20 |
+
|
21 |
+
parent::__construct($test, $left, $right, $lineno);
|
22 |
+
}
|
23 |
+
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php
CHANGED
@@ -25,17 +25,19 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
|
25 |
{
|
26 |
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
27 |
{
|
28 |
-
parent::__construct($node, $name, $arguments, $lineno);
|
29 |
-
|
30 |
if ($node instanceof Twig_Node_Expression_Name) {
|
31 |
$node->setAttribute('is_defined_test', true);
|
32 |
} elseif ($node instanceof Twig_Node_Expression_GetAttr) {
|
33 |
$node->setAttribute('is_defined_test', true);
|
34 |
|
35 |
$this->changeIgnoreStrictCheck($node);
|
|
|
|
|
36 |
} else {
|
37 |
throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getLine());
|
38 |
}
|
|
|
|
|
39 |
}
|
40 |
|
41 |
protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
|
25 |
{
|
26 |
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
27 |
{
|
|
|
|
|
28 |
if ($node instanceof Twig_Node_Expression_Name) {
|
29 |
$node->setAttribute('is_defined_test', true);
|
30 |
} elseif ($node instanceof Twig_Node_Expression_GetAttr) {
|
31 |
$node->setAttribute('is_defined_test', true);
|
32 |
|
33 |
$this->changeIgnoreStrictCheck($node);
|
34 |
+
} elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) {
|
35 |
+
$node = new Twig_Node_Expression_Constant(true, $node->getLine());
|
36 |
} else {
|
37 |
throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getLine());
|
38 |
}
|
39 |
+
|
40 |
+
parent::__construct($node, $name, $arguments, $lineno);
|
41 |
}
|
42 |
|
43 |
protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
|
vendor/twig/twig/lib/Twig/Parser.php
CHANGED
@@ -63,7 +63,12 @@ class Twig_Parser implements Twig_ParserInterface
|
|
63 |
public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
|
64 |
{
|
65 |
// push all variables into the stack to keep the current state of the parser
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
67 |
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
|
68 |
$this->stack[] = $vars;
|
69 |
|
63 |
public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
|
64 |
{
|
65 |
// push all variables into the stack to keep the current state of the parser
|
66 |
+
// using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336
|
67 |
+
$vars = array();
|
68 |
+
foreach ($this as $k => $v) {
|
69 |
+
$vars[$k] = $v;
|
70 |
+
}
|
71 |
+
|
72 |
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
|
73 |
$this->stack[] = $vars;
|
74 |
|
vendor/twig/twig/lib/Twig/SimpleFilter.php
CHANGED
@@ -101,6 +101,11 @@ class Twig_SimpleFilter
|
|
101 |
}
|
102 |
|
103 |
public function isDeprecated()
|
|
|
|
|
|
|
|
|
|
|
104 |
{
|
105 |
return $this->options['deprecated'];
|
106 |
}
|
101 |
}
|
102 |
|
103 |
public function isDeprecated()
|
104 |
+
{
|
105 |
+
return (bool) $this->options['deprecated'];
|
106 |
+
}
|
107 |
+
|
108 |
+
public function getDeprecatedVersion()
|
109 |
{
|
110 |
return $this->options['deprecated'];
|
111 |
}
|
vendor/twig/twig/lib/Twig/SimpleFunction.php
CHANGED
@@ -91,6 +91,11 @@ class Twig_SimpleFunction
|
|
91 |
}
|
92 |
|
93 |
public function isDeprecated()
|
|
|
|
|
|
|
|
|
|
|
94 |
{
|
95 |
return $this->options['deprecated'];
|
96 |
}
|
91 |
}
|
92 |
|
93 |
public function isDeprecated()
|
94 |
+
{
|
95 |
+
return (bool) $this->options['deprecated'];
|
96 |
+
}
|
97 |
+
|
98 |
+
public function getDeprecatedVersion()
|
99 |
{
|
100 |
return $this->options['deprecated'];
|
101 |
}
|
vendor/twig/twig/lib/Twig/SimpleTest.php
CHANGED
@@ -53,6 +53,11 @@ class Twig_SimpleTest
|
|
53 |
}
|
54 |
|
55 |
public function isDeprecated()
|
|
|
|
|
|
|
|
|
|
|
56 |
{
|
57 |
return $this->options['deprecated'];
|
58 |
}
|
53 |
}
|
54 |
|
55 |
public function isDeprecated()
|
56 |
+
{
|
57 |
+
return (bool) $this->options['deprecated'];
|
58 |
+
}
|
59 |
+
|
60 |
+
public function getDeprecatedVersion()
|
61 |
{
|
62 |
return $this->options['deprecated'];
|
63 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php
CHANGED
@@ -50,7 +50,7 @@ class Twig_TokenParser_AutoEscape extends Twig_TokenParser
|
|
50 |
}
|
51 |
|
52 |
if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
|
53 |
-
@trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated.', E_USER_DEPRECATED);
|
54 |
|
55 |
if (false === $value) {
|
56 |
throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename());
|
50 |
}
|
51 |
|
52 |
if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
|
53 |
+
@trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED);
|
54 |
|
55 |
if (false === $value) {
|
56 |
throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename());
|
vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php
CHANGED
@@ -9,35 +9,26 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
-
private $nonce;
|
15 |
private $classname;
|
16 |
private $directory;
|
17 |
private $cache;
|
18 |
|
19 |
protected function setUp()
|
20 |
{
|
21 |
-
$
|
22 |
-
$this->classname = '__Twig_Tests_Cache_FilesystemTest_Template_'.$
|
23 |
-
$this->directory = sys_get_temp_dir().'/twig-test
|
24 |
$this->cache = new Twig_Cache_Filesystem($this->directory);
|
25 |
}
|
26 |
|
27 |
protected function tearDown()
|
28 |
{
|
29 |
if (file_exists($this->directory)) {
|
30 |
-
|
31 |
-
foreach ($iterator as $filename => $fileInfo) {
|
32 |
-
if (!$iterator->isDot()) {
|
33 |
-
if ($fileInfo->isDir()) {
|
34 |
-
rmdir($filename);
|
35 |
-
} else {
|
36 |
-
unlink($filename);
|
37 |
-
}
|
38 |
-
}
|
39 |
-
}
|
40 |
-
rmdir($this->directory);
|
41 |
}
|
42 |
}
|
43 |
|
@@ -86,10 +77,14 @@ class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
86 |
|
87 |
/**
|
88 |
* @expectedException RuntimeException
|
89 |
-
* @
|
90 |
*/
|
91 |
public function testWriteFailMkdir()
|
92 |
{
|
|
|
|
|
|
|
|
|
93 |
$key = $this->directory.'/cache/cachefile.php';
|
94 |
$content = $this->generateSource();
|
95 |
|
@@ -104,10 +99,14 @@ class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
104 |
|
105 |
/**
|
106 |
* @expectedException RuntimeException
|
107 |
-
* @
|
108 |
*/
|
109 |
public function testWriteFailDirWritable()
|
110 |
{
|
|
|
|
|
|
|
|
|
111 |
$key = $this->directory.'/cache/cachefile.php';
|
112 |
$content = $this->generateSource();
|
113 |
|
@@ -124,7 +123,7 @@ class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
124 |
|
125 |
/**
|
126 |
* @expectedException RuntimeException
|
127 |
-
* @
|
128 |
*/
|
129 |
public function testWriteFailWriteFile()
|
130 |
{
|
@@ -160,6 +159,31 @@ class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
160 |
$this->assertSame(0, $this->cache->getTimestamp($key));
|
161 |
}
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
private function generateSource()
|
164 |
{
|
165 |
return strtr('<?php class {{classname}} {}', array(
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
require_once dirname(dirname(__FILE__)).'/FilesystemHelper.php';
|
13 |
+
|
14 |
class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
15 |
{
|
|
|
16 |
private $classname;
|
17 |
private $directory;
|
18 |
private $cache;
|
19 |
|
20 |
protected function setUp()
|
21 |
{
|
22 |
+
$nonce = hash('sha256', uniqid(mt_rand(), true));
|
23 |
+
$this->classname = '__Twig_Tests_Cache_FilesystemTest_Template_'.$nonce;
|
24 |
+
$this->directory = sys_get_temp_dir().'/twig-test';
|
25 |
$this->cache = new Twig_Cache_Filesystem($this->directory);
|
26 |
}
|
27 |
|
28 |
protected function tearDown()
|
29 |
{
|
30 |
if (file_exists($this->directory)) {
|
31 |
+
Twig_Tests_FilesystemHelper::removeDir($this->directory);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
}
|
34 |
|
77 |
|
78 |
/**
|
79 |
* @expectedException RuntimeException
|
80 |
+
* @expectedExceptionMessage Unable to create the cache directory
|
81 |
*/
|
82 |
public function testWriteFailMkdir()
|
83 |
{
|
84 |
+
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
85 |
+
$this->markTestSkipped('Read-only directories not possible on Windows.');
|
86 |
+
}
|
87 |
+
|
88 |
$key = $this->directory.'/cache/cachefile.php';
|
89 |
$content = $this->generateSource();
|
90 |
|
99 |
|
100 |
/**
|
101 |
* @expectedException RuntimeException
|
102 |
+
* @expectedExceptionMessage Unable to write in the cache directory
|
103 |
*/
|
104 |
public function testWriteFailDirWritable()
|
105 |
{
|
106 |
+
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
107 |
+
$this->markTestSkipped('Read-only directories not possible on Windows.');
|
108 |
+
}
|
109 |
+
|
110 |
$key = $this->directory.'/cache/cachefile.php';
|
111 |
$content = $this->generateSource();
|
112 |
|
123 |
|
124 |
/**
|
125 |
* @expectedException RuntimeException
|
126 |
+
* @expectedExceptionMessage Failed to write cache file
|
127 |
*/
|
128 |
public function testWriteFailWriteFile()
|
129 |
{
|
159 |
$this->assertSame(0, $this->cache->getTimestamp($key));
|
160 |
}
|
161 |
|
162 |
+
/**
|
163 |
+
* Test file cache is tolerant towards trailing (back)slashes on the configured cache directory.
|
164 |
+
*
|
165 |
+
* @dataProvider provideDirectories
|
166 |
+
*/
|
167 |
+
public function testGenerateKey($expected, $input)
|
168 |
+
{
|
169 |
+
$cache = new Twig_Cache_Filesystem($input);
|
170 |
+
$this->assertRegExp($expected, $cache->generateKey('_test_', get_class($this)));
|
171 |
+
}
|
172 |
+
|
173 |
+
public function provideDirectories()
|
174 |
+
{
|
175 |
+
$pattern = '#a/b/[a-zA-Z0-9]+/[a-zA-Z0-9]+.php$#';
|
176 |
+
|
177 |
+
return array(
|
178 |
+
array($pattern, 'a/b'),
|
179 |
+
array($pattern, 'a/b/'),
|
180 |
+
array($pattern, 'a/b\\'),
|
181 |
+
array($pattern, 'a/b\\/'),
|
182 |
+
array($pattern, 'a/b\\//'),
|
183 |
+
array('#/'.substr($pattern, 1), '/a/b'),
|
184 |
+
);
|
185 |
+
}
|
186 |
+
|
187 |
private function generateSource()
|
188 |
{
|
189 |
return strtr('<?php class {{classname}} {}', array(
|
vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
private $deprecations = array();
|
@@ -154,8 +156,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
154 |
|
155 |
public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
|
156 |
{
|
157 |
-
$
|
158 |
-
$cache = new Twig_Cache_Filesystem($dir = sys_get_temp_dir().'/twig'.$uid);
|
159 |
$options = array('cache' => $cache, 'auto_reload' => false, 'debug' => false);
|
160 |
|
161 |
// force compilation
|
@@ -178,7 +179,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
178 |
$output = $twig->render('index', array('foo' => 'bar'));
|
179 |
$this->assertEquals('bar', $output);
|
180 |
|
181 |
-
|
182 |
}
|
183 |
|
184 |
public function testAutoReloadCacheMiss()
|
@@ -290,7 +291,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
290 |
$this->assertArrayHasKey('foo_global', $twig->getGlobals());
|
291 |
|
292 |
$this->assertCount(1, $this->deprecations);
|
293 |
-
$this->assertContains('Defining the getGlobals() method in the "environment_test" extension
|
294 |
|
295 |
restore_error_handler();
|
296 |
}
|
@@ -352,7 +353,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
352 |
$twig->initRuntime();
|
353 |
|
354 |
$this->assertCount(1, $this->deprecations);
|
355 |
-
$this->assertContains('Defining the initRuntime() method in the "with_deprecation" extension is deprecated.', $this->deprecations[0]);
|
356 |
|
357 |
restore_error_handler();
|
358 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
require_once dirname(__FILE__).'/FilesystemHelper.php';
|
13 |
+
|
14 |
class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
15 |
{
|
16 |
private $deprecations = array();
|
156 |
|
157 |
public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
|
158 |
{
|
159 |
+
$cache = new Twig_Cache_Filesystem($dir = sys_get_temp_dir().'/twig');
|
|
|
160 |
$options = array('cache' => $cache, 'auto_reload' => false, 'debug' => false);
|
161 |
|
162 |
// force compilation
|
179 |
$output = $twig->render('index', array('foo' => 'bar'));
|
180 |
$this->assertEquals('bar', $output);
|
181 |
|
182 |
+
Twig_Tests_FilesystemHelper::removeDir($dir);
|
183 |
}
|
184 |
|
185 |
public function testAutoReloadCacheMiss()
|
291 |
$this->assertArrayHasKey('foo_global', $twig->getGlobals());
|
292 |
|
293 |
$this->assertCount(1, $this->deprecations);
|
294 |
+
$this->assertContains('Defining the getGlobals() method in the "environment_test" extension ', $this->deprecations[0]);
|
295 |
|
296 |
restore_error_handler();
|
297 |
}
|
353 |
$twig->initRuntime();
|
354 |
|
355 |
$this->assertCount(1, $this->deprecations);
|
356 |
+
$this->assertContains('Defining the initRuntime() method in the "with_deprecation" extension is deprecated since version 1.23.', $this->deprecations[0]);
|
357 |
|
358 |
restore_error_handler();
|
359 |
}
|
vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
CHANGED
@@ -13,7 +13,7 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
13 |
{
|
14 |
protected static $params, $templates;
|
15 |
|
16 |
-
|
17 |
{
|
18 |
self::$params = array(
|
19 |
'name' => 'Fabien',
|
13 |
{
|
14 |
protected static $params, $templates;
|
15 |
|
16 |
+
protected function setUp()
|
17 |
{
|
18 |
self::$params = array(
|
19 |
'name' => 'Fabien',
|
vendor/twig/twig/test/Twig/Tests/FileCachingTest.php
CHANGED
@@ -9,13 +9,14 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
class Twig_Tests_FileCachingTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
-
|
15 |
-
|
16 |
-
protected $tmpDir;
|
17 |
|
18 |
-
|
19 |
{
|
20 |
$this->tmpDir = sys_get_temp_dir().'/TwigTests';
|
21 |
if (!file_exists($this->tmpDir)) {
|
@@ -29,13 +30,9 @@ class Twig_Tests_FileCachingTest extends PHPUnit_Framework_TestCase
|
|
29 |
$this->env = new Twig_Environment(new Twig_Loader_Array(array('index' => 'index', 'index2' => 'index2')), array('cache' => $this->tmpDir));
|
30 |
}
|
31 |
|
32 |
-
|
33 |
{
|
34 |
-
|
35 |
-
unlink($this->fileName);
|
36 |
-
}
|
37 |
-
|
38 |
-
$this->removeDir($this->tmpDir);
|
39 |
}
|
40 |
|
41 |
/**
|
@@ -48,7 +45,6 @@ class Twig_Tests_FileCachingTest extends PHPUnit_Framework_TestCase
|
|
48 |
$cacheFileName = $this->env->getCacheFilename($name);
|
49 |
|
50 |
$this->assertTrue(file_exists($cacheFileName), 'Cache file does not exist.');
|
51 |
-
$this->fileName = $cacheFileName;
|
52 |
}
|
53 |
|
54 |
/**
|
@@ -64,22 +60,4 @@ class Twig_Tests_FileCachingTest extends PHPUnit_Framework_TestCase
|
|
64 |
$this->env->clearCacheFiles();
|
65 |
$this->assertFalse(file_exists($cacheFileName), 'Cache file was not cleared.');
|
66 |
}
|
67 |
-
|
68 |
-
private function removeDir($target)
|
69 |
-
{
|
70 |
-
$fp = opendir($target);
|
71 |
-
while (false !== $file = readdir($fp)) {
|
72 |
-
if (in_array($file, array('.', '..'))) {
|
73 |
-
continue;
|
74 |
-
}
|
75 |
-
|
76 |
-
if (is_dir($target.'/'.$file)) {
|
77 |
-
self::removeDir($target.'/'.$file);
|
78 |
-
} else {
|
79 |
-
unlink($target.'/'.$file);
|
80 |
-
}
|
81 |
-
}
|
82 |
-
closedir($fp);
|
83 |
-
rmdir($target);
|
84 |
-
}
|
85 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
require_once dirname(__FILE__).'/FilesystemHelper.php';
|
13 |
+
|
14 |
class Twig_Tests_FileCachingTest extends PHPUnit_Framework_TestCase
|
15 |
{
|
16 |
+
private $env;
|
17 |
+
private $tmpDir;
|
|
|
18 |
|
19 |
+
protected function setUp()
|
20 |
{
|
21 |
$this->tmpDir = sys_get_temp_dir().'/TwigTests';
|
22 |
if (!file_exists($this->tmpDir)) {
|
30 |
$this->env = new Twig_Environment(new Twig_Loader_Array(array('index' => 'index', 'index2' => 'index2')), array('cache' => $this->tmpDir));
|
31 |
}
|
32 |
|
33 |
+
protected function tearDown()
|
34 |
{
|
35 |
+
Twig_Tests_FilesystemHelper::removeDir($this->tmpDir);
|
|
|
|
|
|
|
|
|
36 |
}
|
37 |
|
38 |
/**
|
45 |
$cacheFileName = $this->env->getCacheFilename($name);
|
46 |
|
47 |
$this->assertTrue(file_exists($cacheFileName), 'Cache file does not exist.');
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
60 |
$this->env->clearCacheFiles();
|
61 |
$this->assertFalse(file_exists($cacheFileName), 'Cache file was not cleared.');
|
62 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}
|
vendor/twig/twig/test/Twig/Tests/FilesystemHelper.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) Fabien Potencier
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
class Twig_Tests_FilesystemHelper
|
13 |
+
{
|
14 |
+
public static function removeDir($dir)
|
15 |
+
{
|
16 |
+
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, PHP_VERSION_ID < 50300 ? 0 : FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
|
17 |
+
foreach ($iterator as $filename => $fileInfo) {
|
18 |
+
if ($iterator->isDot()) {
|
19 |
+
continue;
|
20 |
+
}
|
21 |
+
|
22 |
+
if ($fileInfo->isDir()) {
|
23 |
+
rmdir($filename);
|
24 |
+
} else {
|
25 |
+
unlink($filename);
|
26 |
+
}
|
27 |
+
}
|
28 |
+
rmdir($dir);
|
29 |
+
}
|
30 |
+
}
|
vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test
CHANGED
@@ -17,6 +17,7 @@
|
|
17 |
block1extended
|
18 |
{% endblock %}
|
19 |
{% endembed %}
|
|
|
20 |
{% endblock %}
|
21 |
--TEMPLATE(base.twig)--
|
22 |
A
|
@@ -54,4 +55,6 @@ A
|
|
54 |
block1extended
|
55 |
B
|
56 |
block2
|
57 |
-
|
|
|
|
17 |
block1extended
|
18 |
{% endblock %}
|
19 |
{% endembed %}
|
20 |
+
{{ parent() }}
|
21 |
{% endblock %}
|
22 |
--TEMPLATE(base.twig)--
|
23 |
A
|
55 |
block1extended
|
56 |
B
|
57 |
block2
|
58 |
+
C blockc2base
|
59 |
+
|
60 |
+
B
|
vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined.test
CHANGED
@@ -26,6 +26,13 @@
|
|
26 |
{{ object.self.foo is defined ? 'ok' : 'ko' }}
|
27 |
{{ object.self.undefinedMethod is defined ? 'ko' : 'ok' }}
|
28 |
{{ object.undefinedMethod.self is defined ? 'ko' : 'ok' }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
--DATA--
|
30 |
return array(
|
31 |
'definedVar' => 'defined',
|
@@ -65,6 +72,13 @@ ok
|
|
65 |
ok
|
66 |
ok
|
67 |
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
--DATA--
|
69 |
return array(
|
70 |
'definedVar' => 'defined',
|
@@ -106,3 +120,10 @@ ok
|
|
106 |
ok
|
107 |
ok
|
108 |
ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
{{ object.self.foo is defined ? 'ok' : 'ko' }}
|
27 |
{{ object.self.undefinedMethod is defined ? 'ko' : 'ok' }}
|
28 |
{{ object.undefinedMethod.self is defined ? 'ko' : 'ok' }}
|
29 |
+
{{ 0 is defined ? 'ok' : 'ko' }}
|
30 |
+
{{ "foo" is defined ? 'ok' : 'ko' }}
|
31 |
+
{{ true is defined ? 'ok' : 'ko' }}
|
32 |
+
{{ false is defined ? 'ok' : 'ko' }}
|
33 |
+
{{ null is defined ? 'ok' : 'ko' }}
|
34 |
+
{{ [1, 2] is defined ? 'ok' : 'ko' }}
|
35 |
+
{{ { foo: "bar" } is defined ? 'ok' : 'ko' }}
|
36 |
--DATA--
|
37 |
return array(
|
38 |
'definedVar' => 'defined',
|
72 |
ok
|
73 |
ok
|
74 |
ok
|
75 |
+
ok
|
76 |
+
ok
|
77 |
+
ok
|
78 |
+
ok
|
79 |
+
ok
|
80 |
+
ok
|
81 |
+
ok
|
82 |
--DATA--
|
83 |
return array(
|
84 |
'definedVar' => 'defined',
|
120 |
ok
|
121 |
ok
|
122 |
ok
|
123 |
+
ok
|
124 |
+
ok
|
125 |
+
ok
|
126 |
+
ok
|
127 |
+
ok
|
128 |
+
ok
|
129 |
+
ok
|
vendor/twig/twig/test/Twig/Tests/Fixtures/tests/null_coalesce.test
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
Twig supports the ?? operator
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ 'OK' ?? 'KO' }}
|
5 |
+
{{ null ?? 'OK' }}
|
6 |
+
{{ bar ?? 'KO' }}
|
7 |
+
{{ baz ?? 'OK' }}
|
8 |
+
{{ foo.bar ?? 'KO' }}
|
9 |
+
{{ foo.missing ?? 'OK' }}
|
10 |
+
{{ foo.bar.baz.missing ?? 'OK' }}
|
11 |
+
{{ foo['bar'] ?? 'KO' }}
|
12 |
+
{{ foo['missing'] ?? 'OK' }}
|
13 |
+
{{ nope ?? nada ?? 'OK' }}
|
14 |
+
{{ 1 + nope ?? nada ?? 2 }}
|
15 |
+
{{ 1 + nope ?? 3 + nada ?? 2 }}
|
16 |
+
--DATA--
|
17 |
+
return array('bar' => 'OK', 'foo' => array('bar' => 'OK'))
|
18 |
+
--EXPECT--
|
19 |
+
OK
|
20 |
+
OK
|
21 |
+
OK
|
22 |
+
OK
|
23 |
+
OK
|
24 |
+
OK
|
25 |
+
OK
|
26 |
+
OK
|
27 |
+
OK
|
28 |
+
OK
|
29 |
+
3
|
30 |
+
6
|
vendor/twig/twig/test/Twig/Tests/TokenStreamTest.php
CHANGED
@@ -13,7 +13,7 @@ class Twig_Tests_TokenStreamTest extends PHPUnit_Framework_TestCase
|
|
13 |
{
|
14 |
protected static $tokens;
|
15 |
|
16 |
-
|
17 |
{
|
18 |
self::$tokens = array(
|
19 |
new Twig_Token(Twig_Token::TEXT_TYPE, 1, 1),
|
13 |
{
|
14 |
protected static $tokens;
|
15 |
|
16 |
+
protected function setUp()
|
17 |
{
|
18 |
self::$tokens = array(
|
19 |
new Twig_Token(Twig_Token::TEXT_TYPE, 1, 1),
|
vendor/twig/twig/test/Twig/Tests/escapingTest.php
CHANGED
@@ -144,7 +144,7 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
144 |
|
145 |
protected $env;
|
146 |
|
147 |
-
|
148 |
{
|
149 |
$this->env = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
|
150 |
}
|
144 |
|
145 |
protected $env;
|
146 |
|
147 |
+
protected function setUp()
|
148 |
{
|
149 |
$this->env = new Twig_Environment($this->getMock('Twig_LoaderInterface'));
|
150 |
}
|