Timber - Version 0.15.0

Version Description

  • Cacheing!!!
  • Cacheing!!
  • Cacheing!!!! Timber::render('mytemplate.twig', $data, $expires_time_in_secs);
  • Added post.get_next / post.get_prev for TimberPosts
  • Fixed a thing to make get_preview easier when you want to omit the 'Read More' link
  • Read the Full Release Notes
Download this release

Release Info

Developer jarednova
Plugin Icon 128x128 Timber
Version 0.15.0
Comparing to
See all releases

Code changes from version 0.14.1 to 0.15.0

functions/cache/CacheExtension/CacheProvider/DoctrineCacheAdapter.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\CacheProvider;
13
+
14
+ use Asm89\Twig\CacheExtension\CacheProviderInterface;
15
+ use Doctrine\Common\Cache\Cache;
16
+
17
+ /**
18
+ * Adapter class to use the cache classes provider by Doctrine.
19
+ *
20
+ * @author Alexander <iam.asm89@gmail.com>
21
+ */
22
+ class DoctrineCacheAdapter implements CacheProviderInterface
23
+ {
24
+ private $cache;
25
+
26
+ /**
27
+ * @param Cache $cache
28
+ */
29
+ public function __construct(Cache $cache)
30
+ {
31
+ $this->cache = $cache;
32
+ }
33
+
34
+ /**
35
+ * {@inheritDoc}
36
+ */
37
+ public function fetch($key)
38
+ {
39
+ return $this->cache->fetch($key);
40
+ }
41
+
42
+ /**
43
+ * {@inheritDoc}
44
+ */
45
+ public function save($key, $value, $lifetime = 0)
46
+ {
47
+ return $this->cache->save($key, $value, $lifetime);
48
+ }
49
+ }
functions/cache/CacheExtension/CacheProviderInterface.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension;
13
+
14
+ /**
15
+ * Cache provider interface.
16
+ *
17
+ * @author Alexander <iam.asm89@gmail.com>
18
+ */
19
+ interface CacheProviderInterface
20
+ {
21
+ /**
22
+ * @param string $key
23
+ *
24
+ * @return mixed False, if there was no value to be fetched. Null or a string otherwise.
25
+ */
26
+ public function fetch($key);
27
+
28
+ /**
29
+ * @param string $key
30
+ * @param string $value
31
+ * @param integer $lifetime
32
+ */
33
+ public function save($key, $value, $lifetime = 0);
34
+ }
functions/cache/CacheExtension/CacheStrategy/GenerationalCacheStrategy.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\CacheStrategy;
13
+
14
+ use Asm89\Twig\CacheExtension\CacheProviderInterface;
15
+ use Asm89\Twig\CacheExtension\CacheStrategyInterface;
16
+
17
+ /**
18
+ * Strategy for generational caching.
19
+ *
20
+ * In theory the strategy only saves fragments to the cache with infinite
21
+ * lifetime. The key of the strategy lies in the fact that the keys for blocks
22
+ * will change as the value for which the key is generated changes.
23
+ *
24
+ * For example: entities containing a last update time, would include a
25
+ * timestamp in the key.
26
+ *
27
+ * @see http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works
28
+ *
29
+ * @author Alexander <iam.asm89@gmail.com>
30
+ */
31
+ class GenerationalCacheStrategy implements CacheStrategyInterface
32
+ {
33
+ private $keyGenerator;
34
+ private $cache;
35
+ private $lifetime;
36
+
37
+ /**
38
+ * @param CacheProviderInterface $cache
39
+ * @param KeyGeneratorInterface $keyGenerator
40
+ * @param integer $lifetime
41
+ */
42
+ public function __construct(CacheProviderInterface $cache, KeyGeneratorInterface $keyGenerator, $lifetime = 0)
43
+ {
44
+ $this->keyGenerator = $keyGenerator;
45
+ $this->cache = $cache;
46
+ $this->lifetime = $lifetime;
47
+ }
48
+
49
+ /**
50
+ * {@inheritDoc}
51
+ */
52
+ public function fetchBlock($key)
53
+ {
54
+ return $this->cache->fetch($key);
55
+ }
56
+
57
+ /**
58
+ * {@inheritDoc}
59
+ */
60
+ public function generateKey($annotation, $value)
61
+ {
62
+ $key = $this->keyGenerator->generateKey($value);
63
+
64
+ if (null === $key) {
65
+ // todo: more specific exception
66
+ throw new \RuntimeException('Key generator did not return a key.');
67
+ }
68
+
69
+ return $annotation . '__GCS__' . $key;
70
+ }
71
+
72
+ /**
73
+ * {@inheritDoc}
74
+ */
75
+ public function saveBlock($key, $block)
76
+ {
77
+ return $this->cache->save($key, $block, $this->lifetime);
78
+ }
79
+ }
functions/cache/CacheExtension/CacheStrategy/IndexedChainingCacheStrategy.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\CacheStrategy;
13
+
14
+ use Asm89\Twig\CacheExtension\CacheStrategyInterface;
15
+
16
+ /**
17
+ * Combines several configured cache strategies.
18
+ *
19
+ * Useful for combining for example generational cache strategy with a lifetime
20
+ * cache strategy, but also useful when combining several generational cache
21
+ * strategies which differ on cache lifetime (infinite, 1hr, 5m).
22
+ *
23
+ * @author Alexander <iam.asm89@gmail.com>
24
+ */
25
+ class IndexedChainingCacheStrategy implements CacheStrategyInterface
26
+ {
27
+ private $strategies;
28
+
29
+ /**
30
+ * @param array $strategies
31
+ */
32
+ public function __construct(array $strategies)
33
+ {
34
+ $this->strategies = $strategies;
35
+ }
36
+
37
+ /**
38
+ * {@inheritDoc}
39
+ */
40
+ public function fetchBlock($key)
41
+ {
42
+ return $this->strategies[$key['strategyKey']]->fetchBlock($key['key']);
43
+ }
44
+
45
+ /**
46
+ * {@inheritDoc}
47
+ */
48
+ public function generateKey($annotation, $value)
49
+ {
50
+ if (! is_array($value) || null === $strategyKey = key($value)) {
51
+ //todo: specialized exception
52
+ throw new \RuntimeException('No strategy key found in value.');
53
+ }
54
+
55
+ if (! isset($this->strategies[$strategyKey])) {
56
+ //todo: specialized exception
57
+ throw new \RuntimeException(sprintf('No strategy configured with key "%s".', $strategyKey));
58
+ }
59
+
60
+ $key = $this->strategies[$strategyKey]->generateKey($annotation, current($value));
61
+
62
+ return array(
63
+ 'strategyKey' => $strategyKey,
64
+ 'key' => $key,
65
+ );
66
+ }
67
+
68
+ /**
69
+ * {@inheritDoc}
70
+ */
71
+ public function saveBlock($key, $block)
72
+ {
73
+ return $this->strategies[$key['strategyKey']]->saveBlock($key['key'], $block);
74
+ }
75
+ }
functions/cache/CacheExtension/CacheStrategy/KeyGeneratorInterface.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\CacheStrategy;
13
+
14
+ /**
15
+ * Generates a key for a given value.
16
+ *
17
+ * @author Alexander <iam.asm89@gmail.com>
18
+ */
19
+ interface KeyGeneratorInterface
20
+ {
21
+ /**
22
+ * Generate a cache key for a given value.
23
+ *
24
+ * @param mixed $value
25
+ *
26
+ * @return string
27
+ */
28
+ public function generateKey($value);
29
+ }
functions/cache/CacheExtension/CacheStrategy/LifetimeCacheStrategy.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\CacheStrategy;
13
+
14
+ use Asm89\Twig\CacheExtension\CacheProviderInterface;
15
+ use Asm89\Twig\CacheExtension\CacheStrategyInterface;
16
+
17
+ /**
18
+ * Strategy for caching with a pre-defined lifetime.
19
+ *
20
+ * The value passed to the strategy is the lifetime of the cache block in
21
+ * seconds.
22
+ *
23
+ * @author Alexander <iam.asm89@gmail.com>
24
+ */
25
+ class LifetimeCacheStrategy implements CacheStrategyInterface
26
+ {
27
+ private $cache;
28
+
29
+ /**
30
+ * @param CacheProviderInterface $cache
31
+ */
32
+ public function __construct(CacheProviderInterface $cache)
33
+ {
34
+ $this->cache = $cache;
35
+ }
36
+
37
+ /**
38
+ * {@inheritDoc}
39
+ */
40
+ public function fetchBlock($key)
41
+ {
42
+ return $this->cache->fetch($key['key']);
43
+ }
44
+
45
+ /**
46
+ * {@inheritDoc}
47
+ */
48
+ public function generateKey($annotation, $value)
49
+ {
50
+ if (! is_numeric($value)) {
51
+ //todo: specialized exception
52
+ throw new \RuntimeException('Value is not a valid lifetime.');
53
+ }
54
+
55
+ return array(
56
+ 'lifetime' => $value,
57
+ 'key' => '__LCS__' . $annotation,
58
+ );
59
+ }
60
+
61
+ /**
62
+ * {@inheritDoc}
63
+ */
64
+ public function saveBlock($key, $block)
65
+ {
66
+ return $this->cache->save($key['key'], $block, $key['lifetime']);
67
+ }
68
+ }
functions/cache/CacheExtension/CacheStrategyInterface.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension;
13
+
14
+ /**
15
+ * Cache strategy interface.
16
+ *
17
+ * @author Alexander <iam.asm89@gmail.com>
18
+ */
19
+ interface CacheStrategyInterface
20
+ {
21
+ /**
22
+ * Fetch the block for a given key.
23
+ *
24
+ * @param mixed $key
25
+ *
26
+ * @return string
27
+ */
28
+ public function fetchBlock($key);
29
+
30
+ /**
31
+ * Generate a key for the value.
32
+ *
33
+ * @param string $annotation
34
+ * @param mixed $value
35
+ *
36
+ * @return mixed
37
+ */
38
+ public function generateKey($annotation, $value);
39
+
40
+ /**
41
+ * Save the contents of a rendered block.
42
+ *
43
+ * @param mixed $key
44
+ * @param string $block
45
+ */
46
+ public function saveBlock($key, $block);
47
+ }
functions/cache/CacheExtension/Extension.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension;
13
+
14
+ /**
15
+ * Extension for caching template blocks with twig.
16
+ *
17
+ * @author Alexander <iam.asm89@gmail.com>
18
+ */
19
+ class Extension extends \Twig_Extension
20
+ {
21
+ private $cacheStrategy;
22
+
23
+ /**
24
+ * @param CacheStrategyInterface $cacheStrategy
25
+ */
26
+ public function __construct(CacheStrategyInterface $cacheStrategy)
27
+ {
28
+ $this->cacheStrategy = $cacheStrategy;
29
+ }
30
+
31
+ /**
32
+ * @return CacheStrategyInterface
33
+ */
34
+ public function getCacheStrategy()
35
+ {
36
+ return $this->cacheStrategy;
37
+ }
38
+
39
+ /**
40
+ * {@inheritDoc}
41
+ */
42
+ public function getName()
43
+ {
44
+ return 'asm89_cache';
45
+ }
46
+
47
+ /**
48
+ * {@inheritDoc}
49
+ */
50
+ public function getTokenParsers()
51
+ {
52
+ return array(
53
+ new TokenParser\Cache(),
54
+ );
55
+ }
56
+ }
functions/cache/CacheExtension/Node/CacheNode.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\Node;
13
+
14
+ /**
15
+ * Cache twig node.
16
+ *
17
+ * @author Alexander <iam.asm89@gmail.com>
18
+ */
19
+ class CacheNode extends \Twig_Node
20
+ {
21
+ private static $cacheCount = 1;
22
+
23
+ /**
24
+ * @param string $annotation
25
+ * @param \Twig_Node_Expression $keyInfo
26
+ * @param \Twig_NodeInterface $body
27
+ * @param integer $lineno
28
+ * @param string $tag
29
+ */
30
+ public function __construct($annotation, \Twig_Node_Expression $keyInfo, \Twig_NodeInterface $body, $lineno, $tag = null)
31
+ {
32
+ parent::__construct(array('key_info' => $keyInfo, 'body' => $body), array('annotation' => $annotation), $lineno, $tag);
33
+ }
34
+
35
+ /**
36
+ * {@inheritDoc}
37
+ */
38
+ public function compile(\Twig_Compiler $compiler)
39
+ {
40
+ $i = self::$cacheCount++;
41
+
42
+ $compiler
43
+ ->addDebugInfo($this)
44
+ ->write("\$asm89CacheStrategy".$i." = \$this->getEnvironment()->getExtension('asm89_cache')->getCacheStrategy();\n")
45
+ ->write("\$asm89Key".$i." = \$asm89CacheStrategy".$i."->generateKey('".$this->getAttribute('annotation')."', ")
46
+ ->subcompile($this->getNode('key_info'))
47
+ ->write(");\n")
48
+ ->write("\$asm89CacheBody".$i." = \$asm89CacheStrategy".$i."->fetchBlock(\$asm89Key".$i.");\n")
49
+ ->write("if (\$asm89CacheBody".$i." === false) {\n")
50
+ ->indent()
51
+ ->write("ob_start();\n")
52
+ ->indent()
53
+ ->subcompile($this->getNode('body'))
54
+ ->outdent()
55
+ ->write("\n")
56
+ ->write("\$asm89CacheBody".$i." = ob_get_clean();\n")
57
+ ->write("\$asm89CacheStrategy".$i."->saveBlock(\$asm89Key".$i.", \$asm89CacheBody".$i.");\n")
58
+ ->outdent()
59
+ ->write("}\n")
60
+ ->write("echo \$asm89CacheBody".$i.";\n")
61
+ ;
62
+ }
63
+ }
functions/cache/CacheExtension/TokenParser/Cache.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of twig-cache-extension.
5
+ *
6
+ * (c) Alexander <iam.asm89@gmail.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Asm89\Twig\CacheExtension\TokenParser;
13
+
14
+ use \Twig_Token;
15
+
16
+ /**
17
+ * Parser for cache/endcache blocks.
18
+ *
19
+ * @author Alexander <iam.asm89@gmail.com>
20
+ */
21
+ class Cache extends \Twig_TokenParser
22
+ {
23
+ /**
24
+ * @return boolean
25
+ */
26
+ public function decideCacheEnd(Twig_Token $token)
27
+ {
28
+ return $token->test('endcache');
29
+ }
30
+
31
+ /**
32
+ * {@inheritDoc}
33
+ */
34
+ public function getTag()
35
+ {
36
+ return 'cache';
37
+ }
38
+
39
+ /**
40
+ * {@inheritDoc}
41
+ */
42
+ public function parse(Twig_Token $token)
43
+ {
44
+ $lineno = $token->getLine();
45
+ $stream = $this->parser->getStream();
46
+
47
+ $annotation = $stream->expect(Twig_Token::STRING_TYPE)->getValue();
48
+ $key = $this->parser->getExpressionParser()->parseExpression();
49
+
50
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
51
+ $body = $this->parser->subparse(array($this, 'decideCacheEnd'), true);
52
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
53
+
54
+ return new \Asm89\Twig\CacheExtension\Node\CacheNode($annotation, $key, $body, $lineno, $this->getTag());
55
+ }
56
+ }
functions/cache/KeyGenerator.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Timber\Cache;
4
+
5
+ use Asm89\Twig\CacheExtension\CacheStrategy\KeyGeneratorInterface;
6
+
7
+ class KeyGenerator implements KeyGeneratorInterface
8
+ {
9
+
10
+ public function generateKey( $value ) {
11
+ if ( is_a( $value, 'TimberKeyGeneratorInterface' ) )
12
+ return $value->_get_cache_key();
13
+
14
+ if ( is_array( $value ) && isset( $value['_cache_key'] ) )
15
+ return $value['_cache_key'];
16
+
17
+ $key = md5( json_encode( $value ) );
18
+ if ( is_object( $value ) )
19
+ $key = get_class( $key ) . '|' . $key;
20
+
21
+ return $key;
22
+ }
23
+
24
+ }
functions/cache/TimberKeyGeneratorInterface.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Timber\Cache;
4
+
5
+ interface TimberKeyGeneratorInterface
6
+ {
7
+ public function _get_cache_key();
8
+ }
functions/cache/WPObjectCacheAdapter.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php namespace Timber\Cache;
2
+
3
+ use Asm89\Twig\CacheExtension\CacheProviderInterface;
4
+ use TimberLoader;
5
+
6
+ class WPObjectCacheAdapter implements CacheProviderInterface
7
+ {
8
+
9
+ private $cache_group;
10
+
11
+ /**
12
+ * @var TimberLoader
13
+ */
14
+ private $timberloader;
15
+
16
+ public function __construct( TimberLoader $timberloader, $cache_group = 'timber' ) {
17
+ $this->cache_group = $cache_group;
18
+ $this->timberloader = $timberloader;
19
+ }
20
+
21
+ public function fetch( $key ) {
22
+ return $this->timberloader->get_cache( $key, $this->cache_group, TimberLoader::CACHE_USE_DEFAULT );
23
+ }
24
+
25
+ public function save( $key, $value, $expire = 0 ) {
26
+ return $this->timberloader->set_cache( $key, $value, $this->cache_group, $expire, TimberLoader::CACHE_USE_DEFAULT );
27
+ }
28
+
29
+ }
functions/cache/loader.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class TimberCache_Loader
3
+ {
4
+
5
+ public static function register($prepend = false)
6
+ {
7
+ if (version_compare(phpversion(), '5.3.0', '>=')) {
8
+ spl_autoload_register(array(new self, 'autoload'), true, $prepend);
9
+ } else {
10
+ spl_autoload_register(array(new self, 'autoload'));
11
+ }
12
+ }
13
+
14
+ public static function autoload($class)
15
+ {
16
+ if (0 === strpos($class, 'Timber\Cache') || 0 === strpos($class, 'Asm89\Twig\CacheExtension')) {
17
+ $classes = explode( '\\', $class );
18
+ array_splice( $classes, 0, 2 );
19
+ $path = implode( $classes, '/' );
20
+ if ( is_file($file = dirname(__FILE__) . '/' . $path . '.php'))
21
+ require $file;
22
+ }
23
+ }
24
+ }
functions/functions-timber-helper.php CHANGED
@@ -389,7 +389,7 @@ class TimberHelper {
389
  return $ret;
390
  }
