Passed
Push — master ( cc4e99...e57543 )
by Thomas
02:55
created

SSViewerProxy::getCacheFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace LeKoala\DebugBar\Proxy;
4
5
use LeKoala\DebugBar\DebugBar;
6
use SilverStripe\View\SSViewer;
7
use SilverStripe\Control\Director;
8
9
/**
10
 * The template parser proxy will monitor the templates that are used during a page request. Since the
11
 * use of the template parser is behind cache checks, this will only execute during a cache flush.
12
 */
13
class SSViewerProxy extends SSViewer
14
{
15
    /**
16
     * Tracks all templates used in the current request
17
     *
18
     * @var array
19
     */
20
    protected static $allTemplates = array();
21
22
    /**
23
     * Whether the class has been used, meaning whether the page has been cached
24
     *
25
     * @var boolean
26
     */
27
    protected static $cached = true;
28
29
    /**
30
     * Overloaded to track all templates used in the current request
31
     *
32
     * {@inheritDoc}
33
     */
34
    public function process($item, $arguments = null, $inheritedScope = null)
35
    {
36
        $templateName = self::normalizeTemplateName($this->chosen);
37
        self::trackTemplateUsed($templateName);
38
39
        $startTime = microtime(true);
40
        DebugBar::withDebugBar(function (\DebugBar\DebugBar $debugBar) use ($templateName) {
41
            /** @var $timeData DebugBar\DataCollector\TimeDataCollector */
42
            $timeData = $debugBar->getCollector('time');
43
            if (!$timeData) {
0 ignored issues
show
introduced by Thomas
$timeData is of type LeKoala\DebugBar\DebugBa...ector\TimeDataCollector, thus it always evaluated to true.
Loading history...
44
                return;
45
            }
46
            $timeData->startMeasure($templateName, $templateName);
47
        });
48
49
        $result = parent::process($item, $arguments, $inheritedScope);
50
        $endTime = microtime(true);
51
        $totalTime = sprintf("%.2f", $endTime - $startTime);
52
53
        DebugBar::withDebugBar(function (\DebugBar\DebugBar $debugBar) use ($templateName) {
54
            /** @var $timeData DebugBar\DataCollector\TimeDataCollector */
55
            $timeData = $debugBar->getCollector('time');
56
            if (!$timeData) {
0 ignored issues
show
introduced by Thomas
$timeData is of type LeKoala\DebugBar\DebugBa...ector\TimeDataCollector, thus it always evaluated to true.
Loading history...
57
                return;
58
            }
59
            if ($timeData->hasStartedMeasure($templateName)) {
60
                $timeData->stopMeasure($templateName);
61
            }
62
        });
63
64
        $templateRenderWarningLevel = DebugBar::config()->get('template_rendering_warning_level');
65
        if ($templateRenderWarningLevel && $totalTime > $templateRenderWarningLevel) {
66
            $sourceFile = $this->getCacheFile($this->chosen);
67
            $messages = DebugBar::getDebugBar()->getCollector('messages');
68
            $messages->addMessage(
0 ignored issues
show
Bug introduced by Thomas
The method addMessage() does not exist on DebugBar\DataCollector\DataCollectorInterface. It seems like you code against a sub-type of DebugBar\DataCollector\DataCollectorInterface such as DebugBar\DataCollector\MessagesCollector. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

68
            $messages->/** @scrutinizer ignore-call */ 
69
                       addMessage(
Loading history...
69
                "The template $templateName needed $totalTime seconds to render" .
70
                    "\nYou could reduce this by implementing partial caching." .
71
                    "\nYou can also check the cache file : $sourceFile",
72
                'warning',
73
                false
74
            );
75
        }
76
77
        return $result;
78
    }
79
80
    /**
81
     * Get the cache file for a given template
82
     *
83
     * Useful to get to path to a slow template for example
84
     *
85
     * @param string $template
86
     * @return string
87
     */
88
    public function getCacheFile($template = null)
89
    {
90
        if ($template === null) {
91
            $template = $this->chosen;
92
        }
93
        return TEMP_PATH . DIRECTORY_SEPARATOR . '.cache'
94
            . str_replace(['\\', '/', ':'], '.', Director::makeRelative(realpath($template)));
95
    }
96
97
    /**
98
     * Get the templates used in the current request and the number of times they were called
99
     *
100
     * @return array
101
     */
102
    public static function getTemplatesUsed()
103
    {
104
        return static::$allTemplates;
105
    }
106
107
    /**
108
     * Reset the array
109
     *
110
     * @return void
111
     */
112
    public static function resetTemplatesUsed()
113
    {
114
        static::$allTemplates = [];
115
    }
116
117
    /**
118
     * Helps tracking the use of templates
119
     *
120
     * @param string $templateName
121
     */
122
    protected static function trackTemplateUsed($templateName)
123
    {
124
        static::$allTemplates[] = $templateName;
125
    }
126
127
    /**
128
     * Remove base path from template
129
     *
130
     * @param string $templateName
131
     * @return string
132
     */
133
    protected static function normalizeTemplateName($templateName)
134
    {
135
        return  str_ireplace(BASE_PATH, '', $templateName);
0 ignored issues
show
Bug Best Practice introduced by Thomas
The expression return str_ireplace(LeKo...ATH, '', $templateName) also could return the type array which is incompatible with the documented return type string.
Loading history...
136
    }
137
}
138