CFSTemplateManager::requireSourceFileContent()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
/**
3
 * @author     Andrew Coulton <[email protected]>
4
 * @copyright  2015 inGenerator Ltd
5
 * @license    http://kohanaframework.org/license
6
 */
7
8
namespace Ingenerator\KohanaView\TemplateManager;
9
10
use Ingenerator\KohanaView\Exception\TemplateCacheException;
11
use Ingenerator\KohanaView\Exception\TemplateNotFoundException;
12
use Ingenerator\KohanaView\TemplateCompiler;
13
use Ingenerator\KohanaView\TemplateManager;
14
15
/**
16
 * Manages compilation of templates from view files located within the cascading file system. This allows extension
17
 * modules or applications to provide their own templates that are used in place of defaults provided by other modules.
18
 *
19
 * Templates will be dynamically compiled and cached to disk:
20
 *  * If the recompile_always option is TRUE, then once for every execution
21
 *  * If the recompile_always option is FALSE, then only if the compiled template does not yet exist
22
 *
23
 * @package Ingenerator\KohanaView\TemplateManager
24
 */
25
class CFSTemplateManager implements TemplateManager
26
{
27
    /**
28
     * @var string
29
     */
30
    protected $cache_dir;
31
32
    /**
33
     * @var CFSWrapper
34
     */
35
    protected $cascading_files;
36
37
    /**
38
     * @var array
39
     */
40
    protected $compiled_paths = [];
41
42
    /**
43
     * @var TemplateCompiler
44
     */
45
    protected $compiler;
46
47
    /**
48
     * @var boolean
49
     */
50
    protected $recompile_always;
51
52
    /**
53
     * @var string
54
     */
55
    protected $template_dir;
56
57
    /**
58
     * Valid options:
59
     * * cache_dir        => the path where compiled templates will be cached
60
     * * recompile_always => whether to recompile each template on every execution,
61
     * * template_dir     => directory (in the cascading filesystem) to search for templates
62
     *
63
     * @param TemplateCompiler $compiler
64
     * @param array            $options
65
     * @param null|CFSWrapper  $cascading_files
66
     */
67
    public function __construct(TemplateCompiler $compiler, array $options, CFSWrapper $cascading_files = NULL)
68
    {
69
        $this->cascading_files  = $cascading_files ?: new CFSWrapper;
70
        $this->compiler         = $compiler;
71
        $this->cache_dir        = rtrim($options['cache_dir'], '/');
72
        $this->recompile_always = \Arr::get($options, 'recompile_always', FALSE);
73
        $this->template_dir     = rtrim(\Arr::get($options, 'template_dir', 'views'), '/');
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function getPath($template_name)
80
    {
81
        $compiled_path = $this->cache_dir.'/'.$template_name.'.php';
82
83
        if ($this->isCompileRequired($compiled_path)) {
84
            $source   = $this->requireSourceFileContent($template_name);
85
            $compiled = $this->compiler->compile($source);
86
            $this->writeFile($compiled_path, $compiled);
87
            $this->compiled_paths[$compiled_path] = TRUE;
88
        }
89
90
        return $compiled_path;
91
    }
92
93
    /**
94
     * @param string $compiled_path
95
     *
96
     * @return bool
97
     */
98
    protected function isCompileRequired($compiled_path)
99
    {
100
        if ($this->recompile_always AND ! isset($this->compiled_paths[$compiled_path])) {
101
            return TRUE;
102
        }
103
104
        return ! file_exists($compiled_path);
105
    }
106
107
    /**
108
     * @param string $template_name
109
     *
110
     * @return string
111
     */
112
    protected function requireSourceFileContent($template_name)
113
    {
114
        if ( ! $source_file = $this->cascading_files->find_file($this->template_dir, $template_name)) {
115
            throw TemplateNotFoundException::forSourcePath($this->template_dir.'/'.$template_name);
116
        }
117
118
        return file_get_contents($source_file);
119
    }
120
121
    /**
122
     * @param string $compiled_path
123
     * @param string $compiled
124
     */
125
    protected function writeFile($compiled_path, $compiled)
126
    {
127
        $this->ensureWriteableDirectory(dirname($compiled_path));
128
        file_put_contents($compiled_path, $compiled);
129
    }
130
131
    /**
132
     * @param string $path
133
     */
134
    protected function ensureWriteableDirectory($path)
135
    {
136
        if (is_dir($path)) {
137
            if ( ! is_writeable($path)) {
138
                throw TemplateCacheException::pathNotWriteable($path);
139
            }
140
        } else {
141
            if ( ! mkdir($path, 0777, TRUE)) {
142
                throw TemplateCacheException::cannotCreateDirectory($path);
143
            }
144
        }
145
    }
146
147
}
148