Completed
Pull Request — master (#268)
by
unknown
01:25
created

Xhgui_Controller_Run   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 374
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 31
lcom 1
cbo 5
dl 0
loc 374
rs 9.92
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A callgraph() 0 11 1
A __construct() 0 6 1
A index() 0 34 2
A view() 0 36 3
A deleteAllForm() 0 4 1
A deleteAllSubmit() 0 9 1
A url() 0 32 1
B compare() 0 50 7
A symbol() 0 20 1
A symbolShort() 0 22 1
A callgraphData() 0 17 4
A getWatches() 0 3 1
A setWatches() 0 3 1
A getProfiles() 0 3 1
A setProfiles() 0 3 1
A deleteForm() 0 17 2
A deleteSubmit() 0 20 2
1
<?php
2
3
use Slim\Slim;
4
5
class Xhgui_Controller_Run extends Xhgui_Controller
6
{
7
    /**
8
     * @var Xhgui_Profiles
9
     */
10
    private $profiles;
11
12
    /**
13
     * @var \Xhgui_WatchedFunctionsStorageInterface
14
     */
15
    private $watches;
16
17
    /**
18
     * Xhgui_Controller_Run constructor.
19
     * @param Slim $app
20
     * @param Xhgui_Profiles $profiles
21
     * @param Xhgui_WatchedFunctionsStorageInterface $watches
22
     */
23
    public function __construct(Slim $app, Xhgui_Profiles $profiles, \Xhgui_WatchedFunctionsStorageInterface $watches)
24
    {
25
        parent::__construct($app);
26
        $this->setProfiles($profiles);
27
        $this->setWatches($watches);
28
    }
29
30
    /**
31
     *
32
     */
33
    public function index()
34
    {
35
        $request = $this->app->request();
36
37
        $filter = Xhgui_Storage_Filter::fromRequest($request);
38
39
        $result = $this->getProfiles()->getAll($filter);
40
        $title = 'Recent runs';
41
        $titleMap = array(
42
            'wt'    => 'Longest wall time',
43
            'cpu'   => 'Most CPU time',
44
            'mu'    => 'Highest memory use',
45
        );
46
        if (isset($titleMap[$filter->getSort()])) {
47
            $title = $titleMap[$filter->getSort()];
48
        }
49
        $paging = array(
50
            'total_pages'   => $result['totalPages'],
51
            'page'          => $result['page'],
52
            'sort'          => $filter->getSort(),
53
            'direction'     => $result['direction']
54
        );
55
56
        $this->_template = 'runs/list.twig';
57
58
        $this->set(array(
59
            'paging'        => $paging,
60
            'base_url'      => 'home',
61
            'runs'          => $result['results'],
62
            'date_format'   => $this->app->config('date.format'),
63
            'search'        => $filter->toArray(),
64
            'title'         => $title
65
        ));
66
    }
67
68
    /**
69
     *
70
     */
71
    public function view()
72
    {
73
        $request = $this->app->request();
74
        $detailCount = $this->app->config('detail.count');
75
        $result = $this->getProfiles()->get($request->get('id'));
76
77
        $result->calculateSelf();
78
79
        // Self wall time graph
80
        $timeChart = $result->extractDimension('ewt', $detailCount);
81
82
        // Memory Block
83
        $memoryChart = $result->extractDimension('emu', $detailCount);
84
85
        // Watched Functions Block
86
        $watchedFunctions = array();
87
        foreach ($this->getWatches()->getWatchedFunctions() as $watch) {
88
            $matches = $result->getWatched($watch['name']);
89
90
            if ($matches) {
91
                $watchedFunctions = array_merge($watchedFunctions, $matches);
92
            }
93
        }
94
95
        $profile = $result->sort('ewt', $result->getProfile());
96
97
        $this->_template = 'runs/view.twig';
98
        $this->set(array(
99
            'profile'       => $profile,
100
            'result'        => $result,
101
            'wall_time'     => $timeChart,
102
            'memory'        => $memoryChart,
103
            'watches'       => $watchedFunctions,
104
            'date_format'   => $this->app->config('date.format'),
105
        ));
106
    }
107
108
    /**
109
     * @throws Exception
110
     */
111
    public function deleteForm()
112
    {
113
        $request = $this->app->request();
114
        $id = $request->get('id');
115
        if (empty($id)) {
116
            throw new Exception('The "id" parameter is required.');
117
        }
118
119
        // Get details
120
        $result = $this->getProfiles()->get($id);
121
122
        $this->_template = 'runs/delete-form.twig';
123
        $this->set(array(
124
            'run_id' => $id,
125
            'result' => $result,
126
        ));
127
    }
128
129
    /**
130
     * @throws Exception
131
     */
132
    public function deleteSubmit()
133
    {
134
        $request = $this->app->request();
135
        $id = $request->post('id');
136
137
        // Don't call profilers->delete() unless $id is set,
138
        // otherwise it will turn the null into a MongoId and return "Sucessful".
139
        if (empty($id)) {
140
            // Form checks this already,
141
            // only reachable by handcrafted or malformed requests.
142
            throw new Exception('The "id" parameter is required.');
143
        }
144
145
        // Delete the profile run.
146
        $this->getProfiles()->delete($id);
147
148
        $this->app->flash('success', 'Deleted profile ' . $id);
149
150
        $this->app->redirect($this->app->urlFor('home'));
151
    }
152
153
    /**
154
     *
155
     */
156
    public function deleteAllForm()
157
    {
158
        $this->_template = 'runs/delete-all-form.twig';
159
    }
160
161
    /**
162
     *
163
     */
164
    public function deleteAllSubmit()
165
    {
166
        // Delete all profile runs.
167
        $this->getProfiles()->truncate();
168
169
        $this->app->flash('success', 'Deleted all profiles');
170
171
        $this->app->redirect($this->app->urlFor('home'));
172
    }
173
174
    /**
175
     *
176
     */
177
    public function url()
178
    {
179
        $request = $this->app->request();
180
181
        $filter = Xhgui_Storage_Filter::fromRequest($request);
182
        $filter->setUrl($request->get('url'));
183
        $result = $this->getProfiles()->getAll($filter);
184
185
        $chartData = $this->getProfiles()->getPercentileForUrl(
186
            90,
187
            $request->get('url'),
188
            $filter
189
        );
190
191
        $paging = array(
192
            'total_pages'   => $result['totalPages'],
193
            'sort'          => $filter->getSort(),
194
            'page'          => $result['page'],
195
            'direction'     => $result['direction']
196
        );
197
198
        $this->_template = 'runs/url.twig';
199
        $this->set(array(
200
            'paging'        => $paging,
201
            'base_url'      => 'url.view',
202
            'runs'          => $result['results'],
203
            'url'           => $filter->getUrl(),
204
            'chart_data'    => $chartData,
205
            'date_format'   => $this->app->config('date.format'),
206
            'search'        => array_merge($filter->toArray(), array('url' => $request->get('url'))),
207
        ));
208
    }
209
210
    /**
211
     *
212
     */
213
    public function compare()
214
    {
215
        $request = $this->app->request();
216
217
        $baseRun = $headRun = $candidates = $comparison = null;
218
        $paging = array();
219
220
        if ($request->get('base')) {
221
            $baseRun = $this->getProfiles()->get($request->get('base'));
222
        }
223
224
        // we have one selected but we need to list other runs.
225
        if ($baseRun && !$request->get('head')) {
226
            $filter = Xhgui_Storage_Filter::fromRequest($request);
227
            $filter->setUrl($baseRun->getMeta('simple_url'));
228
229
            $candidates = $this->getProfiles()->getAll($filter);
230
231
            $paging = array(
232
                'total_pages'   => $candidates['totalPages'],
233
                'page'          => $candidates['page'],
234
                'sort'          => $filter->getSort(),
235
                'direction'     => $candidates['direction']
236
            );
237
        }
238
239
        if ($request->get('head')) {
240
            $headRun = $this->getProfiles()->get($request->get('head'));
241
        }
242
243
        if ($baseRun && $headRun) {
244
            $comparison = $baseRun->compare($headRun);
245
        }
246
247
        $this->_template = 'runs/compare.twig';
248
        $this->set(array(
249
            'base_url'      => 'run.compare',
250
            'base_run'      => $baseRun,
251
            'head_run'      => $headRun,
252
            'candidates'    => $candidates,
253
            'url_params'    => $request->get(),
254
            'date_format'   => $this->app->config('date.format'),
255
            'comparison'    => $comparison,
256
            'paging'        => $paging,
257
            'search'        => array(
258
                'base' => $request->get('base'),
259
                'head' => $request->get('head'),
260
            )
261
        ));
262
    }
263
264
    /**
265
     *
266
     */
267
    public function symbol()
268
    {
269
        $request    = $this->app->request();
270
        $id         = $request->get('id');
271
        $symbol     = $request->get('symbol');
272
273
        $profile = $this->getProfiles()->get($id);
274
        $profile->calculateSelf();
275
        list($parents, $current, $children) = $profile->getRelatives($symbol);
276
277
        $this->_template = 'runs/symbol.twig';
278
        $this->set(array(
279
            'symbol'    => $symbol,
280
            'id'        => $id,
281
            'main'      => $profile->get('main()'),
282
            'parents'   => $parents,
283
            'current'   => $current,
284
            'children'  => $children,
285
        ));
286
    }
287
288
    /**
289
     *
290
     */
291
    public function symbolShort()
292
    {
293
        $request    = $this->app->request();
294
        $id         = $request->get('id');
295
        $threshold  = $request->get('threshold');
296
        $symbol     = $request->get('symbol');
297
        $metric     = $request->get('metric');
298
299
        $profile = $this->getProfiles()->get($id);
300
        $profile->calculateSelf();
301
        list($parents, $current, $children) = $profile->getRelatives($symbol, $metric, $threshold);
302
303
        $this->_template = 'runs/symbol-short.twig';
304
        $this->set(array(
305
            'symbol'    => $symbol,
306
            'id'        => $id,
307
            'main'      => $profile->get('main()'),
308
            'parents'   => $parents,
309
            'current'   => $current,
310
            'children'  => $children,
311
        ));
312
    }
313
314
    /**
315
     *
316
     */
317
    public function callgraph()
318
    {
319
        $request = $this->app->request();
320
        $profile = $this->getProfiles()->get($request->get('id'));
321
322
        $this->_template = 'runs/callgraph.twig';
323
        $this->set(array(
324
            'profile'       => $profile,
325
            'date_format'   => $this->app->config('date.format'),
326
        ));
327
    }
328
329
    /**
330
     * @return string
331
     * @throws Exception
332
     */
333
    public function callgraphData($nodes = false)
334
    {
335
        $request    = $this->app->request();
336
        $response   = $this->app->response();
337
        $profile    = $this->getProfiles()->get($request->get('id'));
338
        $metric     = $request->get('metric') ?: 'wt';
339
        $threshold  = (float)$request->get('threshold') ?: 0.01;
340
341
        if ($nodes) {
342
            $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...
343
        } else {
344
            $callgraph  = $profile->getCallgraph($metric, $threshold);
345
        }
346
347
        $response['Content-Type'] = 'application/json';
348
        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...
349
    }
350
351
    /**
352
     * @return Xhgui_WatchedFunctionsStorageInterface
353
     */
354
    public function getWatches() {
355
        return $this->watches;
356
    }
357
358
    /**
359
     * @param Xhgui_WatchedFunctionsStorageInterface $watches
360
     */
361
    public function setWatches($watches) {
362
        $this->watches = $watches;
363
    }
364
365
    /**
366
     * @return Xhgui_Profiles
367
     */
368
    public function getProfiles() {
369
        return $this->profiles;
370
    }
371
372
    /**
373
     * @param Xhgui_Profiles $profiles
374
     */
375
    public function setProfiles($profiles) {
376
        $this->profiles = $profiles;
377
    }
378
}
379