Completed
Push — master ( ca7ebd...ffd42a )
by Nikolas
03:40
created

ExecutionResource::doExecute()   C

Complexity

Conditions 8
Paths 3

Size

Total Lines 37
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 37
rs 5.3846
cc 8
eloc 29
nc 3
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 string $actionId
44
     * @param null|string $token
45
     * @return string
46
     * @throws \Exception
47
     */
48
    public function handleGet($actionId, $token = null) {
49
        return $this->doExecute($actionId, $this->checkToken($actionId, $token));
50
    }
51
52
    /**
53
     * @param string $actionId
54
     * @param null|string $token
55
     * @return string
56
     * @throws \Exception
57
     */
58
    public function handlePost($actionId, $token = null) {
59
        return $this->doExecute($actionId, $this->checkToken($actionId, $token, true));
60
    }
61
62
    private function doExecute($actionId, $mayBeModifying) {
63
        if (!$this->app->access->isPermitted($actionId)) {
64
            throw new \Exception('Permission denied.');
65
        }
66
67
        $action = $this->getAction($actionId);
68
        $headElements = self::baseHeadElements();
69
70
        $form = new ActionForm($this->reader, $this->app->fields, $action, $actionId);
71
        $headElements = array_merge($headElements, $form->getHeadElements());
72
73
        if ($mayBeModifying || !$action->isModifying()) {
74
            $executor = new Executor($this->app->actions, $this->app->fields, $this->reader, $this->app->access);
75
            $result = new ActionResult($executor, $this->app->renderers, $action, $actionId, $this->crumbs);
76
            $headElements = array_merge($headElements, $result->getHeadElements());
77
            $confirm = false;
78
        } else {
79
            $confirm = true;
80
        }
81
82
        return (new Template(__DIR__ . '/ExecutionTemplate.html.php'))
83
            ->render([
84
                'name' => $this->app->name,
85
                'caption' => $action->caption(),
86
                'menu' => $this->app->menu->render(),
87
                'breadcrumbs' => $this->assembleBreadCrumbs(),
88
                'action' => $form->getModel(),
89
                'result' => isset($result) ? $result->getModel() : null,
90
                'headElements' => HeadElements::filter($headElements),
91
                'executed' => isset($result) && $result->wasExecuted(),
92
                'confirmationRequired' => $confirm,
93
                'token' => $action->isModifying() && $this->app->token ? [
94
                    'name' => self::TOKEN_ARG,
95
                    'value' => $this->app->token->generate($actionId)
96
                ]: null
97
            ]);
98
    }
99
100
    /**
101
     * @param $actionId
102
     * @return Action
103
     * @throws \Exception
104
     */
105
    private function getAction($actionId) {
106
        try {
107
            return $this->app->actions->getAction($actionId);
108
        } catch (\Exception $e) {
109
            throw new \Exception("Action [$actionId] is not registered.", 0, $e);
110
        }
111
    }
112
113
    private function assembleBreadCrumbs() {
114
        return array_map(function (BreadCrumb $crumb) {
115
            return [
116
                'target' => $crumb->getTarget(),
117
                'caption' => $crumb->getCaption()
118
            ];
119
        }, $this->crumbs->getCrumbs());
120
    }
121
122
    private function checkToken($actionId, $token, $default = false) {
123
        if (!$this->app->token) {
124
            return $default;
125
        }
126
        return $token && $this->app->token->isValid($token, $actionId);
127
    }
128
}