1<?php
2
3namespace Wpb\String_Blade_Compiler\Compilers;
4
5use Config;
6use Illuminate\Filesystem\Filesystem;
7use Illuminate\Support\Str;
8use Illuminate\View\Compilers\CompilerInterface;
9use InvalidArgumentException;
10
11class StringBladeCompiler extends BladeCompiler {
12
13    private $use_cache_keys = [];
14    private $viewData = [];
15
16    /**
17     * Create a new compiler instance.
18     *
19     * @param  \Illuminate\Filesystem\Filesystem  $files
20     * @param  string  $cachePath
21     * @return void
22     *
23     * @throws \InvalidArgumentException
24     */
25    public function __construct(Filesystem $files, $cachePath)
26    {
27        $this->files = $files;
28        $this->cachePath = $cachePath;
29    }
30
31    public function setViewData($viewData) {
32        $this->viewData = $viewData;
33    }
34
35    /**
36     * Compile the view at the given path.
37     *
38     * @param  object $viewData
39     * @return void
40     */
41    public function compile($viewData = null)
42    {
43        if (!is_null($viewData)) {
44            $this->viewData = $viewData;
45        }
46
47        if (property_exists($this->viewData, 'cache_key'))
48        {
49            $this->setPath($this->viewData->cache_key);
50        }
51
52        $contents = $this->compileString(
53            $this->viewData->template
54        );
55
56        $tokens = $this->getOpenAndClosingPhpTokens($contents);
57
58        // If the tokens we retrieved from the compiled contents have at least
59        // one opening tag and if that last token isn't the closing tag, we
60        // need to close the statement before adding the path at the end.
61        if ($tokens->isNotEmpty() && $tokens->last() !== T_CLOSE_TAG) {
62            $contents .= ' ?>';
63        }
64
65        if (isset($this->viewData->templateRefKey)) {
66            $contents .= "<?php /**PATH {$this->viewData->templateRefKey} ENDPATH**/ ?>";
67        }
68
69        if (! is_null($this->cachePath)) {
70            $this->files->put(
71                $this->getCompiledPath($this->viewData), $contents
72            );
73        }
74    }
75
76    /**
77     * Get the path to the compiled version of a view.
78     *
79     * @param  string  $path
80     * @return string
81     */
82    public function getCompiledPath($viewData)
83    {
84        if (!property_exists($viewData, 'cache_key'))
85        {
86            $cacheKey = Str::random(40);
87            while (in_array($cacheKey, $this->use_cache_keys)) {
88                $cacheKey = Str::random(40);
89            }
90
91            $viewData->cache_key = $cacheKey;
92        }
93
94        return $this->cachePath.'/'.sha1($viewData->cache_key).'.php';
95    }
96
97    /**
98     * Determine if the view at the given path is expired.
99     *
100     * @param  object $viewData
101     * @return bool
102     */
103    public function isExpired($viewData)
104    {
105
106        // adds ability to force template recompile
107        if ($this->forceTemplateRecompile) {
108            return true;
109        }
110
111        $compiled = $this->getCompiledPath($viewData);
112
113        // If the compiled file doesn't exist we will indicate that the view is expired
114        // so that it can be re-compiled. Else, we will verify the last modification
115        // of the views is less than the modification times of the compiled views.
116        if ( ! $this->cachePath || ! $this->files->exists($compiled))
117        {
118            return true;
119        }
120
121        // If set to 0, then return cache has expired
122        if (property_exists($viewData, 'secondsTemplateCacheExpires')) {
123            if ($viewData->secondsTemplateCacheExpires == 0) {
124                return true;
125            }
126        } else {
127            $viewData->secondsTemplateCacheExpires = 0;
128        }
129
130        // Note: The lastModified time for a file on homestead will use the time from the host system.
131        //       This means the vm time could be off, so setting the timeout to seconds may not work as expected.
132
133        return time() >= ($this->files->lastModified($compiled) + $viewData->secondsTemplateCacheExpires) ;
134    }
135}
136