Completed
Push — master ( d98c10...e4052f )
by Nikolas
04:37
created

ExecutionResource::doExecute()   D

Complexity

Conditions 9
Paths 6

Size

Total Lines 41
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
c 6
b 0
f 0
dl 0
loc 41
rs 4.909
cc 9
eloc 31
nc 6
nop 2
1
<?php
2
namespace rtens\domin\delivery\web\resources;
3
4
use rtens\domin\Action;
5
use rtens\domin\delivery\ParameterReader;
6
use rtens\domin\delivery\web\ActionForm;
7
use rtens\domin\delivery\web\ActionResult;
8
use rtens\domin\delivery\web\BreadCrumb;
9
use rtens\domin\delivery\web\BreadCrumbsTrail;
10
use rtens\domin\delivery\web\HeadElements;
11
use rtens\domin\delivery\web\WebApplication;
12
use rtens\domin\Executor;
13
14
class ExecutionResource {
15
16
    const TOKEN_ARG = '__token';
17
18
    /** @var WebApplication */
19
    private $app;
20
21
    /** @var BreadCrumbsTrail */
22
    private $crumbs;
23
24
    /** @var ParameterReader */
25
    private $reader;
26
27
    public function __construct(WebApplication $app, ParameterReader $reader, BreadCrumbsTrail $crumbs) {
28
        $this->app = $app;
29
        $this->crumbs = $crumbs;
30
        $this->reader = $reader;
31
    }
32
33
    private static function baseHeadElements() {
34
        return [
35
            HeadElements::jquery(),
36
            HeadElements::jqueryUi(), // not actually needed but it needs to be included before bootstrap.js too avoid conflicts
37
            HeadElements::bootstrap(),
38
            HeadElements::bootstrapJs(),
39
        ];
40
    }
41
42
    /**
43
     * @param null|string $actionId
44
     * @param null|string $token
45
     * @return string
46
     * @throws \Exception
47
     */
48
    public function handleGet($actionId = null, $token = null) {
49
        return $this->doExecute($actionId, $this->checkToken($actionId, $token));
50
    }
51
52
    /**
53
     * @param null|string $actionId
54
     * @param null|string $token
55
     * @return string
56
     * @throws \Exception
57
     */
58
    public function handlePost($actionId = null, $token = null) {
59
        return $this->doExecute($actionId, $this->checkToken($actionId, $token, true));
60
    }
61
62
    private function doExecute($actionId = null, $mayBeModifying = false) {
63
        if (!$actionId) {
64
            $actionId = $this->app->defaultAction;
65
        }
66
67
        if (!$this->app->access->isPermitted($actionId)) {
68
            throw new \Exception('Permission denied.');
69
        }
70
71
        $action = $this->getAction($actionId);
72
        $headElements = self::baseHeadElements();
73
74
        $form = new ActionForm($this->reader, $this->app->fields, $action, $actionId);
75
        $headElements = array_merge($headElements, $form->getHeadElements());
76
77
        if ($mayBeModifying || !$action->isModifying()) {
78
            $executor = new Executor($this->app->actions, $this->app->fields, $this->reader, $this->app->access);
79
            $result = new ActionResult($executor, $this->app->renderers, $action, $actionId, $this->crumbs);
80
            $headElements = array_merge($headElements, $result->getHeadElements());
81
            $confirm = false;
82
        } else {
83
            $confirm = true;
84
        }
85
86
        return (new Template(__DIR__ . '/ExecutionTemplate.html.php'))
87
            ->render([
88
                'name' => $this->app->name,
89
                'caption' => $action->caption(),
90
                'menu' => $this->app->menu->render(),
91
                'breadcrumbs' => $this->assembleBreadCrumbs(),
92
                'action' => $form->getModel(),
93
                'result' => isset($result) ? $result->getModel() : null,
94
                'headElements' => HeadElements::filter($headElements),
95
                'executed' => isset($result) && $result->wasExecuted(),
96
                'confirmationRequired' => $confirm,
97
                'token' => $action->isModifying() && $this->app->token ? [
98
                    'name' => self::TOKEN_ARG,
99
                    'value' => $this->app->token->generate($actionId)
100
                ]: null
101
            ]);
102
    }
103
104
    /**
105
     * @param $actionId
106
     * @return Action
107
     * @throws \Exception
108
     */
109
    private function getAction($actionId) {
110
        try {
111
            return $this->app->actions->getAction($actionId);
112
        } catch (\Exception $e) {
113
            throw new \Exception("Action [$actionId] is not registered.", 0, $e);
114
        }
115
    }
116
117
    private function assembleBreadCrumbs() {
118
        return array_map(function (BreadCrumb $crumb) {
119
            return [
120
                'target' => $crumb->getTarget(),
121
                'caption' => $crumb->getCaption()
122
            ];
123
        }, $this->crumbs->getCrumbs());
124
    }
125
126
    private function checkToken($actionId, $token, $default = false) {
127
        if (!$this->app->token) {
128
            return $default;
129
        }
130
        return $token && $this->app->token->isValid($token, $actionId);
131
    }
132
}