391
 
392
- function paginate_links( $args = '' ) {
393
  $defaults = array(
394
  'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
395
  'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
389
  return $ret;
390
  }
391
 
392
+ public static function paginate_links( $args = '' ) {
393
  $defaults = array(
394
  'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
395
  'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
functions/timber-comment.php CHANGED
@@ -2,6 +2,10 @@
2
 
3
  class TimberComment extends TimberCore {
4
 
 
 
 
 
5
  function __construct($cid) {
6
  $this->init($cid);
7
  }
2
 
3
  class TimberComment extends TimberCore {
4
 
5
+ var $PostClass = 'TimberPost';
6
+
7
+ public static $representation = 'comment';
8
+
9
  function __construct($cid) {
10
  $this->init($cid);
11
  }
functions/timber-image.php CHANGED
@@ -6,6 +6,8 @@ class TimberImage extends TimberCore {
6
  var $abs_url;
7
  var $PostClass = 'TimberPost';
8
 
 
 
9
  function __construct($iid) {
10
  $this->init($iid);
11
  }
6
  var $abs_url;
7
  var $PostClass = 'TimberPost';
8
 
9
+ public static $representation = 'image';
10
+
11
  function __construct($iid) {
12
  $this->init($iid);
13
  }
functions/timber-loader.php CHANGED
@@ -2,20 +2,63 @@
2
 
3
  class TimberLoader {
4
 
5
- var $locations;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  function __construct($caller = false) {
8
  $this->locations = $this->get_locations($caller);
 
9
  }
10
 
11
- function render($file, $data = null) {
12
- $twig = $this->get_twig();
13
- if (strlen($file)){
14
- $loader = $this->get_loader();
15
- $result = $loader->getCacheKey($file);
16
- do_action('timber_loader_render_file', $result);
17
- }
18
- return $twig->render($file, $data);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  function choose_template($filenames) {
@@ -132,7 +175,80 @@ class TimberLoader {
132
  }
133
  $twig = new Twig_Environment($loader, $params);
134
  $twig->addExtension(new Twig_Extension_Debug());
 
 
135
  $twig = apply_filters('twig_apply_filters', $twig);
136
  return $twig;
137
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  }
2
 
3
  class TimberLoader {
4
 
5
+ const CACHEGROUP = 'timberloader';
6
+
7
+ const TRANS_KEY_LEN = 50;
8
+
9
+ const CACHE_NONE = 'none';
10
+ const CACHE_OBJECT = 'cache';
11
+ const CACHE_TRANSIENT = 'transient';
12
+ const CACHE_SITE_TRANSIENT = 'site-transient';
13
+ const CACHE_USE_DEFAULT = 'default';
14
+
15
+ public static $cache_modes = array(
16
+ self::CACHE_NONE,
17
+ self::CACHE_OBJECT,
18
+ self::CACHE_TRANSIENT,
19
+ self::CACHE_SITE_TRANSIENT
20
+ );
21
+
22
+ protected $cache_mode = self::CACHE_TRANSIENT;
23
+
24
+ var $locations;
25
 
26
  function __construct($caller = false) {
27
  $this->locations = $this->get_locations($caller);
28
+ $this->cache_mode = apply_filters( 'timber_cache_mode', $this->cache_mode );
29
  }
30
 
31
+ function render( $file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT ) {
32
+ // Different $expires if user is anonymous or logged in
33
+ if ( is_array( $expires ) ) {
34
+ if ( is_user_logged_in() && isset( $expires[1] ) )
35
+ $expires = $expires[1];
36
+ else
37
+ $expires = $expires[0];
38
+ }
39
+
40
+ ksort( $data );
41
+ $key = md5( $file . json_encode( $data ) );
42
+
43
+ $output = false;
44
+ if ( false !== $expires )
45
+ $output = $this->get_cache( $key, self::CACHEGROUP, $cache_mode );
46
+
47
+ if ( false === $output || null === $output ) {
48
+ $twig = $this->get_twig();
49
+ if (strlen($file)){
50
+ $loader = $this->get_loader();
51
+ $result = $loader->getCacheKey($file);
52
+ do_action('timber_loader_render_file', $result);
53
+ }
54
+ $data = apply_filters('timber_loader_render_data', $data);
55
+ $output = $twig->render($file, $data);
56
+ }
57
+
58
+ if ( false !== $output && false !== $expires )
59
+ $this->set_cache( $key, $output, self::CACHEGROUP, $expires, $cache_mode );
60
+
61
+ return $output;
62
  }
63
 
64
  function choose_template($filenames) {
175
  }
176
  $twig = new Twig_Environment($loader, $params);
177
  $twig->addExtension(new Twig_Extension_Debug());
178
+ $twig->addExtension($this->_get_cache_extension());
179
+
180
  $twig = apply_filters('twig_apply_filters', $twig);
181
  return $twig;
182
  }
183
+
184
+ private function _get_cache_extension() {
185
+ $loader_loc = trailingslashit(TIMBER_LOC) . 'functions/cache/loader.php';
186
+ require_once($loader_loc);
187
+ TimberCache_Loader::register();
188
+
189
+ $key_generator = new \Timber\Cache\KeyGenerator();
190
+ $cache_provider = new \Timber\Cache\WPObjectCacheAdapter( $this );
191
+ $cache_strategy = new \Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy( $cache_provider, $key_generator );
192
+ $cache_extension = new \Asm89\Twig\CacheExtension\Extension($cache_strategy);
193
+
194
+ return $cache_extension;
195
+ }
196
+
197
+ public function get_cache( $key, $group = self::CACHEGROUP, $cache_mode = self::CACHE_USE_DEFAULT ) {
198
+ $object_cache = false;
199
+
200
+ if ( isset( $GLOBALS[ 'wp_object_cache' ] ) && is_object( $GLOBALS[ 'wp_object_cache' ] ) )
201
+ $object_cache = true;
202
+
203
+ $cache_mode = $this->_get_cache_mode( $cache_mode );
204
+
205
+ $value = null;
206
+
207
+ $trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN);
208
+ if ( self::CACHE_TRANSIENT === $cache_mode )
209
+ $value = get_transient( $trans_key );
210
+
211
+ elseif ( self::CACHE_SITE_TRANSIENT === $cache_mode )
212
+ $value = get_site_transient( $trans_key );
213
+
214
+ elseif ( self::CACHE_OBJECT === $cache_mode && $object_cache )
215
+ $value = wp_cache_get( $key, $group );
216
+
217
+ return $value;
218
+ }
219
+
220
+ public function set_cache( $key, $value, $group = self::CACHEGROUP, $expires = 0, $cache_mode = self::CACHE_USE_DEFAULT ) {
221
+ $object_cache = false;
222
+
223
+ if ( isset( $GLOBALS[ 'wp_object_cache' ] ) && is_object( $GLOBALS[ 'wp_object_cache' ] ) )
224
+ $object_cache = true;
225
+
226
+ if ( (int) $expires < 1 )
227
+ $expires = 0;
228
+
229
+ $cache_mode = self::_get_cache_mode( $cache_mode );
230
+ $trans_key = substr($group . '_' . $key, 0, self::TRANS_KEY_LEN);
231
+
232
+ if ( self::CACHE_TRANSIENT === $cache_mode )
233
+ set_transient( $trans_key, $value, $expires );
234
+
235
+ elseif ( self::CACHE_SITE_TRANSIENT === $cache_mode )
236
+ set_site_transient( $trans_key, $value, $expires );
237
+
238
+ elseif ( self::CACHE_OBJECT === $cache_mode && $object_cache )
239
+ wp_cache_set( $key, $value, $group, $expires );
240
+
241
+ return $value;
242
+ }
243
+
244
+ private function _get_cache_mode( $cache_mode ) {
245
+ if ( empty( $cache_mode ) || self::CACHE_USE_DEFAULT === $cache_mode )
246
+ $cache_mode = $this->cache_mode;
247
+
248
+ // Fallback if self::$cache_mode did not get a valid value
249
+ if ( !in_array( $cache_mode, self::$cache_modes ) )
250
+ $cache_mode = self::CACHE_OBJECT;
251
+
252
+ return $cache_mode;
253
+ }
254
  }
functions/timber-post.php CHANGED
@@ -164,7 +164,9 @@ class TimberPost extends TimberCore {
164
  }
165
  }
166
 
167
- $text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . $readmore . '</a>';
 
 
168
  if (!$strip){
169
  $text .= '</p>';
170
  }
@@ -221,10 +223,21 @@ class TimberPost extends TimberCore {
221
  }
222
 
223
  function get_link() {
224
- if (isset($this->path)) {
225
- return $this->path;
 
 
 
 
226
  }
227
- return null;
 
 
 
 
 
 
 
228
  }
229
 
230
  function get_parent() {
@@ -464,7 +477,11 @@ class TimberPost extends TimberCore {
464
  return $this->get_permalink();
465
  }
466
 
467
- function path(){
 
 
 
 
468
  $path = TimberHelper::get_rel_url($this->get_permalink());
469
  return TimberHelper::preslashit($path);
470
  }
@@ -473,6 +490,10 @@ class TimberPost extends TimberCore {
473
  return $this->get_permalink();
474
  }
475
 
 
 
 
 
476
  function terms($tax = '') {
477
  return $this->get_terms($tax);
478
  }
@@ -491,7 +512,7 @@ class TimberPost extends TimberCore {
491
 
492
  //Deprecated
493
  function get_path() {
494
- return $this->get_link();
495
  }
496
 
497
  }
164
  }
165
  }
166
 
167
+ if($readmore) {
168
+ $text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . $readmore . '</a>';
169
+ }
170
  if (!$strip){
171
  $text .= '</p>';
172
  }
223
  }
224
 
225
  function get_link() {
226
+ return $this->get_permalink();
227
+ }
228
+
229
+ function get_next() {
230
+ if (!isset($this->next)){
231
+ $this->next = new $this->PostClass(get_adjacent_post( false, "", true ));
232
  }
233
+ return $this->next;
234
+ }
235
+
236
+ function get_prev() {
237
+ if (!isset($this->prev)){
238
+ $this->prev = new $this->PostClass(get_adjacent_post( false, "", false ));
239
+ }
240
+ return $this->prev;
241
  }
242
 
243
  function get_parent() {
477
  return $this->get_permalink();
478
  }
479
 
480
+ function next() {
481
+ return $this->get_next();
482
+ }
483
+
484
+ function path() {
485
  $path = TimberHelper::get_rel_url($this->get_permalink());
486
  return TimberHelper::preslashit($path);
487
  }
490
  return $this->get_permalink();
491
  }
492
 
493
+ function prev() {
494
+ return $this->get_prev();
495
+ }
496
+
497
  function terms($tax = '') {
498
  return $this->get_terms($tax);
499
  }
512
 
513
  //Deprecated
514
  function get_path() {
515
+ return TimberHelper::get_rel_url($this->get_link());
516
  }
517
 
518
  }
functions/timber-term.php CHANGED
@@ -3,7 +3,9 @@
3
  class TimberTerm extends TimberCore {
4
 
5
  var $taxonomy;
6
- var $PostClass;
 
 
7
 
8
  function __construct($tid = null) {
9
  if ($tid === null) {
3
  class TimberTerm extends TimberCore {
4
 
5
  var $taxonomy;
6
+ var $PostClass = 'TimberPost';
7
+
8
+ public static $representation = 'term';
9
 
10
  function __construct($tid = null) {
11
  if ($tid === null) {
functions/timber-user.php CHANGED
@@ -2,14 +2,21 @@
2
 
3
  class TimberUser extends TimberCore {
4
 
 
 
 
 
5
  function __construct($uid = false) {
6
  $this->init($uid);
7
  }
8
 
9
  public function get_link() {
10
- $p = TimberHelper::get_path_base();
11
- global $wp_rewrite;
12
- return $p . trailingslashit($wp_rewrite->author_base) . $this->slug();
 
 
 
13
  }
14
 
15
  function init($uid = false) {
2
 
3
  class TimberUser extends TimberCore {
4
 
5
+ var $_link;
6
+
7
+ public static $representation = 'user';
8
+
9
  function __construct($uid = false) {
10
  $this->init($uid);
11
  }
12
 
13
  public function get_link() {
14
+ if (!$this->_link){
15
+ $p = TimberHelper::get_path_base();
16
+ global $wp_rewrite;
17
+ $this->_link = $p . trailingslashit($wp_rewrite->author_base) . $this->slug();
18
+ }
19
+ return $this->_link;
20
  }
21
 
22
  function init($uid = false) {
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: jarednova
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.5
5
- Stable tag: 0.14.1
6
  Tested up to: 3.6.1
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
@@ -38,6 +38,14 @@ Timber is great for any WordPress developer who cares about writing good, mainta
38
 
39
  == Changelog ==
40
 
 
 
 
 
 
 
 
 
41
  = 0.14.1 =
42
  * Added hooks to play nicely with Timber Debug Bar
43
  * Fixed-up Timber Term aliases, link, path, etc.
2
  Contributors: jarednova
3
  Tags: template engine, templates, twig
4
  Requires at least: 3.5
5
+ Stable tag: 0.15.0
6
  Tested up to: 3.6.1
7
  PHP version: 5.3.0 or greater
8
  License: GPLv2 or later
38
 
39
  == Changelog ==
40
 
41
+ = 0.15.0 =
42
+ * Cacheing!!!
43
+ * Cacheing!!
44
+ * Cacheing!!!! Timber::render('mytemplate.twig', $data, $expires_time_in_secs);
45
+ * Added post.get_next / post.get_prev for TimberPosts
46
+ * Fixed a thing to make get_preview easier when you want to omit the 'Read More' link
47
+ * Read the [Full Release Notes](https://github.com/jarednova/timber/releases/tag/0.15.0)
48
+
49
  = 0.14.1 =
50
  * Added hooks to play nicely with Timber Debug Bar
51
  * Fixed-up Timber Term aliases, link, path, etc.
timber.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Timber
4
  Plugin URI: http://timber.upstatement.com
5
  Description: The WordPress Timber Library allows you to write themes using the power Twig templates
6
  Author: Jared Novack + Upstatement
7
- Version: 0.14.1
8
  Author URI: http://upstatement.com/
9
  */
10
 
@@ -290,7 +290,10 @@ class Timber {
290
  $data['wp_footer'] = TimberHelper::function_wrapper('wp_footer');
291
  $data['body_class'] = implode(' ', get_body_class());
292
  if (function_exists('wp_nav_menu')) {
293
- $data['wp_nav_menu'] = wp_nav_menu(array('container_class' => 'menu-header', 'echo' => false, 'menu_class' => 'nav-menu'));
 
 
 
294
  }
295
  $data['theme_dir'] = str_replace(ABSPATH, '', get_stylesheet_directory());
296
  $data['language_attributes'] = TimberHelper::function_wrapper('language_attributes');
@@ -300,19 +303,33 @@ class Timber {
300
  return $data;
301
  }
302
 
303
- public static function render($filenames, $data = array(), $echo = true) {
304
  $caller = self::get_calling_script_dir();
305
  $loader = new TimberLoader($caller);
306
  $file = $loader->choose_template($filenames);
307
  $output = '';
308
  if (strlen($file)) {
309
- $file = apply_filters('timber_render_file', $file);
310
- $data = apply_filters('timber_render_data', $data);
311
- $output = $loader->render($file, $data);
 
 
 
 
 
312
  }
313
- if ($echo) {
314
- echo $output;
 
 
 
 
 
 
 
315
  }
 
 
316
  return $output;
317
  }
318
 
@@ -374,7 +391,7 @@ class Timber {
374
  }
375
  }
376
 
377
- public static function add_route($route, $callback) {
378
  global $timber;
379
  if (!isset($timber->router)) {
380
  require_once('functions/router/Router.php');
@@ -382,7 +399,7 @@ class Timber {
382
  $timber->router = new Router();
383
  $timber->router->setBasePath('/');
384
  }
385
- $timber->router->map($route, $callback);
386
  }
387
 
388
  public static function cancel_query(){
4
  Plugin URI: http://timber.upstatement.com
5
  Description: The WordPress Timber Library allows you to write themes using the power Twig templates
6
  Author: Jared Novack + Upstatement
7
+ Version: 0.15.0
8
  Author URI: http://upstatement.com/
9
  */
10
 
290
  $data['wp_footer'] = TimberHelper::function_wrapper('wp_footer');
291
  $data['body_class'] = implode(' ', get_body_class());
292
  if (function_exists('wp_nav_menu')) {
293
+ $locations = get_nav_menu_locations();
294
+ if (count($locations)){
295
+ $data['wp_nav_menu'] = wp_nav_menu(array('container_class' => 'menu-header', 'echo' => false, 'menu_class' => 'nav-menu'));
296
+ }
297
  }
298
  $data['theme_dir'] = str_replace(ABSPATH, '', get_stylesheet_directory());
299
  $data['language_attributes'] = TimberHelper::function_wrapper('language_attributes');
303
  return $data;
304
  }
305
 
306
+ public static function compile($filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT, $via_render = false) {
307
  $caller = self::get_calling_script_dir();
308
  $loader = new TimberLoader($caller);
309
  $file = $loader->choose_template($filenames);
310
  $output = '';
311
  if (strlen($file)) {
312
+ if ($via_render){
313
+ $file = apply_filters('timber_render_file', $file);
314
+ $data = apply_filters('timber_render_data', $data);
315
+ } else {
316
+ $file = apply_filters('timber_compile_file', $file);
317
+ $data = apply_filters('timber_compile_data', $data);
318
+ }
319
+ $output = $loader->render($file, $data, $expires, $cache_mode);
320
  }
321
+ return $output;
322
+ }
323
+
324
+ public static function render($filenames, $data = array(), $expires = false, $cache_mode = TimberLoader::CACHE_USE_DEFAULT) {
325
+ if ($expires === true){
326
+ //if this is reading as true; the user probably is using the old $echo param
327
+ //so we should move all vars up by a spot
328
+ $expires = $cache_mode;
329
+ $cache_mode = TimberLoader::CACHE_USE_DEFAULT;
330
  }
331
+ $output = self::compile($filenames, $data, $expires, $cache_mode, true);
332
+ echo $output;
333
  return $output;
334
  }
335
 
391
  }
392
  }
393
 
394
+ public static function add_route($route, $callback, $args = array()) {
395
  global $timber;
396
  if (!isset($timber->router)) {
397
  require_once('functions/router/Router.php');
399
  $timber->router = new Router();
400
  $timber->router->setBasePath('/');
401
  }
402
+ $timber->router->map($route, $callback, $args);
403
  }
404
 
405
  public static function cancel_query(){