Completed
Pull Request — master (#237)
by
unknown
06:12
created

Xhgui_Controller_Run::view()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 39
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 24
nc 6
nop 0
1
<?php
2
3
use Slim\Slim;
4
5
class Xhgui_Controller_Run extends Xhgui_Controller
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
6
{
7
    /**
8
     * HTTP GET attribute name for comma separated filters
9
     */
10
    const FILTER_ARGUMENT_NAME = 'filter';
11
12
    /**
13
     * @var Xhgui_Profiles
14
     */
15
    private $profiles;
16
17
    /**
18
     * @var Xhgui_WatchFunctions
19
     */
20
    private $watches;
21
22
    public function __construct(Slim $app, Xhgui_Profiles $profiles, Xhgui_WatchFunctions $watches)
23
    {
24
        $this->app = $app;
25
        $this->profiles = $profiles;
26
        $this->watches = $watches;
27
    }
28
29
    public function index()
30
    {
31
        $request = $this->app->request();
32
33
        $search = array();
34
        $keys = array('date_start', 'date_end', 'url');
35
        foreach ($keys as $key) {
36
            if ($request->get($key)) {
37
                $search[$key] = $request->get($key);
38
            }
39
        }
40
        $sort = $request->get('sort');
41
42
        $result = $this->profiles->getAll(array(
43
            'sort' => $sort,
44
            'page' => $request->get('page'),
45
            'direction' => $request->get('direction'),
46
            'perPage' => $this->app->config('page.limit'),
47
            'conditions' => $search,
48
            'projection' => true,
49
        ));
50
51
        $title = 'Recent runs';
52
        $titleMap = array(
53
            'wt' => 'Longest wall time',
54
            'cpu' => 'Most CPU time',
55
            'mu' => 'Highest memory use',
56
        );
57
        if (isset($titleMap[$sort])) {
58
            $title = $titleMap[$sort];
59
        }
60
61
        $paging = array(
62
            'total_pages' => $result['totalPages'],
63
            'page' => $result['page'],
64
            'sort' => $sort,
65
            'direction' => $result['direction']
66
        );
67
68
        $this->_template = 'runs/list.twig';
69
        $this->set(array(
70
            'paging' => $paging,
71
            'base_url' => 'home',
72
            'runs' => $result['results'],
73
            'date_format' => $this->app->config('date.format'),
74
            'search' => $search,
75
            'has_search' => strlen(implode('', $search)) > 0,
76
            'title' => $title
77
        ));
78
    }
79
80
    public function view()
81
    {
82
        $request = $this->app->request();
83
        $detailCount = $this->app->config('detail.count');
84
        $result = $this->profiles->get($request->get('id'));
85
86
        $result->calculateSelf();
87
88
        // Self wall time graph
89
        $timeChart = $result->extractDimension('ewt', $detailCount);
90
91
        // Memory Block
92
        $memoryChart = $result->extractDimension('emu', $detailCount);
93
94
        // Watched Functions Block
95
        $watchedFunctions = array();
96
        foreach ($this->watches->getAll() as $watch) {
97
            $matches = $result->getWatched($watch['name']);
98
            if ($matches) {
99
                $watchedFunctions = array_merge($watchedFunctions, $matches);
100
            }
101
        }
102
103
        if (false !== $request->get(self::FILTER_ARGUMENT_NAME, false)) {
104
            $profile = $result->sort('ewt', $result->filter($result->getProfile(), $this->getFilters()));
105
        } else {
106
            $profile = $result->sort('ewt', $result->getProfile());
107
        }
108
109
        $this->_template = 'runs/view.twig';
110
        $this->set(array(
111
            'profile' => $profile,
112
            'result' => $result,
113
            'wall_time' => $timeChart,
114
            'memory' => $memoryChart,
115
            'watches' => $watchedFunctions,
116
            'date_format' => $this->app->config('date.format'),
117
        ));
118
    }
119
120
    /**
121
     * @return array
122
     */
123
    protected function getFilters()
124
    {
125
        $request = $this->app->request();
126
        $filterString = $request->get(self::FILTER_ARGUMENT_NAME);
127
        if (strlen($filterString)) {
128
            $filters = explode(',', $filterString);
129
        } else {
130
            $filters = $this->app->config('run.view.filter.names');
131
        }
132
133
        return $filters;
134
    }
135
136
    public function url()
137
    {
138
        $request = $this->app->request();
139
        $pagination = array(
140
            'sort' => $request->get('sort'),
141
            'direction' => $request->get('direction'),
142
            'page' => $request->get('page'),
143
            'perPage' => $this->app->config('page.limit'),
144
        );
145
146
        $search = array();
147
        $keys = array('date_start', 'date_end', 'limit', 'limit_custom');
148
        foreach ($keys as $key) {
149
            $search[$key] = $request->get($key);
150
        }
151
152
        $runs = $this->profiles->getForUrl(
153
            $request->get('url'),
154
            $pagination,
155
            $search
156
        );
157
158
        if (
159
            isset($search['limit_custom'])
160
            && strlen($search['limit_custom']) > 0
161
            && $search['limit_custom'][0] == 'P'
162
        ) {
163
            $search['limit'] = $search['limit_custom'];
164
        }
165
166
        $chartData = $this->profiles->getPercentileForUrl(
167
            90,
168
            $request->get('url'),
169
            $search
170
        );
171
172
        $paging = array(
173
            'total_pages' => $runs['totalPages'],
174
            'sort' => $pagination['sort'],
175
            'page' => $runs['page'],
176
            'direction' => $runs['direction']
177
        );
178
179
        $this->_template = 'runs/url.twig';
180
        $this->set(array(
181
            'paging' => $paging,
182
            'base_url' => 'url.view',
183
            'runs' => $runs['results'],
184
            'url' => $request->get('url'),
185
            'chart_data' => $chartData,
186
            'date_format' => $this->app->config('date.format'),
187
            'search' => array_merge($search, array('url' => $request->get('url'))),
188
        ));
189
    }
190
191
    public function compare()
192
    {
193
        $request = $this->app->request();
194
195
        $baseRun = $headRun = $candidates = $comparison = null;
196
        $paging = array();
197
198
        if ($request->get('base')) {
199
            $baseRun = $this->profiles->get($request->get('base'));
200
        }
201
202
        if ($baseRun && !$request->get('head')) {
203
            $pagination = array(
204
                'direction' => $request->get('direction'),
205
                'sort' => $request->get('sort'),
206
                'page' => $request->get('page'),
207
                'perPage' => $this->app->config('page.limit'),
208
            );
209
            $candidates = $this->profiles->getForUrl(
210
                $baseRun->getMeta('simple_url'),
211
                $pagination
212
            );
213
214
            $paging = array(
215
                'total_pages' => $candidates['totalPages'],
216
                'sort' => $pagination['sort'],
217
                'page' => $candidates['page'],
218
                'direction' => $candidates['direction']
219
            );
220
        }
221
222
        if ($request->get('head')) {
223
            $headRun = $this->profiles->get($request->get('head'));
224
        }
225
226
        if ($baseRun && $headRun) {
227
            $comparison = $baseRun->compare($headRun);
228
        }
229
230
        $this->_template = 'runs/compare.twig';
231
        $this->set(array(
232
            'base_url' => 'run.compare',
233
            'base_run' => $baseRun,
234
            'head_run' => $headRun,
235
            'candidates' => $candidates,
236
            'url_params' => $request->get(),
237
            'date_format' => $this->app->config('date.format'),
238
            'comparison' => $comparison,
239
            'paging' => $paging,
240
            'search' => array(
241
                'base' => $request->get('base'),
242
                'head' => $request->get('head'),
243
            )
244
        ));
245
    }
246
247
    public function symbol()
248
    {
249
        $request = $this->app->request();
250
        $id = $request->get('id');
251
        $symbol = $request->get('symbol');
252
253
        $profile = $this->profiles->get($id);
254
        $profile->calculateSelf();
255
        list($parents, $current, $children) = $profile->getRelatives($symbol);
256
257
        $this->_template = 'runs/symbol.twig';
258
        $this->set(array(
259
            'symbol' => $symbol,
260
            'id' => $id,
261
            'main' => $profile->get('main()'),
262
            'parents' => $parents,
263
            'current' => $current,
264
            'children' => $children,
265
        ));
266
    }
267
268
    public function symbolShort()
269
    {
270
        $request = $this->app->request();
271
        $id = $request->get('id');
272
        $threshold = $request->get('threshold');
273
        $symbol = $request->get('symbol');
274
        $metric = $request->get('metric');
275
276
        $profile = $this->profiles->get($id);
277
        $profile->calculateSelf();
278
        list($parents, $current, $children) = $profile->getRelatives($symbol, $metric, $threshold);
279
280
        $this->_template = 'runs/symbol-short.twig';
281
        $this->set(array(
282
            'symbol' => $symbol,
283
            'id' => $id,
284
            'main' => $profile->get('main()'),
285
            'parents' => $parents,
286
            'current' => $current,
287
            'children' => $children,
288
        ));
289
    }
290
291 View Code Duplication
    public function callgraph()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
292
    {
293
        $request = $this->app->request();
294
        $profile = $this->profiles->get($request->get('id'));
295
296
        $this->_template = 'runs/callgraph.twig';
297
        $this->set(array(
298
            'profile' => $profile,
299
            'date_format' => $this->app->config('date.format'),
300
        ));
301
    }
302
303 View Code Duplication
    public function callgraphData()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
    {
305
        $request = $this->app->request();
306
        $response = $this->app->response();
307
        $profile = $this->profiles->get($request->get('id'));
308
        $metric = $request->get('metric') ?: 'wt';
309
        $threshold = (float)$request->get('threshold') ?: 0.01;
310
        $callgraph = $profile->getCallgraph($metric, $threshold);
311
312
        $response['Content-Type'] = 'application/json';
313
        return $response->body(json_encode($callgraph));
0 ignored issues
show
Bug introduced by
The method body cannot be called on $response (of type array<string,string,{"Content-Type":"string"}>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
314
    }
315
316 View Code Duplication
    public function flamegraph()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
317
    {
318
        $request = $this->app->request();
319
        $profile = $this->profiles->get($request->get('id'));
320
321
        $this->_template = 'runs/flamegraph.twig';
322
        $this->set(array(
323
            'profile' => $profile,
324
            'date_format' => $this->app->config('date.format'),
325
        ));
326
    }
327
328 View Code Duplication
    public function flamegraphData()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
329
    {
330
        $request = $this->app->request();
331
        $response = $this->app->response();
332
        $profile = $this->profiles->get($request->get('id'));
333
        $metric = $request->get('metric') ?: 'wt';
334
        $threshold = (float)$request->get('threshold') ?: 0.01;
335
        $flamegraph = $profile->getFlamegraph($metric, $threshold);
336
337
        $response['Content-Type'] = 'application/json';
338
        return $response->body(json_encode($flamegraph));
0 ignored issues
show
Bug introduced by
The method body cannot be called on $response (of type array<string,string,{"Content-Type":"string"}>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
339
    }
340
341 View Code Duplication
    public function callgraphDataDot()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
342
    {
343
        $request = $this->app->request();
344
        $response = $this->app->response();
345
        $profile = $this->profiles->get($request->get('id'));
346
        $metric = $request->get('metric') ?: 'wt';
347
        $threshold = (float)$request->get('threshold') ?: 0.01;
348
        $callgraph = $profile->getCallgraphNodes($metric, $threshold);
0 ignored issues
show
Bug introduced by
The method getCallgraphNodes() does not exist on Xhgui_Profile. Did you maybe mean getCallgraph()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
349
350
        $response['Content-Type'] = 'application/json';
351
        return $response->body(json_encode($callgraph));
0 ignored issues
show
Bug introduced by
The method body cannot be called on $response (of type array<string,string,{"Content-Type":"string"}>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
352
    }
353
}
354